diff --git a/.github/workflows/docker-build-test.yml b/.github/workflows/docker-build-test.yml index edae497ee..f5872ce8b 100644 --- a/.github/workflows/docker-build-test.yml +++ b/.github/workflows/docker-build-test.yml @@ -4,34 +4,46 @@ on: push: paths-ignore: - 'aider/website/**' - - README.md - - HISTORY.md + - 'README.md' + - 'HISTORY.md' + - '.github/workflows/*' + - '!.github/workflows/docker-build-test.yml' branches: - main pull_request: paths-ignore: - 'aider/website/**' - - README.md + - 'README.md' + - 'HISTORY.md' + - '.github/workflows/*' + - '!.github/workflows/docker-build-test.yml' branches: - main -# copy most of these steps from release.yml, but push: false and no tags: - jobs: - build: + docker_build_and_push: runs-on: ubuntu-latest - steps: - name: Checkout code uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 - + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Build Docker standard image + - name: Login to DockerHub + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + + - name: Build Docker images (PR) + if: ${{ github.event_name == 'pull_request' }} uses: docker/build-push-action@v5 with: context: . @@ -40,7 +52,19 @@ jobs: push: false target: aider - - name: Build Docker full image + - name: Build Docker images (Push) + if: ${{ github.event_name != 'pull_request' }} + uses: docker/build-push-action@v5 + with: + context: . + file: ./docker/Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ secrets.DOCKERHUB_USERNAME }}/aider:dev + target: aider + + - name: Build Docker full image (PR) + if: ${{ github.event_name == 'pull_request' }} uses: docker/build-push-action@v5 with: context: . @@ -48,3 +72,14 @@ jobs: platforms: linux/amd64,linux/arm64 push: false target: aider-full + + - name: Build Docker full image (Push) + if: ${{ github.event_name != 'pull_request' }} + uses: docker/build-push-action@v5 + with: + context: . + file: ./docker/Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ secrets.DOCKERHUB_USERNAME }}/aider-full:dev + target: aider-full diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml index b9268de91..9e7efc2f5 100644 --- a/.github/workflows/docker-release.yml +++ b/.github/workflows/docker-release.yml @@ -12,6 +12,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml new file mode 100644 index 000000000..29751ebfb --- /dev/null +++ b/.github/workflows/issues.yml @@ -0,0 +1,29 @@ +name: Process GitHub Issues +on: + schedule: + - cron: '0 */12 * * *' # Run every 12 hours + workflow_dispatch: # Allow manual triggers + +jobs: + process-issues: + runs-on: ubuntu-latest + permissions: + issues: write # Required to modify issues + + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install requests python-dotenv tqdm + + - name: Run issues script + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: python scripts/issues.py --yes diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 1eb78382e..4454e832f 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -12,6 +12,7 @@ on: - "main" paths: - "aider/website/**" + - ".github/workflows/pages.yml" # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -36,7 +37,9 @@ jobs: working-directory: aider/website steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup Ruby uses: ruby/setup-ruby@v1 with: @@ -53,10 +56,9 @@ jobs: env: JEKYLL_ENV: production - name: Upload artifact - # Automatically uploads an artifact from the './_site' directory by default - uses: actions/upload-pages-artifact@v1 + uses: actions/upload-pages-artifact@v3 with: - path: "aider/website/_site/" + path: "aider/website/_site" # Deployment job deploy: @@ -68,7 +70,7 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v2 + uses: actions/deploy-pages@v4 - name: Set up Python 3.12 uses: actions/setup-python@v5 @@ -82,4 +84,4 @@ jobs: - name: Run linkchecker run: | - linkchecker https://aider.chat + linkchecker --ignore-url='.+\.(mp4|mov|avi)' https://aider.chat diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 274be72c5..ade95897a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,6 +12,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v5 diff --git a/.github/workflows/ubuntu-tests.yml b/.github/workflows/ubuntu-tests.yml index 3654df7bb..632c03757 100644 --- a/.github/workflows/ubuntu-tests.yml +++ b/.github/workflows/ubuntu-tests.yml @@ -4,14 +4,19 @@ on: push: paths-ignore: - 'aider/website/**' - - README.md - - HISTORY.md + - 'README.md' + - 'HISTORY.md' + - '.github/workflows/*' + - '!.github/workflows/ubuntu-tests.yml' branches: - main pull_request: paths-ignore: - 'aider/website/**' - - README.md + - 'README.md' + - 'HISTORY.md' + - '.github/workflows/*' + - '!.github/workflows/ubuntu-tests.yml' branches: - main @@ -25,12 +30,19 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y libportaudio2 + - name: Install dependencies run: | python -m pip install --upgrade pip @@ -38,5 +50,7 @@ jobs: pip install . - name: Run tests + env: + AIDER_ANALYTICS: false run: | pytest diff --git a/.github/workflows/windows-tests.yml b/.github/workflows/windows-tests.yml index c79b0dd5f..21799563e 100644 --- a/.github/workflows/windows-tests.yml +++ b/.github/workflows/windows-tests.yml @@ -4,14 +4,19 @@ on: push: paths-ignore: - 'aider/website/**' - - README.md - - HISTORY.md + - 'README.md' + - 'HISTORY.md' + - '.github/workflows/*' + - '!.github/workflows/windows-tests.yml' branches: - main pull_request: paths-ignore: - 'aider/website/**' - - README.md + - 'README.md' + - 'HISTORY.md' + - '.github/workflows/*' + - '!.github/workflows/windows-tests.yml' branches: - main @@ -25,6 +30,8 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 @@ -38,6 +45,8 @@ jobs: pip install . - name: Run tests + env: + AIDER_ANALYTICS: false run: | pytest diff --git a/.gitignore b/.gitignore index df9efed89..8ad33fd3c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,8 @@ _site .jekyll-cache/ .jekyll-metadata aider/__version__.py +aider/_version.py .venv/ +.#* .gitattributes +tmp.benchmarks/ \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 648256e10..abe35a1c0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -56,13 +56,6 @@ It is recommended to create a virtual environment outside of the repository to k python -m venv /path/to/venv ``` -#### Using `virtualenv` (for older Python versions) - -``` -pip install virtualenv -virtualenv /path/to/venv -``` - ### Activate the Virtual Environment #### On Windows diff --git a/HISTORY.md b/HISTORY.md index e2785d6f0..b2e99c033 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,13 +1,180 @@ # Release history -### main branch +### Aider v0.74.1 + +- Have o1 & o3-mini generate markdown by sending the magic "Formatting re-enabled." string. +- Bugfix for multi-line inputs, which should not include the ". " continuation prompt. + +### Aider v0.74.0 + +- Dynamically changes the Ollama context window to hold the current chat. +- Better support for o3-mini, DeepSeek V3 & R1, o1-mini, o1 especially via third-party API providers. +- Remove `` tags from R1 responses for commit messages (and other weak model uses). +- Can now specify `use_temperature: ` in model settings, not just true/false. +- The full docker container now includes `boto3` for Bedrock. +- Docker containers now set `HOME=/app` which is the normal project mount-point, to persist `~/.aider`. +- Bugfix to prevent creating incorrect filenames like `python`, `php`, etc. +- Bugfix for `--timeout` +- Bugfix so that `/model` now correctly reports that the weak model is not changed. +- Bugfix so that multi-line mode persists through ^C at confirmation prompts. +- Watch files now fully ignores top-level directories named in ignore files, to reduce the chance of hitting OS watch limits. Helpful to ignore giant subtrees like `node_modules`. +- Fast startup with more providers and when model metadata provided in local files. +- Improved .gitignore handling: + - Honor ignores already in effect regardless of how they've been configured. + - Check for .env only when the file exists. +- Yes/No prompts now accept All/Skip as alias for Y/N even when not processing a group of confirmations. +- Aider wrote 77% of the code in this release. + +### Aider v0.73.0 + +- Full support for o3-mini: `aider --model o3-mini` +- New `--reasoning-effort` argument: low, medium, high. +- Improved handling of context window size limits, with better messaging and Ollama-specific guidance. +- Added support for removing model-specific reasoning tags from responses with `remove_reasoning: tagname` model setting. +- Auto-create parent directories when creating new files, by xqyz. +- Support for R1 free on OpenRouter: `--model openrouter/deepseek/deepseek-r1:free` +- Aider wrote 69% of the code in this release. + +### Aider v0.72.3 + +- Enforce user/assistant turn order to avoid R1 errors, by miradnanali. +- Case-insensitive model name matching while preserving original case. + +### Aider v0.72.2 +- Harden against user/assistant turn order problems which cause R1 errors. + +### Aider v0.72.1 +- Fix model metadata for `openrouter/deepseek/deepseek-r1` + +### Aider v0.72.0 +- Support for DeepSeek R1. + - Use shortcut: `--model r1` + - Also via OpenRouter: `--model openrouter/deepseek/deepseek-r1` +- Added Kotlin syntax support to repo map, by Paul Walker. +- Added `--line-endings` for file writing, by Titusz Pan. +- Added examples_as_sys_msg=True for GPT-4o models, improves benchmark scores. +- Bumped all dependencies, to pick up litellm support for o1 system messages. +- Bugfix for turn taking when reflecting lint/test errors. +- Aider wrote 52% of the code in this release. + +### Aider v0.71.1 + +- Fix permissions issue in Docker images. +- Added read-only file announcements. +- Bugfix: ASCII fallback for unicode errors. +- Bugfix: integer indices for list slicing in repomap calculations. + +### Aider v0.71.0 + +- Prompts to help DeepSeek work better when alternating between `/ask` and `/code`. +- Streaming pretty LLM responses is smoother and faster for long replies. +- Streaming automatically turns of for model that don't support it + - Can now switch to/from `/model o1` and a streaming model +- Pretty output remains enabled even when editing files with triple-backtick fences +- Bare `/ask`, `/code` and `/architect` commands now switch the chat mode. +- Increased default size of the repomap. +- Increased max chat history tokens limit from 4k to 8k. +- Turn off fancy input and watch files if terminal is dumb. +- Added support for custom voice format and input device settings. +- Disabled Streamlit email prompt, by apaz-cli. +- Docker container runs as non-root user. +- Fixed lint command handling of nested spaced strings, by Aaron Weisberg. +- Added token count feedback when adding command output to chat. +- Improved error handling for large audio files with automatic format conversion. +- Improved handling of git repo index errors, by Krazer. +- Improved unicode handling in console output with ASCII fallback. +- Added AssertionError, AttributeError to git error handling. +- Aider wrote 60% of the code in this release. + +### Aider v0.70.0 + +- Full support for o1 models. +- Watch files now honors `--subtree-only`, and only watches that subtree. +- Improved prompting for watch files, to work more reliably with more models. +- New install methods via uv, including one-liners. +- Support for openrouter/deepseek/deepseek-chat model. +- Better error handling when interactive commands are attempted via `/load` or `--load`. +- Display read-only files with abs path if its shorter than rel path. +- Ask 10% of users to opt-in to analytics. +- Bugfix for auto-suggest. +- Gracefully handle unicode errors in git path names. +- Aider wrote 74% of the code in this release. + +### Aider v0.69.1 + +- Fix for gemini model names in model metadata. +- Show hints about AI! and AI? when user makes AI comments. +- Support for running without git installed. +- Improved environment variable setup messages on Windows. + +### Aider v0.69.0 + +- [Watch files](https://aider.chat/docs/usage/watch.html) improvements: + - Use `# ... AI?` comments to trigger aider and ask questions about your code. + - Now watches *all* files, not just certain source files. + - Use `# AI comments`, `// AI comments`, or `-- AI comments` to give aider instructions in any text file. +- Full support for Gemini Flash 2.0 Exp: + - `aider --model flash` or `aider --model gemini/gemini-2.0-flash-exp` +- [New `--multiline` flag and `/multiline-mode` command](https://aider.chat/docs/usage/commands.html#entering-multi-line-chat-messages) makes ENTER a soft newline and META-ENTER send the message, by @miradnanali. +- `/copy-context ` now takes optional "instructions" when [copying code context to the clipboard](https://aider.chat/docs/usage/copypaste.html#copy-aiders-code-context-to-your-clipboard-paste-into-the-web-ui). +- Improved clipboard error handling with helpful requirements install info. +- Ask 5% of users if they want to opt-in to analytics. +- `/voice` now lets you edit the transcribed text before sending. +- Disabled auto-complete in Y/N prompts. +- Aider wrote 68% of the code in this release. + +### Aider v0.68.0 + +- [Aider works with LLM web chat UIs](https://aider.chat/docs/usage/copypaste.html). + - New `--copy-paste` mode. + - New `/copy-context` command. +- [Set API keys and other environment variables for all providers from command line or yaml conf file](https://aider.chat/docs/config/aider_conf.html#storing-llm-keys). + - New `--api-key provider=key` setting. + - New `--set-env VAR=value` setting. +- Added bash and zsh support to `--watch-files`. +- Better error messages when missing dependencies for Gemini and Bedrock models. +- Control-D now properly exits the program. +- Don't count token costs when API provider returns a hard error. +- Bugfix so watch files works with files that don't have tree-sitter support. +- Bugfix so o1 models can be used as weak model. +- Updated shell command prompt. +- Added docstrings for all Coders. +- Reorganized command line arguments with improved help messages and grouping. +- Use the exact `sys.python` for self-upgrades. +- Added experimental Gemini models. +- Aider wrote 71% of the code in this release. + +### Aider v0.67.0 + +- [Use aider in your IDE or editor](https://aider.chat/docs/usage/watch.html). + - Run `aider --watch-files` and it will watch for instructions you add to your source files. + - One-liner `# ...` or `// ...` comments that start or end with "AI" are instructions to aider. + - When aider sees "AI!" it reads and follows all the instructions in AI comments. +- Support for new Amazon Bedrock Nova models. +- When `/run` or `/test` have non-zero exit codes, pre-fill "Fix that" into the next message prompt. +- `/diff` now invokes `git diff` to use your preferred diff tool. +- Added Ctrl-Z support for process suspension. +- Spinner now falls back to ASCII art if fancy symbols throw unicode errors. +- `--read` now expands `~` home dirs. +- Enabled exception capture in analytics. +- [Aider wrote 61% of the code in this release.](https://aider.chat/HISTORY.html) + +### Aider v0.66.0 - PDF support for Sonnet and Gemini models. +- Added `--voice-input-device` to select audio input device for voice recording, by @preynal. +- Added `--timeout` option to configure API call timeouts. - Set cwd to repo root when running shell commands. +- Added Ctrl-Up/Down keyboard shortcuts for per-message history navigation. - Improved error handling for failed .gitignore file operations. - Improved error handling for input history file permissions. - Improved error handling for analytics file access. -- Aider wrote 85% of the code in this release. +- Removed spurious warning about disabling pretty in VSCode. +- Removed broken support for Dart. +- Bugfix when scraping URLs found in chat messages. +- Better handling of __version__ import errors. +- Improved `/drop` command to support substring matching for non-glob patterns. +- Aider wrote 82% of the code in this release. ### Aider v0.65.1 diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 000000000..9ab273215 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,20 @@ +# This needs to sync with aider/help_pats.py + +global-exclude .DS_Store + +recursive-exclude aider/website/examples * +recursive-exclude aider/website/_posts * + +exclude aider/website/HISTORY.md +exclude aider/website/docs/benchmarks*.md +exclude aider/website/docs/ctags.md +exclude aider/website/docs/unified-diffs.md + +exclude aider/website/install.ps1 +exclude aider/website/install.sh + +recursive-exclude aider/website/docs/leaderboards * +recursive-exclude aider/website/assets * +recursive-exclude aider/website *.js +recursive-exclude aider/website *.html +recursive-exclude aider/website *.yml diff --git a/README.md b/README.md index b19b01074..a3734aa19 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ Aider lets you pair program with LLMs, to edit code in your local git repository. -Start a new project or work with an existing git repo. -Aider works best with GPT-4o & Claude 3.5 Sonnet and can -[connect to almost any LLM](https://aider.chat/docs/llms.html). +Start a new project or work with an existing code base. +Aider works best with Claude 3.5 Sonnet, DeepSeek V3, o1 & GPT-4o and can [connect to almost any LLM](https://aider.chat/docs/llms.html). +

@@ -43,28 +43,36 @@ VIDEO END --> cog.out(open("aider/website/_includes/get-started.md").read()) ]]]--> -You can get started quickly like this: +If you already have python 3.8-3.13 installed, you can get started quickly like this: -``` -python -m pip install -U aider-chat +```bash +python -m pip install aider-install +aider-install -# Change directory into a git repo -cd /to/your/git/repo +# Change directory into your code base +cd /to/your/project -# Work with Claude 3.5 Sonnet on your repo -export ANTHROPIC_API_KEY=your-key-goes-here -aider +# Work with DeepSeek via DeepSeek's API +aider --model deepseek --api-key deepseek=your-key-goes-here -# Work with GPT-4o on your repo -export OPENAI_API_KEY=your-key-goes-here -aider +# Work with Claude 3.5 Sonnet via Anthropic's API +aider --model sonnet --api-key anthropic=your-key-goes-here + +# Work with GPT-4o via OpenAI's API +aider --model gpt-4o --api-key openai=your-key-goes-here + +# Work with Sonnet via OpenRouter's API +aider --model openrouter/anthropic/claude-3.5-sonnet --api-key openrouter=your-key-goes-here + +# Work with DeepSeek via OpenRouter's API +aider --model openrouter/deepseek/deepseek-chat --api-key openrouter=your-key-goes-here ``` See the [installation instructions](https://aider.chat/docs/install.html) -and other -[documentation](https://aider.chat/docs/usage.html) +and +[usage documentation](https://aider.chat/docs/usage.html) for more details. ## Features @@ -73,21 +81,22 @@ for more details. - Ask for changes: - Add new features or test cases. - Describe a bug. - - Paste in an error message or or GitHub issue URL. + - Paste in an error message or GitHub issue URL. - Refactor code. - Update docs. - Aider will edit your files to complete your request. - Aider [automatically git commits](https://aider.chat/docs/git.html) changes with a sensible commit message. +- [Use aider inside your favorite editor or IDE](https://aider.chat/docs/usage/watch.html). - Aider works with [most popular languages](https://aider.chat/docs/languages.html): python, javascript, typescript, php, html, css, and more... -- Aider works best with GPT-4o & Claude 3.5 Sonnet and can [connect to almost any LLM](https://aider.chat/docs/llms.html). - Aider can edit multiple files at once for complex requests. - Aider uses a [map of your entire git repo](https://aider.chat/docs/repomap.html), which helps it work well in larger codebases. -- Edit files in your editor while chatting with aider, +- Edit files in your editor or IDE while chatting with aider, and it will always use the latest version. Pair program with AI. - [Add images to the chat](https://aider.chat/docs/usage/images-urls.html) (GPT-4o, Claude 3.5 Sonnet, etc). - [Add URLs to the chat](https://aider.chat/docs/usage/images-urls.html) and aider will read their content. - [Code with your voice](https://aider.chat/docs/usage/voice.html). +- Aider works best with Claude 3.5 Sonnet, DeepSeek V3, o1 & GPT-4o and can [connect to almost any LLM](https://aider.chat/docs/llms.html). ## Top tier performance diff --git a/aider/__init__.py b/aider/__init__.py index db056f0ff..cb071ae73 100644 --- a/aider/__init__.py +++ b/aider/__init__.py @@ -1,6 +1,20 @@ +from packaging import version + +__version__ = "0.74.2.dev" +safe_version = __version__ + try: - from aider.__version__ import __version__ + from aider._version import __version__ except Exception: - __version__ = "0.65.2.dev" + __version__ = safe_version + "+import" + +if type(__version__) is not str: + __version__ = safe_version + "+type" +else: + try: + if version.parse(__version__) < version.parse(safe_version): + __version__ = safe_version + "+less" + except Exception: + __version__ = safe_version + "+parse" __all__ = [__version__] diff --git a/aider/analytics.py b/aider/analytics.py index 82c888247..d5c37c10a 100644 --- a/aider/analytics.py +++ b/aider/analytics.py @@ -5,13 +5,53 @@ import time import uuid from pathlib import Path -from mixpanel import Mixpanel, MixpanelException +from mixpanel import MixpanelException from posthog import Posthog from aider import __version__ from aider.dump import dump # noqa: F401 from aider.models import model_info_manager +PERCENT = 10 + + +def compute_hex_threshold(percent): + """Convert percentage to 6-digit hex threshold. + + Args: + percent: Percentage threshold (0-100) + + Returns: + str: 6-digit hex threshold + """ + return format(int(0xFFFFFF * percent / 100), "06x") + + +def is_uuid_in_percentage(uuid_str, percent): + """Check if a UUID string falls within the first X percent of the UUID space. + + Args: + uuid_str: UUID string to test + percent: Percentage threshold (0-100) + + Returns: + bool: True if UUID falls within the first X percent + """ + if not (0 <= percent <= 100): + raise ValueError("Percentage must be between 0 and 100") + + if not uuid_str: + return False + + # Convert percentage to hex threshold (1% = "04...", 10% = "1a...", etc) + # Using first 6 hex digits + if percent == 0: + return False + + threshold = compute_hex_threshold(percent) + return uuid_str[:6] <= threshold + + mixpanel_project_token = "6da9a43058a5d1b9f3353153921fb04d" posthog_project_api_key = "phc_99T7muzafUMMZX15H8XePbMSreEUzahHbtWjy3l5Qbv" posthog_host = "https://us.i.posthog.com" @@ -50,8 +90,14 @@ class Analytics: self.disable(False) return - self.mp = Mixpanel(mixpanel_project_token) - self.ph = Posthog(project_api_key=posthog_project_api_key, host=posthog_host) + # self.mp = Mixpanel(mixpanel_project_token) + self.ph = Posthog( + project_api_key=posthog_project_api_key, + host=posthog_host, + on_error=self.posthog_error, + enable_exception_autocapture=True, + super_properties=self.get_system_info(), # Add system info to all events + ) def disable(self, permanently): self.mp = None @@ -78,31 +124,7 @@ class Analytics: if not self.user_id: return False - PERCENT = 2.5 - return self.is_uuid_in_percentage(self.user_id, PERCENT) - - def is_uuid_in_percentage(self, uuid_str, percent): - """Check if a UUID string falls within the first X percent of the UUID space. - - Args: - uuid_str: UUID string to test - percent: Percentage threshold (0-100) - - Returns: - bool: True if UUID falls within the first X percent - """ - if not (0 <= percent <= 100): - raise ValueError("Percentage must be between 0 and 100") - - if not uuid_str: - return False - - # Convert percentage to hex threshold (1% = "04...", 10% = "1a...", etc) - # Using first 6 hex digits - if percent == 0: - return False - threshold = format(int(0xFFFFFF * percent / 100), "06x") - return uuid_str[:6] <= threshold + return is_uuid_in_percentage(self.user_id, PERCENT) def get_data_file_path(self): try: @@ -159,6 +181,7 @@ class Analytics: "os_platform": platform.system(), "os_release": platform.release(), "machine": platform.machine(), + "aider_version": __version__, } def _redact_model_name(self, model): @@ -172,6 +195,13 @@ class Analytics: return model.name.split("/")[0] + "/REDACTED" return None + def posthog_error(self): + """disable posthog if we get an error""" + print("X" * 100) + # https://github.com/PostHog/posthog-python/blob/9e1bb8c58afaa229da24c4fb576c08bb88a75752/posthog/consumer.py#L86 + # https://github.com/Aider-AI/aider/issues/2532 + self.ph = None + def event(self, event_name, main_model=None, **kwargs): if not self.mp and not self.ph and not self.logfile: return @@ -184,7 +214,6 @@ class Analytics: 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(): @@ -193,8 +222,6 @@ class Analytics: else: properties[key] = str(value) - properties["aider_version"] = __version__ - if self.mp: try: self.mp.track(self.user_id, event_name, dict(properties)) @@ -211,10 +238,13 @@ class Analytics: "user_id": self.user_id, "time": int(time.time()), } - with open(self.logfile, "a") as f: - json.dump(log_entry, f) - f.write("\n") + try: + with open(self.logfile, "a") as f: + json.dump(log_entry, f) + f.write("\n") + except OSError: + pass # Ignore OS errors when writing to logfile - def __del__(self): - if self.ph: - self.ph.shutdown() + +if __name__ == "__main__": + dump(compute_hex_threshold(PERCENT)) diff --git a/aider/args.py b/aider/args.py index 58a08f5a0..e20d99db4 100644 --- a/aider/args.py +++ b/aider/args.py @@ -28,22 +28,10 @@ def get_parser(default_config_files, git_root): config_file_parser_class=configargparse.YAMLConfigFileParser, auto_env_var_prefix="AIDER_", ) - group = parser.add_argument_group("Main") + group = parser.add_argument_group("Main model") group.add_argument( "files", metavar="FILE", nargs="*", help="files to edit with an LLM (optional)" ) - group.add_argument( - "--openai-api-key", - metavar="OPENAI_API_KEY", - env_var="OPENAI_API_KEY", - help="Specify the OpenAI API key", - ) - group.add_argument( - "--anthropic-api-key", - metavar="ANTHROPIC_API_KEY", - env_var="ANTHROPIC_API_KEY", - help="Specify the Anthropic API key", - ) group.add_argument( "--model", metavar="MODEL", @@ -83,7 +71,7 @@ def get_parser(default_config_files, git_root): const=gpt_4_model, help=f"Use {gpt_4_model} model for the main chat", ) - gpt_4o_model = "gpt-4o-2024-08-06" + gpt_4o_model = "gpt-4o" group.add_argument( "--4o", action="store_const", @@ -118,7 +106,7 @@ def get_parser(default_config_files, git_root): const=gpt_3_model_name, help=f"Use {gpt_3_model_name} model for the main chat", ) - deepseek_model = "deepseek/deepseek-coder" + deepseek_model = "deepseek/deepseek-chat" group.add_argument( "--deepseek", action="store_const", @@ -144,43 +132,59 @@ def get_parser(default_config_files, git_root): ) ########## - group = parser.add_argument_group("Model Settings") + group = parser.add_argument_group("API Keys and settings") + group.add_argument( + "--openai-api-key", + help="Specify the OpenAI API key", + ) + group.add_argument( + "--anthropic-api-key", + help="Specify the Anthropic API key", + ) + group.add_argument( + "--openai-api-base", + help="Specify the api base url", + ) + group.add_argument( + "--openai-api-type", + help="(deprecated, use --set-env OPENAI_API_TYPE=)", + ) + group.add_argument( + "--openai-api-version", + help="(deprecated, use --set-env OPENAI_API_VERSION=)", + ) + group.add_argument( + "--openai-api-deployment-id", + help="(deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=)", + ) + group.add_argument( + "--openai-organization-id", + help="(deprecated, use --set-env OPENAI_ORGANIZATION=)", + ) + group.add_argument( + "--set-env", + action="append", + metavar="ENV_VAR_NAME=value", + help="Set an environment variable (to control API settings, can be used multiple times)", + default=[], + ) + group.add_argument( + "--api-key", + action="append", + metavar="PROVIDER=KEY", + help=( + "Set an API key for a provider (eg: --api-key provider= sets" + " PROVIDER_API_KEY=)" + ), + default=[], + ) + group = parser.add_argument_group("Model settings") group.add_argument( "--list-models", "--models", metavar="MODEL", help="List known models which match the (partial) MODEL name", ) - group.add_argument( - "--openai-api-base", - metavar="OPENAI_API_BASE", - env_var="OPENAI_API_BASE", - help="Specify the api base url", - ) - group.add_argument( - "--openai-api-type", - metavar="OPENAI_API_TYPE", - env_var="OPENAI_API_TYPE", - help="Specify the api_type", - ) - group.add_argument( - "--openai-api-version", - metavar="OPENAI_API_VERSION", - env_var="OPENAI_API_VERSION", - help="Specify the api_version", - ) - group.add_argument( - "--openai-api-deployment-id", - metavar="OPENAI_API_DEPLOYMENT_ID", - env_var="OPENAI_API_DEPLOYMENT_ID", - help="Specify the deployment_id", - ) - group.add_argument( - "--openai-organization-id", - metavar="OPENAI_ORGANIZATION_ID", - env_var="OPENAI_ORGANIZATION_ID", - help="Specify the OpenAI organization ID", - ) group.add_argument( "--model-settings-file", metavar="MODEL_SETTINGS_FILE", @@ -199,12 +203,23 @@ def get_parser(default_config_files, git_root): metavar="ALIAS:MODEL", help="Add a model alias (can be used multiple times)", ) + group.add_argument( + "--reasoning-effort", + type=str, + help="Set the reasoning_effort API parameter (default: not set)", + ) group.add_argument( "--verify-ssl", action=argparse.BooleanOptionalAction, default=True, help="Verify the SSL cert when connecting to models (default: True)", ) + group.add_argument( + "--timeout", + type=float, + default=None, + help="Timeout in seconds for API calls (default: None)", + ) group.add_argument( "--edit-format", "--chat-mode", @@ -255,17 +270,9 @@ def get_parser(default_config_files, git_root): " If unspecified, defaults to the model's max_chat_history_tokens." ), ) - # This is a duplicate of the argument in the preparser and is a no-op by this time of - # argument parsing, but it's here so that the help is displayed as expected. - group.add_argument( - "--env-file", - metavar="ENV_FILE", - default=default_env_file(git_root), - help="Specify the .env file to load (default: .env in git root)", - ) ########## - group = parser.add_argument_group("Cache Settings") + group = parser.add_argument_group("Cache settings") group.add_argument( "--cache-prompts", action=argparse.BooleanOptionalAction, @@ -280,12 +287,12 @@ def get_parser(default_config_files, git_root): ) ########## - group = parser.add_argument_group("Repomap Settings") + group = parser.add_argument_group("Repomap settings") group.add_argument( "--map-tokens", type=int, default=None, - help="Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)", + help="Suggested number of tokens to use for repo map, use 0 to disable", ) group.add_argument( "--map-refresh", @@ -337,7 +344,7 @@ def get_parser(default_config_files, git_root): ) ########## - group = parser.add_argument_group("Output Settings") + group = parser.add_argument_group("Output settings") group.add_argument( "--dark-mode", action="store_true", @@ -425,7 +432,8 @@ def get_parser(default_config_files, git_root): default="default", help=( "Set the markdown code theme (default: default, other options include monokai," - " solarized-dark, solarized-light)" + " solarized-dark, solarized-light, or a Pygments builtin style," + " see https://pygments.org/styles for available themes)" ), ) group.add_argument( @@ -436,7 +444,7 @@ def get_parser(default_config_files, git_root): ) ########## - group = parser.add_argument_group("Git Settings") + group = parser.add_argument_group("Git settings") group.add_argument( "--git", action=argparse.BooleanOptionalAction, @@ -523,6 +531,12 @@ def get_parser(default_config_files, git_root): help="Skip the sanity check for the git repository (default: False)", default=False, ) + group.add_argument( + "--watch-files", + action=argparse.BooleanOptionalAction, + default=False, + help="Enable/disable watching files for ai coding comments (default: False)", + ) group = parser.add_argument_group("Fixing and committing") group.add_argument( "--lint", @@ -559,7 +573,7 @@ def get_parser(default_config_files, git_root): group.add_argument( "--test", action="store_true", - help="Run tests and fix problems found", + help="Run tests, fix problems found and then exit", default=False, ) @@ -583,37 +597,8 @@ def get_parser(default_config_files, git_root): default=False, ) - group = parser.add_argument_group("Other Settings") - group.add_argument( - "--file", - action="append", - metavar="FILE", - help="specify a file to edit (can be used multiple times)", - ) - group.add_argument( - "--read", - action="append", - metavar="FILE", - help="specify a read-only file (can be used multiple times)", - ) - group.add_argument( - "--vim", - action="store_true", - help="Use VI editing mode in the terminal (default: False)", - default=False, - ) - group.add_argument( - "--chat-language", - metavar="CHAT_LANGUAGE", - default=None, - help="Specify the language to use in the chat (default: None, uses system settings)", - ) - group.add_argument( - "--version", - action="version", - version=f"%(prog)s {__version__}", - help="Show the version number and exit", - ) + ######### + group = parser.add_argument_group("Upgrading") group.add_argument( "--just-check-update", action="store_true", @@ -646,47 +631,14 @@ def get_parser(default_config_files, git_root): default=False, ) group.add_argument( - "--apply", - metavar="FILE", - help="Apply the changes from the given file instead of running the chat (debug)", - ) - group.add_argument( - "--apply-clipboard-edits", - action="store_true", - help="Apply clipboard contents as edits using the main model's editor format", - default=False, - ) - group.add_argument( - "--yes-always", - action="store_true", - help="Always say yes to every confirmation", - default=None, - ) - group.add_argument( - "-v", - "--verbose", - action="store_true", - help="Enable verbose output", - default=False, - ) - group.add_argument( - "--show-repo-map", - action="store_true", - help="Print the repo map and exit (debug)", - default=False, - ) - group.add_argument( - "--show-prompts", - action="store_true", - help="Print the system prompts and exit (debug)", - default=False, - ) - group.add_argument( - "--exit", - action="store_true", - help="Do all startup activities then exit before accepting user input (debug)", - default=False, + "--version", + action="version", + version=f"%(prog)s {__version__}", + help="Show the version number and exit", ) + + ########## + group = parser.add_argument_group("Modes") group.add_argument( "--message", "--msg", @@ -705,6 +657,110 @@ def get_parser(default_config_files, git_root): " (disables chat mode)" ), ) + group.add_argument( + "--gui", + "--browser", + action=argparse.BooleanOptionalAction, + help="Run aider in your browser (default: False)", + default=False, + ) + group.add_argument( + "--copy-paste", + action=argparse.BooleanOptionalAction, + default=False, + help="Enable automatic copy/paste of chat between aider and web UI (default: False)", + ) + group.add_argument( + "--apply", + metavar="FILE", + help="Apply the changes from the given file instead of running the chat (debug)", + ) + group.add_argument( + "--apply-clipboard-edits", + action="store_true", + help="Apply clipboard contents as edits using the main model's editor format", + default=False, + ) + group.add_argument( + "--exit", + action="store_true", + help="Do all startup activities then exit before accepting user input (debug)", + default=False, + ) + group.add_argument( + "--show-repo-map", + action="store_true", + help="Print the repo map and exit (debug)", + default=False, + ) + group.add_argument( + "--show-prompts", + action="store_true", + help="Print the system prompts and exit (debug)", + default=False, + ) + + ########## + group = parser.add_argument_group("Voice settings") + group.add_argument( + "--voice-format", + metavar="VOICE_FORMAT", + default="wav", + choices=["wav", "mp3", "webm"], + help="Audio format for voice recording (default: wav). webm and mp3 require ffmpeg", + ) + group.add_argument( + "--voice-language", + metavar="VOICE_LANGUAGE", + default="en", + help="Specify the language for voice using ISO 639-1 code (default: auto)", + ) + group.add_argument( + "--voice-input-device", + metavar="VOICE_INPUT_DEVICE", + default=None, + help="Specify the input device name for voice recording", + ) + + ###### + group = parser.add_argument_group("Other settings") + group.add_argument( + "--file", + action="append", + metavar="FILE", + help="specify a file to edit (can be used multiple times)", + ) + group.add_argument( + "--read", + action="append", + metavar="FILE", + help="specify a read-only file (can be used multiple times)", + ) + group.add_argument( + "--vim", + action="store_true", + help="Use VI editing mode in the terminal (default: False)", + default=False, + ) + group.add_argument( + "--chat-language", + metavar="CHAT_LANGUAGE", + default=None, + help="Specify the language to use in the chat (default: None, uses system settings)", + ) + group.add_argument( + "--yes-always", + action="store_true", + help="Always say yes to every confirmation", + default=None, + ) + group.add_argument( + "-v", + "--verbose", + action="store_true", + help="Enable verbose output", + default=False, + ) group.add_argument( "--load", metavar="LOAD_FILE", @@ -715,6 +771,12 @@ def get_parser(default_config_files, git_root): default="utf-8", help="Specify the encoding for input and output (default: utf-8)", ) + group.add_argument( + "--line-endings", + choices=["platform", "lf", "crlf"], + default="platform", + help="Line endings to use when writing files (default: platform)", + ) group.add_argument( "-c", "--config", @@ -725,12 +787,13 @@ def get_parser(default_config_files, git_root): " or home directory)" ), ) + # This is a duplicate of the argument in the preparser and is a no-op by this time of + # argument parsing, but it's here so that the help is displayed as expected. group.add_argument( - "--gui", - "--browser", - action=argparse.BooleanOptionalAction, - help="Run aider in your browser (default: False)", - default=False, + "--env-file", + metavar="ENV_FILE", + default=default_env_file(git_root), + help="Specify the .env file to load (default: .env in git root)", ) group.add_argument( "--suggest-shell-commands", @@ -744,6 +807,12 @@ def get_parser(default_config_files, git_root): default=True, help="Enable/disable fancy input with history and completion (default: True)", ) + group.add_argument( + "--multiline", + action=argparse.BooleanOptionalAction, + default=False, + help="Enable/disable multi-line input mode with Meta-Enter to submit (default: False)", + ) group.add_argument( "--detect-urls", action=argparse.BooleanOptionalAction, @@ -755,22 +824,6 @@ def get_parser(default_config_files, git_root): help="Specify which editor to use for the /editor command", ) - ########## - group = parser.add_argument_group("Voice Settings") - group.add_argument( - "--voice-format", - metavar="VOICE_FORMAT", - default="wav", - choices=["wav", "mp3", "webm"], - help="Audio format for voice recording (default: wav). webm and mp3 require ffmpeg", - ) - group.add_argument( - "--voice-language", - metavar="VOICE_LANGUAGE", - default="en", - help="Specify the language for voice using ISO 639-1 code (default: auto)", - ) - return parser diff --git a/aider/coders/ask_prompts.py b/aider/coders/ask_prompts.py index 198ec6172..dcedf2d14 100644 --- a/aider/coders/ask_prompts.py +++ b/aider/coders/ask_prompts.py @@ -7,6 +7,8 @@ class AskPrompts(CoderPrompts): main_system = """Act as an expert code analyst. Answer questions about the supplied code. Always reply to the user in {language}. + +Describe code changes however you like. Don't use SEARCH/REPLACE blocks! """ example_messages = [] diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index 3926cd987..85228df2b 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -27,10 +27,10 @@ from aider.history import ChatSummary from aider.io import ConfirmGroup, InputOutput from aider.linter import Linter from aider.llm import litellm +from aider.models import RETRY_TIMEOUT from aider.repo import ANY_GIT_ERROR, GitRepo from aider.repomap import RepoMap from aider.run_cmd import run_cmd -from aider.sendchat import RETRY_TIMEOUT, send_completion from aider.utils import format_content, format_messages, format_tokens, is_image_file from ..dump import dump # noqa: F401 @@ -59,7 +59,8 @@ def wrap_fence(name): all_fences = [ - ("``" + "`", "``" + "`"), + ("`" * 3, "`" * 3), + ("`" * 4, "`" * 4), # LLMs ignore and revert to triple-backtick, causing #2879 wrap_fence("source"), wrap_fence("code"), wrap_fence("pre"), @@ -84,7 +85,7 @@ class Coder: max_reflections = 3 edit_format = None yield_stream = False - temperature = 0 + temperature = None auto_lint = True auto_test = False test_cmd = None @@ -103,6 +104,7 @@ class Coder: detect_urls = True ignore_mentions = None chat_language = None + file_watcher = None @classmethod def create( @@ -142,7 +144,13 @@ class Coder: # the system prompt. done_messages = from_coder.done_messages if edit_format != from_coder.edit_format and done_messages and summarize_from_coder: - done_messages = from_coder.summarizer.summarize_all(done_messages) + try: + done_messages = from_coder.summarizer.summarize_all(done_messages) + except ValueError: + # If summarization fails, keep the original messages and warn the user + io.tool_warning( + "Chat history summarization failed, continuing with full history" + ) # Bring along context from the old Coder update = dict( @@ -153,8 +161,9 @@ class Coder: aider_commit_hashes=from_coder.aider_commit_hashes, commands=from_coder.commands.clone(), total_cost=from_coder.total_cost, + ignore_mentions=from_coder.ignore_mentions, + file_watcher=from_coder.file_watcher, ) - use_kwargs.update(update) # override to complete the switch use_kwargs.update(kwargs) # override passed kwargs @@ -175,7 +184,6 @@ class Coder: def clone(self, **kwargs): new_coder = Coder.create(from_coder=self, **kwargs) - new_coder.ignore_mentions = self.ignore_mentions return new_coder def get_announcements(self): @@ -229,10 +237,10 @@ class Coder: if map_tokens > 0: refresh = self.repo_map.refresh lines.append(f"Repo-map: using {map_tokens} tokens, {refresh} refresh") - max_map_tokens = 2048 + max_map_tokens = self.main_model.get_repo_map_tokens() * 2 if map_tokens > max_map_tokens: lines.append( - f"Warning: map-tokens > {max_map_tokens} is not recommended as too much" + f"Warning: map-tokens > {max_map_tokens} is not recommended. Too much" " irrelevant code can confuse LLMs." ) else: @@ -244,9 +252,16 @@ class Coder: for fname in self.get_inchat_relative_files(): lines.append(f"Added {fname} to the chat.") + for fname in self.abs_read_only_fnames: + rel_fname = self.get_rel_fname(fname) + lines.append(f"Added {rel_fname} to the chat (read-only).") + if self.done_messages: lines.append("Restored previous conversation history.") + if self.io.multiline_mode: + lines.append("Multiline mode: Enabled. Enter inserts newline, Alt-Enter submits text") + return lines def __init__( @@ -283,6 +298,9 @@ class Coder: suggest_shell_commands=True, chat_language=None, detect_urls=True, + ignore_mentions=None, + file_watcher=None, + auto_copy_context=False, ): # Fill in a dummy Analytics if needed, but it is never .enable()'d self.analytics = analytics if analytics is not None else Analytics() @@ -293,7 +311,16 @@ class Coder: self.aider_commit_hashes = set() self.rejected_urls = set() self.abs_root_path_cache = {} - self.ignore_mentions = set() + + self.auto_copy_context = auto_copy_context + + self.ignore_mentions = ignore_mentions + if not self.ignore_mentions: + self.ignore_mentions = set() + + self.file_watcher = file_watcher + if self.file_watcher: + self.file_watcher.coder = self self.suggest_shell_commands = suggest_shell_commands self.detect_urls = detect_urls @@ -332,7 +359,6 @@ class Coder: self.done_messages = [] self.io = io - self.stream = stream self.shell_commands = [] @@ -347,6 +373,8 @@ class Coder: self.main_model = main_model + self.stream = stream and main_model.streaming + if cache_prompts and self.main_model.cache_control: self.add_cache_headers = True @@ -437,6 +465,7 @@ class Coder: self.summarizer_thread = None self.summarized_done_messages = [] + self.summarizing_messages = None if not self.done_messages and restore_chat_history: history_md = self.io.read_text(self.io.chat_history_file) @@ -503,7 +532,7 @@ class Coder: return False # only show pretty output if fences are the normal triple-backtick - if self.fence != self.fences[0]: + if self.fence[0][0] != "`": return False return True @@ -597,9 +626,19 @@ class Coder: def get_ident_filename_matches(self, idents): all_fnames = defaultdict(set) for fname in self.get_all_relative_files(): - base = Path(fname).with_suffix("").name.lower() - if len(base) >= 5: - all_fnames[base].add(fname) + # Skip empty paths or just '.' + if not fname or fname == ".": + continue + + try: + # Handle dotfiles properly + path = Path(fname) + base = path.stem.lower() # Use stem instead of with_suffix("").name + if len(base) >= 5: + all_fnames[base].add(fname) + except ValueError: + # Skip paths that can't be processed + continue matches = set() for ident in idents: @@ -771,6 +810,7 @@ class Coder: self.lint_outcome = None self.test_outcome = None self.shell_commands = [] + self.message_cost = 0 if self.repo: self.commit_before_message.append(self.repo.get_head_commit_sha()) @@ -781,9 +821,10 @@ class Coder: self.io.user_input(with_message) self.run_one(with_message, preproc) return self.partial_response_content - while True: try: + if not self.io.placeholder: + self.copy_context() user_message = self.get_input() self.run_one(user_message, preproc) self.show_undo_hint() @@ -792,6 +833,10 @@ class Coder: except EOFError: return + def copy_context(self): + if self.auto_copy_context: + self.commands.cmd_copy_context() + def get_input(self): inchat_files = self.get_inchat_relative_files() read_only_files = [self.get_rel_fname(fname) for fname in self.abs_read_only_fnames] @@ -884,6 +929,7 @@ class Coder: thresh = 2 # seconds if self.last_keyboard_interrupt and now - self.last_keyboard_interrupt < thresh: self.io.tool_warning("\n\n^C KeyboardInterrupt") + self.event("exit", reason="Control-C") sys.exit() self.io.tool_warning("\n\n^C again to exit") @@ -903,8 +949,9 @@ class Coder: self.summarizer_thread.start() def summarize_worker(self): + self.summarizing_messages = list(self.done_messages) try: - self.summarized_done_messages = self.summarizer.summarize(self.done_messages) + self.summarized_done_messages = self.summarizer.summarize(self.summarizing_messages) except ValueError as err: self.io.tool_warning(err.args[0]) @@ -918,7 +965,9 @@ class Coder: self.summarizer_thread.join() self.summarizer_thread = None - self.done_messages = self.summarized_done_messages + if self.summarizing_messages == self.done_messages: + self.done_messages = self.summarized_done_messages + self.summarizing_messages = None self.summarized_done_messages = [] def move_back_cur_messages(self, message): @@ -1012,14 +1061,26 @@ class Coder: else: language = "the same language they are using" + if self.fence[0] == "`" * 4: + quad_backtick_reminder = ( + "\nIMPORTANT: Use *quadruple* backticks ```` as fences, not triple backticks!\n" + ) + else: + quad_backtick_reminder = "" + prompt = prompt.format( fence=self.fence, + quad_backtick_reminder=quad_backtick_reminder, lazy_prompt=lazy_prompt, platform=platform_text, shell_cmd_prompt=shell_cmd_prompt, shell_cmd_reminder=shell_cmd_reminder, language=language, ) + + if self.main_model.system_prompt_prefix: + prompt = self.main_model.system_prompt_prefix + prompt + return prompt def format_chat_chunks(self): @@ -1102,7 +1163,10 @@ class Coder: # add the reminder anyway total_tokens = 0 - final = chunks.cur[-1] + if chunks.cur: + final = chunks.cur[-1] + else: + final = None max_input_tokens = self.main_model.info.get("max_input_tokens") or 0 # Add the reminder prompt if we still have room to include it. @@ -1113,7 +1177,7 @@ class Coder: ): if self.main_model.reminder == "sys": chunks.reminder = reminder_message - elif self.main_model.reminder == "user" and final["role"] == "user": + elif self.main_model.reminder == "user" and final and final["role"] == "user": # stuff it into the user message new_content = ( final["content"] @@ -1184,13 +1248,40 @@ class Coder: return chunks + def check_tokens(self, messages): + """Check if the messages will fit within the model's token limits.""" + input_tokens = self.main_model.token_count(messages) + max_input_tokens = self.main_model.info.get("max_input_tokens") or 0 + + if max_input_tokens and input_tokens >= max_input_tokens: + self.io.tool_error( + f"Your estimated chat context of {input_tokens:,} tokens exceeds the" + f" {max_input_tokens:,} token limit for {self.main_model.name}!" + ) + self.io.tool_output("To reduce the chat context:") + self.io.tool_output("- Use /drop to remove unneeded files from the chat") + self.io.tool_output("- Use /clear to clear the chat history") + self.io.tool_output("- Break your code into smaller files") + self.io.tool_output( + "It's probably safe to try and send the request, most providers won't charge if" + " the context limit is exceeded." + ) + + if not self.io.confirm_ask("Try to proceed anyway?"): + return False + return True + def send_message(self, inp): + self.event("message_send_starting") + self.cur_messages += [ dict(role="user", content=inp), ] chunks = self.format_messages() messages = chunks.all_messages() + if not self.check_tokens(messages): + return self.warm_cache(chunks) if self.verbose: @@ -1251,7 +1342,7 @@ class Coder: exhausted = True break - self.multi_response_content = self.get_multi_response_content() + self.multi_response_content = self.get_multi_response_content_in_progress() if messages[-1]["role"] == "assistant": messages[-1]["content"] = self.multi_response_content @@ -1264,20 +1355,34 @@ class Coder: lines = traceback.format_exception(type(err), err, err.__traceback__) self.io.tool_warning("".join(lines)) self.io.tool_error(str(err)) + self.event("message_send_exception", exception=str(err)) return finally: if self.mdstream: self.live_incremental_response(True) self.mdstream = None - self.partial_response_content = self.get_multi_response_content(True) + self.partial_response_content = self.get_multi_response_content_in_progress(True) + self.partial_response_content = self.main_model.remove_reasoning_content( + self.partial_response_content + ) self.multi_response_content = "" self.io.tool_output() self.show_usage_report() + self.add_assistant_reply_to_cur_messages() + if exhausted: + if self.cur_messages and self.cur_messages[-1]["role"] == "user": + self.cur_messages += [ + dict( + role="assistant", + content="FinishReasonLength exception: you sent too many tokens", + ), + ] + self.show_exhausted_error() self.num_exhausted_context_windows += 1 return @@ -1308,14 +1413,17 @@ class Coder: interrupted = True if interrupted: - content += "\n^C KeyboardInterrupt" - self.cur_messages += [dict(role="assistant", content=content)] + if self.cur_messages and self.cur_messages[-1]["role"] == "user": + self.cur_messages[-1]["content"] += "\n^C KeyboardInterrupt" + else: + self.cur_messages += [dict(role="user", content="^C KeyboardInterrupt")] + self.cur_messages += [ + dict(role="assistant", content="I see that you interrupted my previous reply.") + ] return edited = self.apply_updates() - self.update_cur_messages() - if edited: self.aider_edited_files.update(edited) saved_message = self.auto_commit(edited) @@ -1336,7 +1444,6 @@ class Coder: ok = self.io.confirm_ask("Attempt to fix lint errors?") if ok: self.reflected_message = lint_errors - self.update_cur_messages() return shared_output = self.run_shell_commands() @@ -1353,7 +1460,6 @@ class Coder: ok = self.io.confirm_ask("Attempt to fix test errors?") if ok: self.reflected_message = test_errors - self.update_cur_messages() return def reply_completed(self): @@ -1415,6 +1521,8 @@ class Coder: def lint_edited(self, fnames): res = "" for fname in fnames: + if not fname: + continue errors = self.linter.lint(self.abs_root_path(fname)) if errors: @@ -1427,7 +1535,7 @@ class Coder: return res - def update_cur_messages(self): + def add_assistant_reply_to_cur_messages(self): if self.partial_response_content: self.cur_messages += [dict(role="assistant", content=self.partial_response_content)] if self.partial_response_function_call: @@ -1443,7 +1551,7 @@ class Coder: words = set(word for word in content.split()) # drop sentence punctuation from the end - words = set(word.rstrip(",.!;:") for word in words) + words = set(word.rstrip(",.!;:?") for word in words) # strip away all kinds of quotes quotes = "".join(['"', "'", "`"]) @@ -1493,7 +1601,9 @@ class Coder: added_fnames = [] group = ConfirmGroup(new_mentions) for rel_fname in sorted(new_mentions): - if self.io.confirm_ask(f"Add {rel_fname} to the chat?", group=group, allow_never=True): + if self.io.confirm_ask( + "Add file to the chat?", subject=rel_fname, group=group, allow_never=True + ): self.add_rel_fname(rel_fname) added_fnames.append(rel_fname) else: @@ -1511,20 +1621,13 @@ class Coder: self.io.log_llm_history("TO LLM", format_messages(messages)) - if self.main_model.use_temperature: - temp = self.temperature - else: - temp = None - completion = None try: - hash_object, completion = send_completion( - model.name, + hash_object, completion = model.send_completion( messages, functions, self.stream, - temp, - extra_params=model.extra_params, + self.temperature, ) self.chat_completion_call_hashes.append(hash_object.hexdigest()) @@ -1532,6 +1635,16 @@ class Coder: yield from self.show_send_output_stream(completion) else: self.show_send_output(completion) + + # Calculate costs for successful responses + self.calculate_and_show_tokens_and_cost(messages, completion) + + except LiteLLMExceptions().exceptions_tuple() as err: + ex_info = LiteLLMExceptions().get_ex_info(err) + if ex_info.name == "ContextWindowExceededError": + # Still calculate costs for context window errors + self.calculate_and_show_tokens_and_cost(messages, completion) + raise except KeyboardInterrupt as kbi: self.keyboard_interrupt() raise kbi @@ -1549,8 +1662,6 @@ class Coder: if args: self.io.ai_output(json.dumps(args, indent=4)) - self.calculate_and_show_tokens_and_cost(messages, completion) - def show_send_output(self, completion): if self.verbose: print(completion) @@ -1643,7 +1754,7 @@ class Coder: self.mdstream.update(show_resp, final=final) def render_incremental_response(self, final): - return self.get_multi_response_content() + return self.get_multi_response_content_in_progress() def calculate_and_show_tokens_and_cost(self, messages, completion=None): prompt_tokens = 0 @@ -1766,12 +1877,13 @@ class Coder: self.message_tokens_sent = 0 self.message_tokens_received = 0 - def get_multi_response_content(self, final=False): + def get_multi_response_content_in_progress(self, final=False): cur = self.multi_response_content or "" new = self.partial_response_content or "" if new.rstrip() != new and not final: new = new.rstrip() + return cur + new def get_rel_fname(self, fname): diff --git a/aider/coders/editblock_coder.py b/aider/coders/editblock_coder.py index ecd94e47a..321a6a921 100644 --- a/aider/coders/editblock_coder.py +++ b/aider/coders/editblock_coder.py @@ -401,6 +401,9 @@ missing_filename_err = ( " {fence[0]}" ) +# Always be willing to treat triple-backticks as a fence when searching for filenames +triple_backticks = "`" * 3 + def strip_filename(filename, fence): filename = filename.strip() @@ -409,7 +412,7 @@ def strip_filename(filename, fence): return start_fence = fence[0] - if filename.startswith(start_fence): + if filename.startswith(start_fence) or filename.startswith(triple_backticks): return filename = filename.rstrip(":") @@ -546,7 +549,7 @@ def find_filename(lines, fence, valid_fnames): filenames.append(filename) # Only continue as long as we keep seeing fences - if not line.startswith(fence[0]): + if not line.startswith(fence[0]) and not line.startswith(triple_backticks): break if not filenames: diff --git a/aider/coders/editblock_prompts.py b/aider/coders/editblock_prompts.py index da2acdf95..d183b0ab5 100644 --- a/aider/coders/editblock_prompts.py +++ b/aider/coders/editblock_prompts.py @@ -35,7 +35,9 @@ ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! Just suggest shell commands this way, not example code. Only suggest complete shell commands that are ready to execute, without placeholders. -Only suggest at most a few shell commands at a time, not more than 1-3. +Only suggest at most a few shell commands at a time, not more than 1-3, one per line. +Do not suggest multi-line shell commands. +All shell commands will run from the root directory of the user's project. Use the appropriate shell based on the user's system info: {platform} @@ -155,7 +157,7 @@ Every *SEARCH/REPLACE block* must use this format: 8. The closing fence: {fence[1]} Use the *FULL* file path, as shown to you by the user. - +{quad_backtick_reminder} Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc. If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup. @@ -181,6 +183,9 @@ If you want to put code in a new file, use a *SEARCH/REPLACE block* with: To rename files which have been added to the chat, use shell commands at the end of your response. +If the user just says something like "ok" or "go ahead" or "do that" they probably want you to make SEARCH/REPLACE blocks for the code changes you just proposed. +The user will say when they've applied your edits. If they haven't explicitly confirmed the edits have been applied, they probably want proper SEARCH/REPLACE blocks. + {lazy_prompt} ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! {shell_cmd_reminder} diff --git a/aider/coders/editor_editblock_coder.py b/aider/coders/editor_editblock_coder.py index 301ab14af..98628ed77 100644 --- a/aider/coders/editor_editblock_coder.py +++ b/aider/coders/editor_editblock_coder.py @@ -3,5 +3,6 @@ from .editor_editblock_prompts import EditorEditBlockPrompts class EditorEditBlockCoder(EditBlockCoder): + "A coder that uses search/replace blocks, focused purely on editing files." edit_format = "editor-diff" gpt_prompts = EditorEditBlockPrompts() diff --git a/aider/coders/editor_whole_coder.py b/aider/coders/editor_whole_coder.py index d3b4d278e..9f37a3698 100644 --- a/aider/coders/editor_whole_coder.py +++ b/aider/coders/editor_whole_coder.py @@ -3,5 +3,6 @@ from .wholefile_coder import WholeFileCoder class EditorWholeFileCoder(WholeFileCoder): + "A coder that operates on entire files, focused purely on editing files." edit_format = "editor-whole" gpt_prompts = EditorWholeFilePrompts() diff --git a/aider/coders/search_replace.py b/aider/coders/search_replace.py index f89f629cb..a72a7845b 100755 --- a/aider/coders/search_replace.py +++ b/aider/coders/search_replace.py @@ -3,7 +3,11 @@ import sys from pathlib import Path -import git +try: + import git +except ImportError: + git = None + from diff_match_patch import diff_match_patch from tqdm import tqdm diff --git a/aider/coders/single_wholefile_func_coder.py b/aider/coders/single_wholefile_func_coder.py index a10efdbb4..493581c46 100644 --- a/aider/coders/single_wholefile_func_coder.py +++ b/aider/coders/single_wholefile_func_coder.py @@ -38,7 +38,7 @@ class SingleWholeFileFunctionCoder(Coder): self.gpt_prompts = SingleWholeFileFunctionPrompts() super().__init__(*args, **kwargs) - def update_cur_messages(self, edited): + def add_assistant_reply_to_cur_messages(self, edited): if edited: self.cur_messages += [ dict(role="assistant", content=self.gpt_prompts.redacted_edit_message) diff --git a/aider/coders/wholefile_coder.py b/aider/coders/wholefile_coder.py index 7cd9bac1b..ad93aff69 100644 --- a/aider/coders/wholefile_coder.py +++ b/aider/coders/wholefile_coder.py @@ -17,10 +17,10 @@ class WholeFileCoder(Coder): try: return self.get_edits(mode="diff") except ValueError: - return self.get_multi_response_content() + return self.get_multi_response_content_in_progress() def get_edits(self, mode="update"): - content = self.get_multi_response_content() + content = self.get_multi_response_content_in_progress() chat_files = self.get_inchat_relative_files() diff --git a/aider/coders/wholefile_func_coder.py b/aider/coders/wholefile_func_coder.py index 987010ea7..3c4fbd3ca 100644 --- a/aider/coders/wholefile_func_coder.py +++ b/aider/coders/wholefile_func_coder.py @@ -49,7 +49,7 @@ class WholeFileFunctionCoder(Coder): self.gpt_prompts = WholeFileFunctionPrompts() super().__init__(*args, **kwargs) - def update_cur_messages(self, edited): + def add_assistant_reply_to_cur_messages(self, edited): if edited: self.cur_messages += [ dict(role="assistant", content=self.gpt_prompts.redacted_edit_message) diff --git a/aider/commands.py b/aider/commands.py index af74e281c..f48873049 100644 --- a/aider/commands.py +++ b/aider/commands.py @@ -43,6 +43,8 @@ class Commands: verify_ssl=self.verify_ssl, args=self.args, parser=self.parser, + verbose=self.verbose, + editor=self.editor, ) def __init__( @@ -50,6 +52,8 @@ class Commands: io, coder, voice_language=None, + voice_input_device=None, + voice_format=None, verify_ssl=True, args=None, parser=None, @@ -67,6 +71,8 @@ class Commands: voice_language = None self.voice_language = voice_language + self.voice_format = voice_format + self.voice_input_device = voice_input_device self.help = None self.editor = editor @@ -75,7 +81,7 @@ class Commands: "Switch to a new LLM" model_name = args.strip() - model = models.Model(model_name) + model = models.Model(model_name, weak_model=self.coder.main_model.weak_model.name) models.sanity_check_models(self.io, model) raise SwitchCoder(main_model=model) @@ -101,6 +107,13 @@ class Commands: ("help", "Get help about using aider (usage, config, troubleshoot)."), ("ask", "Ask questions about your code without making any changes."), ("code", "Ask for changes to your code (using the best edit format)."), + ( + "architect", + ( + "Work with an architect model to design code changes, and an editor to make" + " them." + ), + ), ] ) @@ -588,6 +601,10 @@ class Commands: self.io.tool_output(f"Diff since {commit_before_message[:7]}...") + if self.coder.pretty: + run_cmd(f"git diff {commit_before_message}") + return + diff = self.coder.repo.diff_commits( self.coder.pretty, commit_before_message, @@ -739,6 +756,7 @@ class Commands: if self.io.confirm_ask(f"No files matched '{word}'. Do you want to create {fname}?"): try: + fname.parent.mkdir(parents=True, exist_ok=True) fname.touch() all_matched_files.add(str(fname)) except OSError as e: @@ -785,7 +803,8 @@ class Commands: self.io.tool_error(f"Unable to read {matched_file}") else: self.coder.abs_fnames.add(abs_file_path) - self.io.tool_output(f"Added {matched_file} to the chat") + fname = self.coder.get_rel_fname(abs_file_path) + self.io.tool_output(f"Added {fname} to the chat") self.coder.check_added_files() def completions_drop(self): @@ -808,15 +827,33 @@ class Commands: # Expand tilde in the path expanded_word = os.path.expanduser(word) - # Handle read-only files separately, without glob_filtered_to_repo - read_only_matched = [f for f in self.coder.abs_read_only_fnames if expanded_word in f] + # Handle read-only files with substring matching and samefile check + read_only_matched = [] + for f in self.coder.abs_read_only_fnames: + if expanded_word in f: + read_only_matched.append(f) + continue - if read_only_matched: - for matched_file in read_only_matched: - self.coder.abs_read_only_fnames.remove(matched_file) - self.io.tool_output(f"Removed read-only file {matched_file} from the chat") + # Try samefile comparison for relative paths + try: + abs_word = os.path.abspath(expanded_word) + if os.path.samefile(abs_word, f): + read_only_matched.append(f) + except (FileNotFoundError, OSError): + continue - matched_files = self.glob_filtered_to_repo(expanded_word) + for matched_file in read_only_matched: + self.coder.abs_read_only_fnames.remove(matched_file) + self.io.tool_output(f"Removed read-only file {matched_file} from the chat") + + # For editable files, use glob if word contains glob chars, otherwise use substring + if any(c in expanded_word for c in "*?[]"): + matched_files = self.glob_filtered_to_repo(expanded_word) + else: + # Use substring matching like we do for read-only files + matched_files = [ + self.coder.get_rel_fname(f) for f in self.coder.abs_fnames if expanded_word in f + ] if not matched_files: matched_files.append(expanded_word) @@ -882,10 +919,14 @@ class Commands: if combined_output is None: return + # Calculate token count of output + token_count = self.coder.main_model.token_count(combined_output) + k_tokens = token_count / 1000 + if add_on_nonzero_exit: add = exit_status != 0 else: - add = self.io.confirm_ask("Add command output to the chat?") + add = self.io.confirm_ask(f"Add {k_tokens:.1f}k tokens of command output to the chat?") if add: num_lines = len(combined_output.strip().splitlines()) @@ -902,13 +943,17 @@ class Commands: dict(role="assistant", content="Ok."), ] + if add and exit_status != 0: + self.io.placeholder = "What's wrong? Fix" + def cmd_exit(self, args): "Exit the application" + self.coder.event("exit", reason="/exit") sys.exit() def cmd_quit(self, args): "Exit the application" - sys.exit() + self.cmd_exit(args) def cmd_ls(self, args): "List all known files and indicate which are included in the chat session" @@ -973,7 +1018,7 @@ class Commands: return self.coder.event("interactive help") - from aider.coders import Coder + from aider.coders.base_coder import Coder if not self.help: res = install_help_extra(self.io) @@ -1017,23 +1062,23 @@ class Commands: ) def cmd_ask(self, args): - "Ask questions about the code base without editing any files" + """Ask questions about the code base without editing any files. If no prompt provided, switches to ask mode.""" # noqa return self._generic_chat_command(args, "ask") def cmd_code(self, args): - "Ask for changes to your code" + """Ask for changes to your code. If no prompt provided, switches to code mode.""" # noqa return self._generic_chat_command(args, self.coder.main_model.edit_format) def cmd_architect(self, args): - "Enter architect mode to discuss high-level design and architecture" + """Enter architect/editor mode using 2 different models. If no prompt provided, switches to architect/editor mode.""" # noqa return self._generic_chat_command(args, "architect") def _generic_chat_command(self, args, edit_format): if not args.strip(): - self.io.tool_error(f"Please provide a question or topic for the {edit_format} chat.") - return + # Switch to the corresponding chat mode if no args provided + return self.cmd_chat_mode(edit_format) - from aider.coders import Coder + from aider.coders.base_coder import Coder coder = Coder.create( io=self.io, @@ -1080,43 +1125,23 @@ class Commands: self.io.tool_error("To use /voice you must provide an OpenAI API key.") return try: - self.voice = voice.Voice(audio_format=self.args.voice_format) + self.voice = voice.Voice( + audio_format=self.voice_format or "wav", device_name=self.voice_input_device + ) except voice.SoundDeviceError: self.io.tool_error( "Unable to import `sounddevice` and/or `soundfile`, is portaudio installed?" ) return - history_iter = self.io.get_input_history() - - history = [] - size = 0 - for line in history_iter: - if line.startswith("/"): - continue - if line in history: - continue - if size + len(line) > 1024: - break - size += len(line) - history.append(line) - - history.reverse() - history = "\n".join(history) - try: - text = self.voice.record_and_transcribe(history, language=self.voice_language) + text = self.voice.record_and_transcribe(None, language=self.voice_language) except litellm.OpenAIError as err: self.io.tool_error(f"Unable to use OpenAI whisper model: {err}") return if text: - self.io.add_to_input_history(text) - self.io.print() - self.io.user_input(text, log_only=False) - self.io.print() - - return text + self.io.placeholder = text def cmd_paste(self, args): """Paste image/text from the clipboard into the chat.\ @@ -1169,9 +1194,14 @@ class Commands: self.io.tool_error(f"Error processing clipboard content: {e}") def cmd_read_only(self, args): - "Add files to the chat that are for reference, not to be edited" + "Add files to the chat that are for reference only, or turn added files to read-only" if not args.strip(): - self.io.tool_error("Please provide filenames or directories to read.") + # Convert all files in chat to read-only + for fname in list(self.coder.abs_fnames): + self.coder.abs_fnames.remove(fname) + self.coder.abs_read_only_fnames.add(fname) + rel_fname = self.coder.get_rel_fname(fname) + self.io.tool_output(f"Converted {rel_fname} to read-only") return filenames = parse_quoted_filenames(args) @@ -1288,7 +1318,12 @@ class Commands: continue self.io.tool_output(f"\nExecuting: {cmd}") - self.run(cmd) + try: + self.run(cmd) + except SwitchCoder: + self.io.tool_error( + f"Command '{cmd}' is only supported in interactive mode, skipping." + ) def completions_raw_save(self, document, complete_event): return self.completions_raw_read_only(document, complete_event) @@ -1320,6 +1355,10 @@ class Commands: except Exception as e: self.io.tool_error(f"Error saving commands to file: {e}") + def cmd_multiline_mode(self, args): + "Toggle multiline mode (swaps behavior of Enter and Meta+Enter)" + self.io.toggle_multiline_mode() + def cmd_copy(self, args): "Copy the last assistant message to the clipboard" all_messages = self.coder.done_messages + self.coder.cur_messages @@ -1368,6 +1407,50 @@ class Commands: if user_input.strip(): self.io.set_placeholder(user_input.rstrip()) + def cmd_copy_context(self, args=None): + """Copy the current chat context as markdown, suitable to paste into a web UI""" + + chunks = self.coder.format_chat_chunks() + + markdown = "" + + # Only include specified chunks in order + for messages in [chunks.repo, chunks.readonly_files, chunks.chat_files]: + for msg in messages: + # Only include user messages + if msg["role"] != "user": + continue + + content = msg["content"] + + # Handle image/multipart content + if isinstance(content, list): + for part in content: + if part.get("type") == "text": + markdown += part["text"] + "\n\n" + else: + markdown += content + "\n\n" + + args = args or "" + markdown += f""" +Just tell me how to edit the files to make the changes. +Don't give me back entire files. +Just show me the edits I need to make. + +{args} +""" + + try: + pyperclip.copy(markdown) + self.io.tool_output("Copied code context to clipboard.") + except pyperclip.PyperclipException as e: + self.io.tool_error(f"Failed to copy to clipboard: {str(e)}") + self.io.tool_output( + "You may need to install xclip or xsel on Linux, or pbcopy on macOS." + ) + except Exception as e: + self.io.tool_error(f"An unexpected error occurred while copying to clipboard: {str(e)}") + def expand_subdir(file_path): if file_path.is_file(): diff --git a/aider/copypaste.py b/aider/copypaste.py new file mode 100644 index 000000000..c8dfbe378 --- /dev/null +++ b/aider/copypaste.py @@ -0,0 +1,72 @@ +import threading +import time + +import pyperclip + + +class ClipboardWatcher: + """Watches clipboard for changes and updates IO placeholder""" + + def __init__(self, io, verbose=False): + self.io = io + self.verbose = verbose + self.stop_event = None + self.watcher_thread = None + self.last_clipboard = None + self.io.clipboard_watcher = self + + def start(self): + """Start watching clipboard for changes""" + self.stop_event = threading.Event() + self.last_clipboard = pyperclip.paste() + + def watch_clipboard(): + while not self.stop_event.is_set(): + try: + current = pyperclip.paste() + if current != self.last_clipboard: + self.last_clipboard = current + self.io.interrupt_input() + self.io.placeholder = current + if len(current.splitlines()) > 1: + self.io.placeholder = "\n" + self.io.placeholder + "\n" + + time.sleep(0.5) + except Exception as e: + if self.verbose: + from aider.dump import dump + + dump(f"Clipboard watcher error: {e}") + continue + + self.watcher_thread = threading.Thread(target=watch_clipboard, daemon=True) + self.watcher_thread.start() + + def stop(self): + """Stop watching clipboard for changes""" + if self.stop_event: + self.stop_event.set() + if self.watcher_thread: + self.watcher_thread.join() + self.watcher_thread = None + self.stop_event = None + + +def main(): + """Example usage of the clipboard watcher""" + from aider.io import InputOutput + + io = InputOutput() + watcher = ClipboardWatcher(io, verbose=True) + + try: + watcher.start() + while True: + time.sleep(1) + except KeyboardInterrupt: + print("\nStopped watching clipboard") + watcher.stop() + + +if __name__ == "__main__": + main() diff --git a/aider/exceptions.py b/aider/exceptions.py index e8fcc5997..2fc810430 100644 --- a/aider/exceptions.py +++ b/aider/exceptions.py @@ -1,5 +1,7 @@ from dataclasses import dataclass +from aider.dump import dump # noqa: F401 + @dataclass class ExInfo: @@ -50,6 +52,7 @@ EXCEPTIONS = [ class LiteLLMExceptions: exceptions = dict() + exception_info = {exi.name: exi for exi in EXCEPTIONS} def __init__(self): self._load() @@ -58,24 +61,26 @@ class LiteLLMExceptions: import litellm for var in dir(litellm): - if not var.endswith("Error"): - continue - - ex_info = None - for exi in EXCEPTIONS: - if var == exi.name: - ex_info = exi - break - - if strict and not ex_info: - raise ValueError(f"{var} is in litellm but not in aider's exceptions list") + if var.endswith("Error"): + if var not in self.exception_info: + raise ValueError(f"{var} is in litellm but not in aider's exceptions list") + for var in self.exception_info: ex = getattr(litellm, var) - self.exceptions[ex] = ex_info + self.exceptions[ex] = self.exception_info[var] def exceptions_tuple(self): return tuple(self.exceptions) def get_ex_info(self, ex): """Return the ExInfo for a given exception instance""" + import litellm + + if ex.__class__ is litellm.APIConnectionError: + if "google.auth" in str(ex): + return ExInfo( + "APIConnectionError", False, "You need to: pip install google-generativeai" + ) + if "boto3" in str(ex): + return ExInfo("APIConnectionError", False, "You need to: pip install boto3") return self.exceptions.get(ex.__class__, ExInfo(None, None, None)) diff --git a/aider/help_pats.py b/aider/help_pats.py index b86ef51f8..5d2b14865 100644 --- a/aider/help_pats.py +++ b/aider/help_pats.py @@ -1,4 +1,7 @@ +# This needs to sync with MANIFEST.in + exclude_website_pats = [ + "**/.DS_Store", "examples/**", "_posts/**", "HISTORY.md", @@ -7,5 +10,4 @@ exclude_website_pats = [ "docs/unified-diffs.md", "docs/leaderboards/index.md", "assets/**", - "**/.DS_Store", ] diff --git a/aider/history.py b/aider/history.py index d758ccbe7..a4727b941 100644 --- a/aider/history.py +++ b/aider/history.py @@ -2,7 +2,6 @@ import argparse from aider import models, prompts from aider.dump import dump # noqa: F401 -from aider.sendchat import simple_send_with_retries class ChatSummary: @@ -26,6 +25,12 @@ class ChatSummary: return sized def summarize(self, messages, depth=0): + messages = self.summarize_real(messages) + if messages and messages[-1]["role"] != "assistant": + messages.append(dict(role="assistant", content="Ok.")) + return messages + + def summarize_real(self, messages, depth=0): if not self.models: raise ValueError("No models available for summarization") @@ -88,7 +93,7 @@ class ChatSummary: if summary_tokens + tail_tokens < self.max_tokens: return result - return self.summarize(result, depth + 1) + return self.summarize_real(result, depth + 1) def summarize_all(self, messages): content = "" @@ -108,9 +113,7 @@ class ChatSummary: for model in self.models: try: - summary = simple_send_with_retries( - model.name, summarize_messages, extra_params=model.extra_params - ) + summary = model.simple_send_with_retries(summarize_messages) if summary is not None: summary = prompts.summary_prefix + summary return [dict(role="user", content=summary)] diff --git a/aider/io.py b/aider/io.py index df6e71317..5ab11f0d6 100644 --- a/aider/io.py +++ b/aider/io.py @@ -1,5 +1,7 @@ import base64 +import functools import os +import signal import time import webbrowser from collections import defaultdict @@ -11,9 +13,12 @@ from pathlib import Path from prompt_toolkit.completion import Completer, Completion, ThreadedCompleter from prompt_toolkit.cursor_shapes import ModalCursorShapeConfig from prompt_toolkit.enums import EditingMode +from prompt_toolkit.filters import Condition, is_searching from prompt_toolkit.history import FileHistory from prompt_toolkit.key_binding import KeyBindings +from prompt_toolkit.keys import Keys from prompt_toolkit.lexers import PygmentsLexer +from prompt_toolkit.output.vt100 import is_dumb_terminal from prompt_toolkit.shortcuts import CompleteStyle, PromptSession from prompt_toolkit.styles import Style from pygments.lexers import MarkdownLexer, guess_lexer_for_filename @@ -30,6 +35,23 @@ from .dump import dump # noqa: F401 from .utils import is_image_file +def restore_multiline(func): + """Decorator to restore multiline mode after function execution""" + + @functools.wraps(func) + def wrapper(self, *args, **kwargs): + orig_multiline = self.multiline_mode + self.multiline_mode = False + try: + return func(self, *args, **kwargs) + except Exception: + raise + finally: + self.multiline_mode = orig_multiline + + return wrapper + + @dataclass class ConfirmGroup: preference: str = None @@ -173,6 +195,7 @@ class AutoCompleter(Completer): class InputOutput: num_error_outputs = 0 num_user_asks = 0 + clipboard_watcher = None def __init__( self, @@ -193,14 +216,20 @@ class InputOutput: completion_menu_current_bg_color=None, code_theme="default", encoding="utf-8", + line_endings="platform", dry_run=False, llm_history_file=None, editingmode=EditingMode.EMACS, fancy_input=True, + file_watcher=None, + multiline_mode=False, + root=".", ): self.placeholder = None + self.interrupted = False self.never_prompts = set() self.editingmode = editingmode + self.multiline_mode = multiline_mode no_color = os.environ.get("NO_COLOR") if no_color is not None and no_color != "": pretty = False @@ -234,14 +263,29 @@ class InputOutput: self.chat_history_file = None self.encoding = encoding + valid_line_endings = {"platform", "lf", "crlf"} + if line_endings not in valid_line_endings: + raise ValueError( + f"Invalid line_endings value: {line_endings}. " + f"Must be one of: {', '.join(valid_line_endings)}" + ) + self.newline = ( + None if line_endings == "platform" else "\n" if line_endings == "lf" else "\r\n" + ) self.dry_run = dry_run current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.append_chat_history(f"\n# aider chat started at {current_time}\n\n") self.prompt_session = None + self.is_dumb_terminal = is_dumb_terminal() + + if self.is_dumb_terminal: + self.pretty = False + fancy_input = False + if fancy_input: - # Initialize PromptSession + # Initialize PromptSession only if we have a capable terminal session_kwargs = { "input": self.input, "output": self.output, @@ -260,6 +304,11 @@ class InputOutput: self.tool_error(f"Can't initialize prompt toolkit: {err}") # non-pretty else: self.console = Console(force_terminal=False, no_color=True) # non-pretty + if self.is_dumb_terminal: + self.tool_output("Detected dumb terminal, disabling fancy input and pretty output.") + + self.file_watcher = file_watcher + self.root = root def _get_style(self): style_dict = {} @@ -314,25 +363,29 @@ class InputOutput: self.tool_error(f"{filename}: {e}") return - def read_text(self, filename): + def read_text(self, filename, silent=False): if is_image_file(filename): return self.read_image(filename) try: with open(str(filename), "r", encoding=self.encoding) as f: return f.read() - except OSError as err: - self.tool_error(f"{filename}: unable to read: {err}") - return except FileNotFoundError: - self.tool_error(f"{filename}: file not found error") + if not silent: + self.tool_error(f"{filename}: file not found error") return except IsADirectoryError: - self.tool_error(f"{filename}: is a directory") + if not silent: + self.tool_error(f"{filename}: is a directory") + return + except OSError as err: + if not silent: + self.tool_error(f"{filename}: unable to read: {err}") return except UnicodeError as e: - self.tool_error(f"{filename}: {e}") - self.tool_error("Use --encoding to set the unicode encoding.") + if not silent: + self.tool_error(f"{filename}: {e}") + self.tool_error("Use --encoding to set the unicode encoding.") return def write_text(self, filename, content, max_retries=5, initial_delay=0.1): @@ -350,7 +403,7 @@ class InputOutput: delay = initial_delay for attempt in range(max_retries): try: - with open(str(filename), "w", encoding=self.encoding) as f: + with open(str(filename), "w", encoding=self.encoding, newline=self.newline) as f: f.write(content) return # Successfully wrote the file except PermissionError as err: @@ -373,6 +426,13 @@ class InputOutput: else: print() + def interrupt_input(self): + if self.prompt_session and self.prompt_session.app: + # Store any partial input before interrupting + self.placeholder = self.prompt_session.app.current_buffer.text + self.interrupted = True + self.prompt_session.app.exit() + def get_input( self, root, @@ -393,6 +453,8 @@ class InputOutput: show = self.format_files_for_input(rel_fnames, rel_read_only_fnames) if edit_format: show += edit_format + if self.multiline_mode: + show += (" " if edit_format else "") + "multi" show += "> " inp = "" @@ -411,16 +473,51 @@ class InputOutput: ) ) + def suspend_to_bg(event): + """Suspend currently running application.""" + event.app.suspend_to_background() + kb = KeyBindings() + @kb.add(Keys.ControlZ, filter=Condition(lambda: hasattr(signal, "SIGTSTP"))) + def _(event): + "Suspend to background with ctrl-z" + suspend_to_bg(event) + @kb.add("c-space") def _(event): "Ignore Ctrl when pressing space bar" event.current_buffer.insert_text(" ") - @kb.add("escape", "c-m", eager=True) + @kb.add("c-up") def _(event): - event.current_buffer.insert_text("\n") + "Navigate backward through history" + event.current_buffer.history_backward() + + @kb.add("c-down") + def _(event): + "Navigate forward through history" + event.current_buffer.history_forward() + + @kb.add("enter", eager=True, filter=~is_searching) + def _(event): + "Handle Enter key press" + if self.multiline_mode: + # In multiline mode, Enter adds a newline + event.current_buffer.insert_text("\n") + else: + # In normal mode, Enter submits + event.current_buffer.validate_and_handle() + + @kb.add("escape", "enter", eager=True, filter=~is_searching) # This is Alt+Enter + def _(event): + "Handle Alt+Enter key press" + if self.multiline_mode: + # In multiline mode, Alt+Enter submits + event.current_buffer.validate_and_handle() + else: + # In normal mode, Alt+Enter adds a newline + event.current_buffer.insert_text("\n") while True: if multiline_input: @@ -432,6 +529,16 @@ class InputOutput: default = self.placeholder or "" self.placeholder = None + self.interrupted = False + if not multiline_input: + if self.file_watcher: + self.file_watcher.start() + if self.clipboard_watcher: + self.clipboard_watcher.start() + + def get_continuation(width, line_number, is_soft_wrap): + return ". " + line = self.prompt_session.prompt( show, default=default, @@ -440,12 +547,35 @@ class InputOutput: complete_style=CompleteStyle.MULTI_COLUMN, style=style, key_bindings=kb, + complete_while_typing=True, + prompt_continuation=get_continuation, ) else: line = input(show) + + # Check if we were interrupted by a file change + if self.interrupted: + line = line or "" + if self.file_watcher: + cmd = self.file_watcher.process_changes() + return cmd + + except EOFError: + raise + except Exception as err: + import traceback + + self.tool_error(str(err)) + self.tool_error(traceback.format_exc()) + return "" except UnicodeEncodeError as err: self.tool_error(str(err)) return "" + finally: + if self.file_watcher: + self.file_watcher.stop() + if self.clipboard_watcher: + self.clipboard_watcher.stop() if line.strip("\r\n") and not multiline_input: stripped = line.strip("\r\n") @@ -554,6 +684,7 @@ class InputOutput: return True return False + @restore_multiline def confirm_ask( self, question, @@ -575,19 +706,22 @@ class InputOutput: if group: allow_never = True - valid_responses = ["yes", "no"] + valid_responses = ["yes", "no", "skip", "all"] options = " (Y)es/(N)o" if group: if not explicit_yes_required: options += "/(A)ll" - valid_responses.append("all") options += "/(S)kip all" - valid_responses.append("skip") if allow_never: options += "/(D)on't ask again" valid_responses.append("don't") - question += options + " [Yes]: " + if default.lower().startswith("y"): + question += options + " [Yes]: " + elif default.lower().startswith("n"): + question += options + " [No]: " + else: + question += options + f" [{default}]: " if subject: self.tool_output() @@ -620,12 +754,13 @@ class InputOutput: res = self.prompt_session.prompt( question, style=style, + complete_while_typing=False, ) else: res = input(question) if not res: - res = "y" # Default to Yes if no input + res = default break res = res.lower() good = any(valid_response.startswith(res) for valid_response in valid_responses) @@ -662,6 +797,7 @@ class InputOutput: return is_yes + @restore_multiline def prompt_ask(self, question, default="", subject=None): self.num_user_asks += 1 @@ -677,7 +813,12 @@ class InputOutput: res = "no" else: if self.prompt_session: - res = self.prompt_session.prompt(question + " ", default=default, style=style) + res = self.prompt_session.prompt( + question + " ", + default=default, + style=style, + complete_while_typing=True, + ) else: res = input(question + " ") @@ -697,9 +838,17 @@ class InputOutput: hist = message.strip() if strip else message self.append_chat_history(hist, linebreak=True, blockquote=True) - message = Text(message) + if not isinstance(message, Text): + message = Text(message) style = dict(style=color) if self.pretty and color else dict() - self.console.print(message, **style) + try: + self.console.print(message, **style) + except UnicodeEncodeError: + # Fallback to ASCII-safe output + if isinstance(message, Text): + message = message.plain + message = str(message).encode("ascii", errors="replace").decode("ascii") + self.console.print(message, **style) def tool_error(self, message="", strip=True): self.num_error_outputs += 1 @@ -755,6 +904,18 @@ class InputOutput: def print(self, message=""): print(message) + def toggle_multiline_mode(self): + """Toggle between normal and multiline input modes""" + self.multiline_mode = not self.multiline_mode + if self.multiline_mode: + self.tool_output( + "Multiline mode: Enabled. Enter inserts newline, Alt-Enter submits text" + ) + else: + self.tool_output( + "Multiline mode: Disabled. Alt-Enter inserts newline, Enter submits text" + ) + def append_chat_history(self, text, linebreak=False, blockquote=False, strip=True): if blockquote: if strip: @@ -796,7 +957,13 @@ class InputOutput: editable_files = [f for f in sorted(rel_fnames) if f not in rel_read_only_fnames] if read_only_files: - files_with_label = ["Readonly:"] + read_only_files + # Use shorter of abs/rel paths for readonly files + ro_paths = [] + for rel_path in read_only_files: + abs_path = os.path.abspath(os.path.join(self.root, rel_path)) + ro_paths.append(abs_path if len(abs_path) < len(rel_path) else rel_path) + + files_with_label = ["Readonly:"] + ro_paths read_only_output = StringIO() Console(file=read_only_output, force_terminal=False).print(Columns(files_with_label)) read_only_lines = read_only_output.getvalue().splitlines() diff --git a/aider/linter.py b/aider/linter.py index 529cacb9d..77d9b5eb2 100644 --- a/aider/linter.py +++ b/aider/linter.py @@ -11,6 +11,7 @@ from grep_ast import TreeContext, filename_to_lang from tree_sitter_languages import get_parser # noqa: E402 from aider.dump import dump # noqa: F401 +from aider.run_cmd import run_cmd_subprocess # noqa: F401 # tree_sitter is throwing a FutureWarning warnings.simplefilter("ignore", category=FutureWarning) @@ -44,26 +45,22 @@ class Linter: def run_cmd(self, cmd, rel_fname, code): cmd += " " + rel_fname - cmd = cmd.split() + returncode = 0 + stdout = "" try: - process = subprocess.Popen( + returncode, stdout = run_cmd_subprocess( cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - encoding=self.encoding, - errors="replace", cwd=self.root, + encoding=self.encoding, ) except OSError as err: print(f"Unable to execute lint command: {err}") return - stdout, _ = process.communicate() errors = stdout - if process.returncode == 0: + if returncode == 0: return # zero exit status - cmd = " ".join(cmd) res = f"## Running: {cmd}\n\n" res += errors diff --git a/aider/llm.py b/aider/llm.py index f750f41af..c57c274db 100644 --- a/aider/llm.py +++ b/aider/llm.py @@ -2,6 +2,8 @@ import importlib import os import warnings +from aider.dump import dump # noqa: F401 + warnings.filterwarnings("ignore", category=UserWarning, module="pydantic") AIDER_SITE_URL = "https://aider.chat" @@ -13,6 +15,8 @@ os.environ["LITELLM_MODE"] = "PRODUCTION" # `import litellm` takes 1.5 seconds, defer it! +VERBOSE = False + class LazyLiteLLM: _lazy_module = None @@ -27,6 +31,9 @@ class LazyLiteLLM: if self._lazy_module is not None: return + if VERBOSE: + print("Loading litellm...") + self._lazy_module = importlib.import_module("litellm") self._lazy_module.suppress_debug_info = True diff --git a/aider/main.py b/aider/main.py index 29c6a9efb..f88b8268b 100644 --- a/aider/main.py +++ b/aider/main.py @@ -9,7 +9,11 @@ import webbrowser from dataclasses import fields from pathlib import Path -import git +try: + import git +except ImportError: + git = None + import importlib_resources from dotenv import load_dotenv from prompt_toolkit.enums import EditingMode @@ -20,6 +24,7 @@ from aider.args import get_parser from aider.coders import Coder from aider.coders.base_coder import UnknownEditFormat from aider.commands import Commands, SwitchCoder +from aider.copypaste import ClipboardWatcher from aider.format_settings import format_settings, scrub_sensitive_info from aider.history import ChatSummary from aider.io import InputOutput @@ -28,6 +33,7 @@ from aider.models import ModelSettings from aider.repo import ANY_GIT_ERROR, GitRepo from aider.report import report_uncaught_exceptions from aider.versioncheck import check_version, install_from_main_branch, install_upgrade +from aider.watch import FileWatcher from .dump import dump # noqa: F401 @@ -91,6 +97,9 @@ def make_new_repo(git_root, io): def setup_git(git_root, io): + if git is None: + return + try: cwd = Path.cwd() except OSError: @@ -104,7 +113,9 @@ def setup_git(git_root, io): except ANY_GIT_ERROR: pass elif cwd == Path.home(): - io.tool_warning("You should probably run aider in a directory, not your home dir.") + io.tool_warning( + "You should probably run aider in your project's directory, not your home dir." + ) return elif cwd and io.confirm_ask( "No git repo found, create one to track aider's changes (recommended)?" @@ -147,39 +158,39 @@ def check_gitignore(git_root, io, ask=True): try: repo = git.Repo(git_root) - if repo.ignored(".aider") and repo.ignored(".env"): + patterns_to_add = [] + + if not repo.ignored(".aider"): + patterns_to_add.append(".aider*") + + env_path = Path(git_root) / ".env" + if env_path.exists() and not repo.ignored(".env"): + patterns_to_add.append(".env") + + if not patterns_to_add: return - except ANY_GIT_ERROR: - pass - patterns = [".aider*", ".env"] - patterns_to_add = [] - - gitignore_file = Path(git_root) / ".gitignore" - if gitignore_file.exists(): - try: - content = io.read_text(gitignore_file) - if content is None: + gitignore_file = Path(git_root) / ".gitignore" + if gitignore_file.exists(): + try: + content = io.read_text(gitignore_file) + if content is None: + return + if not content.endswith("\n"): + content += "\n" + except OSError as e: + io.tool_error(f"Error when trying to read {gitignore_file}: {e}") return - existing_lines = content.splitlines() - for pat in patterns: - if pat not in existing_lines: - patterns_to_add.append(pat) - except OSError as e: - io.tool_error(f"Error when trying to read {gitignore_file}: {e}") + else: + content = "" + except ANY_GIT_ERROR: + return + + if ask: + io.tool_output("You can skip this check with --no-gitignore") + if not io.confirm_ask(f"Add {', '.join(patterns_to_add)} to .gitignore (recommended)?"): return - else: - content = "" - patterns_to_add = patterns - if not patterns_to_add: - return - - if ask and not io.confirm_ask(f"Add {', '.join(patterns_to_add)} to .gitignore (recommended)?"): - return - - if content and not content.endswith("\n"): - content += "\n" content += "\n".join(patterns_to_add) + "\n" try: @@ -203,6 +214,22 @@ def check_streamlit_install(io): ) +def write_streamlit_credentials(): + from streamlit.file_util import get_streamlit_file_path + + # See https://github.com/Aider-AI/aider/issues/772 + + credential_path = Path(get_streamlit_file_path()) / "credentials.toml" + if not os.path.exists(credential_path): + empty_creds = '[general]\nemail = ""\n' + + os.makedirs(os.path.dirname(credential_path), exist_ok=True) + with open(credential_path, "w") as f: + f.write(empty_creds) + else: + print("Streamlit credentials already exist.") + + def launch_gui(args): from streamlit.web import cli @@ -211,6 +238,9 @@ def launch_gui(args): print() print("CONTROL-C to exit...") + # Necessary so streamlit does not prompt the user for an email address. + write_streamlit_credentials() + target = gui.__file__ st_args = ["run", target] @@ -348,18 +378,18 @@ def load_dotenv_files(git_root, dotenv_fname, encoding="utf-8"): def register_litellm_models(git_root, model_metadata_fname, io, verbose=False): - model_metatdata_files = [] + model_metadata_files = [] # Add the resource file path resource_metadata = importlib_resources.files("aider.resources").joinpath("model-metadata.json") - model_metatdata_files.append(str(resource_metadata)) + model_metadata_files.append(str(resource_metadata)) - model_metatdata_files += generate_search_path_list( + model_metadata_files += generate_search_path_list( ".aider.model.metadata.json", git_root, model_metadata_fname ) try: - model_metadata_files_loaded = models.register_litellm_models(model_metatdata_files) + model_metadata_files_loaded = models.register_litellm_models(model_metadata_files) if len(model_metadata_files_loaded) > 0 and verbose: io.tool_output("Loaded model metadata from:") for model_metadata_file in model_metadata_files_loaded: @@ -383,6 +413,12 @@ def sanity_check_repo(repo, io): if not repo.git_repo_error: return True error_msg = str(repo.git_repo_error) + except UnicodeDecodeError as exc: + error_msg = ( + "Failed to read the Git repository. This issue is likely caused by a path encoded " + f'in a format different from the expected encoding "{sys.getfilesystemencoding()}".\n' + f"Internal error: {str(exc)}" + ) except ANY_GIT_ERROR as exc: error_msg = str(exc) bad_ver = "version in (1, 2)" in error_msg @@ -408,7 +444,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F if argv is None: argv = sys.argv[1:] - if force_git_root: + if git is None: + git_root = None + elif force_git_root: git_root = force_git_root else: git_root = get_git_root() @@ -455,6 +493,9 @@ 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 git is None: + args.git = False + if args.analytics_disable: analytics = Analytics(permanently_disable=True) print("Analytics have been permanently disabled.") @@ -467,6 +508,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F litellm._lazy_module.client_session = httpx.Client(verify=False) litellm._lazy_module.aclient_session = httpx.AsyncClient(verify=False) + if args.timeout: + models.request_timeout = args.timeout + if args.dark_mode: args.user_input_color = "#32FF32" args.tool_error_color = "#FF3333" @@ -506,9 +550,11 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F code_theme=args.code_theme, dry_run=args.dry_run, encoding=args.encoding, + line_endings=args.line_endings, llm_history_file=args.llm_history_file, editingmode=editing_mode, fancy_input=args.fancy_input, + multiline_mode=args.multiline, ) io = get_io(args.pretty) @@ -520,6 +566,50 @@ 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)") + # Process any environment variables set via --set-env + if args.set_env: + for env_setting in args.set_env: + try: + name, value = env_setting.split("=", 1) + os.environ[name.strip()] = value.strip() + except ValueError: + io.tool_error(f"Invalid --set-env format: {env_setting}") + io.tool_output("Format should be: ENV_VAR_NAME=value") + return 1 + + # Process any API keys set via --api-key + if args.api_key: + for api_setting in args.api_key: + try: + provider, key = api_setting.split("=", 1) + env_var = f"{provider.strip().upper()}_API_KEY" + os.environ[env_var] = key.strip() + except ValueError: + io.tool_error(f"Invalid --api-key format: {api_setting}") + io.tool_output("Format should be: provider=key") + return 1 + + if args.anthropic_api_key: + os.environ["ANTHROPIC_API_KEY"] = args.anthropic_api_key + + if args.openai_api_key: + os.environ["OPENAI_API_KEY"] = args.openai_api_key + if args.openai_api_base: + os.environ["OPENAI_API_BASE"] = args.openai_api_base + if args.openai_api_version: + io.tool_warning( + "--openai-api-version is deprecated, use --set-env OPENAI_API_VERSION=" + ) + os.environ["OPENAI_API_VERSION"] = args.openai_api_version + if args.openai_api_type: + io.tool_warning("--openai-api-type is deprecated, use --set-env OPENAI_API_TYPE=") + os.environ["OPENAI_API_TYPE"] = args.openai_api_type + if args.openai_organization_id: + io.tool_warning( + "--openai-organization-id is deprecated, use --set-env OPENAI_ORGANIZATION=" + ) + os.environ["OPENAI_ORGANIZATION"] = args.openai_organization_id + analytics = Analytics(logfile=args.analytics_log, permanently_disable=args.analytics_disable) if args.analytics is not False: if analytics.need_to_ask(args.analytics): @@ -547,9 +637,11 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F if args.gui and not return_coder: if not check_streamlit_install(io): + analytics.event("exit", reason="Streamlit not installed") return analytics.event("gui session") launch_gui(argv) + analytics.event("exit", reason="GUI session ended") return if args.verbose: @@ -560,7 +652,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F fnames = [str(Path(fn).resolve()) for fn in all_files] read_only_fnames = [] for fn in args.read or []: - path = Path(fn).resolve() + path = Path(fn).expanduser().resolve() if path.is_dir(): read_only_fnames.extend(str(f) for f in path.rglob("*") if f.is_file()) else: @@ -576,6 +668,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F io.tool_output( "Provide either a single directory of a git repo, or a list of one or more files." ) + analytics.event("exit", reason="Invalid directory input") return 1 git_dname = None @@ -586,26 +679,31 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F fnames = [] else: io.tool_error(f"{all_files[0]} is a directory, but --no-git selected.") + analytics.event("exit", reason="Directory with --no-git") return 1 # We can't know the git repo for sure until after parsing the args. # If we guessed wrong, reparse because that changes things like # the location of the config.yml and history files. - if args.git and not force_git_root: + if args.git and not force_git_root and git is not None: right_repo_root = guessed_wrong_repo(io, git_root, fnames, git_dname) if right_repo_root: + analytics.event("exit", reason="Recursing with correct repo") return main(argv, input, output, right_repo_root, return_coder=return_coder) if args.just_check_update: update_available = check_version(io, just_check=True, verbose=args.verbose) + analytics.event("exit", reason="Just checking update") return 0 if not update_available else 1 if args.install_main_branch: success = install_from_main_branch(io) + analytics.event("exit", reason="Installed main branch") return 0 if success else 1 if args.upgrade: success = install_upgrade(io) + analytics.event("exit", reason="Upgrade completed") return 0 if success else 1 if args.check_update: @@ -613,6 +711,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F if args.list_models: models.print_matching_models(io, args.list_models) + analytics.event("exit", reason="Listed models") return 0 if args.git: @@ -631,20 +730,6 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F is_first_run = is_first_run_of_new_version(io, verbose=args.verbose) check_and_load_imports(io, is_first_run, verbose=args.verbose) - if args.anthropic_api_key: - os.environ["ANTHROPIC_API_KEY"] = args.anthropic_api_key - - if args.openai_api_key: - os.environ["OPENAI_API_KEY"] = args.openai_api_key - if args.openai_api_base: - os.environ["OPENAI_API_BASE"] = args.openai_api_base - if args.openai_api_version: - os.environ["OPENAI_API_VERSION"] = args.openai_api_version - if args.openai_api_type: - os.environ["OPENAI_API_TYPE"] = args.openai_api_type - if args.openai_organization_id: - os.environ["OPENAI_ORGANIZATION"] = args.openai_organization_id - register_models(git_root, args.model_settings_file, io, verbose=args.verbose) register_litellm_models(git_root, args.model_metadata_file, io, verbose=args.verbose) @@ -656,14 +741,32 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F if len(parts) != 2: io.tool_error(f"Invalid alias format: {alias_def}") io.tool_output("Format should be: alias:model-name") + analytics.event("exit", reason="Invalid alias format error") return 1 alias, model = parts models.MODEL_ALIASES[alias.strip()] = model.strip() if not args.model: - args.model = "gpt-4o-2024-08-06" - if os.environ.get("ANTHROPIC_API_KEY"): - args.model = "claude-3-5-sonnet-20241022" + # Select model based on available API keys + model_key_pairs = [ + ("ANTHROPIC_API_KEY", "sonnet"), + ("DEEPSEEK_API_KEY", "deepseek"), + ("OPENROUTER_API_KEY", "openrouter/anthropic/claude-3.5-sonnet"), + ("OPENAI_API_KEY", "gpt-4o"), + ("GEMINI_API_KEY", "flash"), + ] + + for env_key, model_name in model_key_pairs: + if os.environ.get(env_key): + args.model = model_name + io.tool_warning( + f"Found {env_key} so using {model_name} since no --model was specified." + ) + break + if not args.model: + io.tool_error("You need to specify a --model and an --api-key to use.") + io.offer_url(urls.models_and_keys, "Open documentation url for more info?") + return 1 main_model = models.Model( args.model, @@ -672,6 +775,18 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F editor_edit_format=args.editor_edit_format, ) + # add --reasoning-effort cli param + if args.reasoning_effort is not None: + if not getattr(main_model, "extra_params", None): + main_model.extra_params = {} + if "extra_body" not in main_model.extra_params: + main_model.extra_params["extra_body"] = {} + main_model.extra_params["extra_body"]["reasoning_effort"] = args.reasoning_effort + + if args.copy_paste and args.edit_format is None: + if main_model.edit_format in ("diff", "whole"): + main_model.edit_format = "editor-" + main_model.edit_format + if args.verbose: io.tool_output("Model metadata:") io.tool_output(json.dumps(main_model.info, indent=4)) @@ -684,6 +799,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F lint_cmds = parse_lint_cmds(args.lint_cmd, io) if lint_cmds is None: + analytics.event("exit", reason="Invalid lint command format") return 1 if args.show_model_warnings: @@ -696,6 +812,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F io.offer_url(urls.model_warnings, "Open documentation url for more info?") io.tool_output() except KeyboardInterrupt: + analytics.event("exit", reason="Keyboard interrupt during model warnings") return 1 repo = None @@ -719,11 +836,20 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F if not args.skip_sanity_check_repo: if not sanity_check_repo(repo, io): + analytics.event("exit", reason="Repository sanity check failed") return 1 + if repo: + analytics.event("repo", num_files=len(repo.get_tracked_files())) + else: + analytics.event("no-repo") + commands = Commands( io, None, + voice_language=args.voice_language, + voice_input_device=args.voice_input_device, + voice_format=args.voice_format, verify_ssl=args.verify_ssl, args=args, parser=parser, @@ -746,6 +872,11 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F ) args.stream = False + if args.map_tokens is None: + map_tokens = main_model.get_repo_map_tokens() + else: + map_tokens = args.map_tokens + try: coder = Coder.create( main_model=main_model, @@ -758,7 +889,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F auto_commits=args.auto_commits, dirty_commits=args.dirty_commits, dry_run=args.dry_run, - map_tokens=args.map_tokens, + map_tokens=map_tokens, verbose=args.verbose, stream=args.stream, use_git=args.git, @@ -777,18 +908,42 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F suggest_shell_commands=args.suggest_shell_commands, chat_language=args.chat_language, detect_urls=args.detect_urls, + auto_copy_context=args.copy_paste, ) except UnknownEditFormat as err: io.tool_error(str(err)) io.offer_url(urls.edit_formats, "Open documentation about edit formats?") + analytics.event("exit", reason="Unknown edit format") return 1 except ValueError as err: io.tool_error(str(err)) + analytics.event("exit", reason="ValueError during coder creation") return 1 if return_coder: + analytics.event("exit", reason="Returning coder object") return coder + ignores = [] + if git_root: + ignores.append(str(Path(git_root) / ".gitignore")) + if args.aiderignore: + ignores.append(args.aiderignore) + + if args.watch_files: + file_watcher = FileWatcher( + coder, + gitignores=ignores, + verbose=args.verbose, + analytics=analytics, + root=str(Path.cwd()) if args.subtree_only else None, + ) + coder.file_watcher = file_watcher + + if args.copy_paste: + analytics.event("copy-paste mode") + ClipboardWatcher(coder.io, verbose=args.verbose) + coder.show_announcements() if args.show_prompts: @@ -797,6 +952,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F ] messages = coder.format_messages().all_messages() utils.show_messages(messages) + analytics.event("exit", reason="Showed prompts") return if args.lint: @@ -805,10 +961,11 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F if args.test: if not args.test_cmd: io.tool_error("No --test-cmd provided.") + analytics.event("exit", reason="No test command provided") return 1 - test_errors = coder.commands.cmd_test(args.test_cmd) - if test_errors: - coder.run(test_errors) + coder.commands.cmd_test(args.test_cmd) + if io.placeholder: + coder.run(io.placeholder) if args.commit: if args.dry_run: @@ -817,32 +974,33 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F coder.commands.cmd_commit() if args.lint or args.test or args.commit: + analytics.event("exit", reason="Completed lint/test/commit") return if args.show_repo_map: repo_map = coder.get_repo_map() if repo_map: io.tool_output(repo_map) + analytics.event("exit", reason="Showed repo map") return if args.apply: content = io.read_text(args.apply) if content is None: + analytics.event("exit", reason="Failed to read apply content") return coder.partial_response_content = content + # For testing #2879 + # from aider.coders.base_coder import all_fences + # coder.fence = all_fences[1] coder.apply_updates() + analytics.event("exit", reason="Applied updates") return if args.apply_clipboard_edits: args.edit_format = main_model.editor_edit_format args.message = "/paste" - if "VSCODE_GIT_IPC_HANDLE" in os.environ: - args.pretty = False - io.tool_output("VSCode terminal detected, pretty output has been disabled.") - - io.tool_output('Use /help for help, run "aider --help" to see cmd line args') - if args.show_release_notes is True: io.tool_output(f"Opening release notes: {urls.release_notes}") io.tool_output() @@ -874,6 +1032,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F coder.run(with_message=args.message) except SwitchCoder: pass + analytics.event("exit", reason="Completed --message") return if args.message_file: @@ -883,13 +1042,18 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F coder.run(with_message=message_from_file) except FileNotFoundError: io.tool_error(f"Message file not found: {args.message_file}") + analytics.event("exit", reason="Message file not found") return 1 except IOError as e: io.tool_error(f"Error reading message file: {e}") + analytics.event("exit", reason="Message file IO error") return 1 + + analytics.event("exit", reason="Completed --message-file") return if args.exit: + analytics.event("exit", reason="Exit flag set") return analytics.event("cli session", main_model=main_model, edit_format=main_model.edit_format) @@ -897,6 +1061,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F while True: try: coder.run() + analytics.event("exit", reason="Completed main CLI coder.run") return except SwitchCoder as switch: kwargs = dict(io=io, from_coder=coder) @@ -915,6 +1080,10 @@ def is_first_run_of_new_version(io, verbose=False): installs_file = Path.home() / ".aider" / "installs.json" key = (__version__, sys.executable) + # Never show notes for .dev versions + if ".dev" in __version__: + return False + if verbose: io.tool_output( f"Checking imports for version {__version__} and executable {sys.executable}" diff --git a/aider/mdstream.py b/aider/mdstream.py index 947777651..e7e19df87 100755 --- a/aider/mdstream.py +++ b/aider/mdstream.py @@ -10,10 +10,17 @@ from rich.text import Text from aider.dump import dump # noqa: F401 -_text = """ +_text_prefix = """ # Header -Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. +Lorem Ipsum is simply dummy text of the printing and typesetting industry. +Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, +when an unknown printer took a galley of type and scrambled it to make a type +specimen book. It has survived not only five centuries, but also the leap into +electronic typesetting, remaining essentially unchanged. It was popularised in +the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, +and more recently with desktop publishing software like Aldus PageMaker +including versions of Lorem Ipsum. @@ -27,10 +34,9 @@ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem ```python -import sys +""" -def greeting(): - print("Hello world!") +_text_suffix = """ ``` ## Sub header too @@ -41,81 +47,146 @@ The end. class MarkdownStream: - live = None - when = 0 - min_delay = 0.050 - live_window = 6 + """Streaming markdown renderer that progressively displays content with a live updating window. + + Uses rich.console and rich.live to render markdown content with smooth scrolling + and partial updates. Maintains a sliding window of visible content while streaming + in new markdown text. + """ + + live = None # Rich Live display instance + when = 0 # Timestamp of last update + min_delay = 1.0 / 20 # Minimum time between updates (20fps) + live_window = 6 # Number of lines to keep visible at bottom during streaming def __init__(self, mdargs=None): - self.printed = [] + """Initialize the markdown stream. + + Args: + mdargs (dict, optional): Additional arguments to pass to rich Markdown renderer + """ + self.printed = [] # Stores lines that have already been printed if mdargs: self.mdargs = mdargs else: self.mdargs = dict() + # Initialize rich Live display with empty text self.live = Live(Text(""), refresh_per_second=1.0 / self.min_delay) self.live.start() + def _render_markdown_to_lines(self, text): + """Render markdown text to a list of lines. + + Args: + text (str): Markdown text to render + + Returns: + list: List of rendered lines with line endings preserved + """ + # Render the markdown to a string buffer + string_io = io.StringIO() + console = Console(file=string_io, force_terminal=True) + markdown = Markdown(text, **self.mdargs) + console.print(markdown) + output = string_io.getvalue() + + # Split rendered output into lines + return output.splitlines(keepends=True) + def __del__(self): + """Destructor to ensure Live display is properly cleaned up.""" if self.live: try: self.live.stop() except Exception: - pass + pass # Ignore any errors during cleanup def update(self, text, final=False): + """Update the displayed markdown content. + + Args: + text (str): The markdown text received so far + final (bool): If True, this is the final update and we should clean up + + Splits the output into "stable" older lines and the "last few" lines + which aren't considered stable. They may shift around as new chunks + are appended to the markdown text. + + The stable lines emit to the console above the Live window. + The unstable lines emit into the Live window so they can be repainted. + + Markdown going to the console works better in terminal scrollback buffers. + The live window doesn't play nice with terminal scrollback. + """ now = time.time() + # Throttle updates to maintain smooth rendering if not final and now - self.when < self.min_delay: return self.when = now - string_io = io.StringIO() - console = Console(file=string_io, force_terminal=True) + # Measure render time and adjust min_delay to maintain smooth rendering + start = time.time() + lines = self._render_markdown_to_lines(text) + render_time = time.time() - start - markdown = Markdown(text, **self.mdargs) + # Set min_delay to render time plus a small buffer + self.min_delay = min(max(render_time * 10, 1.0 / 20), 2) - console.print(markdown) - output = string_io.getvalue() - - lines = output.splitlines(keepends=True) num_lines = len(lines) + # How many lines have "left" the live window and are now considered stable? + # Or if final, consider all lines to be stable. if not final: num_lines -= self.live_window + # If we have stable content to display... if final or num_lines > 0: + # How many stable lines do we need to newly show above the live window? num_printed = len(self.printed) - show = num_lines - num_printed + # Skip if no new lines to show above live window if show <= 0: return + # Get the new lines and display them show = lines[num_printed:num_lines] show = "".join(show) show = Text.from_ansi(show) - self.live.console.print(show) + self.live.console.print(show) # to the console above the live area + # Update our record of printed lines self.printed = lines[:num_lines] + # Handle final update cleanup if final: self.live.update(Text("")) self.live.stop() self.live = None - else: - rest = lines[num_lines:] - rest = "".join(rest) - # rest = '...\n' + rest - rest = Text.from_ansi(rest) - self.live.update(rest) + return + + # Update the live window with remaining lines + rest = lines[num_lines:] + rest = "".join(rest) + rest = Text.from_ansi(rest) + self.live.update(rest) + + def find_minimal_suffix(self, text, match_lines=50): + """ + Splits text into chunks on blank lines "\n\n". + """ if __name__ == "__main__": - _text = 5 * _text + with open("aider/io.py", "r") as f: + code = f.read() + _text = _text_prefix + code + _text_suffix + _text = _text * 10 pm = MarkdownStream() - for i in range(6, len(_text)): + for i in range(6, len(_text), 5): pm.update(_text[:i]) time.sleep(0.01) diff --git a/aider/models.py b/aider/models.py index 12e809c0f..4f4ed499b 100644 --- a/aider/models.py +++ b/aider/models.py @@ -1,13 +1,16 @@ import difflib +import hashlib +import importlib.resources import json import math import os import platform +import re import sys import time from dataclasses import dataclass, fields from pathlib import Path -from typing import Optional +from typing import Optional, Union import json5 import yaml @@ -15,11 +18,20 @@ from PIL import Image from aider.dump import dump # noqa: F401 from aider.llm import litellm +from aider.sendchat import ensure_alternating_roles, sanity_check_messages + +RETRY_TIMEOUT = 60 + +request_timeout = 600 DEFAULT_MODEL_NAME = "gpt-4o" ANTHROPIC_BETA_HEADER = "prompt-caching-2024-07-31,pdfs-2024-09-25" OPENAI_MODELS = """ +o1 +o1-preview +o1-mini +o3-mini gpt-4 gpt-4o gpt-4o-2024-05-13 @@ -69,14 +81,17 @@ MODEL_ALIASES = { "opus": "claude-3-opus-20240229", # GPT models "4": "gpt-4-0613", - "4o": "gpt-4o-2024-08-06", + "4o": "gpt-4o", "4-turbo": "gpt-4-1106-preview", "35turbo": "gpt-3.5-turbo", "35-turbo": "gpt-3.5-turbo", "3": "gpt-3.5-turbo", # Other models - "deepseek": "deepseek/deepseek-coder", + "deepseek": "deepseek/deepseek-chat", + "r1": "deepseek/deepseek-reasoner", + "flash": "gemini/gemini-2.0-flash-exp", } +# Model metadata loaded from resources and user's files. @dataclass @@ -94,663 +109,20 @@ class ModelSettings: cache_control: bool = False caches_by_default: bool = False use_system_prompt: bool = True - use_temperature: bool = True + use_temperature: Union[bool, float] = True streaming: bool = True editor_model_name: Optional[str] = None editor_edit_format: Optional[str] = None + remove_reasoning: Optional[str] = None + system_prompt_prefix: Optional[str] = None -# https://platform.openai.com/docs/models/gpt-4-and-gpt-4-turbo -# https://platform.openai.com/docs/models/gpt-3-5-turbo -# https://openai.com/pricing - -MODEL_SETTINGS = [ - # gpt-3.5 - ModelSettings( - "gpt-3.5-turbo", - "whole", - weak_model_name="gpt-4o-mini", - reminder="sys", - ), - ModelSettings( - "gpt-3.5-turbo-0125", - "whole", - weak_model_name="gpt-4o-mini", - reminder="sys", - ), - ModelSettings( - "gpt-3.5-turbo-1106", - "whole", - weak_model_name="gpt-4o-mini", - reminder="sys", - ), - ModelSettings( - "gpt-3.5-turbo-0613", - "whole", - weak_model_name="gpt-4o-mini", - reminder="sys", - ), - ModelSettings( - "gpt-3.5-turbo-16k-0613", - "whole", - weak_model_name="gpt-4o-mini", - reminder="sys", - ), - # gpt-4 - ModelSettings( - "gpt-4-turbo-2024-04-09", - "udiff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - lazy=True, - reminder="sys", - ), - ModelSettings( - "gpt-4-turbo", - "udiff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - lazy=True, - reminder="sys", - ), - ModelSettings( - "openai/gpt-4o", - "diff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - lazy=True, - reminder="sys", - editor_edit_format="editor-diff", - ), - ModelSettings( - "openai/gpt-4o-2024-08-06", - "diff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - lazy=True, - reminder="sys", - ), - ModelSettings( - "gpt-4o-2024-08-06", - "diff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - lazy=True, - reminder="sys", - ), - ModelSettings( - "gpt-4o-2024-11-20", - "diff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - lazy=True, - reminder="sys", - ), - ModelSettings( - "openai/gpt-4o-2024-11-20", - "diff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - lazy=True, - reminder="sys", - ), - ModelSettings( - "gpt-4o", - "diff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - lazy=True, - reminder="sys", - editor_edit_format="editor-diff", - ), - ModelSettings( - "gpt-4o-mini", - "whole", - weak_model_name="gpt-4o-mini", - lazy=True, - reminder="sys", - ), - ModelSettings( - "openai/gpt-4o-mini", - "whole", - weak_model_name="openai/gpt-4o-mini", - lazy=True, - reminder="sys", - ), - ModelSettings( - "gpt-4-0125-preview", - "udiff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - lazy=True, - reminder="sys", - examples_as_sys_msg=True, - ), - ModelSettings( - "gpt-4-1106-preview", - "udiff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - lazy=True, - reminder="sys", - ), - ModelSettings( - "gpt-4-vision-preview", - "diff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - reminder="sys", - ), - ModelSettings( - "gpt-4-0314", - "diff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - reminder="sys", - examples_as_sys_msg=True, - ), - ModelSettings( - "gpt-4-0613", - "diff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - reminder="sys", - ), - ModelSettings( - "gpt-4-32k-0613", - "diff", - weak_model_name="gpt-4o-mini", - use_repo_map=True, - reminder="sys", - ), - # Claude - ModelSettings( - "claude-3-opus-20240229", - "diff", - weak_model_name="claude-3-5-haiku-20241022", - use_repo_map=True, - ), - ModelSettings( - "openrouter/anthropic/claude-3-opus", - "diff", - weak_model_name="openrouter/anthropic/claude-3-5-haiku", - use_repo_map=True, - ), - ModelSettings( - "claude-3-sonnet-20240229", - "whole", - weak_model_name="claude-3-5-haiku-20241022", - ), - ModelSettings( - "claude-3-5-sonnet-20240620", - "diff", - weak_model_name="claude-3-5-haiku-20241022", - editor_model_name="claude-3-5-sonnet-20240620", - editor_edit_format="editor-diff", - use_repo_map=True, - examples_as_sys_msg=True, - extra_params={ - "extra_headers": { - "anthropic-beta": ANTHROPIC_BETA_HEADER, - }, - "max_tokens": 8192, - }, - cache_control=True, - reminder="user", - ), - ModelSettings( - "anthropic/claude-3-5-sonnet-20240620", - "diff", - weak_model_name="anthropic/claude-3-5-haiku-20241022", - editor_model_name="anthropic/claude-3-5-sonnet-20240620", - editor_edit_format="editor-diff", - use_repo_map=True, - examples_as_sys_msg=True, - extra_params={ - "extra_headers": { - "anthropic-beta": ANTHROPIC_BETA_HEADER, - }, - "max_tokens": 8192, - }, - cache_control=True, - reminder="user", - ), - ModelSettings( - "anthropic/claude-3-5-sonnet-20241022", - "diff", - weak_model_name="anthropic/claude-3-5-haiku-20241022", - editor_model_name="anthropic/claude-3-5-sonnet-20241022", - editor_edit_format="editor-diff", - use_repo_map=True, - examples_as_sys_msg=True, - extra_params={ - "extra_headers": { - "anthropic-beta": ANTHROPIC_BETA_HEADER, - }, - "max_tokens": 8192, - }, - cache_control=True, - reminder="user", - ), - ModelSettings( - "bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0", - "diff", - weak_model_name="bedrock/anthropic.claude-3-5-haiku-20241022-v1:0", - editor_model_name="bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0", - editor_edit_format="editor-diff", - use_repo_map=True, - examples_as_sys_msg=True, - extra_params={ - "extra_headers": { - "anthropic-beta": ANTHROPIC_BETA_HEADER, - }, - "max_tokens": 8192, - }, - cache_control=True, - reminder="user", - ), - ModelSettings( - "anthropic/claude-3-5-sonnet-latest", - "diff", - weak_model_name="anthropic/claude-3-5-haiku-20241022", - editor_model_name="anthropic/claude-3-5-sonnet-20241022", - editor_edit_format="editor-diff", - use_repo_map=True, - examples_as_sys_msg=True, - extra_params={ - "extra_headers": { - "anthropic-beta": ANTHROPIC_BETA_HEADER, - }, - "max_tokens": 8192, - }, - cache_control=True, - reminder="user", - ), - ModelSettings( - "claude-3-5-sonnet-20241022", - "diff", - weak_model_name="claude-3-5-haiku-20241022", - editor_model_name="claude-3-5-sonnet-20241022", - editor_edit_format="editor-diff", - use_repo_map=True, - examples_as_sys_msg=True, - extra_params={ - "extra_headers": { - "anthropic-beta": ANTHROPIC_BETA_HEADER, - }, - "max_tokens": 8192, - }, - cache_control=True, - reminder="user", - ), - ModelSettings( - "anthropic/claude-3-haiku-20240307", - "whole", - weak_model_name="anthropic/claude-3-haiku-20240307", - examples_as_sys_msg=True, - extra_params={ - "extra_headers": { - "anthropic-beta": ANTHROPIC_BETA_HEADER, - }, - }, - cache_control=True, - ), - ModelSettings( - "anthropic/claude-3-5-haiku-20241022", - "diff", - weak_model_name="anthropic/claude-3-5-haiku-20241022", - use_repo_map=True, - extra_params={ - "extra_headers": { - "anthropic-beta": ANTHROPIC_BETA_HEADER, - }, - }, - cache_control=True, - ), - ModelSettings( - "bedrock/anthropic.claude-3-5-haiku-20241022-v1:0", - "diff", - weak_model_name="bedrock/anthropic.claude-3-5-haiku-20241022-v1:0", - use_repo_map=True, - extra_params={ - "extra_headers": { - "anthropic-beta": ANTHROPIC_BETA_HEADER, - }, - }, - cache_control=True, - ), - ModelSettings( - "claude-3-5-haiku-20241022", - "diff", - weak_model_name="claude-3-5-haiku-20241022", - use_repo_map=True, - examples_as_sys_msg=True, - extra_params={ - "extra_headers": { - "anthropic-beta": ANTHROPIC_BETA_HEADER, - }, - }, - cache_control=True, - ), - ModelSettings( - "vertex_ai/claude-3-5-haiku@20241022", - "diff", - weak_model_name="vertex_ai/claude-3-5-haiku@20241022", - use_repo_map=True, - extra_params={ - "max_tokens": 4096, - }, - ), - ModelSettings( - "claude-3-haiku-20240307", - "whole", - weak_model_name="claude-3-haiku-20240307", - examples_as_sys_msg=True, - extra_params={ - "extra_headers": { - "anthropic-beta": ANTHROPIC_BETA_HEADER, - }, - }, - cache_control=True, - ), - ModelSettings( - "openrouter/anthropic/claude-3.5-sonnet", - "diff", - weak_model_name="openrouter/anthropic/claude-3-5-haiku", - editor_model_name="openrouter/anthropic/claude-3.5-sonnet", - editor_edit_format="editor-diff", - use_repo_map=True, - examples_as_sys_msg=True, - extra_params={ - "max_tokens": 8192, - }, - reminder="user", - cache_control=True, - ), - ModelSettings( - "openrouter/anthropic/claude-3.5-sonnet:beta", - "diff", - weak_model_name="openrouter/anthropic/claude-3-5-haiku:beta", - editor_model_name="openrouter/anthropic/claude-3.5-sonnet:beta", - editor_edit_format="editor-diff", - use_repo_map=True, - examples_as_sys_msg=True, - extra_params={ - "max_tokens": 8192, - }, - reminder="user", - cache_control=True, - ), - # Vertex AI Claude models - # Does not yet support 8k token - ModelSettings( - "vertex_ai/claude-3-5-sonnet@20240620", - "diff", - weak_model_name="vertex_ai/claude-3-5-haiku@20241022", - editor_model_name="vertex_ai/claude-3-5-sonnet@20240620", - editor_edit_format="editor-diff", - use_repo_map=True, - examples_as_sys_msg=True, - extra_params={ - "max_tokens": 8192, - }, - reminder="user", - ), - ModelSettings( - "vertex_ai/claude-3-5-sonnet-v2@20241022", - "diff", - weak_model_name="vertex_ai/claude-3-5-haiku@20241022", - editor_model_name="vertex_ai/claude-3-5-sonnet-v2@20241022", - editor_edit_format="editor-diff", - use_repo_map=True, - examples_as_sys_msg=True, - extra_params={ - "max_tokens": 8192, - }, - reminder="user", - ), - ModelSettings( - "vertex_ai/claude-3-opus@20240229", - "diff", - weak_model_name="vertex_ai/claude-3-5-haiku@20241022", - use_repo_map=True, - ), - ModelSettings( - "vertex_ai/claude-3-sonnet@20240229", - "whole", - weak_model_name="vertex_ai/claude-3-5-haiku@20241022", - ), - # Cohere - ModelSettings( - "command-r-plus", - "whole", - weak_model_name="command-r-plus", - use_repo_map=True, - ), - # New Cohere models - ModelSettings( - "command-r-08-2024", - "whole", - weak_model_name="command-r-08-2024", - use_repo_map=True, - ), - ModelSettings( - "command-r-plus-08-2024", - "whole", - weak_model_name="command-r-plus-08-2024", - use_repo_map=True, - ), - # Groq llama3 - ModelSettings( - "groq/llama3-70b-8192", - "diff", - weak_model_name="groq/llama3-8b-8192", - use_repo_map=False, - send_undo_reply=False, - examples_as_sys_msg=True, - ), - # Openrouter llama3 - ModelSettings( - "openrouter/meta-llama/llama-3-70b-instruct", - "diff", - weak_model_name="openrouter/meta-llama/llama-3-70b-instruct", - use_repo_map=False, - send_undo_reply=False, - examples_as_sys_msg=True, - ), - # Gemini - ModelSettings( - "gemini/gemini-1.5-pro-002", - "diff", - use_repo_map=True, - ), - ModelSettings( - "gemini/gemini-1.5-flash-002", - "whole", - ), - ModelSettings( - "gemini/gemini-1.5-pro", - "diff-fenced", - use_repo_map=True, - ), - ModelSettings( - "gemini/gemini-1.5-pro-latest", - "diff-fenced", - use_repo_map=True, - ), - ModelSettings( - "gemini/gemini-1.5-pro-exp-0827", - "diff-fenced", - use_repo_map=True, - ), - ModelSettings( - "vertex_ai/gemini-pro-experimental", - "diff-fenced", - use_repo_map=True, - ), - ModelSettings( - "gemini/gemini-1.5-flash-exp-0827", - "whole", - use_repo_map=False, - send_undo_reply=False, - ), - ModelSettings( - "deepseek/deepseek-chat", - "diff", - use_repo_map=True, - examples_as_sys_msg=True, - reminder="sys", - extra_params={ - "max_tokens": 8192, - }, - ), - ModelSettings( - "deepseek/deepseek-coder", - "diff", - use_repo_map=True, - examples_as_sys_msg=True, - reminder="sys", - caches_by_default=True, - extra_params={ - "max_tokens": 8192, - }, - ), - ModelSettings( - "deepseek-chat", - "diff", - use_repo_map=True, - examples_as_sys_msg=True, - reminder="sys", - extra_params={ - "max_tokens": 8192, - }, - ), - ModelSettings( - "deepseek-coder", - "diff", - use_repo_map=True, - examples_as_sys_msg=True, - reminder="sys", - caches_by_default=True, - extra_params={ - "max_tokens": 8192, - }, - ), - ModelSettings( - "openrouter/deepseek/deepseek-coder", - "diff", - use_repo_map=True, - examples_as_sys_msg=True, - reminder="sys", - ), - ModelSettings( - "openrouter/openai/gpt-4o", - "diff", - weak_model_name="openrouter/openai/gpt-4o-mini", - use_repo_map=True, - lazy=True, - reminder="sys", - editor_edit_format="editor-diff", - ), - ModelSettings( - "openai/o1-mini", - "whole", - weak_model_name="openai/gpt-4o-mini", - editor_model_name="openai/gpt-4o", - editor_edit_format="editor-diff", - use_repo_map=True, - reminder="user", - use_system_prompt=False, - use_temperature=False, - ), - ModelSettings( - "azure/o1-mini", - "whole", - weak_model_name="azure/gpt-4o-mini", - editor_model_name="azure/gpt-4o", - editor_edit_format="editor-diff", - use_repo_map=True, - reminder="user", - use_system_prompt=False, - use_temperature=False, - ), - ModelSettings( - "o1-mini", - "whole", - weak_model_name="gpt-4o-mini", - editor_model_name="gpt-4o", - editor_edit_format="editor-diff", - use_repo_map=True, - reminder="user", - use_system_prompt=False, - use_temperature=False, - ), - ModelSettings( - "openai/o1-preview", - "diff", - weak_model_name="openai/gpt-4o-mini", - editor_model_name="openai/gpt-4o", - editor_edit_format="editor-diff", - use_repo_map=True, - reminder="user", - use_system_prompt=False, - use_temperature=False, - ), - ModelSettings( - "azure/o1-preview", - "diff", - weak_model_name="azure/gpt-4o-mini", - editor_model_name="azure/gpt-4o", - editor_edit_format="editor-diff", - use_repo_map=True, - reminder="user", - use_system_prompt=False, - use_temperature=False, - ), - ModelSettings( - "o1-preview", - "architect", - weak_model_name="gpt-4o-mini", - editor_model_name="gpt-4o", - editor_edit_format="editor-diff", - use_repo_map=True, - reminder="user", - use_system_prompt=False, - use_temperature=False, - ), - ModelSettings( - "openrouter/openai/o1-mini", - "whole", - weak_model_name="openrouter/openai/gpt-4o-mini", - editor_model_name="openrouter/openai/gpt-4o", - editor_edit_format="editor-diff", - use_repo_map=True, - reminder="user", - use_system_prompt=False, - use_temperature=False, - streaming=False, - ), - ModelSettings( - "openrouter/openai/o1-preview", - "diff", - weak_model_name="openrouter/openai/gpt-4o-mini", - editor_model_name="openrouter/openai/gpt-4o", - editor_edit_format="editor-diff", - use_repo_map=True, - reminder="user", - use_system_prompt=False, - use_temperature=False, - streaming=False, - ), - ModelSettings( - "openrouter/qwen/qwen-2.5-coder-32b-instruct", - "diff", - weak_model_name="openrouter/qwen/qwen-2.5-coder-32b-instruct", - editor_model_name="openrouter/qwen/qwen-2.5-coder-32b-instruct", - editor_edit_format="editor-diff", - use_repo_map=True, - ), -] +# Load model settings from package resource +MODEL_SETTINGS = [] +with importlib.resources.open_text("aider.resources", "model-settings.yml") as f: + model_settings_list = yaml.safe_load(f) + for model_settings_dict in model_settings_list: + MODEL_SETTINGS.append(ModelSettings(**model_settings_dict)) class ModelInfoManager: @@ -764,6 +136,7 @@ class ModelInfoManager: self.cache_dir = Path.home() / ".aider" / "caches" self.cache_file = self.cache_dir / "model_prices_and_context_window.json" self.content = None + self.local_model_metadata = {} self._load_cache() def _load_cache(self): @@ -796,6 +169,10 @@ class ModelInfoManager: pass def get_model_from_cached_json_db(self, model): + data = self.local_model_metadata.get(model) + if data: + return data + if not self.content: self._update_cache() @@ -858,10 +235,9 @@ class Model(ModelSettings): self.keys_in_environment = res.get("keys_in_environment") max_input_tokens = self.info.get("max_input_tokens") or 0 - if max_input_tokens < 32 * 1024: - self.max_chat_history_tokens = 1024 - else: - self.max_chat_history_tokens = 2 * 1024 + # Calculate max_chat_history_tokens as 1/16th of max_input_tokens, + # with minimum 1k and maximum 8k + self.max_chat_history_tokens = min(max(max_input_tokens / 16, 1024), 8192) self.configure_model_settings(model) if weak_model is False: @@ -915,6 +291,49 @@ class Model(ModelSettings): self.extra_params[key] = value def apply_generic_model_settings(self, model): + if "/o3-mini" in model: + self.edit_format = "diff" + self.use_repo_map = True + self.use_temperature = False + self.system_prompt_prefix = "Formatting re-enabled. " + return # <-- + + if "/o1-mini" in model: + self.use_repo_map = True + self.use_temperature = False + self.use_system_prompt = False + return # <-- + + if "/o1-preview" in model: + self.edit_format = "diff" + self.use_repo_map = True + self.use_temperature = False + self.use_system_prompt = False + return # <-- + + if "/o1" in model: + self.edit_format = "diff" + self.use_repo_map = True + self.use_temperature = False + self.streaming = False + self.system_prompt_prefix = "Formatting re-enabled. " + return # <-- + + if "deepseek" in model and "v3" in model: + self.edit_format = "diff" + self.use_repo_map = True + self.reminder = "sys" + self.examples_as_sys_msg = True + return # <-- + + if "deepseek" in model and ("r1" in model or "reasoning" in model): + self.edit_format = "diff" + self.use_repo_map = True + self.examples_as_sys_msg = True + self.use_temperature = False + self.remove_reasoning = "think" + return # <-- + if ("llama3" in model or "llama-3" in model) and "70b" in model: self.edit_format = "diff" self.use_repo_map = True @@ -959,8 +378,6 @@ class Model(ModelSettings): self.edit_format = "diff" self.editor_edit_format = "editor-diff" self.use_repo_map = True - if model.startswith("ollama/") or model.startswith("ollama_chat/"): - self.extra_params = dict(num_ctx=8 * 1024) return # <-- # use the defaults @@ -1082,14 +499,31 @@ class Model(ModelSettings): """Fast path for common models. Avoids forcing litellm import.""" model = self.name - if model in OPENAI_MODELS or model.startswith("openai/"): + + pieces = model.split("/") + if len(pieces) > 1: + provider = pieces[0] + else: + provider = None + + keymap = dict( + openrouter="OPENROUTER_API_KEY", + openai="OPENAI_API_KEY", + deepseek="DEEPSEEK_API_KEY", + gemini="GEMINI_API_KEY", + anthropic="ANTHROPIC_API_KEY", + groq="GROQ_API_KEY", + fireworks_ai="FIREWORKS_API_KEY", + ) + var = None + if model in OPENAI_MODELS: var = "OPENAI_API_KEY" - elif model in ANTHROPIC_MODELS or model.startswith("anthropic/"): + elif model in ANTHROPIC_MODELS: var = "ANTHROPIC_API_KEY" else: - return + var = keymap.get(provider) - if os.environ.get(var): + if var and os.environ.get(var): return dict(keys_in_environment=[var], missing_keys=[]) def validate_environment(self): @@ -1116,6 +550,113 @@ class Model(ModelSettings): return res + def get_repo_map_tokens(self): + map_tokens = 1024 + max_inp_tokens = self.info.get("max_input_tokens") + if max_inp_tokens: + map_tokens = max_inp_tokens / 8 + map_tokens = min(map_tokens, 4096) + map_tokens = max(map_tokens, 1024) + return map_tokens + + def is_deepseek_r1(self): + name = self.name.lower() + if "deepseek" not in name: + return + return "r1" in name or "reasoner" in name + + def is_ollama(self): + return self.name.startswith("ollama/") or self.name.startswith("ollama_chat/") + + def send_completion(self, messages, functions, stream, temperature=None): + if os.environ.get("AIDER_SANITY_CHECK_TURNS"): + sanity_check_messages(messages) + + if self.is_deepseek_r1(): + messages = ensure_alternating_roles(messages) + + kwargs = dict( + model=self.name, + messages=messages, + stream=stream, + ) + + if self.use_temperature is not False: + if temperature is None: + if isinstance(self.use_temperature, bool): + temperature = 0 + else: + temperature = float(self.use_temperature) + + kwargs["temperature"] = temperature + + if functions is not None: + function = functions[0] + kwargs["tools"] = [dict(type="function", function=function)] + kwargs["tool_choice"] = {"type": "function", "function": {"name": function["name"]}} + if self.extra_params: + kwargs.update(self.extra_params) + if self.is_ollama() and "num_ctx" not in kwargs: + num_ctx = int(self.token_count(messages) * 1.25) + 8192 + kwargs["num_ctx"] = num_ctx + key = json.dumps(kwargs, sort_keys=True).encode() + + # dump(kwargs) + + hash_object = hashlib.sha1(key) + if "timeout" not in kwargs: + kwargs["timeout"] = request_timeout + res = litellm.completion(**kwargs) + return hash_object, res + + def remove_reasoning_content(self, res): + if not self.remove_reasoning: + return res + + pattern = f"<{self.remove_reasoning}>.*?" + res = re.sub(pattern, "", res, flags=re.DOTALL).strip() + return res + + def simple_send_with_retries(self, messages): + from aider.exceptions import LiteLLMExceptions + + litellm_ex = LiteLLMExceptions() + if "deepseek-reasoner" in self.name: + messages = ensure_alternating_roles(messages) + retry_delay = 0.125 + + while True: + try: + kwargs = { + "messages": messages, + "functions": None, + "stream": False, + } + + _hash, response = self.send_completion(**kwargs) + if not response or not hasattr(response, "choices") or not response.choices: + return None + res = response.choices[0].message.content + return self.remove_reasoning_content(res) + + except litellm_ex.exceptions_tuple() as err: + ex_info = litellm_ex.get_ex_info(err) + print(str(err)) + if ex_info.description: + print(ex_info.description) + should_retry = ex_info.retry + if should_retry: + retry_delay *= 2 + if retry_delay > RETRY_TIMEOUT: + should_retry = False + if not should_retry: + return None + print(f"Retrying in {retry_delay:.1f} seconds...") + time.sleep(retry_delay) + continue + except AttributeError: + return None + def register_models(model_settings_fnames): files_loaded = [] @@ -1160,9 +701,8 @@ def register_litellm_models(model_fnames): if not model_def: continue - # only load litellm if we have actual data - litellm._load_litellm() - litellm.register_model(model_def) + # Defer registration with litellm to faster path. + model_info_manager.local_model_metadata.update(model_def) except Exception as e: raise Exception(f"Error loading model definition from {model_fname}: {e}") @@ -1210,10 +750,10 @@ def sanity_check_model(io, model): status = "Set" if value else "Not set" io.tool_output(f"- {key}: {status}") - if platform.system() == "Windows" or True: + if platform.system() == "Windows": io.tool_output( - "If you just set these environment variables using `setx` you may need to restart" - " your terminal or command prompt for the changes to take effect." + "Note: You may need to restart your terminal or command prompt for `setx` to take" + " effect." ) elif not model.keys_in_environment: @@ -1239,8 +779,8 @@ def fuzzy_match_models(name): name = name.lower() chat_models = set() - for model, attrs in litellm.model_cost.items(): - model = model.lower() + for orig_model, attrs in litellm.model_cost.items(): + model = orig_model.lower() if attrs.get("mode") != "chat": continue provider = attrs.get("litellm_provider", "").lower() @@ -1249,12 +789,12 @@ def fuzzy_match_models(name): provider += "/" if model.startswith(provider): - fq_model = model + fq_model = orig_model else: - fq_model = provider + model + fq_model = provider + orig_model chat_models.add(fq_model) - chat_models.add(model) + chat_models.add(orig_model) chat_models = sorted(chat_models) # exactly matching model @@ -1288,16 +828,38 @@ def print_matching_models(io, search): def get_model_settings_as_yaml(): + from dataclasses import fields + import yaml model_settings_list = [] - for ms in MODEL_SETTINGS: - model_settings_dict = { - field.name: getattr(ms, field.name) for field in fields(ModelSettings) - } - model_settings_list.append(model_settings_dict) + # Add default settings first with all field values + defaults = {} + for field in fields(ModelSettings): + defaults[field.name] = field.default + defaults["name"] = "(default values)" + model_settings_list.append(defaults) - return yaml.dump(model_settings_list, default_flow_style=False) + # Sort model settings by name + for ms in sorted(MODEL_SETTINGS, key=lambda x: x.name): + # Create dict with explicit field order + model_settings_dict = {} + for field in fields(ModelSettings): + value = getattr(ms, field.name) + if value != field.default: + model_settings_dict[field.name] = value + model_settings_list.append(model_settings_dict) + # Add blank line between entries + model_settings_list.append(None) + + # Filter out None values before dumping + yaml_str = yaml.dump( + [ms for ms in model_settings_list if ms is not None], + default_flow_style=False, + sort_keys=False, # Preserve field order from dataclass + ) + # Add actual blank lines between entries + return yaml_str.replace("\n- ", "\n\n- ") def main(): diff --git a/aider/queries/tree-sitter-hcl-tags.scm b/aider/queries/tree-sitter-hcl-tags.scm new file mode 100644 index 000000000..0e746cb2e --- /dev/null +++ b/aider/queries/tree-sitter-hcl-tags.scm @@ -0,0 +1,77 @@ +;; Based on https://github.com/tree-sitter-grammars/tree-sitter-hcl/blob/main/make_grammar.js +;; Which has Apache 2.0 License +;; tags.scm for Terraform (tree-sitter-hcl) + +; === Definitions: Terraform Blocks === +(block + (identifier) @block_type + (string_lit (template_literal) @resource_type) + (string_lit (template_literal) @name.definition.resource) + (body) @definition.resource +) (#eq? @block_type "resource") + +(block + (identifier) @block_type + (string_lit (template_literal) @name.definition.module) + (body) @definition.module +) (#eq? @block_type "module") + +(block + (identifier) @block_type + (string_lit (template_literal) @name.definition.variable) + (body) @definition.variable +) (#eq? @block_type "variable") + +(block + (identifier) @block_type + (string_lit (template_literal) @name.definition.output) + (body) @definition.output +) (#eq? @block_type "output") + +(block + (identifier) @block_type + (string_lit (template_literal) @name.definition.provider) + (body) @definition.provider +) (#eq? @block_type "provider") + +(block + (identifier) @block_type + (body + (attribute + (identifier) @name.definition.local + (expression) @definition.local + )+ + ) +) (#eq? @block_type "locals") + +; === References: Variables, Locals, Modules, Data, Resources === +((variable_expr) @ref_type + (get_attr (identifier) @name.reference.variable) +) @reference.variable + (#eq? @ref_type "var") + +((variable_expr) @ref_type + (get_attr (identifier) @name.reference.local) +) @reference.local + (#eq? @ref_type "local") + +((variable_expr) @ref_type + (get_attr (identifier) @name.reference.module) +) @reference.module + (#eq? @ref_type "module") + +((variable_expr) @ref_type + (get_attr (identifier) @data_source_type) + (get_attr (identifier) @name.reference.data) +) @reference.data + (#eq? @ref_type "data") + +((variable_expr) @resource_type + (get_attr (identifier) @name.reference.resource) +) @reference.resource + (#not-eq? @resource_type "var") + (#not-eq? @resource_type "local") + (#not-eq? @resource_type "module") + (#not-eq? @resource_type "data") + (#not-eq? @resource_type "provider") + (#not-eq? @resource_type "output") diff --git a/aider/queries/tree-sitter-kotlin-tags.scm b/aider/queries/tree-sitter-kotlin-tags.scm new file mode 100644 index 000000000..9770a4c0e --- /dev/null +++ b/aider/queries/tree-sitter-kotlin-tags.scm @@ -0,0 +1,27 @@ +; Definitions + +(class_declaration + (type_identifier) @name.definition.class) @definition.class + +(function_declaration + (simple_identifier) @name.definition.function) @definition.function + +(object_declaration + (type_identifier) @name.definition.object) @definition.object + +; References + +(call_expression + [ + (simple_identifier) @name.reference.call + (navigation_expression + (navigation_suffix + (simple_identifier) @name.reference.call)) + ]) @reference.call + +(delegation_specifier + [ + (user_type) @name.reference.type + (constructor_invocation + (user_type) @name.reference.type) + ]) @reference.type diff --git a/aider/repo.py b/aider/repo.py index 3445a1848..a46a9f412 100644 --- a/aider/repo.py +++ b/aider/repo.py @@ -2,23 +2,35 @@ import os import time from pathlib import Path, PurePosixPath -import git +try: + import git + + ANY_GIT_ERROR = [ + git.exc.ODBError, + git.exc.GitError, + git.exc.InvalidGitRepositoryError, + ] +except ImportError: + git = None + ANY_GIT_ERROR = [] + import pathspec from aider import prompts, utils -from aider.sendchat import simple_send_with_retries from .dump import dump # noqa: F401 -ANY_GIT_ERROR = ( - git.exc.ODBError, - git.exc.GitError, +ANY_GIT_ERROR += [ OSError, IndexError, BufferError, TypeError, ValueError, -) + AttributeError, + AssertionError, + TimeoutError, +] +ANY_GIT_ERROR = tuple(ANY_GIT_ERROR) class GitRepo: @@ -141,7 +153,7 @@ class GitRepo: os.environ["GIT_COMMITTER_NAME"] = committer_name if aider_edits and self.attribute_author: - original_auther_name_env = os.environ.get("GIT_AUTHOR_NAME") + original_author_name_env = os.environ.get("GIT_AUTHOR_NAME") os.environ["GIT_AUTHOR_NAME"] = committer_name try: @@ -161,8 +173,8 @@ class GitRepo: del os.environ["GIT_COMMITTER_NAME"] if aider_edits and self.attribute_author: - if original_auther_name_env is not None: - os.environ["GIT_AUTHOR_NAME"] = original_auther_name_env + if original_author_name_env is not None: + os.environ["GIT_AUTHOR_NAME"] = original_author_name_env else: del os.environ["GIT_AUTHOR_NAME"] @@ -192,9 +204,7 @@ class GitRepo: max_tokens = model.info.get("max_input_tokens") or 0 if max_tokens and num_tokens > max_tokens: continue - commit_message = simple_send_with_retries( - model.name, messages, extra_params=model.extra_params - ) + commit_message = model.simple_send_with_retries(messages) if commit_message: break @@ -278,9 +288,17 @@ class GitRepo: files = self.tree_files[commit] else: try: - for blob in commit.tree.traverse(): - if blob.type == "blob": # blob is a file - files.add(blob.path) + iterator = commit.tree.traverse() + while True: + try: + blob = next(iterator) + if blob.type == "blob": # blob is a file + files.add(blob.path) + except IndexError: + self.io.tool_warning(f"GitRepo: read error skipping {blob.path}") + continue + except StopIteration: + break except ANY_GIT_ERROR as err: self.git_repo_error = err self.io.tool_error(f"Unable to list files in git repo: {err}") @@ -352,8 +370,8 @@ class GitRepo: def ignored_file_raw(self, fname): if self.subtree_only: - fname_path = Path(self.normalize_path(fname)) try: + fname_path = Path(self.normalize_path(fname)) cwd_path = Path.cwd().resolve().relative_to(Path(self.root).resolve()) except ValueError: # Issue #1524 diff --git a/aider/repomap.py b/aider/repomap.py index 5c9707565..cfc20f9a1 100644 --- a/aider/repomap.py +++ b/aider/repomap.py @@ -608,7 +608,7 @@ class RepoMap: self.tree_cache = dict() - middle = min(max_map_tokens // 25, num_tags) + middle = min(int(max_map_tokens // 25), num_tags) while lower_bound <= upper_bound: # dump(lower_bound, middle, upper_bound) @@ -631,7 +631,7 @@ class RepoMap: else: upper_bound = middle - 1 - middle = (lower_bound + upper_bound) // 2 + middle = int((lower_bound + upper_bound) // 2) spin.end() return best_tree diff --git a/aider/resources/model-metadata.json b/aider/resources/model-metadata.json index e69de29bb..1057ee581 100644 --- a/aider/resources/model-metadata.json +++ b/aider/resources/model-metadata.json @@ -0,0 +1,118 @@ +{ + "deepseek-reasoner": { + "max_tokens": 8192, + "max_input_tokens": 64000, + "max_output_tokens": 8192, + "input_cost_per_token": 0.00000055, + "input_cost_per_token_cache_hit": 0.00000014, + "cache_read_input_token_cost": 0.00000014, + "cache_creation_input_token_cost": 0.0, + "output_cost_per_token": 0.00000219, + "litellm_provider": "deepseek", + "mode": "chat", + //"supports_function_calling": true, + "supports_assistant_prefill": true, + //"supports_tool_choice": true, + "supports_prompt_caching": true + }, + "openrouter/deepseek/deepseek-r1": { + "max_tokens": 8192, + "max_input_tokens": 64000, + "max_output_tokens": 8192, + "input_cost_per_token": 0.00000055, + "input_cost_per_token_cache_hit": 0.00000014, + "cache_read_input_token_cost": 0.00000014, + "cache_creation_input_token_cost": 0.0, + "output_cost_per_token": 0.00000219, + "litellm_provider": "openrouter", + "mode": "chat", + //"supports_function_calling": true, + "supports_assistant_prefill": true, + //"supports_tool_choice": true, + "supports_prompt_caching": true + }, + "openrouter/deepseek/deepseek-r1:free": { + "max_tokens": 8192, + "max_input_tokens": 64000, + "max_output_tokens": 8192, + "input_cost_per_token": 0.0, + "input_cost_per_token_cache_hit": 0.0, + "cache_read_input_token_cost": 0.00, + "cache_creation_input_token_cost": 0.0, + "output_cost_per_token": 0.0, + "litellm_provider": "openrouter", + "mode": "chat", + //"supports_function_calling": true, + "supports_assistant_prefill": true, + //"supports_tool_choice": true, + "supports_prompt_caching": true + }, + "fireworks_ai/accounts/fireworks/models/deepseek-r1": { + "max_tokens": 160000, + "max_input_tokens": 128000, + "max_output_tokens": 20480, + "litellm_provider": "fireworks_ai", + "input_cost_per_token": 0.000008, + "output_cost_per_token": 0.000008, + "mode": "chat", + }, + "fireworks_ai/accounts/fireworks/models/deepseek-v3": { + "max_tokens": 128000, + "max_input_tokens": 100000, + "max_output_tokens": 8192, + "litellm_provider": "fireworks_ai", + "input_cost_per_token": 0.0000009, + "output_cost_per_token": 0.0000009, + "mode": "chat", + }, + "o3-mini": { + "max_tokens": 100000, + "max_input_tokens": 200000, + "max_output_tokens": 100000, + "input_cost_per_token": 0.0000011, + "output_cost_per_token": 0.0000044, + "cache_read_input_token_cost": 0.00000055, + "litellm_provider": "openai", + "mode": "chat", + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_vision": true, + "supports_prompt_caching": true, + "supports_system_messages": true, + "supports_response_schema": true + }, + "openrouter/openai/o3-mini": { + "max_tokens": 100000, + "max_input_tokens": 200000, + "max_output_tokens": 100000, + "input_cost_per_token": 0.0000011, + "output_cost_per_token": 0.0000044, + "cache_read_input_token_cost": 0.00000055, + "litellm_provider": "openrouter", + "mode": "chat", + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_vision": true, + "supports_prompt_caching": true, + "supports_system_messages": true, + "supports_response_schema": true + }, + "openrouter/openai/gpt-4o-mini": { + "max_tokens": 16384, + "max_input_tokens": 128000, + "max_output_tokens": 16384, + "input_cost_per_token": 0.00000015, + "output_cost_per_token": 0.00000060, + "input_cost_per_token_batches": 0.000000075, + "output_cost_per_token_batches": 0.00000030, + "cache_read_input_token_cost": 0.000000075, + "litellm_provider": "openrouter", + "mode": "chat", + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_response_schema": true, + "supports_vision": true, + "supports_prompt_caching": true, + "supports_system_messages": true + }, +} diff --git a/aider/resources/model-settings.yml b/aider/resources/model-settings.yml new file mode 100644 index 000000000..8a314c86a --- /dev/null +++ b/aider/resources/model-settings.yml @@ -0,0 +1,669 @@ +- name: gpt-3.5-turbo + weak_model_name: gpt-4o-mini + reminder: sys + +- name: gpt-3.5-turbo-0125 + weak_model_name: gpt-4o-mini + reminder: sys + +- name: gpt-3.5-turbo-1106 + weak_model_name: gpt-4o-mini + reminder: sys + +- name: gpt-3.5-turbo-0613 + weak_model_name: gpt-4o-mini + reminder: sys + +- name: gpt-3.5-turbo-16k-0613 + weak_model_name: gpt-4o-mini + reminder: sys + +- name: gpt-4-turbo-2024-04-09 + edit_format: udiff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + +- name: gpt-4-turbo + edit_format: udiff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + +- name: openai/gpt-4o + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + editor_edit_format: editor-diff + +- name: openai/gpt-4o-2024-08-06 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + +- name: gpt-4o-2024-08-06 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + +- name: gpt-4o-2024-11-20 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + +- name: openai/gpt-4o-2024-11-20 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + +- name: gpt-4o + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + editor_edit_format: editor-diff + +- name: gpt-4o-mini + weak_model_name: gpt-4o-mini + lazy: true + reminder: sys + +- name: openai/gpt-4o-mini + weak_model_name: openai/gpt-4o-mini + lazy: true + reminder: sys + +- name: gpt-4-0125-preview + edit_format: udiff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + +- name: gpt-4-1106-preview + edit_format: udiff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + +- name: gpt-4-vision-preview + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + reminder: sys + +- name: gpt-4-0314 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + +- name: gpt-4-0613 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + reminder: sys + +- name: gpt-4-32k-0613 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + reminder: sys + +- name: claude-3-opus-20240229 + edit_format: diff + weak_model_name: claude-3-5-haiku-20241022 + use_repo_map: true + +- name: openrouter/anthropic/claude-3-opus + edit_format: diff + weak_model_name: openrouter/anthropic/claude-3-5-haiku + use_repo_map: true + +- name: claude-3-sonnet-20240229 + weak_model_name: claude-3-5-haiku-20241022 + +- name: claude-3-5-sonnet-20240620 + edit_format: diff + weak_model_name: claude-3-5-haiku-20241022 + use_repo_map: true + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + max_tokens: 8192 + cache_control: true + editor_model_name: claude-3-5-sonnet-20240620 + editor_edit_format: editor-diff + +- name: anthropic/claude-3-5-sonnet-20240620 + edit_format: diff + weak_model_name: anthropic/claude-3-5-haiku-20241022 + use_repo_map: true + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + max_tokens: 8192 + cache_control: true + editor_model_name: anthropic/claude-3-5-sonnet-20240620 + editor_edit_format: editor-diff + +- name: anthropic/claude-3-5-sonnet-20241022 + edit_format: diff + weak_model_name: anthropic/claude-3-5-haiku-20241022 + use_repo_map: true + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + max_tokens: 8192 + cache_control: true + editor_model_name: anthropic/claude-3-5-sonnet-20241022 + editor_edit_format: editor-diff + +- name: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0 + edit_format: diff + weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0 + use_repo_map: true + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + max_tokens: 8192 + cache_control: true + editor_model_name: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0 + editor_edit_format: editor-diff + +- name: anthropic/claude-3-5-sonnet-latest + edit_format: diff + weak_model_name: anthropic/claude-3-5-haiku-20241022 + use_repo_map: true + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + max_tokens: 8192 + cache_control: true + editor_model_name: anthropic/claude-3-5-sonnet-20241022 + editor_edit_format: editor-diff + +- name: claude-3-5-sonnet-20241022 + edit_format: diff + weak_model_name: claude-3-5-haiku-20241022 + use_repo_map: true + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + max_tokens: 8192 + cache_control: true + editor_model_name: claude-3-5-sonnet-20241022 + editor_edit_format: editor-diff + +- name: anthropic/claude-3-haiku-20240307 + weak_model_name: anthropic/claude-3-haiku-20240307 + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + cache_control: true + +- name: anthropic/claude-3-5-haiku-20241022 + edit_format: diff + weak_model_name: anthropic/claude-3-5-haiku-20241022 + use_repo_map: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + cache_control: true + +- name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0 + edit_format: diff + weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0 + use_repo_map: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + cache_control: true + +- name: claude-3-5-haiku-20241022 + edit_format: diff + weak_model_name: claude-3-5-haiku-20241022 + use_repo_map: true + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + cache_control: true + +- name: vertex_ai/claude-3-5-haiku@20241022 + edit_format: diff + weak_model_name: vertex_ai/claude-3-5-haiku@20241022 + use_repo_map: true + extra_params: + max_tokens: 4096 + +- name: claude-3-haiku-20240307 + weak_model_name: claude-3-haiku-20240307 + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + cache_control: true + +- name: openrouter/anthropic/claude-3.5-sonnet + edit_format: diff + weak_model_name: openrouter/anthropic/claude-3-5-haiku + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + cache_control: true + editor_model_name: openrouter/anthropic/claude-3.5-sonnet + editor_edit_format: editor-diff + +- name: openrouter/anthropic/claude-3.5-sonnet:beta + edit_format: diff + weak_model_name: openrouter/anthropic/claude-3-5-haiku:beta + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + cache_control: true + editor_model_name: openrouter/anthropic/claude-3.5-sonnet:beta + editor_edit_format: editor-diff + +- name: vertex_ai/claude-3-5-sonnet@20240620 + edit_format: diff + weak_model_name: vertex_ai/claude-3-5-haiku@20241022 + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + editor_model_name: vertex_ai/claude-3-5-sonnet@20240620 + editor_edit_format: editor-diff + +- name: vertex_ai/claude-3-5-sonnet-v2@20241022 + edit_format: diff + weak_model_name: vertex_ai/claude-3-5-haiku@20241022 + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + editor_model_name: vertex_ai/claude-3-5-sonnet-v2@20241022 + editor_edit_format: editor-diff + +- name: vertex_ai/claude-3-opus@20240229 + edit_format: diff + weak_model_name: vertex_ai/claude-3-5-haiku@20241022 + use_repo_map: true + +- name: vertex_ai/claude-3-sonnet@20240229 + weak_model_name: vertex_ai/claude-3-5-haiku@20241022 + +- name: command-r-plus + weak_model_name: command-r-plus + use_repo_map: true + +- name: command-r-08-2024 + weak_model_name: command-r-08-2024 + use_repo_map: true + +- name: command-r-plus-08-2024 + weak_model_name: command-r-plus-08-2024 + use_repo_map: true + +- name: groq/llama3-70b-8192 + edit_format: diff + weak_model_name: groq/llama3-8b-8192 + examples_as_sys_msg: true + +- name: openrouter/meta-llama/llama-3-70b-instruct + edit_format: diff + weak_model_name: openrouter/meta-llama/llama-3-70b-instruct + examples_as_sys_msg: true + +- name: gemini/gemini-1.5-pro-002 + edit_format: diff + use_repo_map: true + +- name: gemini/gemini-1.5-flash-002 + +- name: gemini/gemini-1.5-pro + edit_format: diff-fenced + use_repo_map: true + +- name: gemini/gemini-1.5-pro-latest + edit_format: diff-fenced + use_repo_map: true + +- name: gemini/gemini-1.5-pro-exp-0827 + edit_format: diff-fenced + use_repo_map: true + +- name: gemini/gemini-exp-1206 + edit_format: diff + use_repo_map: true + +- name: gemini/gemini-exp-1114 + edit_format: diff + use_repo_map: true + +- name: gemini/gemini-exp-1121 + edit_format: diff + use_repo_map: true + +- name: vertex_ai/gemini-pro-experimental + edit_format: diff-fenced + use_repo_map: true + +- name: gemini/gemini-1.5-flash-exp-0827 + +- name: gemini/gemini-2.0-flash-exp + edit_format: diff + use_repo_map: true + +- name: gemini/gemini-2.0-flash + edit_format: diff + use_repo_map: true + +- name: openrouter/deepseek/deepseek-r1 + edit_format: diff + weak_model_name: openrouter/deepseek/deepseek-chat + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + use_temperature: false + editor_model_name: openrouter/deepseek/deepseek-chat + editor_edit_format: editor-diff + +- name: openrouter/deepseek/deepseek-r1:free + edit_format: diff + weak_model_name: openrouter/deepseek/deepseek-r1:free + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + use_temperature: false + editor_model_name: openrouter/deepseek/deepseek-r1:free + editor_edit_format: editor-diff + +- name: deepseek/deepseek-reasoner + edit_format: diff + weak_model_name: deepseek/deepseek-chat + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + use_temperature: false + editor_model_name: deepseek/deepseek-chat + editor_edit_format: editor-diff + +- name: deepseek/deepseek-chat + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + +- name: deepseek/deepseek-coder + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + +- name: deepseek-chat + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + +- name: deepseek-coder + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + +- name: openrouter/deepseek/deepseek-coder + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + +- name: openrouter/deepseek/deepseek-chat + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + +- name: openrouter/openai/gpt-4o + edit_format: diff + weak_model_name: openrouter/openai/gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + editor_edit_format: editor-diff + +- name: openai/o1-mini + weak_model_name: openai/gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + editor_model_name: openai/gpt-4o + editor_edit_format: editor-diff + +- name: azure/o1-mini + weak_model_name: azure/gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + editor_model_name: azure/gpt-4o + editor_edit_format: editor-diff + +- name: o1-mini + weak_model_name: gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + editor_model_name: gpt-4o + editor_edit_format: editor-diff + +- name: openai/o1-preview + edit_format: diff + weak_model_name: openai/gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + editor_model_name: openai/gpt-4o + editor_edit_format: editor-diff + +- name: azure/o1-preview + edit_format: diff + weak_model_name: azure/gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + editor_model_name: azure/gpt-4o + editor_edit_format: editor-diff + +- name: azure/o1 + edit_format: diff + weak_model_name: azure/gpt-4o-mini + use_repo_map: true + use_temperature: false + streaming: false + editor_model_name: azure/gpt-4o + editor_edit_format: editor-diff + +- name: o1-preview + edit_format: architect + weak_model_name: gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + editor_model_name: gpt-4o + editor_edit_format: editor-diff + +- name: openrouter/openai/o1-mini + weak_model_name: openrouter/openai/gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + streaming: false + editor_model_name: openrouter/openai/gpt-4o + editor_edit_format: editor-diff + +- name: openrouter/openai/o1-preview + edit_format: diff + weak_model_name: openrouter/openai/gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + streaming: false + editor_model_name: openrouter/openai/gpt-4o + editor_edit_format: editor-diff + +- name: openrouter/openai/o1 + edit_format: diff + weak_model_name: openrouter/openai/gpt-4o-mini + use_repo_map: true + use_temperature: false + streaming: false + editor_model_name: openrouter/openai/gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: "Formatting re-enabled. " + +- name: openai/o1 + edit_format: diff + weak_model_name: openai/gpt-4o-mini + use_repo_map: true + use_temperature: false + streaming: false + editor_model_name: openai/gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: "Formatting re-enabled. " + +- name: o1 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + use_temperature: false + streaming: false + editor_model_name: gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: "Formatting re-enabled. " + +- name: openrouter/qwen/qwen-2.5-coder-32b-instruct + edit_format: diff + weak_model_name: openrouter/qwen/qwen-2.5-coder-32b-instruct + use_repo_map: true + editor_model_name: openrouter/qwen/qwen-2.5-coder-32b-instruct + editor_edit_format: editor-diff + +- name: openrouter/deepseek/deepseek-r1-distill-llama-70b + edit_format: diff + weak_model_name: openrouter/deepseek/deepseek-chat + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + use_temperature: false + editor_model_name: openrouter/deepseek/deepseek-chat + editor_edit_format: editor-diff + +- name: fireworks_ai/accounts/fireworks/models/deepseek-r1 + edit_format: diff + weak_model_name: fireworks_ai/accounts/fireworks/models/deepseek-v3 + use_repo_map: true + use_temperature: false + streaming: true + editor_model_name: fireworks_ai/accounts/fireworks/models/deepseek-v3 + editor_edit_format: editor-diff + remove_reasoning: think + extra_params: + max_tokens: 160000 + +- name: fireworks_ai/accounts/fireworks/models/deepseek-v3 + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + extra_params: + max_tokens: 128000 + +- name: openai/o3-mini + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + use_temperature: false + editor_model_name: gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: "Formatting re-enabled. " + +- name: o3-mini + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + use_temperature: false + editor_model_name: gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: "Formatting re-enabled. " + +- name: openrouter/openai/o3-mini + edit_format: diff + weak_model_name: openrouter/openai/gpt-4o-mini + use_repo_map: true + use_temperature: false + editor_model_name: openrouter/openai/gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: "Formatting re-enabled. " + +- name: azure/o3-mini + edit_format: diff + weak_model_name: azure/gpt-4o-mini + use_repo_map: true + use_temperature: false + editor_model_name: azure/gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: "Formatting re-enabled. " + + \ No newline at end of file diff --git a/aider/run_cmd.py b/aider/run_cmd.py index 69d5bd7c6..f201b41dc 100644 --- a/aider/run_cmd.py +++ b/aider/run_cmd.py @@ -39,7 +39,7 @@ def get_windows_parent_process_name(): return None -def run_cmd_subprocess(command, verbose=False, cwd=None): +def run_cmd_subprocess(command, verbose=False, cwd=None, encoding=sys.stdout.encoding): if verbose: print("Using run_cmd_subprocess:", command) @@ -65,7 +65,7 @@ def run_cmd_subprocess(command, verbose=False, cwd=None): stderr=subprocess.STDOUT, text=True, shell=True, - encoding=sys.stdout.encoding, + encoding=encoding, errors="replace", bufsize=0, # Set bufsize to 0 for unbuffered output universal_newlines=True, @@ -113,7 +113,7 @@ def run_cmd_pexpect(command, verbose=False, cwd=None): # Use the shell from SHELL environment variable if verbose: print("Running pexpect.spawn with shell:", shell) - child = pexpect.spawn(shell, args=["-c", command], encoding="utf-8", cwd=cwd) + child = pexpect.spawn(shell, args=["-i", "-c", command], encoding="utf-8", cwd=cwd) else: # Fall back to spawning the command directly if verbose: diff --git a/aider/sendchat.py b/aider/sendchat.py index 3d1224bc6..3f06cbfb9 100644 --- a/aider/sendchat.py +++ b/aider/sendchat.py @@ -1,97 +1,61 @@ -import hashlib -import json -import time - from aider.dump import dump # noqa: F401 -from aider.exceptions import LiteLLMExceptions -from aider.llm import litellm - -# from diskcache import Cache +from aider.utils import format_messages -CACHE_PATH = "~/.aider.send.cache.v1" -CACHE = None -# CACHE = Cache(CACHE_PATH) +def sanity_check_messages(messages): + """Check if messages alternate between user and assistant roles. + System messages can be interspersed anywhere. + Also verifies the last non-system message is from the user. + Returns True if valid, False otherwise.""" + last_role = None + last_non_system_role = None -RETRY_TIMEOUT = 60 - - -def send_completion( - model_name, - messages, - functions, - stream, - temperature=0, - extra_params=None, -): - kwargs = dict( - model=model_name, - messages=messages, - stream=stream, - ) - if temperature is not None: - kwargs["temperature"] = temperature - - if functions is not None: - function = functions[0] - kwargs["tools"] = [dict(type="function", function=function)] - kwargs["tool_choice"] = {"type": "function", "function": {"name": function["name"]}} - - if extra_params is not None: - kwargs.update(extra_params) - - key = json.dumps(kwargs, sort_keys=True).encode() - - # Generate SHA1 hash of kwargs and append it to chat_completion_call_hashes - hash_object = hashlib.sha1(key) - - if not stream and CACHE is not None and key in CACHE: - return hash_object, CACHE[key] - - res = litellm.completion(**kwargs) - - if not stream and CACHE is not None: - CACHE[key] = res - - return hash_object, res - - -def simple_send_with_retries(model_name, messages, extra_params=None): - litellm_ex = LiteLLMExceptions() - - retry_delay = 0.125 - while True: - try: - kwargs = { - "model_name": model_name, - "messages": messages, - "functions": None, - "stream": False, - "extra_params": extra_params, - } - - _hash, response = send_completion(**kwargs) - if not response or not hasattr(response, "choices") or not response.choices: - return None - return response.choices[0].message.content - except litellm_ex.exceptions_tuple() as err: - ex_info = litellm_ex.get_ex_info(err) - - print(str(err)) - if ex_info.description: - print(ex_info.description) - - should_retry = ex_info.retry - if should_retry: - retry_delay *= 2 - if retry_delay > RETRY_TIMEOUT: - should_retry = False - - if not should_retry: - return None - - print(f"Retrying in {retry_delay:.1f} seconds...") - time.sleep(retry_delay) + for msg in messages: + role = msg.get("role") + if role == "system": continue - except AttributeError: - return None + + if last_role and role == last_role: + turns = format_messages(messages) + raise ValueError("Messages don't properly alternate user/assistant:\n\n" + turns) + + last_role = role + last_non_system_role = role + + # Ensure last non-system message is from user + return last_non_system_role == "user" + + +def ensure_alternating_roles(messages): + """Ensure messages alternate between 'assistant' and 'user' roles. + + Inserts empty messages of the opposite role when consecutive messages + of the same role are found. + + Args: + messages: List of message dictionaries with 'role' and 'content' keys. + + Returns: + List of messages with alternating roles. + """ + if not messages: + return messages + + fixed_messages = [] + prev_role = None + + for msg in messages: + current_role = msg.get("role") # Get 'role', None if missing + + # If current role same as previous, insert empty message + # of the opposite role + if current_role == prev_role: + if current_role == "user": + fixed_messages.append({"role": "assistant", "content": ""}) + else: + fixed_messages.append({"role": "user", "content": ""}) + + fixed_messages.append(msg) + prev_role = current_role + + return fixed_messages diff --git a/aider/urls.py b/aider/urls.py index 81c3558e8..cff92e36d 100644 --- a/aider/urls.py +++ b/aider/urls.py @@ -14,3 +14,4 @@ install_properly = "https://aider.chat/docs/troubleshooting/imports.html" analytics = "https://aider.chat/docs/more/analytics.html" release_notes = "https://aider.chat/HISTORY.html#release-notes" edit_formats = "https://aider.chat/docs/more/edit-formats.html" +models_and_keys = "https://aider.chat/docs/troubleshooting/models-and-keys.html" diff --git a/aider/utils.py b/aider/utils.py index e91e5deb0..322a44316 100644 --- a/aider/utils.py +++ b/aider/utils.py @@ -2,15 +2,12 @@ import itertools import os import platform import shlex -import shutil import subprocess import sys import tempfile import time from pathlib import Path -import git - from aider.dump import dump # noqa: F401 IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".webp", ".pdf"} @@ -74,6 +71,8 @@ class GitTemporaryDirectory(ChdirTemporaryDirectory): def make_repo(path=None): + import git + if not path: path = "." repo = git.Repo.init(path) @@ -113,7 +112,7 @@ def format_messages(messages, title=None): output.append(f"{title.upper()} {'*' * 50}") for msg in messages: - output.append("") + output.append("-------") role = msg["role"].upper() content = msg.get("content") if isinstance(content, list): # Handle list content (e.g., image messages) @@ -194,25 +193,9 @@ def split_chat_history_markdown(text, include_tool=False): return messages -# Copied from pip, MIT license -# https://github.com/pypa/pip/blob/b989e6ef04810bbd4033a3683020bd4ddcbdb627/src/pip/_internal/utils/entrypoints.py#L73 -def get_best_invocation_for_this_python() -> str: - """Try to figure out the best way to invoke the current Python.""" - exe = sys.executable - exe_name = os.path.basename(exe) - - # Try to use the basename, if it's the first executable. - found_executable = shutil.which(exe_name) - if found_executable and os.path.samefile(found_executable, exe): - return exe_name - - # Use the full executable name, because we couldn't find something simpler. - return exe - - def get_pip_install(args): cmd = [ - get_best_invocation_for_this_python(), + sys.executable, "-m", "pip", "install", @@ -268,7 +251,8 @@ def run_install(cmd): class Spinner: - spinner_chars = itertools.cycle(["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]) + unicode_spinner = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"] + ascii_spinner = ["|", "/", "-", "\\"] def __init__(self, text): self.text = text @@ -276,6 +260,20 @@ class Spinner: self.last_update = 0 self.visible = False self.is_tty = sys.stdout.isatty() + self.tested = False + + def test_charset(self): + if self.tested: + return + self.tested = True + # Try unicode first, fall back to ascii if needed + try: + # Test if we can print unicode characters + print(self.unicode_spinner[0], end="", flush=True) + print("\r", end="", flush=True) + self.spinner_chars = itertools.cycle(self.unicode_spinner) + except UnicodeEncodeError: + self.spinner_chars = itertools.cycle(self.ascii_spinner) def step(self): if not self.is_tty: @@ -293,6 +291,7 @@ class Spinner: if not self.visible: return + self.test_charset() print(f"\r{self.text} {next(self.spinner_chars)}\r{self.text} ", end="", flush=True) def end(self): @@ -301,12 +300,15 @@ class Spinner: def find_common_root(abs_fnames): - if len(abs_fnames) == 1: - return safe_abs_path(os.path.dirname(list(abs_fnames)[0])) - elif abs_fnames: - return safe_abs_path(os.path.commonpath(list(abs_fnames))) - else: - return safe_abs_path(os.getcwd()) + try: + if len(abs_fnames) == 1: + return safe_abs_path(os.path.dirname(list(abs_fnames)[0])) + elif abs_fnames: + return safe_abs_path(os.path.commonpath(list(abs_fnames))) + except OSError: + pass + + return safe_abs_path(os.getcwd()) def format_tokens(count): @@ -382,3 +384,15 @@ def printable_shell_command(cmd_list): return subprocess.list2cmdline(cmd_list) else: return shlex.join(cmd_list) + + +def main(): + spinner = Spinner("Running spinner...") + for _ in range(40): # 40 steps * 0.25 seconds = 10 seconds + time.sleep(0.25) + spinner.step() + spinner.end() + + +if __name__ == "__main__": + main() diff --git a/aider/voice.py b/aider/voice.py index 47fb49c6e..c9af7ae99 100644 --- a/aider/voice.py +++ b/aider/voice.py @@ -14,8 +14,11 @@ from .dump import dump # noqa: F401 warnings.filterwarnings( "ignore", message="Couldn't find ffmpeg or avconv - defaulting to ffmpeg, but may not work" ) +warnings.filterwarnings("ignore", category=SyntaxWarning) + from pydub import AudioSegment # noqa +from pydub.exceptions import CouldntDecodeError, CouldntEncodeError # noqa try: import soundfile as sf @@ -34,7 +37,7 @@ class Voice: threshold = 0.15 - def __init__(self, audio_format="wav"): + def __init__(self, audio_format="wav", device_name=None): if sf is None: raise SoundDeviceError try: @@ -42,6 +45,29 @@ class Voice: import sounddevice as sd self.sd = sd + + devices = sd.query_devices() + + if device_name: + # Find the device with matching name + device_id = None + for i, device in enumerate(devices): + if device_name in device["name"]: + device_id = i + break + if device_id is None: + available_inputs = [d["name"] for d in devices if d["max_input_channels"] > 0] + raise ValueError( + f"Device '{device_name}' not found. Available input devices:" + f" {available_inputs}" + ) + + print(f"Using input device: {device_name} (ID: {device_id})") + + self.device_id = device_id + else: + self.device_id = None + except (OSError, ModuleNotFoundError): raise SoundDeviceError if audio_format not in ["wav", "mp3", "webm"]: @@ -93,7 +119,7 @@ class Voice: temp_wav = tempfile.mktemp(suffix=".wav") try: - sample_rate = int(self.sd.query_devices(None, "input")["default_samplerate"]) + sample_rate = int(self.sd.query_devices(self.device_id, "input")["default_samplerate"]) except (TypeError, ValueError): sample_rate = 16000 # fallback to 16kHz if unable to query device except self.sd.PortAudioError: @@ -104,7 +130,9 @@ class Voice: self.start_time = time.time() try: - with self.sd.InputStream(samplerate=sample_rate, channels=1, callback=self.callback): + with self.sd.InputStream( + samplerate=sample_rate, channels=1, callback=self.callback, device=self.device_id + ): prompt(self.get_prompt, refresh_interval=0.1) except self.sd.PortAudioError as err: raise SoundDeviceError(f"Error accessing audio input device: {err}") @@ -113,13 +141,28 @@ class Voice: while not self.q.empty(): file.write(self.q.get()) - if self.audio_format != "wav": - filename = tempfile.mktemp(suffix=f".{self.audio_format}") - audio = AudioSegment.from_wav(temp_wav) - audio.export(filename, format=self.audio_format) - os.remove(temp_wav) - else: - filename = temp_wav + use_audio_format = self.audio_format + + # Check file size and offer to convert to mp3 if too large + file_size = os.path.getsize(temp_wav) + if file_size > 24.9 * 1024 * 1024 and self.audio_format == "wav": + print("\nWarning: {temp_wav} is too large, switching to mp3 format.") + use_audio_format = "mp3" + + filename = temp_wav + if use_audio_format != "wav": + try: + new_filename = tempfile.mktemp(suffix=f".{use_audio_format}") + audio = AudioSegment.from_wav(temp_wav) + audio.export(new_filename, format=use_audio_format) + os.remove(temp_wav) + filename = new_filename + except (CouldntDecodeError, CouldntEncodeError) as e: + print(f"Error converting audio: {e}") + except (OSError, FileNotFoundError) as e: + print(f"File system error during conversion: {e}") + except Exception as e: + print(f"Unexpected error during audio conversion: {e}") with open(filename, "rb") as fh: try: @@ -130,7 +173,7 @@ class Voice: print(f"Unable to transcribe {filename}: {err}") return - if self.audio_format != "wav": + if filename != temp_wav: os.remove(filename) text = transcript.text diff --git a/aider/watch.py b/aider/watch.py new file mode 100644 index 000000000..989aa8bf6 --- /dev/null +++ b/aider/watch.py @@ -0,0 +1,307 @@ +import re +import threading +from pathlib import Path +from typing import Optional + +from grep_ast import TreeContext +from pathspec import PathSpec +from pathspec.patterns import GitWildMatchPattern +from watchfiles import watch + +from aider.dump import dump # noqa +from aider.watch_prompts import watch_ask_prompt, watch_code_prompt + + +def load_gitignores(gitignore_paths: list[Path]) -> Optional[PathSpec]: + """Load and parse multiple .gitignore files into a single PathSpec""" + if not gitignore_paths: + return None + + patterns = [ + ".aider*", + ".git", + # Common editor backup/temp files + "*~", # Emacs/vim backup + "*.bak", # Generic backup + "*.swp", # Vim swap + "*.swo", # Vim swap + "\\#*\\#", # Emacs auto-save + ".#*", # Emacs lock files + "*.tmp", # Generic temp files + "*.temp", # Generic temp files + "*.orig", # Merge conflict originals + "*.pyc", # Python bytecode + "__pycache__/", # Python cache dir + ".DS_Store", # macOS metadata + "Thumbs.db", # Windows thumbnail cache + # IDE files + ".idea/", # JetBrains IDEs + ".vscode/", # VS Code + "*.sublime-*", # Sublime Text + ".project", # Eclipse + ".settings/", # Eclipse + "*.code-workspace", # VS Code workspace + # Environment files + ".env", # Environment variables + ".venv/", # Python virtual environments + "node_modules/", # Node.js dependencies + "vendor/", # Various dependencies + # Logs and caches + "*.log", # Log files + ".cache/", # Cache directories + ".pytest_cache/", # Python test cache + "coverage/", # Code coverage reports + ] # Always ignore + for path in gitignore_paths: + if path.exists(): + with open(path) as f: + patterns.extend(f.readlines()) + + return PathSpec.from_lines(GitWildMatchPattern, patterns) if patterns else None + + +class FileWatcher: + """Watches source files for changes and AI comments""" + + # Compiled regex pattern for AI comments + ai_comment_pattern = re.compile(r"(?:#|//|--) *(ai\b.*|ai\b.*|.*\bai[?!]?) *$", re.IGNORECASE) + + def __init__(self, coder, gitignores=None, verbose=False, analytics=None, root=None): + self.coder = coder + self.io = coder.io + self.root = Path(root) if root else Path(coder.root) + self.verbose = verbose + self.analytics = analytics + self.stop_event = None + self.watcher_thread = None + self.changed_files = set() + self.gitignores = gitignores + + self.gitignore_spec = load_gitignores( + [Path(g) for g in self.gitignores] if self.gitignores else [] + ) + + coder.io.file_watcher = self + + def filter_func(self, change_type, path): + """Filter function for the file watcher""" + path_obj = Path(path) + path_abs = path_obj.absolute() + + if not path_abs.is_relative_to(self.root.absolute()): + return False + + rel_path = path_abs.relative_to(self.root) + if self.verbose: + dump(rel_path) + + if self.gitignore_spec and self.gitignore_spec.match_file( + rel_path.as_posix() + ("/" if path_abs.is_dir() else "") + ): + return False + + if self.verbose: + dump("ok", rel_path) + + # Check if file contains AI markers + try: + comments, _, _ = self.get_ai_comments(str(path_abs)) + return bool(comments) + except Exception: + return + + def get_roots_to_watch(self): + """Determine which root paths to watch based on gitignore rules""" + if self.gitignore_spec: + roots = [ + str(path) + for path in self.root.iterdir() + if not self.gitignore_spec.match_file( + path.relative_to(self.root).as_posix() + ("/" if path.is_dir() else "") + ) + ] + # Fallback to watching root if all top-level items are filtered out + return roots if roots else [str(self.root)] + return [str(self.root)] + + def handle_changes(self, changes): + """Process the detected changes and update state""" + if not changes: + return False + + changed_files = {str(Path(change[1])) for change in changes} + self.changed_files.update(changed_files) + self.io.interrupt_input() + return True + + def watch_files(self): + """Watch for file changes and process them""" + try: + roots_to_watch = self.get_roots_to_watch() + + for changes in watch( + *roots_to_watch, watch_filter=self.filter_func, stop_event=self.stop_event + ): + if self.handle_changes(changes): + return + + except Exception as e: + if self.verbose: + dump(f"File watcher error: {e}") + raise e + + def start(self): + """Start watching for file changes""" + self.stop_event = threading.Event() + self.changed_files = set() + + self.watcher_thread = threading.Thread(target=self.watch_files, daemon=True) + self.watcher_thread.start() + + def stop(self): + """Stop watching for file changes""" + if self.stop_event: + self.stop_event.set() + if self.watcher_thread: + self.watcher_thread.join() + self.watcher_thread = None + self.stop_event = None + + def process_changes(self): + """Get any detected file changes""" + + has_action = None + added = False + for fname in self.changed_files: + _, _, action = self.get_ai_comments(fname) + if action in ("!", "?"): + has_action = action + + if fname in self.coder.abs_fnames: + continue + if self.analytics: + self.analytics.event("ai-comments file-add") + self.coder.abs_fnames.add(fname) + rel_fname = self.coder.get_rel_fname(fname) + if not added: + self.io.tool_output() + added = True + self.io.tool_output(f"Added {rel_fname} to the chat") + + if not has_action: + if added: + self.io.tool_output( + "End your comment with AI! to request changes or AI? to ask questions" + ) + return "" + + if self.analytics: + self.analytics.event("ai-comments execute") + self.io.tool_output("Processing your request...") + + if has_action == "!": + res = watch_code_prompt + elif has_action == "?": + res = watch_ask_prompt + + # Refresh all AI comments from tracked files + for fname in self.coder.abs_fnames: + line_nums, comments, _action = self.get_ai_comments(fname) + if not line_nums: + continue + + code = self.io.read_text(fname) + if not code: + continue + + rel_fname = self.coder.get_rel_fname(fname) + res += f"\n{rel_fname}:\n" + + # Convert comment line numbers to line indices (0-based) + lois = [ln - 1 for ln, _ in zip(line_nums, comments) if ln > 0] + + try: + context = TreeContext( + rel_fname, + code, + color=False, + line_number=False, + child_context=False, + last_line=False, + margin=0, + mark_lois=True, + loi_pad=3, + show_top_of_file_parent_scope=False, + ) + context.lines_of_interest = set() + context.add_lines_of_interest(lois) + context.add_context() + res += context.format() + except ValueError: + for ln, comment in zip(line_nums, comments): + res += f" Line {ln}: {comment}\n" + + return res + + def get_ai_comments(self, filepath): + """Extract AI comment line numbers, comments and action status from a file""" + line_nums = [] + comments = [] + has_action = None # None, "!" or "?" + content = self.io.read_text(filepath, silent=True) + if not content: + return None, None, None + + for i, line in enumerate(content.splitlines(), 1): + if match := self.ai_comment_pattern.search(line): + comment = match.group(0).strip() + if comment: + line_nums.append(i) + comments.append(comment) + comment = comment.lower() + comment = comment.lstrip("/#-") + comment = comment.strip() + if comment.startswith("ai!") or comment.endswith("ai!"): + has_action = "!" + elif comment.startswith("ai?") or comment.endswith("ai?"): + has_action = "?" + if not line_nums: + return None, None, None + return line_nums, comments, has_action + + +def main(): + """Example usage of the file watcher""" + import argparse + + parser = argparse.ArgumentParser(description="Watch source files for changes") + parser.add_argument("directory", help="Directory to watch") + parser.add_argument( + "--gitignore", + action="append", + help="Path to .gitignore file (can be specified multiple times)", + ) + args = parser.parse_args() + + directory = args.directory + print(f"Watching source files in {directory}...") + + # Example ignore function that ignores files with "test" in the name + def ignore_test_files(path): + return "test" in path.name.lower() + + watcher = FileWatcher(directory, gitignores=args.gitignore) + try: + watcher.start() + while True: + if changes := watcher.get_changes(): + for file in sorted(changes.keys()): + print(file) + watcher.changed_files = None + except KeyboardInterrupt: + print("\nStopped watching files") + watcher.stop() + + +if __name__ == "__main__": + main() diff --git a/aider/watch_prompts.py b/aider/watch_prompts.py new file mode 100644 index 000000000..93f917f30 --- /dev/null +++ b/aider/watch_prompts.py @@ -0,0 +1,12 @@ +watch_code_prompt = """ +I've written your instructions in comments in the code and marked them with "ai" +You can see the "AI" comments shown below (marked with █). +Find them in the code files I've shared with you, and follow their instructions. + +After completing those instructions, also be sure to remove all the "AI" comments from the code too. +""" + +watch_ask_prompt = """/ask +Find the "AI" comments below (marked with █) in the code files I've shared with you. +They contain my questions that I need you to answer and other instructions for you. +""" diff --git a/aider/website/HISTORY.md b/aider/website/HISTORY.md index 61755d118..219fd67e0 100644 --- a/aider/website/HISTORY.md +++ b/aider/website/HISTORY.md @@ -1,7 +1,6 @@ --- title: Release history -parent: More info -nav_order: 900 +nav_order: 925 highlight_image: /assets/blame.jpg description: Release notes and stats on aider writing its own code. --- @@ -24,14 +23,181 @@ cog.out(text) ]]]--> -### main branch +### Aider v0.74.1 + +- Have o1 & o3-mini generate markdown by sending the magic "Formatting re-enabled." string. +- Bugfix for multi-line inputs, which should not include the ". " continuation prompt. + +### Aider v0.74.0 + +- Dynamically changes the Ollama context window to hold the current chat. +- Better support for o3-mini, DeepSeek V3 & R1, o1-mini, o1 especially via third-party API providers. +- Remove `` tags from R1 responses for commit messages (and other weak model uses). +- Can now specify `use_temperature: ` in model settings, not just true/false. +- The full docker container now includes `boto3` for Bedrock. +- Docker containers now set `HOME=/app` which is the normal project mount-point, to persist `~/.aider`. +- Bugfix to prevent creating incorrect filenames like `python`, `php`, etc. +- Bugfix for `--timeout` +- Bugfix so that `/model` now correctly reports that the weak model is not changed. +- Bugfix so that multi-line mode persists through ^C at confirmation prompts. +- Watch files now fully ignores top-level directories named in ignore files, to reduce the chance of hitting OS watch limits. Helpful to ignore giant subtrees like `node_modules`. +- Fast startup with more providers and when model metadata provided in local files. +- Improved .gitignore handling: + - Honor ignores already in effect regardless of how they've been configured. + - Check for .env only when the file exists. +- Yes/No prompts now accept All/Skip as alias for Y/N even when not processing a group of confirmations. +- Aider wrote 77% of the code in this release. + +### Aider v0.73.0 + +- Full support for o3-mini: `aider --model o3-mini` +- New `--reasoning-effort` argument: low, medium, high. +- Improved handling of context window size limits, with better messaging and Ollama-specific guidance. +- Added support for removing model-specific reasoning tags from responses with `remove_reasoning: tagname` model setting. +- Auto-create parent directories when creating new files, by xqyz. +- Support for R1 free on OpenRouter: `--model openrouter/deepseek/deepseek-r1:free` +- Aider wrote 69% of the code in this release. + +### Aider v0.72.3 + +- Enforce user/assistant turn order to avoid R1 errors, by miradnanali. +- Case-insensitive model name matching while preserving original case. + +### Aider v0.72.2 +- Harden against user/assistant turn order problems which cause R1 errors. + +### Aider v0.72.1 +- Fix model metadata for `openrouter/deepseek/deepseek-r1` + +### Aider v0.72.0 +- Support for DeepSeek R1. + - Use shortcut: `--model r1` + - Also via OpenRouter: `--model openrouter/deepseek/deepseek-r1` +- Added Kotlin syntax support to repo map, by Paul Walker. +- Added `--line-endings` for file writing, by Titusz Pan. +- Added examples_as_sys_msg=True for GPT-4o models, improves benchmark scores. +- Bumped all dependencies, to pick up litellm support for o1 system messages. +- Bugfix for turn taking when reflecting lint/test errors. +- Aider wrote 52% of the code in this release. + +### Aider v0.71.1 + +- Fix permissions issue in Docker images. +- Added read-only file announcements. +- Bugfix: ASCII fallback for unicode errors. +- Bugfix: integer indices for list slicing in repomap calculations. + +### Aider v0.71.0 + +- Prompts to help DeepSeek work better when alternating between `/ask` and `/code`. +- Streaming pretty LLM responses is smoother and faster for long replies. +- Streaming automatically turns of for model that don't support it + - Can now switch to/from `/model o1` and a streaming model +- Pretty output remains enabled even when editing files with triple-backtick fences +- Bare `/ask`, `/code` and `/architect` commands now switch the chat mode. +- Increased default size of the repomap. +- Increased max chat history tokens limit from 4k to 8k. +- Turn off fancy input and watch files if terminal is dumb. +- Added support for custom voice format and input device settings. +- Disabled Streamlit email prompt, by apaz-cli. +- Docker container runs as non-root user. +- Fixed lint command handling of nested spaced strings, by Aaron Weisberg. +- Added token count feedback when adding command output to chat. +- Improved error handling for large audio files with automatic format conversion. +- Improved handling of git repo index errors, by Krazer. +- Improved unicode handling in console output with ASCII fallback. +- Added AssertionError, AttributeError to git error handling. +- Aider wrote 60% of the code in this release. + +### Aider v0.70.0 + +- Full support for o1 models. +- Watch files now honors `--subtree-only`, and only watches that subtree. +- Improved prompting for watch files, to work more reliably with more models. +- New install methods via uv, including one-liners. +- Support for openrouter/deepseek/deepseek-chat model. +- Better error handling when interactive commands are attempted via `/load` or `--load`. +- Display read-only files with abs path if its shorter than rel path. +- Ask 10% of users to opt-in to analytics. +- Bugfix for auto-suggest. +- Gracefully handle unicode errors in git path names. +- Aider wrote 74% of the code in this release. + +### Aider v0.69.1 + +- Fix for gemini model names in model metadata. +- Show hints about AI! and AI? when user makes AI comments. +- Support for running without git installed. +- Improved environment variable setup messages on Windows. + +### Aider v0.69.0 + +- [Watch files](https://aider.chat/docs/usage/watch.html) improvements: + - Use `# ... AI?` comments to trigger aider and ask questions about your code. + - Now watches *all* files, not just certain source files. + - Use `# AI comments`, `// AI comments`, or `-- AI comments` to give aider instructions in any text file. +- Full support for Gemini Flash 2.0 Exp: + - `aider --model flash` or `aider --model gemini/gemini-2.0-flash-exp` +- [New `--multiline` flag and `/multiline-mode` command](https://aider.chat/docs/usage/commands.html#entering-multi-line-chat-messages) makes ENTER a soft newline and META-ENTER send the message, by @miradnanali. +- `/copy-context ` now takes optional "instructions" when [copying code context to the clipboard](https://aider.chat/docs/usage/copypaste.html#copy-aiders-code-context-to-your-clipboard-paste-into-the-web-ui). +- Improved clipboard error handling with helpful requirements install info. +- Ask 5% of users if they want to opt-in to analytics. +- `/voice` now lets you edit the transcribed text before sending. +- Disabled auto-complete in Y/N prompts. +- Aider wrote 68% of the code in this release. + +### Aider v0.68.0 + +- [Aider works with LLM web chat UIs](https://aider.chat/docs/usage/copypaste.html). + - New `--copy-paste` mode. + - New `/copy-context` command. +- [Set API keys and other environment variables for all providers from command line or yaml conf file](https://aider.chat/docs/config/aider_conf.html#storing-llm-keys). + - New `--api-key provider=key` setting. + - New `--set-env VAR=value` setting. +- Added bash and zsh support to `--watch-files`. +- Better error messages when missing dependencies for Gemini and Bedrock models. +- Control-D now properly exits the program. +- Don't count token costs when API provider returns a hard error. +- Bugfix so watch files works with files that don't have tree-sitter support. +- Bugfix so o1 models can be used as weak model. +- Updated shell command prompt. +- Added docstrings for all Coders. +- Reorganized command line arguments with improved help messages and grouping. +- Use the exact `sys.python` for self-upgrades. +- Added experimental Gemini models. +- Aider wrote 71% of the code in this release. + +### Aider v0.67.0 + +- [Use aider in your IDE or editor](https://aider.chat/docs/usage/watch.html). + - Run `aider --watch-files` and it will watch for instructions you add to your source files. + - One-liner `# ...` or `// ...` comments that start or end with "AI" are instructions to aider. + - When aider sees "AI!" it reads and follows all the instructions in AI comments. +- Support for new Amazon Bedrock Nova models. +- When `/run` or `/test` have non-zero exit codes, pre-fill "Fix that" into the next message prompt. +- `/diff` now invokes `git diff` to use your preferred diff tool. +- Added Ctrl-Z support for process suspension. +- Spinner now falls back to ASCII art if fancy symbols throw unicode errors. +- `--read` now expands `~` home dirs. +- Enabled exception capture in analytics. +- [Aider wrote 61% of the code in this release.](https://aider.chat/HISTORY.html) + +### Aider v0.66.0 - PDF support for Sonnet and Gemini models. +- Added `--voice-input-device` to select audio input device for voice recording, by @preynal. +- Added `--timeout` option to configure API call timeouts. - Set cwd to repo root when running shell commands. +- Added Ctrl-Up/Down keyboard shortcuts for per-message history navigation. - Improved error handling for failed .gitignore file operations. - Improved error handling for input history file permissions. - Improved error handling for analytics file access. -- Aider wrote 85% of the code in this release. +- Removed spurious warning about disabling pretty in VSCode. +- Removed broken support for Dart. +- Bugfix when scraping URLs found in chat messages. +- Better handling of __version__ import errors. +- Improved `/drop` command to support substring matching for non-glob patterns. +- Aider wrote 82% of the code in this release. ### Aider v0.65.1 diff --git a/aider/website/_config.yml b/aider/website/_config.yml index b735e8b0e..b34011eb3 100644 --- a/aider/website/_config.yml +++ b/aider/website/_config.yml @@ -1,6 +1,12 @@ theme: just-the-docs url: "https://aider.chat" +# Analytics configuration +analytics: + enabled: false # Single switch to control analytics and cookie consent + posthog_key: 'phc_99T7muzafUMMZX15H8XePbMSreEUzahHbtWjy3l5Qbv' + posthog_host: 'https://us.i.posthog.com' + plugins: - jekyll-redirect-from - jekyll-sitemap @@ -45,4 +51,4 @@ callouts: note: title: Note color: yellow - \ No newline at end of file + diff --git a/aider/website/_data/blame.yml b/aider/website/_data/blame.yml index 29813934d..00c32ad8b 100644 --- a/aider/website/_data/blame.yml +++ b/aider/website/_data/blame.yml @@ -1,5 +1,5 @@ -- aider_percentage: 31.33 - aider_total: 47 +- aider_percentage: 29.08 + aider_total: 41 end_date: '2023-06-15' end_tag: v0.6.0 file_counts: @@ -17,44 +17,44 @@ Paul Gauthier: 6 Paul Gauthier (aider): 1 aider/utils.py: - Paul Gauthier: 25 - Paul Gauthier (aider): 21 + Paul Gauthier: 22 + Paul Gauthier (aider): 17 setup.py: Paul Gauthier: 7 Paul Gauthier (aider): 7 tests/test_utils.py: - Paul Gauthier (aider): 9 + Paul Gauthier (aider): 7 grand_total: - Paul Gauthier: 103 - Paul Gauthier (aider): 47 + Paul Gauthier: 100 + Paul Gauthier (aider): 41 start_tag: v0.5.0 - total_lines: 150 -- aider_percentage: 10.35 - aider_total: 182 + total_lines: 141 +- aider_percentage: 15.99 + aider_total: 224 end_date: '2023-06-25' end_tag: v0.7.0 file_counts: .github/workflows/release.yml: Paul Gauthier: 2 - Paul Gauthier (aider): 29 + Paul Gauthier (aider): 25 aider/__init__.py: Paul Gauthier: 1 aider/coders/__init__.py: Paul Gauthier: 6 aider/coders/base_coder.py: - Paul Gauthier: 314 + Paul Gauthier: 305 aider/coders/editblock_coder.py: - Paul Gauthier: 338 + Paul Gauthier: 32 aider/coders/wholefile_coder.py: - Paul Gauthier: 115 + Paul Gauthier: 86 Paul Gauthier (aider): 3 aider/coders/wholefile_func_coder.py: - Paul Gauthier: 120 + Paul Gauthier: 116 Paul Gauthier (aider): 11 aider/commands.py: Paul Gauthier: 28 aider/diffs.py: - Paul Gauthier: 18 + Paul Gauthier: 17 aider/io.py: Paul Gauthier: 16 aider/main.py: @@ -77,22 +77,22 @@ tests/test_commands.py: Paul Gauthier: 3 tests/test_editblock.py: - Paul Gauthier: 28 + Paul Gauthier: 24 tests/test_main.py: Paul Gauthier: 8 tests/test_models.py: Paul Gauthier: 21 Paul Gauthier (aider): 7 tests/test_wholefile.py: - Paul Gauthier: 113 - Paul Gauthier (aider): 38 + Paul Gauthier: 67 + Paul Gauthier (aider): 84 grand_total: - Paul Gauthier: 1576 - Paul Gauthier (aider): 182 + Paul Gauthier: 1177 + Paul Gauthier (aider): 224 start_tag: v0.6.0 - total_lines: 1758 -- aider_percentage: 7.97 - aider_total: 150 + total_lines: 1401 +- aider_percentage: 8.21 + aider_total: 142 end_date: '2023-07-06' end_tag: v0.8.0 file_counts: @@ -106,15 +106,15 @@ aider/coders/__init__.py: Paul Gauthier: 10 aider/coders/base_coder.py: - Paul Gauthier: 161 + Paul Gauthier: 159 Paul Gauthier (aider): 5 aider/coders/editblock_coder.py: - Paul Gauthier: 26 + Paul Gauthier: 14 aider/coders/editblock_func_coder.py: - Paul Gauthier: 144 + Paul Gauthier: 123 Paul Gauthier (aider): 8 aider/coders/single_wholefile_func_coder.py: - Paul Gauthier: 122 + Paul Gauthier: 45 aider/coders/wholefile_coder.py: Paul Gauthier: 24 aider/coders/wholefile_func_coder.py: @@ -137,7 +137,7 @@ benchmark/Dockerfile: Paul Gauthier: 7 benchmark/benchmark.py: - Paul Gauthier: 447 + Paul Gauthier: 446 Paul Gauthier (aider): 29 benchmark/docker.sh: Paul Gauthier: 11 @@ -149,39 +149,40 @@ benchmark/rungrid.py: Paul Gauthier: 60 benchmark/test_benchmark.py: - Paul Gauthier: 47 + Paul Gauthier: 34 + Paul Gauthier (aider): 13 tests/test_coder.py: - Paul Gauthier: 95 - Paul Gauthier (aider): 38 - tests/test_commands.py: - Paul Gauthier: 21 + Paul Gauthier: 87 Paul Gauthier (aider): 24 + tests/test_commands.py: + Paul Gauthier: 14 + Paul Gauthier (aider): 17 tests/test_editblock.py: Paul Gauthier: 94 tests/test_io.py: Paul Gauthier: 3 Paul Gauthier (aider): 6 tests/test_main.py: - Paul Gauthier: 29 + Paul Gauthier: 26 tests/test_repomap.py: Paul Gauthier: 26 tests/test_wholefile.py: Paul Gauthier: 193 grand_total: - Paul Gauthier: 1726 - Paul Gauthier (aider): 150 + Paul Gauthier: 1582 + Paul Gauthier (aider): 142 kwmiebach: 5 start_tag: v0.7.0 - total_lines: 1881 -- aider_percentage: 16.75 - aider_total: 161 + total_lines: 1729 +- aider_percentage: 17.67 + aider_total: 144 end_date: '2023-07-16' end_tag: v0.9.0 file_counts: aider/__init__.py: Paul Gauthier: 1 aider/coders/base_coder.py: - Paul Gauthier: 75 + Paul Gauthier: 74 aider/coders/editblock_coder.py: Paul Gauthier: 8 aider/coders/single_wholefile_func_coder.py: @@ -191,71 +192,72 @@ aider/coders/wholefile_func_coder.py: Paul Gauthier: 1 aider/commands.py: - Paul Gauthier: 87 + Paul Gauthier: 86 Paul Gauthier (aider): 4 aider/io.py: - Paul Gauthier: 8 + Paul Gauthier: 7 aider/main.py: - Paul Gauthier: 189 - Paul Gauthier (aider): 53 + Paul Gauthier: 126 + Paul Gauthier (aider): 59 aider/repomap.py: - Paul Gauthier: 37 + Paul Gauthier: 36 aider/utils.py: Paul Gauthier: 8 benchmark/benchmark.py: Paul Gauthier: 3 scripts/versionbump.py: Paul Gauthier: 15 - Paul Gauthier (aider): 13 + Paul Gauthier (aider): 10 setup.py: Paul Gauthier (aider): 1 tests/test_coder.py: - Paul Gauthier: 121 - Paul Gauthier (aider): 30 + Paul Gauthier: 110 + Paul Gauthier (aider): 23 tests/test_commands.py: - Paul Gauthier: 38 - Paul Gauthier (aider): 59 + Paul Gauthier: 36 + Paul Gauthier (aider): 43 tests/test_editblock.py: Paul Gauthier: 1 tests/test_io.py: Paul Gauthier: 1 tests/test_main.py: - Paul Gauthier: 23 + Paul Gauthier: 12 tests/test_repomap.py: Paul Gauthier: 13 Paul Gauthier (aider): 1 tests/test_wholefile.py: - Paul Gauthier: 77 + Paul Gauthier: 42 tests/utils.py: - Paul Gauthier: 46 + Paul Gauthier: 43 + Paul Gauthier (aider): 3 grand_total: - Paul Gauthier: 800 - Paul Gauthier (aider): 161 + Paul Gauthier: 671 + Paul Gauthier (aider): 144 start_tag: v0.8.0 - total_lines: 961 -- aider_percentage: 13.21 - aider_total: 44 + total_lines: 815 +- aider_percentage: 11.34 + aider_total: 33 end_date: '2023-07-22' end_tag: v0.10.0 file_counts: aider/__init__.py: Paul Gauthier: 1 aider/coders/base_coder.py: - Paul Gauthier: 34 + Paul Gauthier: 23 aider/coders/editblock_coder.py: Paul Gauthier: 11 aider/coders/single_wholefile_func_coder.py: - Paul Gauthier: 2 + Paul Gauthier: 1 aider/coders/wholefile_coder.py: - Paul Gauthier: 2 + Paul Gauthier: 1 aider/coders/wholefile_func_coder.py: - Paul Gauthier: 2 + Paul Gauthier: 1 aider/commands.py: - Amer Amayreh: 4 - Paul Gauthier (aider): 17 + Amer Amayreh: 8 + Paul Gauthier (aider): 4 aider/io.py: - Paul Gauthier: 4 - Paul Gauthier (aider): 5 + Paul Gauthier: 3 + Paul Gauthier (aider): 6 aider/main.py: Paul Gauthier: 62 aider/versioncheck.py: @@ -266,72 +268,72 @@ scripts/versionbump.py: Paul Gauthier (aider): 2 tests/test_coder.py: - Paul Gauthier: 43 + Paul Gauthier: 35 tests/test_commands.py: - Paul Gauthier: 31 - Paul Gauthier (aider): 12 + Paul Gauthier: 22 + Paul Gauthier (aider): 13 tests/test_editblock.py: - Paul Gauthier: 20 + Paul Gauthier: 17 tests/test_main.py: Paul Gauthier: 44 Paul Gauthier (aider): 3 tests/utils.py: Paul Gauthier: 6 grand_total: - Amer Amayreh: 4 - Paul Gauthier: 285 - Paul Gauthier (aider): 44 + Amer Amayreh: 8 + Paul Gauthier: 250 + Paul Gauthier (aider): 33 start_tag: v0.9.0 - total_lines: 333 -- aider_percentage: 5.09 - aider_total: 48 + total_lines: 291 +- aider_percentage: 6.62 + aider_total: 49 end_date: '2023-08-02' end_tag: v0.11.0 file_counts: aider/__init__.py: Paul Gauthier: 1 aider/coders/base_coder.py: - Paul Gauthier: 148 + Paul Gauthier: 104 aider/coders/wholefile_coder.py: Paul Gauthier: 2 aider/commands.py: Paul Gauthier: 38 Paul Gauthier (aider): 2 aider/history.py: - Paul Gauthier: 110 - Paul Gauthier (aider): 18 + Paul Gauthier: 103 + Paul Gauthier (aider): 25 aider/main.py: Paul Gauthier: 86 Paul Gauthier (aider): 3 aider/repo.py: - Paul Gauthier: 164 - Paul Gauthier (aider): 13 + Paul Gauthier: 113 + Paul Gauthier (aider): 7 aider/sendchat.py: Paul Gauthier: 64 scripts/versionbump.py: Paul Gauthier: 4 tests/test_coder.py: - Paul Gauthier: 35 + Paul Gauthier: 26 tests/test_commands.py: - Paul Gauthier: 57 + Paul Gauthier: 53 Paul Gauthier (aider): 6 tests/test_main.py: - Paul Gauthier: 30 + Paul Gauthier: 24 Paul Gauthier (aider): 1 tests/test_repo.py: - Paul Gauthier: 109 + Paul Gauthier: 56 Paul Gauthier (aider): 5 tests/test_sendchat.py: - Paul Gauthier: 41 + Paul Gauthier: 11 tests/utils.py: Paul Gauthier: 6 grand_total: - Paul Gauthier: 895 - Paul Gauthier (aider): 48 + Paul Gauthier: 691 + Paul Gauthier (aider): 49 start_tag: v0.10.0 - total_lines: 943 -- aider_percentage: 5.16 - aider_total: 28 + total_lines: 740 +- aider_percentage: 4.71 + aider_total: 24 end_date: '2023-08-11' end_tag: v0.12.0 file_counts: @@ -341,13 +343,13 @@ Arseniy Pavlenko: 3 Paul Gauthier: 4 aider/coders/editblock_coder.py: - Paul Gauthier: 130 + Paul Gauthier: 123 aider/commands.py: Joshua Vial: 2 Paul Gauthier: 17 Paul Gauthier (aider): 3 aider/history.py: - Paul Gauthier: 10 + Paul Gauthier: 6 aider/io.py: Paul Gauthier: 10 aider/main.py: @@ -362,27 +364,27 @@ Paul Gauthier: 77 Paul Gauthier (aider): 8 benchmark/benchmark.py: - Paul Gauthier: 60 + Paul Gauthier: 57 scripts/versionbump.py: Paul Gauthier: 1 tests/test_coder.py: Paul Gauthier: 1 - Paul Gauthier (aider): 17 + Paul Gauthier (aider): 13 tests/test_commands.py: - Paul Gauthier: 22 + Paul Gauthier: 19 tests/test_editblock.py: - Paul Gauthier: 52 + Paul Gauthier: 43 tests/test_repo.py: - Paul Gauthier: 58 + Paul Gauthier: 55 grand_total: Arseniy Pavlenko: 3 Joshua Vial: 2 - Paul Gauthier: 510 - Paul Gauthier (aider): 28 + Paul Gauthier: 481 + Paul Gauthier (aider): 24 start_tag: v0.11.0 - total_lines: 543 -- aider_percentage: 4.07 - aider_total: 24 + total_lines: 510 +- aider_percentage: 4.32 + aider_total: 23 end_date: '2023-08-22' end_tag: v0.13.0 file_counts: @@ -393,7 +395,7 @@ aider/__init__.py: Paul Gauthier: 1 aider/coders/base_coder.py: - Paul Gauthier: 93 + Paul Gauthier: 89 Paul Gauthier (aider): 2 aider/coders/editblock_coder.py: Paul Gauthier: 6 @@ -408,31 +410,31 @@ aider/commands.py: Paul Gauthier: 34 aider/io.py: - Paul Gauthier: 8 + Paul Gauthier: 7 aider/main.py: Paul Gauthier: 2 - Paul Gauthier (aider): 20 + Paul Gauthier (aider): 19 aider/repo.py: - Paul Gauthier: 59 + Paul Gauthier: 56 aider/voice.py: - Paul Gauthier: 26 + Paul Gauthier: 24 setup.py: Paul Gauthier (aider): 1 tests/test_coder.py: - Paul Gauthier: 283 + Paul Gauthier: 255 Paul Gauthier (aider): 1 tests/test_main.py: Paul Gauthier: 1 tests/test_repo.py: - Paul Gauthier: 27 + Paul Gauthier: 9 tests/test_wholefile.py: Paul Gauthier: 1 grand_total: - Paul Gauthier: 566 - Paul Gauthier (aider): 24 + Paul Gauthier: 510 + Paul Gauthier (aider): 23 start_tag: v0.12.0 - total_lines: 590 -- aider_percentage: 0.53 + total_lines: 533 +- aider_percentage: 0.55 aider_total: 1 end_date: '2023-09-08' end_tag: v0.14.0 @@ -440,7 +442,7 @@ aider/__init__.py: Paul Gauthier: 1 aider/coders/base_coder.py: - Joshua Vial: 20 + Joshua Vial: 19 Paul Gauthier: 4 aider/commands.py: JV: 1 @@ -451,10 +453,10 @@ JV: 1 Joshua Vial: 1 aider/models/__init__.py: - JV: 1 - Paul Gauthier: 14 + JV: 2 + Paul Gauthier: 13 aider/models/model.py: - JV: 27 + JV: 21 Joshua Vial: 4 Paul Gauthier: 8 aider/models/openai.py: @@ -482,14 +484,14 @@ Joshua Vial: 22 Paul Gauthier: 13 grand_total: - JV: 67 - Joshua Vial: 60 - Paul Gauthier: 61 + JV: 62 + Joshua Vial: 59 + Paul Gauthier: 60 Paul Gauthier (aider): 1 start_tag: v0.13.0 - total_lines: 189 -- aider_percentage: 9.69 - aider_total: 41 + total_lines: 182 +- aider_percentage: 11.28 + aider_total: 38 end_date: '2023-10-20' end_tag: v0.15.0 file_counts: @@ -506,15 +508,15 @@ Paul Gauthier: 49 aider/main.py: Paul Gauthier: 29 - Paul Gauthier (aider): 24 - Thinh Nguyen: 7 + Paul Gauthier (aider): 21 + Thinh Nguyen: 6 aider/repo.py: Paul Gauthier: 26 Paul Gauthier (aider): 2 aider/repomap.py: Paul Gauthier: 11 aider/voice.py: - Paul Gauthier: 9 + Paul Gauthier: 8 benchmark/Dockerfile: Joshua Vial: 1 benchmark/benchmark.py: @@ -524,20 +526,20 @@ scripts/versionbump.py: Paul Gauthier: 2 tests/test_commands.py: - Paul Gauthier: 129 + Paul Gauthier: 95 tests/test_main.py: Paul Gauthier: 17 tests/test_repo.py: - Paul Gauthier: 67 + Paul Gauthier: 20 grand_total: Alexander Kjeldaas (aider): 1 Joshua Vial: 2 - Paul Gauthier: 371 - Paul Gauthier (aider): 40 - Thinh Nguyen: 9 + Paul Gauthier: 289 + Paul Gauthier (aider): 37 + Thinh Nguyen: 8 start_tag: v0.14.0 - total_lines: 423 -- aider_percentage: 1.71 + total_lines: 337 +- aider_percentage: 1.76 aider_total: 16 end_date: '2023-10-29' end_tag: v0.16.0 @@ -585,7 +587,7 @@ aider/queries/tree-sitter-typescript-tags.scm: Paul Gauthier: 23 aider/repomap.py: - Paul Gauthier: 193 + Paul Gauthier: 187 Paul Gauthier (aider): 2 benchmark/Dockerfile: Paul Gauthier: 4 @@ -595,28 +597,26 @@ Paul Gauthier: 2 Paul Gauthier (aider): 2 tests/test_coder.py: - Paul Gauthier: 21 + Paul Gauthier: 19 tests/test_commands.py: - Paul Gauthier: 10 - paul-gauthier: 1 + Paul Gauthier: 5 tests/test_editblock.py: - Paul Gauthier: 55 + Paul Gauthier: 44 tests/test_repomap.py: Paul Gauthier: 5 grand_total: - Paul Gauthier: 918 + Paul Gauthier: 894 Paul Gauthier (aider): 16 - paul-gauthier: 1 start_tag: v0.15.0 - total_lines: 935 -- aider_percentage: 7.46 - aider_total: 22 + total_lines: 910 +- aider_percentage: 5.35 + aider_total: 13 end_date: '2023-11-06' end_tag: v0.17.0 file_counts: .github/workflows/docker-build-test.yml: - Paul Gauthier: 21 - Paul Gauthier (aider): 16 + Paul Gauthier: 7 + Paul Gauthier (aider): 7 .github/workflows/release.yml: Paul Gauthier: 4 aider/__init__.py: @@ -632,9 +632,9 @@ aider/io.py: Paul Gauthier: 1 aider/main.py: - Paul Gauthier: 3 + Paul Gauthier: 1 aider/models/openai.py: - Paul Gauthier: 9 + Paul Gauthier: 8 aider/queries/tree-sitter-elisp-tags.scm: Paul Gauthier: 3 aider/repomap.py: @@ -649,29 +649,29 @@ Jack Hallam: 3 Paul Gauthier: 10 tests/test_commands.py: - Paul Gauthier: 72 + Paul Gauthier: 51 tests/test_editblock.py: - Paul Gauthier: 23 + Paul Gauthier: 21 tests/test_io.py: Paul Gauthier: 24 tests/utils.py: - Paul Gauthier: 6 + Paul Gauthier: 3 grand_total: Jack Hallam: 3 Omri Bloch: 1 - Paul Gauthier: 269 - Paul Gauthier (aider): 22 + Paul Gauthier: 226 + Paul Gauthier (aider): 13 start_tag: v0.16.0 - total_lines: 295 -- aider_percentage: 35.43 - aider_total: 107 + total_lines: 243 +- aider_percentage: 39.3 + aider_total: 90 end_date: '2023-11-17' end_tag: v0.18.0 file_counts: aider/__init__.py: Paul Gauthier: 1 aider/coders/base_coder.py: - Paul Gauthier: 33 + Paul Gauthier: 27 aider/commands.py: Paul Gauthier: 12 Paul Gauthier (aider): 3 @@ -683,27 +683,27 @@ Paul Gauthier: 10 benchmark/benchmark.py: Paul Gauthier: 22 - Paul Gauthier (aider): 50 + Paul Gauthier (aider): 33 benchmark/rungrid.py: Paul Gauthier: 16 scripts/versionbump.py: Paul Gauthier (aider): 41 tests/test_coder.py: - Paul Gauthier: 25 + Paul Gauthier: 14 tests/test_commands.py: - Paul Gauthier: 26 + Paul Gauthier: 10 tests/test_main.py: - Paul Gauthier: 4 + Paul Gauthier: 3 Paul Gauthier (aider): 13 tests/test_repomap.py: - Paul Gauthier: 30 + Paul Gauthier: 8 grand_total: - Paul Gauthier: 195 - Paul Gauthier (aider): 107 + Paul Gauthier: 139 + Paul Gauthier (aider): 90 start_tag: v0.17.0 - total_lines: 302 + total_lines: 229 - aider_percentage: 0.72 - aider_total: 14 + aider_total: 13 end_date: '2023-12-19' end_tag: v0.19.0 file_counts: @@ -712,13 +712,13 @@ aider/coders/__init__.py: Paul Gauthier: 2 aider/coders/base_coder.py: - Paul Gauthier: 66 + Paul Gauthier: 54 aider/coders/editblock_coder.py: Paul Gauthier: 2 aider/coders/search_replace.py: - Paul Gauthier: 769 + Paul Gauthier: 767 aider/coders/udiff_coder.py: - Paul Gauthier: 395 + Paul Gauthier: 389 aider/coders/wholefile_coder.py: Paul Gauthier: 2 aider/commands.py: @@ -726,9 +726,9 @@ aider/history.py: Paul Gauthier: 3 aider/main.py: - Paul Gauthier: 44 + Paul Gauthier: 41 Your Name: 3 - Your Name (aider): 14 + Your Name (aider): 13 aider/models/__init__.py: Paul Gauthier: 3 aider/models/model.py: @@ -742,11 +742,11 @@ aider/sendchat.py: Paul Gauthier: 15 aider/utils.py: - Paul Gauthier: 63 + Paul Gauthier: 15 aider/voice.py: Paul Gauthier: 7 benchmark/benchmark.py: - Paul Gauthier: 235 + Paul Gauthier: 175 benchmark/refactor_tools.py: Paul Gauthier: 209 tests/test_coder.py: @@ -757,9 +757,9 @@ Paul Gauthier: 1 tests/test_main.py: Paul Gauthier: 10 - Your Name: 18 + Your Name: 16 tests/test_models.py: - Paul Gauthier: 10 + Paul Gauthier: 8 tests/test_repo.py: Paul Gauthier: 1 tests/test_repomap.py: @@ -769,13 +769,13 @@ tests/test_wholefile.py: Paul Gauthier: 10 grand_total: - Paul Gauthier: 1913 - Your Name: 21 - Your Name (aider): 14 + Paul Gauthier: 1780 + Your Name: 19 + Your Name (aider): 13 start_tag: v0.18.0 - total_lines: 1948 -- aider_percentage: 11.3 - aider_total: 40 + total_lines: 1812 +- aider_percentage: 11.38 + aider_total: 38 end_date: '2024-01-04' end_tag: v0.20.0 file_counts: @@ -784,8 +784,8 @@ aider/__init__.py: Paul Gauthier: 1 aider/coders/base_coder.py: - Joshua Vial: 28 - Paul Gauthier: 25 + Joshua Vial: 26 + Paul Gauthier: 23 aider/coders/search_replace.py: Paul Gauthier: 2 aider/coders/udiff_coder.py: @@ -795,9 +795,9 @@ Christopher Toth: 2 Joshua Vial: 16 Paul Gauthier: 2 - Paul Gauthier (aider): 7 + Paul Gauthier (aider): 6 aider/io.py: - Joshua Vial: 21 + Joshua Vial: 14 aider/models/model.py: Joshua Vial: 43 aider/models/openrouter.py: @@ -813,22 +813,22 @@ benchmark/benchmark.py: Joshua Vial: 16 tests/test_commands.py: - Paul Gauthier: 21 - Paul Gauthier (aider): 24 + Paul Gauthier: 17 + Paul Gauthier (aider): 20 tests/test_models.py: Joshua Vial: 13 tests/test_udiff.py: - Paul Gauthier: 66 - Paul Gauthier (aider): 7 + Paul Gauthier: 63 + Paul Gauthier (aider): 10 grand_total: Christopher Toth: 7 - Joshua Vial: 179 - Paul Gauthier: 128 - Paul Gauthier (aider): 40 + Joshua Vial: 170 + Paul Gauthier: 119 + Paul Gauthier (aider): 38 start_tag: v0.19.0 - total_lines: 354 -- aider_percentage: 19.78 - aider_total: 18 + total_lines: 334 +- aider_percentage: 19.32 + aider_total: 17 end_date: '2024-01-08' end_tag: v0.21.0 file_counts: @@ -841,18 +841,18 @@ aider/coders/udiff_coder.py: Paul Gauthier: 22 aider/main.py: - Paul Gauthier (aider): 10 + Paul Gauthier (aider): 9 aider/versioncheck.py: Paul Gauthier (aider): 8 setup.py: Paul Gauthier: 2 tests/test_udiff.py: - Paul Gauthier: 46 + Paul Gauthier: 44 grand_total: - Paul Gauthier: 73 - Paul Gauthier (aider): 18 + Paul Gauthier: 71 + Paul Gauthier (aider): 17 start_tag: v0.20.0 - total_lines: 91 + total_lines: 88 - aider_percentage: 0.0 aider_total: 0 end_date: '2024-01-22' @@ -865,14 +865,14 @@ aider/coders/udiff_coder.py: Paul Gauthier: 5 aider/commands.py: - Paul Gauthier: 48 + Paul Gauthier: 44 aider/main.py: Paul Gauthier: 2 grand_total: - Paul Gauthier: 58 + Paul Gauthier: 54 start_tag: v0.21.0 - total_lines: 58 -- aider_percentage: 1.11 + total_lines: 54 +- aider_percentage: 1.16 aider_total: 2 end_date: '2024-02-03' end_tag: v0.23.0 @@ -882,25 +882,25 @@ aider/coders/base_coder.py: Paul Gauthier: 10 aider/commands.py: - Paul Gauthier: 5 + Paul Gauthier: 2 aider/main.py: - Paul Gauthier: 15 - Zachary Vorhies: 7 + Paul Gauthier: 13 + Zachary Vorhies: 6 aider/mdstream.py: Paul Gauthier: 120 Paul Gauthier (aider): 2 aider/models/openai.py: Paul Gauthier: 3 benchmark/benchmark.py: - Paul Gauthier: 17 + Paul Gauthier: 16 grand_total: - Paul Gauthier: 171 + Paul Gauthier: 165 Paul Gauthier (aider): 2 - Zachary Vorhies: 7 + Zachary Vorhies: 6 start_tag: v0.22.0 - total_lines: 180 -- aider_percentage: 5.07 - aider_total: 19 + total_lines: 173 +- aider_percentage: 6.68 + aider_total: 25 end_date: '2024-02-10' end_tag: v0.24.0 file_counts: @@ -920,31 +920,31 @@ aider/models/openai.py: Paul Gauthier: 135 aider/scrape.py: - Paul Gauthier: 176 - Paul Gauthier (aider): 11 + Paul Gauthier: 170 + Paul Gauthier (aider): 17 aider/utils.py: - Paul Gauthier: 8 + Paul Gauthier: 7 tests/test_models.py: Paul Gauthier: 8 grand_total: - Paul Gauthier: 356 - Paul Gauthier (aider): 19 + Paul Gauthier: 349 + Paul Gauthier (aider): 25 start_tag: v0.23.0 - total_lines: 375 -- aider_percentage: 5.48 - aider_total: 8 + total_lines: 374 +- aider_percentage: 5.79 + aider_total: 7 end_date: '2024-03-04' end_tag: v0.25.0 file_counts: aider/__init__.py: Paul Gauthier: 1 aider/coders/base_coder.py: - Paul Gauthier: 55 + Paul Gauthier: 46 aider/commands.py: Paul Gauthier: 5 aider/main.py: Paul Gauthier: 4 - Paul Gauthier (aider): 8 + Paul Gauthier (aider): 7 aider/models/openai.py: Paul Gauthier: 1 aider/repo.py: @@ -952,14 +952,14 @@ aider/scrape.py: Paul Gauthier: 1 tests/test_coder.py: - Paul Gauthier: 28 + Paul Gauthier: 22 tests/test_commands.py: - Paul Gauthier: 32 + Paul Gauthier: 23 grand_total: - Paul Gauthier: 138 - Paul Gauthier (aider): 8 + Paul Gauthier: 114 + Paul Gauthier (aider): 7 start_tag: v0.24.0 - total_lines: 146 + total_lines: 121 - aider_percentage: 0.0 aider_total: 0 end_date: '2024-03-08' @@ -970,11 +970,11 @@ aider/coders/base_coder.py: Paul Gauthier: 8 aider/main.py: - Paul Gauthier: 30 + Paul Gauthier: 26 grand_total: - Paul Gauthier: 39 + Paul Gauthier: 35 start_tag: v0.25.0 - total_lines: 39 + total_lines: 35 - aider_percentage: 0.0 aider_total: 0 end_date: '2024-03-22' @@ -987,20 +987,20 @@ aider/main.py: Paul Gauthier: 14 aider/queries/tree-sitter-typescript-tags.scm: - Ryan Freckleton: 32 + Ryan Freckleton: 21 aider/repomap.py: Paul Gauthier: 6 benchmark/benchmark.py: - Paul Gauthier: 136 + Paul Gauthier: 91 tests/test_commands.py: Paul Gauthier: 3 tests/test_repomap.py: - Ryan Freckleton: 59 + Ryan Freckleton: 48 grand_total: - Paul Gauthier: 170 - Ryan Freckleton: 91 + Paul Gauthier: 125 + Ryan Freckleton: 69 start_tag: v0.26.0 - total_lines: 261 + total_lines: 194 - aider_percentage: 0.0 aider_total: 0 end_date: '2024-04-09' @@ -1009,12 +1009,12 @@ aider/__init__.py: Paul Gauthier: 1 aider/models/openai.py: - Paul Gauthier: 10 + Paul Gauthier: 3 grand_total: - Paul Gauthier: 11 + Paul Gauthier: 4 start_tag: v0.27.0 - total_lines: 11 -- aider_percentage: 5.33 + total_lines: 4 +- aider_percentage: 5.69 aider_total: 35 end_date: '2024-04-21' end_tag: v0.29.0 @@ -1041,9 +1041,9 @@ aider/history.py: Paul Gauthier: 6 aider/main.py: - Paul Gauthier: 81 + Paul Gauthier: 68 aider/models.py: - Paul Gauthier: 225 + Paul Gauthier: 216 Paul Gauthier (aider): 33 aider/repo.py: Paul Gauthier: 19 @@ -1065,7 +1065,7 @@ tests/test_models.py: Paul Gauthier: 13 tests/test_repo.py: - Paul Gauthier: 37 + Paul Gauthier: 17 tests/test_repomap.py: Paul Gauthier: 13 tests/test_sendchat.py: @@ -1074,10 +1074,10 @@ Paul Gauthier: 14 grand_total: Aloha: 1 - Paul Gauthier: 621 + Paul Gauthier: 579 Paul Gauthier (aider): 35 start_tag: v0.28.0 - total_lines: 657 + total_lines: 615 - aider_percentage: 0.0 aider_total: 0 end_date: '2024-04-23' @@ -1090,9 +1090,9 @@ aider/history.py: Paul Gauthier: 2 aider/main.py: - Paul Gauthier: 27 + Paul Gauthier: 26 aider/models.py: - Paul Gauthier: 173 + Paul Gauthier: 154 aider/sendchat.py: Paul Gauthier: 3 aider/voice.py: @@ -1114,10 +1114,10 @@ tests/test_wholefile.py: Paul Gauthier: 1 grand_total: - Paul Gauthier: 233 + Paul Gauthier: 213 start_tag: v0.29.0 - total_lines: 233 -- aider_percentage: 0.15 + total_lines: 213 +- aider_percentage: 0.16 aider_total: 2 end_date: '2024-05-02' end_tag: v0.31.0 @@ -1127,35 +1127,35 @@ aider/args.py: Paul Gauthier: 375 aider/coders/base_coder.py: - Paul Gauthier: 153 + Paul Gauthier: 120 aider/commands.py: Paul Gauthier: 45 aider/gui.py: Paul Gauthier: 531 Paul Gauthier (aider): 2 aider/main.py: - Paul Gauthier: 136 + Paul Gauthier: 114 aider/models.py: Paul Gauthier: 14 aider/scrape.py: - Paul Gauthier: 32 + Paul Gauthier: 15 aider/sendchat.py: Paul Gauthier: 3 tests/test_coder.py: Paul Gauthier: 16 tests/test_commands.py: - Paul Gauthier: 17 + Paul Gauthier: 8 tests/test_editblock.py: Paul Gauthier: 4 tests/test_wholefile.py: Paul Gauthier: 1 grand_total: - Paul Gauthier: 1328 + Paul Gauthier: 1247 Paul Gauthier (aider): 2 start_tag: v0.30.0 - total_lines: 1330 -- aider_percentage: 0.44 - aider_total: 3 + total_lines: 1249 +- aider_percentage: 3.29 + aider_total: 8 end_date: '2024-05-07' end_tag: v0.32.0 file_counts: @@ -1166,9 +1166,9 @@ aider/coders/__init__.py: Paul Gauthier: 2 aider/coders/base_coder.py: - Paul Gauthier: 55 + Paul Gauthier: 54 aider/coders/editblock_coder.py: - Paul Gauthier: 4 + Paul Gauthier: 3 aider/coders/editblock_fenced_coder.py: Paul Gauthier: 11 aider/gui.py: @@ -1177,24 +1177,25 @@ Paul Gauthier: 5 Paul Gauthier (aider): 3 aider/models.py: - Paul Gauthier: 54 + Paul Gauthier: 45 aider/sendchat.py: Paul Gauthier: 10 aider/utils.py: Paul Gauthier: 1 benchmark/benchmark.py: - Paul Gauthier: 86 + Paul Gauthier: 78 + Paul Gauthier (aider): 5 benchmark/plots.py: - Paul Gauthier: 417 + Paul Gauthier: 3 tests/test_main.py: - Paul Gauthier: 18 + Paul Gauthier: 10 tests/test_sendchat.py: Paul Gauthier: 4 grand_total: - Paul Gauthier: 676 - Paul Gauthier (aider): 3 + Paul Gauthier: 235 + Paul Gauthier (aider): 8 start_tag: v0.31.0 - total_lines: 679 + total_lines: 243 - aider_percentage: 0.0 aider_total: 0 end_date: '2024-05-08' @@ -1211,15 +1212,15 @@ aider/main.py: Paul Gauthier: 1 aider/models.py: - Paul Gauthier: 9 + Paul Gauthier: 3 aider/sendchat.py: Paul Gauthier: 1 aider/voice.py: Paul Gauthier: 2 grand_total: - Paul Gauthier: 27 + Paul Gauthier: 21 start_tag: v0.32.0 - total_lines: 27 + total_lines: 21 - aider_percentage: 0.0 aider_total: 0 end_date: '2024-05-10' @@ -1234,18 +1235,18 @@ aider/main.py: Paul Gauthier: 9 aider/models.py: - Paul Gauthier: 14 + Paul Gauthier: 7 aider/repomap.py: Paul Gauthier: 3 aider/sendchat.py: - Paul Gauthier: 7 + Paul Gauthier: 6 tests/test_sendchat.py: Paul Gauthier: 4 grand_total: - Paul Gauthier: 62 + Paul Gauthier: 54 start_tag: v0.33.0 - total_lines: 62 -- aider_percentage: 6.42 + total_lines: 54 +- aider_percentage: 6.8 aider_total: 17 end_date: '2024-05-13' end_tag: v0.35.0 @@ -1253,36 +1254,36 @@ aider/__init__.py: Paul Gauthier: 1 aider/args.py: - Paul Gauthier: 18 + Paul Gauthier: 15 Paul Gauthier (aider): 5 aider/coders/base_coder.py: Paul Gauthier: 22 Paul Gauthier (aider): 1 aider/coders/editblock_coder.py: - Paul Gauthier: 84 + Paul Gauthier: 82 Paul Gauthier (aider): 10 aider/history.py: Paul Gauthier: 20 aider/io.py: - Paul Gauthier: 8 + Paul Gauthier: 7 aider/main.py: Paul Gauthier: 1 Paul Gauthier (aider): 1 aider/models.py: - Paul Gauthier: 25 + Paul Gauthier: 18 aider/sendchat.py: - Paul Gauthier: 8 + Paul Gauthier: 6 aider/utils.py: Paul Gauthier: 51 aider/versioncheck.py: Paul Gauthier: 10 grand_total: - Paul Gauthier: 248 + Paul Gauthier: 233 Paul Gauthier (aider): 17 start_tag: v0.34.0 - total_lines: 265 -- aider_percentage: 14.42 - aider_total: 89 + total_lines: 250 +- aider_percentage: 15.38 + aider_total: 92 end_date: '2024-05-22' end_tag: v0.36.0 file_counts: @@ -1291,15 +1292,15 @@ aider/__init__.py: Paul Gauthier: 1 aider/args.py: - Paul Gauthier: 43 - Paul Gauthier (aider): 1 + Paul Gauthier: 37 + Paul Gauthier (aider): 3 aider/coders/base_coder.py: - Paul Gauthier: 113 + Paul Gauthier: 110 Paul Gauthier (aider): 3 aider/coders/wholefile_coder.py: Paul Gauthier (aider): 2 aider/commands.py: - Paul Gauthier: 49 + Paul Gauthier: 45 aider/io.py: Paul Gauthier: 9 aider/linter.py: @@ -1311,15 +1312,15 @@ Paul Gauthier: 48 Paul Gauthier (aider): 2 aider/models.py: - Paul Gauthier: 11 + Paul Gauthier: 3 aider/repo.py: Paul Gauthier: 4 Paul Gauthier (aider): 14 benchmark/benchmark.py: Paul Gauthier: 5 benchmark/over_time.py: - Paul Gauthier: 30 - Paul Gauthier (aider): 27 + Paul Gauthier: 29 + Paul Gauthier (aider): 28 scripts/jekyll_build.sh: Paul Gauthier: 1 Paul Gauthier (aider): 3 @@ -1327,11 +1328,11 @@ Paul Gauthier: 1 Paul Gauthier (aider): 3 grand_total: - Paul Gauthier: 528 - Paul Gauthier (aider): 89 + Paul Gauthier: 506 + Paul Gauthier (aider): 92 start_tag: v0.35.0 - total_lines: 617 -- aider_percentage: 18.65 + total_lines: 598 +- aider_percentage: 19.06 aider_total: 113 end_date: '2024-06-04' end_tag: v0.37.0 @@ -1339,7 +1340,7 @@ aider/__init__.py: Paul Gauthier: 1 aider/coders/base_coder.py: - Paul Gauthier: 73 + Paul Gauthier: 71 Paul Gauthier (aider): 3 aider/coders/editblock_coder.py: Paul Gauthier: 1 @@ -1348,14 +1349,14 @@ Aleksandr Bobrov (aider): 1 Paul Gauthier: 24 aider/io.py: - Paul Gauthier: 7 + Paul Gauthier: 6 Paul Gauthier (aider): 1 aider/linter.py: Paul Gauthier: 4 aider/litellm.py: Paul Gauthier: 1 aider/repomap.py: - Paul Gauthier: 115 + Paul Gauthier: 113 aider/sendchat.py: Paul Gauthier: 2 aider/voice.py: @@ -1363,23 +1364,23 @@ benchmark/over_time.py: Paul Gauthier (aider): 7 benchmark/swe_bench.py: - Paul Gauthier: 101 - Paul Gauthier (aider): 30 + Paul Gauthier: 99 + Paul Gauthier (aider): 24 scripts/blame.py: - Paul Gauthier: 159 - Paul Gauthier (aider): 53 + Paul Gauthier: 153 + Paul Gauthier (aider): 59 tests/test_io.py: Paul Gauthier: 4 Paul Gauthier (aider): 14 grand_total: Aleksandr Bobrov: 1 Aleksandr Bobrov (aider): 1 - Paul Gauthier: 492 + Paul Gauthier: 479 Paul Gauthier (aider): 112 start_tag: v0.36.0 - total_lines: 606 -- aider_percentage: 7.8 - aider_total: 44 + total_lines: 593 +- aider_percentage: 9.53 + aider_total: 53 end_date: '2024-06-16' end_tag: v0.38.0 file_counts: @@ -1398,15 +1399,15 @@ Paul Gauthier: 1 aider/args.py: Krazer: 4 - Paul Gauthier: 58 + Paul Gauthier: 57 develmusa: 1 aider/args_formatter.py: - Paul Gauthier: 125 - Paul Gauthier (aider): 11 + Paul Gauthier: 116 + Paul Gauthier (aider): 20 aider/coders/base_coder.py: - Paul Gauthier: 78 + Paul Gauthier: 77 aider/commands.py: - Paul Gauthier: 35 + Paul Gauthier: 29 aider/gui.py: Paul Gauthier: 22 aider/io.py: @@ -1439,13 +1440,13 @@ Paul Gauthier: 4 grand_total: Krazer: 28 - Paul Gauthier: 491 - Paul Gauthier (aider): 44 + Paul Gauthier: 474 + Paul Gauthier (aider): 53 develmusa: 1 start_tag: v0.37.0 - total_lines: 564 -- aider_percentage: 24.93 - aider_total: 95 + total_lines: 556 +- aider_percentage: 15.56 + aider_total: 47 end_date: '2024-06-20' end_tag: v0.39.0 file_counts: @@ -1455,13 +1456,13 @@ Paul Gauthier (aider): 4 aider/args.py: Daniel Vainsencher: 6 - John-Mason P. Shackelford: 18 - Paul Gauthier: 23 + John-Mason P. Shackelford: 14 + Paul Gauthier: 14 aider/args_formatter.py: Paul Gauthier: 24 - Paul Gauthier (aider): 51 + Paul Gauthier (aider): 9 aider/coders/base_coder.py: - Daniel Vainsencher: 5 + Daniel Vainsencher: 4 Daniel Vainsencher (aider): 2 Paul Gauthier: 2 aider/commands.py: @@ -1472,7 +1473,7 @@ Daniel Vainsencher: 1 John-Mason P. Shackelford: 14 aider/models.py: - Paul Gauthier: 18 + Paul Gauthier: 14 aider/repo.py: Paul Gauthier: 23 aider/scrape.py: @@ -1480,29 +1481,29 @@ aider/tests/test_commands.py: Paul Gauthier: 6 aider/tests/test_main.py: - John-Mason P. Shackelford: 88 + John-Mason P. Shackelford: 80 aider/tests/test_repo.py: - Paul Gauthier: 24 - Paul Gauthier (aider): 24 + Paul Gauthier: 19 + Paul Gauthier (aider): 21 aider/urls.py: Nicolas Perez: 1 Paul Gauthier: 1 aider/utils.py: Daniel Vainsencher: 7 - Daniel Vainsencher (aider): 14 + Daniel Vainsencher (aider): 11 John-Mason P. Shackelford: 7 scripts/update-docs.sh: Paul Gauthier: 1 grand_total: - Daniel Vainsencher: 33 - Daniel Vainsencher (aider): 16 - John-Mason P. Shackelford: 127 + Daniel Vainsencher: 32 + Daniel Vainsencher (aider): 13 + John-Mason P. Shackelford: 115 Nicolas Perez: 2 - Paul Gauthier: 124 - Paul Gauthier (aider): 79 + Paul Gauthier: 106 + Paul Gauthier (aider): 34 start_tag: v0.38.0 - total_lines: 381 -- aider_percentage: 5.57 + total_lines: 302 +- aider_percentage: 6.42 aider_total: 21 end_date: '2024-06-24' end_tag: v0.40.0 @@ -1511,36 +1512,34 @@ Paul Gauthier: 1 aider/args.py: Krazer: 6 - Paul Gauthier: 44 - paul-gauthier: 5 + Paul Gauthier: 27 aider/coders/base_coder.py: Paul Gauthier: 28 aider/coders/editblock_coder.py: Paul Gauthier: 64 aider/linter.py: - Paul Gauthier: 24 + Paul Gauthier: 23 Paul Gauthier (aider): 21 aider/main.py: - Krazer: 36 + Krazer: 32 Paul Gauthier: 23 aider/models.py: - Dustin Miller: 14 + Dustin Miller: 13 Krazer: 31 - Paul Gauthier: 28 + Paul Gauthier: 16 aider/repo.py: Paul Gauthier: 26 aider/tests/test_editblock.py: - Paul Gauthier: 26 + Paul Gauthier: 16 grand_total: - Dustin Miller: 14 - Krazer: 73 - Paul Gauthier: 264 + Dustin Miller: 13 + Krazer: 69 + Paul Gauthier: 224 Paul Gauthier (aider): 21 - paul-gauthier: 5 start_tag: v0.39.0 - total_lines: 377 -- aider_percentage: 5.54 - aider_total: 15 + total_lines: 327 +- aider_percentage: 4.74 + aider_total: 11 end_date: '2024-07-01' end_tag: v0.41.0 file_counts: @@ -1549,26 +1548,26 @@ aider/__init__.py: Paul Gauthier: 1 aider/args.py: - Paul Gauthier: 25 - Paul Gauthier (aider): 6 + Paul Gauthier: 5 + Paul Gauthier (aider): 5 aider/coders/base_coder.py: - Paul Gauthier: 125 + Paul Gauthier: 122 Paul Gauthier (aider): 2 aider/coders/wholefile_coder.py: - Paul Gauthier: 3 + Paul Gauthier: 2 aider/commands.py: - Amir Elaguizy (aider): 6 + Amir Elaguizy (aider): 3 Paul Gauthier: 1 aider/gui.py: Paul Gauthier: 4 aider/main.py: - Paul Gauthier: 11 + Paul Gauthier: 10 Paul Gauthier (aider): 1 aider/mdstream.py: Paul Gauthier: 1 aider/models.py: Mitsuki Ogasahara: 3 - Paul Gauthier: 38 + Paul Gauthier: 28 aider/repo.py: Paul Gauthier: 7 aider/repomap.py: @@ -1586,12 +1585,12 @@ setup.py: Paul Gauthier: 3 grand_total: - Amir Elaguizy (aider): 6 + Amir Elaguizy (aider): 3 Mitsuki Ogasahara: 3 - Paul Gauthier: 253 - Paul Gauthier (aider): 9 + Paul Gauthier: 218 + Paul Gauthier (aider): 8 start_tag: v0.40.0 - total_lines: 271 + total_lines: 232 - aider_percentage: 2.29 aider_total: 7 end_date: '2024-07-04' @@ -1637,8 +1636,8 @@ Paul Gauthier (aider): 7 start_tag: v0.41.0 total_lines: 306 -- aider_percentage: 9.82 - aider_total: 38 +- aider_percentage: 10.61 + aider_total: 40 end_date: '2024-07-07' end_tag: v0.43.0 file_counts: @@ -1659,11 +1658,11 @@ aider/coders/__init__.py: Paul Gauthier: 2 aider/coders/base_coder.py: - Paul Gauthier: 45 + Paul Gauthier: 44 aider/coders/help_coder.py: - Paul Gauthier: 17 + Paul Gauthier: 15 aider/commands.py: - Paul Gauthier: 69 + Paul Gauthier: 63 Paul Gauthier (aider): 5 aider/help.py: Paul Gauthier: 114 @@ -1673,14 +1672,14 @@ aider/llm.py: Paul Gauthier: 1 aider/main.py: - Paul Gauthier: 36 + Paul Gauthier: 35 aider/repomap.py: Paul Gauthier: 14 aider/tests/test_commands.py: Paul Gauthier: 1 aider/tests/test_help.py: - Paul Gauthier: 7 - Paul Gauthier (aider): 24 + Paul Gauthier: 5 + Paul Gauthier (aider): 26 aider/versioncheck.py: Paul Gauthier: 2 scripts/jekyll_run.sh: @@ -1691,12 +1690,12 @@ Paul Gauthier: 6 Paul Gauthier (aider): 3 grand_total: - Paul Gauthier: 349 - Paul Gauthier (aider): 38 + Paul Gauthier: 337 + Paul Gauthier (aider): 40 start_tag: v0.42.0 - total_lines: 387 -- aider_percentage: 26.86 - aider_total: 159 + total_lines: 377 +- aider_percentage: 27.02 + aider_total: 157 end_date: '2024-07-16' end_tag: v0.44.0 file_counts: @@ -1707,7 +1706,7 @@ aider/__init__.py: Paul Gauthier: 1 aider/args.py: - Paul Gauthier: 5 + Paul Gauthier: 4 aider/args_formatter.py: Paul Gauthier: 1 aider/coders/base_coder.py: @@ -1720,16 +1719,16 @@ aider/help.py: Paul Gauthier: 20 aider/main.py: - Paul Gauthier: 22 + Paul Gauthier: 20 aider/models.py: Paul Gauthier: 11 aider/scrape.py: - Paul Gauthier: 54 + Paul Gauthier: 53 aider/utils.py: Paul Gauthier: 78 Paul Gauthier (aider): 16 aider/versioncheck.py: - Paul Gauthier: 28 + Paul Gauthier: 27 aider/voice.py: Paul Gauthier: 6 benchmark/Dockerfile: @@ -1745,26 +1744,26 @@ scripts/update-docs.sh: Paul Gauthier: 2 setup.py: - Paul Gauthier: 30 + Paul Gauthier: 26 Paul Gauthier (aider): 1 tests/basic/test_coder.py: Paul Gauthier: 25 Paul Gauthier (aider): 37 tests/browser/test_browser.py: Paul Gauthier: 13 - Paul Gauthier (aider): 18 + Paul Gauthier (aider): 16 tests/help/test_help.py: Paul Gauthier: 23 tests/scrape/test_scrape.py: Paul Gauthier: 16 Paul Gauthier (aider): 26 grand_total: - Paul Gauthier: 433 - Paul Gauthier (aider): 159 + Paul Gauthier: 424 + Paul Gauthier (aider): 157 start_tag: v0.43.0 - total_lines: 592 -- aider_percentage: 42.48 - aider_total: 113 + total_lines: 581 +- aider_percentage: 44.93 + aider_total: 93 end_date: '2024-07-18' end_tag: v0.45.0 file_counts: @@ -1780,29 +1779,29 @@ Paul Gauthier: 1 Paul Gauthier (aider): 5 aider/models.py: - Paul Gauthier: 16 + Paul Gauthier: 7 aider/repomap.py: Paul Gauthier: 1 aider/scrape.py: - Paul Gauthier: 9 + Paul Gauthier: 8 aider/versioncheck.py: Paul Gauthier: 14 tests/basic/test_coder.py: Paul Gauthier: 15 - Paul Gauthier (aider): 25 + Paul Gauthier (aider): 21 tests/basic/test_commands.py: - Paul Gauthier: 44 - Paul Gauthier (aider): 71 + Paul Gauthier: 15 + Paul Gauthier (aider): 55 tests/basic/test_main.py: Paul Gauthier: 27 Paul Gauthier (aider): 5 grand_total: - Paul Gauthier: 153 - Paul Gauthier (aider): 113 + Paul Gauthier: 114 + Paul Gauthier (aider): 93 start_tag: v0.44.0 - total_lines: 266 -- aider_percentage: 53.3 - aider_total: 339 + total_lines: 207 +- aider_percentage: 52.87 + aider_total: 313 end_date: '2024-07-29' end_tag: v0.46.0 file_counts: @@ -1817,7 +1816,7 @@ Your Name: 9 aider/coders/base_coder.py: Paul Gauthier: 17 - Paul Gauthier (aider): 45 + Paul Gauthier (aider): 43 Your Name: 27 Your Name (aider): 6 aider/coders/editblock_coder.py: @@ -1833,19 +1832,19 @@ Your Name (aider): 2 aider/commands.py: Paul Gauthier: 43 - Your Name: 28 - Your Name (aider): 34 + Your Name: 26 + Your Name (aider): 25 aider/io.py: Paul Gauthier: 3 aider/llm.py: - Paul Gauthier: 11 + Paul Gauthier: 10 aider/main.py: Paul Gauthier: 3 Paul Gauthier (aider): 8 Your Name: 6 Your Name (aider): 1 aider/models.py: - Paul Gauthier: 24 + Paul Gauthier: 9 aider/queries/tree-sitter-elm-tags.scm: Charles Joachim: 4 aider/repomap.py: @@ -1865,37 +1864,37 @@ Paul Gauthier (aider): 13 tests/basic/test_repomap.py: Paul Gauthier: 70 - Paul Gauthier (aider): 25 + Paul Gauthier (aider): 10 tests/scrape/test_scrape.py: Paul Gauthier: 14 Paul Gauthier (aider): 73 grand_total: Charles Joachim: 4 - Paul Gauthier: 220 - Paul Gauthier (aider): 289 - Your Name: 73 - Your Name (aider): 50 + Paul Gauthier: 204 + Paul Gauthier (aider): 272 + Your Name: 71 + Your Name (aider): 41 start_tag: v0.45.0 - total_lines: 636 -- aider_percentage: 57.16 - aider_total: 415 + total_lines: 592 +- aider_percentage: 56.98 + aider_total: 355 end_date: '2024-07-31' end_tag: v0.47.0 file_counts: .github/workflows/docker-release.yml: - Paul Gauthier (aider): 50 + Paul Gauthier (aider): 20 .github/workflows/release.yml: Paul Gauthier (aider): 2 aider/__init__.py: Paul Gauthier: 1 aider/args.py: - Paul Gauthier: 12 + Paul Gauthier: 4 Paul Gauthier (aider): 5 aider/coders/base_coder.py: - Paul Gauthier: 21 + Paul Gauthier: 8 Paul Gauthier (aider): 3 aider/commands.py: - Paul Gauthier: 23 + Paul Gauthier: 20 Paul Gauthier (aider): 4 aider/history.py: Paul Gauthier: 16 @@ -1907,7 +1906,7 @@ Paul Gauthier: 14 Paul Gauthier (aider): 1 aider/main.py: - Paul Gauthier: 9 + Paul Gauthier: 3 Paul Gauthier (aider): 1 aider/queries/tree-sitter-ocaml-tags.scm: Paul Gauthier: 12 @@ -1924,37 +1923,38 @@ aider/utils.py: Paul Gauthier: 7 aider/website/docs/leaderboards/index.md: - Paul Gauthier: 24 + Paul Gauthier: 11 + Paul Gauthier (aider): 12 docker/Dockerfile: Paul Gauthier: 19 - Paul Gauthier (aider): 21 + Paul Gauthier (aider): 18 scripts/blame.py: - Paul Gauthier: 64 - Paul Gauthier (aider): 117 + Paul Gauthier: 65 + Paul Gauthier (aider): 99 scripts/update-blame.sh: Paul Gauthier: 6 scripts/update-docs.sh: Paul Gauthier: 1 tests/basic/test_coder.py: - Paul Gauthier: 33 + Paul Gauthier: 32 Paul Gauthier (aider): 4 tests/basic/test_commands.py: Paul Gauthier: 11 - Paul Gauthier (aider): 43 + Paul Gauthier (aider): 25 tests/basic/test_history.py: Paul Gauthier (aider): 109 tests/basic/test_repo.py: Paul Gauthier: 4 - Paul Gauthier (aider): 12 + Paul Gauthier (aider): 9 tests/basic/test_repomap.py: Paul Gauthier: 1 grand_total: - Paul Gauthier: 311 - Paul Gauthier (aider): 415 + Paul Gauthier: 268 + Paul Gauthier (aider): 355 start_tag: v0.46.0 - total_lines: 726 -- aider_percentage: 44.44 - aider_total: 276 + total_lines: 623 +- aider_percentage: 45.67 + aider_total: 269 end_date: '2024-08-06' end_tag: v0.48.0 file_counts: @@ -1974,18 +1974,18 @@ aider/history.py: Paul Gauthier: 2 aider/main.py: - Paul Gauthier: 21 + Paul Gauthier: 20 Paul Gauthier (aider): 30 aider/models.py: Paul Gauthier: 9 Paul Gauthier (aider): 7 Thinh Nguyen: 1 aider/repo.py: - Paul Gauthier: 51 + Paul Gauthier: 42 Paul Gauthier (aider): 23 aider/repomap.py: - Paul Gauthier: 62 - Paul Gauthier (aider): 2 + Paul Gauthier: 60 + Paul Gauthier (aider): 3 aider/sendchat.py: Paul Gauthier: 26 Paul Gauthier (aider): 2 @@ -1995,71 +1995,71 @@ scripts/blame.py: Paul Gauthier (aider): 2 tests/basic/test_coder.py: - Paul Gauthier: 13 + Paul Gauthier: 10 tests/basic/test_commands.py: Paul Gauthier: 19 - Paul Gauthier (aider): 18 + Paul Gauthier (aider): 14 tests/basic/test_history.py: Paul Gauthier: 2 tests/basic/test_main.py: - Paul Gauthier: 25 - Paul Gauthier (aider): 42 + Paul Gauthier: 15 + Paul Gauthier (aider): 39 tests/basic/test_repo.py: Paul Gauthier: 8 - Paul Gauthier (aider): 36 + Paul Gauthier (aider): 35 tests/basic/test_scripting.py: Paul Gauthier (aider): 39 grand_total: - Paul Gauthier: 343 - Paul Gauthier (aider): 276 + Paul Gauthier: 318 + Paul Gauthier (aider): 269 Thinh Nguyen: 1 paul-gauthier: 1 start_tag: v0.47.0 - total_lines: 621 -- aider_percentage: 61.2 - aider_total: 489 + total_lines: 589 +- aider_percentage: 59.83 + aider_total: 429 end_date: '2024-08-10' end_tag: v0.49.0 file_counts: aider/__init__.py: Paul Gauthier: 1 aider/args.py: - Paul Gauthier: 9 - Paul Gauthier (aider): 13 + Paul Gauthier: 7 + Paul Gauthier (aider): 9 aider/coders/base_coder.py: - Paul Gauthier: 91 - Paul Gauthier (aider): 44 + Paul Gauthier: 81 + Paul Gauthier (aider): 41 aider/commands.py: Paul Gauthier: 34 - Paul Gauthier (aider): 108 + Paul Gauthier (aider): 105 aider/io.py: Paul Gauthier: 7 - Paul Gauthier (aider): 24 + Paul Gauthier (aider): 23 aider/llm.py: Paul Gauthier (aider): 5 aider/main.py: Paul Gauthier: 1 Paul Gauthier (aider): 4 aider/models.py: - Paul Gauthier: 34 + Paul Gauthier: 17 Paul Gauthier (aider): 3 aider/repo.py: Paul Gauthier: 8 - Paul Gauthier (aider): 13 + Paul Gauthier (aider): 12 aider/repomap.py: Paul Gauthier: 11 Paul Gauthier (aider): 23 aider/scrape.py: Paul Gauthier (aider): 17 aider/sendchat.py: - Paul Gauthier: 21 + Paul Gauthier: 20 aider/urls.py: Paul Gauthier: 1 aider/utils.py: Paul Gauthier (aider): 11 aider/versioncheck.py: Paul Gauthier: 3 - Paul Gauthier (aider): 11 + Paul Gauthier (aider): 9 aider/website/docs/leaderboards/index.md: Paul Gauthier: 11 Paul Gauthier (aider): 11 @@ -2067,28 +2067,28 @@ Paul Gauthier: 5 Paul Gauthier (aider): 2 tests/basic/test_coder.py: - Paul Gauthier (aider): 7 + Paul Gauthier (aider): 5 tests/basic/test_commands.py: - Paul Gauthier: 25 - Paul Gauthier (aider): 109 + Paul Gauthier: 35 + Paul Gauthier (aider): 83 tests/basic/test_editblock.py: Paul Gauthier (aider): 1 tests/basic/test_main.py: - Paul Gauthier (aider): 33 + Paul Gauthier (aider): 28 tests/basic/test_sendchat.py: - Paul Gauthier: 47 + Paul Gauthier: 45 tests/basic/test_wholefile.py: Paul Gauthier (aider): 1 tests/scrape/test_scrape.py: Paul Gauthier: 1 - Paul Gauthier (aider): 49 + Paul Gauthier (aider): 36 grand_total: - Paul Gauthier: 310 - Paul Gauthier (aider): 489 + Paul Gauthier: 288 + Paul Gauthier (aider): 429 start_tag: v0.48.0 - total_lines: 799 -- aider_percentage: 66.05 - aider_total: 214 + total_lines: 717 +- aider_percentage: 65.23 + aider_total: 182 end_date: '2024-08-13' end_tag: v0.50.0 file_counts: @@ -2097,14 +2097,14 @@ aider/__init__.py: Paul Gauthier: 1 aider/args.py: - Paul Gauthier (aider): 10 + Paul Gauthier (aider): 8 aider/coders/base_coder.py: Paul Gauthier: 24 - Paul Gauthier (aider): 32 + Paul Gauthier (aider): 30 aider/commands.py: - Amir Elaguizy (aider): 13 - Paul Gauthier: 28 - Paul Gauthier (aider): 18 + Amir Elaguizy (aider): 11 + Paul Gauthier: 26 + Paul Gauthier (aider): 15 aider/io.py: Paul Gauthier: 1 aider/main.py: @@ -2127,24 +2127,24 @@ Paul Gauthier (aider): 34 tests/basic/test_coder.py: Paul Gauthier: 3 - Paul Gauthier (aider): 24 + Paul Gauthier (aider): 16 tests/basic/test_commands.py: - Paul Gauthier: 18 - Paul Gauthier (aider): 41 + Paul Gauthier: 7 + Paul Gauthier (aider): 27 tests/basic/test_main.py: Paul Gauthier: 1 - Paul Gauthier (aider): 8 + Paul Gauthier (aider): 7 tests/help/test_help.py: Paul Gauthier: 7 grand_total: - Amir Elaguizy (aider): 13 + Amir Elaguizy (aider): 11 Branch Vincent: 2 - Paul Gauthier: 108 - Paul Gauthier (aider): 201 + Paul Gauthier: 95 + Paul Gauthier (aider): 171 start_tag: v0.49.0 - total_lines: 324 -- aider_percentage: 52.49 - aider_total: 580 + total_lines: 279 +- aider_percentage: 56.95 + aider_total: 582 end_date: '2024-08-20' end_tag: v0.51.0 file_counts: @@ -2152,14 +2152,14 @@ Paul Gauthier: 1 aider/args.py: Paul Gauthier: 2 - Paul Gauthier (aider): 10 + Paul Gauthier (aider): 8 aider/coders/__init__.py: - Paul Gauthier: 4 + Paul Gauthier: 3 aider/coders/base_coder.py: - Paul Gauthier: 172 - Paul Gauthier (aider): 60 + Paul Gauthier: 168 + Paul Gauthier (aider): 45 aider/coders/single_wholefile_func_coder.py: - Paul Gauthier: 29 + Paul Gauthier: 28 aider/commands.py: Paul Gauthier: 3 Paul Gauthier (aider): 5 @@ -2167,13 +2167,13 @@ Paul Gauthier: 2 aider/main.py: Paul Gauthier: 6 - Paul Gauthier (aider): 16 + Paul Gauthier (aider): 13 aider/models.py: - Paul Gauthier: 45 - Paul Gauthier (aider): 2 + Paul Gauthier: 35 + Paul Gauthier (aider): 4 aider/repomap.py: - Paul Gauthier: 16 - Paul Gauthier (aider): 58 + Paul Gauthier: 11 + Paul Gauthier (aider): 55 aider/sendchat.py: Paul Gauthier: 3 aider/utils.py: @@ -2182,8 +2182,8 @@ Paul Gauthier: 101 Paul Gauthier (aider): 64 aider/website/_includes/code-in-json-syntax.js: - Paul Gauthier: 73 - Paul Gauthier (aider): 66 + Paul Gauthier: 23 + Paul Gauthier (aider): 116 aider/website/docs/leaderboards/index.md: Paul Gauthier: 1 benchmark/benchmark.py: @@ -2198,18 +2198,18 @@ tests/basic/test_commands.py: Paul Gauthier: 5 tests/basic/test_main.py: - Paul Gauthier: 16 - Paul Gauthier (aider): 115 + Paul Gauthier: 4 + Paul Gauthier (aider): 92 tests/basic/test_repomap.py: - Paul Gauthier: 15 - Paul Gauthier (aider): 104 + Paul Gauthier: 13 + Paul Gauthier (aider): 100 grand_total: - Paul Gauthier: 525 - Paul Gauthier (aider): 580 + Paul Gauthier: 440 + Paul Gauthier (aider): 582 start_tag: v0.50.0 - total_lines: 1105 -- aider_percentage: 68.1 - aider_total: 521 + total_lines: 1022 +- aider_percentage: 67.74 + aider_total: 485 end_date: '2024-08-23' end_tag: v0.52.0 file_counts: @@ -2219,22 +2219,22 @@ Paul Gauthier: 2 Paul Gauthier (aider): 6 aider/coders/base_coder.py: - Paul Gauthier: 88 - Paul Gauthier (aider): 15 + Paul Gauthier: 77 + Paul Gauthier (aider): 25 aider/coders/chat_chunks.py: Paul Gauthier (aider): 53 aider/coders/editblock_coder.py: - Paul Gauthier: 45 - Paul Gauthier (aider): 68 + Paul Gauthier: 42 + Paul Gauthier (aider): 67 aider/coders/wholefile_coder.py: Paul Gauthier: 1 aider/commands.py: Paul Gauthier: 5 - Paul Gauthier (aider): 42 + Paul Gauthier (aider): 40 pcamp: 1 aider/io.py: - Paul Gauthier: 40 - Paul Gauthier (aider): 41 + Paul Gauthier: 41 + Paul Gauthier (aider): 40 aider/main.py: Paul Gauthier: 2 aider/models.py: @@ -2254,7 +2254,7 @@ scripts/blame.py: Paul Gauthier: 1 tests/basic/test_commands.py: - Paul Gauthier (aider): 100 + Paul Gauthier (aider): 74 tests/basic/test_editblock.py: Paul Gauthier (aider): 1 tests/basic/test_find_or_blocks.py: @@ -2264,17 +2264,17 @@ Paul Gauthier (aider): 32 tests/basic/test_main.py: Paul Gauthier: 2 - Paul Gauthier (aider): 43 + Paul Gauthier (aider): 27 tests/basic/test_wholefile.py: Paul Gauthier: 8 grand_total: - Paul Gauthier: 243 - Paul Gauthier (aider): 521 + Paul Gauthier: 230 + Paul Gauthier (aider): 485 pcamp: 1 start_tag: v0.51.0 - total_lines: 765 -- aider_percentage: 61.4 - aider_total: 455 + total_lines: 716 +- aider_percentage: 62.36 + aider_total: 434 end_date: '2024-08-27' end_tag: v0.53.0 file_counts: @@ -2284,7 +2284,7 @@ Paul Gauthier: 2 Paul Gauthier (aider): 10 aider/coders/base_coder.py: - Paul Gauthier: 57 + Paul Gauthier: 55 Paul Gauthier (aider): 18 aider/coders/chat_chunks.py: Paul Gauthier (aider): 9 @@ -2292,7 +2292,7 @@ Paul Gauthier: 44 Paul Gauthier (aider): 6 aider/commands.py: - Paul Gauthier: 19 + Paul Gauthier: 18 aider/history.py: Paul Gauthier (aider): 3 aider/io.py: @@ -2313,7 +2313,7 @@ Paul Gauthier: 7 Paul Gauthier (aider): 11 aider/utils.py: - Paul Gauthier: 12 + Paul Gauthier: 9 Paul Gauthier (aider): 9 aider/versioncheck.py: Paul Gauthier: 2 @@ -2321,13 +2321,13 @@ scripts/versionbump.py: Paul Gauthier: 1 tests/basic/test_commands.py: - Paul Gauthier: 23 - tests/basic/test_editblock.py: Paul Gauthier: 6 - Paul Gauthier (aider): 26 + tests/basic/test_editblock.py: + Paul Gauthier: 5 + Paul Gauthier (aider): 27 tests/basic/test_io.py: Paul Gauthier: 2 - Paul Gauthier (aider): 66 + Paul Gauthier (aider): 44 tests/basic/test_main.py: Paul Gauthier: 2 tests/basic/test_models.py: @@ -2344,12 +2344,12 @@ tests/fixtures/sample-code-base/sample.py: Paul Gauthier (aider): 68 grand_total: - Paul Gauthier: 286 - Paul Gauthier (aider): 455 + Paul Gauthier: 262 + Paul Gauthier (aider): 434 start_tag: v0.52.0 - total_lines: 741 -- aider_percentage: 63.75 - aider_total: 204 + total_lines: 696 +- aider_percentage: 67.4 + aider_total: 184 end_date: '2024-08-28' end_tag: v0.54.0 file_counts: @@ -2363,7 +2363,7 @@ Paul Gauthier: 1 aider/args.py: Paul Gauthier: 1 - Paul Gauthier (aider): 12 + Paul Gauthier (aider): 10 aider/coders/base_coder.py: Paul Gauthier: 25 Paul Gauthier (aider): 12 @@ -2374,36 +2374,37 @@ Paul Gauthier: 28 aider/main.py: Paul Gauthier: 2 - Paul Gauthier (aider): 6 + Paul Gauthier (aider): 4 aider/models.py: - Paul Gauthier (aider): 11 + Paul Gauthier (aider): 7 aider/run_cmd.py: - Paul Gauthier (aider): 72 + Paul Gauthier: 3 + Paul Gauthier (aider): 66 aider/utils.py: - Paul Gauthier (aider): 15 + Paul Gauthier (aider): 14 aider/versioncheck.py: Paul Gauthier: 1 - Paul Gauthier (aider): 13 + Paul Gauthier (aider): 9 aider/website/docs/leaderboards/index.md: Paul Gauthier: 1 tests/basic/test_coder.py: - Paul Gauthier: 36 - Paul Gauthier (aider): 27 + Paul Gauthier: 6 + Paul Gauthier (aider): 43 tests/basic/test_io.py: Paul Gauthier: 4 tests/basic/test_main.py: Antti Kaihola: 4 - Paul Gauthier (aider): 29 + Paul Gauthier (aider): 12 tests/scrape/test_scrape.py: Paul Gauthier: 1 grand_total: Antti Kaihola: 4 - Paul Gauthier: 112 - Paul Gauthier (aider): 204 + Paul Gauthier: 85 + Paul Gauthier (aider): 184 start_tag: v0.53.0 - total_lines: 320 -- aider_percentage: 52.87 - aider_total: 811 + total_lines: 273 +- aider_percentage: 52.82 + aider_total: 759 end_date: '2024-09-04' end_tag: v0.55.0 file_counts: @@ -2413,8 +2414,8 @@ aider/args.py: Paul Gauthier (aider): 7 aider/coders/base_coder.py: - Paul Gauthier: 63 - Paul Gauthier (aider): 42 + Paul Gauthier: 62 + Paul Gauthier (aider): 39 aider/coders/editblock_coder.py: Nikolay Sedelnikov: 8 aider/coders/editblock_func_coder.py: @@ -2425,15 +2426,15 @@ Paul Gauthier: 16 aider/commands.py: Antti Kaihola: 7 - Paul Gauthier: 85 - Paul Gauthier (aider): 27 + Paul Gauthier: 74 + Paul Gauthier (aider): 25 aider/format_settings.py: - Paul Gauthier (aider): 26 + Paul Gauthier (aider): 2 aider/gui.py: Paul Gauthier: 4 aider/io.py: - Paul Gauthier: 63 - Paul Gauthier (aider): 13 + Paul Gauthier: 56 + Paul Gauthier (aider): 11 aider/linter.py: Paul Gauthier: 5 aider/llm.py: @@ -2467,7 +2468,7 @@ Paul Gauthier: 31 Paul Gauthier (aider): 29 aider/versioncheck.py: - Paul Gauthier: 32 + Paul Gauthier: 22 Paul Gauthier (aider): 6 aider/voice.py: Paul Gauthier: 7 @@ -2475,23 +2476,23 @@ aider/website/docs/leaderboards/index.md: Paul Gauthier: 1 scripts/versionbump.py: - Paul Gauthier: 9 + Paul Gauthier: 7 tests/basic/test_coder.py: Paul Gauthier: 3 - Paul Gauthier (aider): 105 + Paul Gauthier (aider): 96 tests/basic/test_editblock.py: Antti Kaihola: 3 - Nikolay Sedelnikov: 37 + Nikolay Sedelnikov: 23 tests/basic/test_io.py: Paul Gauthier: 2 - Paul Gauthier (aider): 15 + Paul Gauthier (aider): 14 tests/basic/test_main.py: Paul Gauthier: 2 Paul Gauthier (aider): 10 tests/basic/test_models.py: Paul Gauthier (aider): 4 tests/basic/test_repomap.py: - Paul Gauthier (aider): 42 + Paul Gauthier (aider): 31 tests/basic/test_run_cmd.py: Paul Gauthier (aider): 11 tests/basic/test_special.py: @@ -2501,13 +2502,13 @@ Paul Gauthier (aider): 11 grand_total: Antti Kaihola: 12 - Nikolay Sedelnikov: 45 - Paul Gauthier: 666 - Paul Gauthier (aider): 811 + Nikolay Sedelnikov: 31 + Paul Gauthier: 635 + Paul Gauthier (aider): 759 start_tag: v0.54.0 - total_lines: 1534 -- aider_percentage: 55.4 - aider_total: 154 + total_lines: 1437 +- aider_percentage: 56.23 + aider_total: 149 end_date: '2024-09-09' end_tag: v0.56.0 file_counts: @@ -2527,15 +2528,15 @@ aider/linter.py: Paul Gauthier: 6 Paul Gauthier (aider): 4 - fry69: 12 + fry69: 9 aider/main.py: - Paul Gauthier: 35 - Paul Gauthier (aider): 48 + Paul Gauthier: 32 + Paul Gauthier (aider): 49 aider/models.py: Paul Gauthier: 2 fry69: 3 aider/repo.py: - Paul Gauthier: 16 + Paul Gauthier: 14 aider/repomap.py: Paul Gauthier: 13 aider/report.py: @@ -2550,15 +2551,15 @@ Paul Gauthier (aider): 51 tests/basic/test_main.py: Paul Gauthier: 2 - Paul Gauthier (aider): 9 + Paul Gauthier (aider): 3 grand_total: - Paul Gauthier: 109 - Paul Gauthier (aider): 154 - fry69: 15 + Paul Gauthier: 104 + Paul Gauthier (aider): 149 + fry69: 12 start_tag: v0.55.0 - total_lines: 278 -- aider_percentage: 70.36 - aider_total: 406 + total_lines: 265 +- aider_percentage: 70.27 + aider_total: 390 end_date: '2024-09-21' end_tag: v0.57.0 file_counts: @@ -2569,10 +2570,10 @@ Paul Gauthier (aider): 1 aider/coders/base_coder.py: Krazer: 1 - Paul Gauthier: 17 + Paul Gauthier: 14 Paul Gauthier (aider): 2 aider/coders/chat_chunks.py: - Paul Gauthier: 5 + Paul Gauthier: 4 aider/coders/editblock_coder.py: Paul Gauthier (aider): 27 aider/commands.py: @@ -2580,22 +2581,21 @@ Paul Gauthier: 1 Paul Gauthier (aider): 34 aider/io.py: - Krazer: 27 + Krazer: 23 Paul Gauthier: 8 Paul Gauthier (aider): 42 aider/main.py: - Krazer: 2 Paul Gauthier: 5 Paul Gauthier (aider): 8 aider/models.py: Jay Alammar: 1 Jay Alammar (aider): 13 - Paul Gauthier: 43 - Paul Gauthier (aider): 46 + Paul Gauthier: 48 + Paul Gauthier (aider): 30 aider/repo.py: Paul Gauthier: 3 aider/run_cmd.py: - Paul Gauthier: 8 + Paul Gauthier: 7 Paul Gauthier (aider): 33 aider/sendchat.py: Paul Gauthier: 3 @@ -2626,36 +2626,35 @@ Christian Clauss: 2 Jay Alammar: 1 Jay Alammar (aider): 13 - Krazer: 33 + Krazer: 27 Paul Gauthier: 134 - Paul Gauthier (aider): 393 + Paul Gauthier (aider): 377 start_tag: v0.56.0 - total_lines: 577 -- aider_percentage: 47.95 - aider_total: 712 + total_lines: 555 +- aider_percentage: 44.68 + aider_total: 600 end_date: '2024-09-29' end_tag: v0.58.0 file_counts: .github/workflows/docker-build-test.yml: Paul Gauthier: 1 - Paul Gauthier (aider): 11 + Paul Gauthier (aider): 5 aider/__init__.py: Paul Gauthier: 1 aider/args.py: + Mike Bailey: 7 Paul Gauthier: 8 - Paul Gauthier (aider): 109 + Paul Gauthier (aider): 51 Stein Martin Hustad: 17 fry69: 2 aider/coders/__init__.py: Paul Gauthier: 6 - Paul Gauthier (aider): 2 aider/coders/architect_coder.py: Paul Gauthier: 40 Paul Gauthier (aider): 3 aider/coders/base_coder.py: - Jonathan Ellis: 1 Paul Gauthier: 32 - Paul Gauthier (aider): 8 + Paul Gauthier (aider): 4 aider/coders/editor_editblock_coder.py: Paul Gauthier: 6 Paul Gauthier (aider): 1 @@ -2666,8 +2665,8 @@ aider/commands.py: Jonathan Ellis: 1 Mike Bailey: 1 - Paul Gauthier: 20 - Paul Gauthier (aider): 78 + Paul Gauthier: 17 + Paul Gauthier (aider): 77 fry69: 2 aider/help.py: Paul Gauthier: 27 @@ -2675,12 +2674,12 @@ aider/history.py: Paul Gauthier: 1 aider/io.py: - Paul Gauthier: 39 + Paul Gauthier: 38 Paul Gauthier (aider): 62 Stein Martin Hustad: 5 - fry69: 10 + fry69: 9 aider/linter.py: - Paul Gauthier: 6 + Paul Gauthier: 5 aider/main.py: Paul Gauthier: 13 Paul Gauthier (aider): 6 @@ -2689,7 +2688,7 @@ rti: 1 aider/models.py: Paul Gauthier: 58 - Paul Gauthier (aider): 85 + Paul Gauthier (aider): 79 aider/repo.py: Paul Gauthier: 16 Paul Gauthier (aider): 2 @@ -2707,26 +2706,26 @@ aider/voice.py: Mike Bailey: 17 Paul Gauthier: 2 - Paul Gauthier (aider): 10 + Paul Gauthier (aider): 6 aider/website/docs/leaderboards/index.md: - Paul Gauthier: 153 + Paul Gauthier: 152 benchmark/benchmark.py: Paul Gauthier: 25 Paul Gauthier (aider): 29 fry69: 3 scripts/issues.py: Paul Gauthier: 5 - Paul Gauthier (aider): 45 + Paul Gauthier (aider): 43 scripts/update-docs.sh: Paul Gauthier: 1 scripts/yank-old-versions.py: Paul Gauthier (aider): 51 tests/basic/test_commands.py: Paul Gauthier: 2 - Paul Gauthier (aider): 98 + Paul Gauthier (aider): 82 tests/basic/test_io.py: Paul Gauthier: 2 - Paul Gauthier (aider): 97 + Paul Gauthier (aider): 84 tests/basic/test_main.py: Paul Gauthier: 2 tests/basic/test_models.py: @@ -2734,19 +2733,19 @@ tests/basic/test_sanity_check_repo.py: fry69: 179 tests/basic/test_wholefile.py: - Paul Gauthier: 38 + Paul Gauthier: 9 grand_total: - Jonathan Ellis: 2 - Mike Bailey: 18 - Paul Gauthier: 529 - Paul Gauthier (aider): 712 + Jonathan Ellis: 1 + Mike Bailey: 25 + Paul Gauthier: 494 + Paul Gauthier (aider): 600 Stein Martin Hustad: 26 - fry69: 197 + fry69: 196 rti: 1 start_tag: v0.57.0 - total_lines: 1485 -- aider_percentage: 75.44 - aider_total: 172 + total_lines: 1343 +- aider_percentage: 68.72 + aider_total: 123 end_date: '2024-10-04' end_tag: v0.59.0 file_counts: @@ -2765,7 +2764,7 @@ Paul Gauthier: 1 aider/commands.py: Paul Gauthier: 3 - Paul Gauthier (aider): 49 + Paul Gauthier (aider): 47 aider/gui.py: Paul Gauthier: 2 aider/main.py: @@ -2788,7 +2787,7 @@ Paul Gauthier: 2 tests/basic/test_commands.py: Paul Gauthier: 4 - Paul Gauthier (aider): 80 + Paul Gauthier (aider): 33 tests/basic/test_models.py: Paul Gauthier: 1 Paul Gauthier (aider): 18 @@ -2798,11 +2797,11 @@ Paul Gauthier: 1 grand_total: Paul Gauthier: 56 - Paul Gauthier (aider): 172 + Paul Gauthier (aider): 123 start_tag: v0.58.0 - total_lines: 228 -- aider_percentage: 48.95 - aider_total: 140 + total_lines: 179 +- aider_percentage: 57.2 + aider_total: 139 end_date: '2024-10-22' end_tag: v0.60.0 file_counts: @@ -2832,9 +2831,9 @@ Paul Gauthier: 20 Paul Gauthier (aider): 39 aider/models.py: - Paul Gauthier: 18 - Sven Grunewaldt: 24 - fry69: 16 + Paul Gauthier: 9 + Sven Grunewaldt: 10 + fry69: 5 aider/resources/__init__.py: Paul Gauthier: 3 aider/sendchat.py: @@ -2842,22 +2841,22 @@ aider/website/docs/leaderboards/index.md: Paul Gauthier: 1 tests/basic/test_editblock.py: - Paul Gauthier: 23 + Paul Gauthier: 15 tests/basic/test_main.py: Paul Gauthier: 1 tests/help/test_help.py: Paul Gauthier: 4 - Paul Gauthier (aider): 46 + Paul Gauthier (aider): 45 grand_total: Jonathan Ellis: 10 - Paul Gauthier: 94 - Paul Gauthier (aider): 140 - Sven Grunewaldt: 24 - fry69: 18 + Paul Gauthier: 77 + Paul Gauthier (aider): 139 + Sven Grunewaldt: 10 + fry69: 7 start_tag: v0.59.0 - total_lines: 286 -- aider_percentage: 67.61 - aider_total: 860 + total_lines: 243 +- aider_percentage: 67.04 + aider_total: 781 end_date: '2024-11-01' end_tag: v0.61.0 file_counts: @@ -2867,31 +2866,31 @@ Paul Gauthier: 75 Paul Gauthier (aider): 89 aider/args.py: - Paul Gauthier: 5 - Paul Gauthier (aider): 29 + Paul Gauthier: 9 + Paul Gauthier (aider): 21 aider/coders/base_coder.py: - Paul Gauthier: 56 + Paul Gauthier: 55 Paul Gauthier (aider): 43 aider/coders/editblock_coder.py: Paul Gauthier: 14 aider/commands.py: - Paul Gauthier: 14 - Paul Gauthier (aider): 86 + Paul Gauthier: 12 + Paul Gauthier (aider): 88 aider/io.py: Paul Gauthier: 12 Paul Gauthier (aider): 32 aider/linter.py: Paul Gauthier: 6 aider/main.py: - Paul Gauthier: 48 - Paul Gauthier (aider): 10 + Paul Gauthier: 46 + Paul Gauthier (aider): 12 aider/models.py: - Paul Gauthier: 54 - Paul Gauthier (aider): 63 + Paul Gauthier: 22 + Paul Gauthier (aider): 54 kAIto47802: 4 aider/repomap.py: - Paul Gauthier: 12 - Paul Gauthier (aider): 52 + Paul Gauthier: 8 + Paul Gauthier (aider): 54 aider/sendchat.py: Paul Gauthier: 23 Paul Gauthier (aider): 23 @@ -2910,12 +2909,11 @@ Paul Gauthier: 1 Paul Gauthier (aider): 99 tests/basic/test_commands.py: - Konstantin L: 34 - Paul Gauthier: 45 - Paul Gauthier (aider): 267 + Konstantin L: 10 + Paul Gauthier: 80 + Paul Gauthier (aider): 197 tests/basic/test_io.py: - Paul Gauthier: 2 - Paul Gauthier (aider): 4 + Paul Gauthier (aider): 6 tests/basic/test_main.py: Paul Gauthier (aider): 3 tests/basic/test_models.py: @@ -2926,38 +2924,38 @@ tests/basic/test_sendchat.py: Paul Gauthier (aider): 8 grand_total: - Konstantin L: 34 - Paul Gauthier: 374 - Paul Gauthier (aider): 860 + Konstantin L: 10 + Paul Gauthier: 370 + Paul Gauthier (aider): 781 kAIto47802: 4 start_tag: v0.60.0 - total_lines: 1272 -- aider_percentage: 82.42 - aider_total: 75 + total_lines: 1165 +- aider_percentage: 77.78 + aider_total: 56 end_date: '2024-11-04' end_tag: v0.62.0 file_counts: aider/__init__.py: Paul Gauthier: 1 aider/args.py: - Paul Gauthier (aider): 14 + Paul Gauthier (aider): 12 aider/coders/editblock_coder.py: Paul Gauthier: 6 aider/main.py: Paul Gauthier (aider): 4 aider/models.py: Paul Gauthier: 5 - Paul Gauthier (aider): 45 + Paul Gauthier (aider): 28 aider/website/docs/leaderboards/index.md: Paul Gauthier: 4 Paul Gauthier (aider): 12 grand_total: Paul Gauthier: 16 - Paul Gauthier (aider): 75 + Paul Gauthier (aider): 56 start_tag: v0.61.0 - total_lines: 91 -- aider_percentage: 55.08 - aider_total: 385 + total_lines: 72 +- aider_percentage: 55.21 + aider_total: 350 end_date: '2024-11-13' end_tag: v0.63.0 file_counts: @@ -2982,13 +2980,13 @@ Paul Gauthier: 9 Paul Gauthier (aider): 9 aider/models.py: - Logan Attwood: 29 - Paul Gauthier: 50 - Paul Gauthier (aider): 7 + Logan Attwood: 13 + Paul Gauthier: 37 + Paul Gauthier (aider): 4 aider/repo.py: Paul Gauthier: 7 aider/repomap.py: - Paul Gauthier: 4 + Paul Gauthier: 3 aider/sendchat.py: Paul Gauthier: 17 Paul Gauthier (aider): 4 @@ -2996,11 +2994,11 @@ Paul Gauthier: 1 scripts/issues.py: Paul Gauthier: 4 - Paul Gauthier (aider): 195 + Paul Gauthier (aider): 179 tests/basic/test_coder.py: Paul Gauthier: 2 tests/basic/test_commands.py: - Paul Gauthier (aider): 20 + Paul Gauthier (aider): 13 tests/basic/test_editblock.py: Paul Gauthier: 41 tests/basic/test_exceptions.py: @@ -3012,17 +3010,17 @@ Paul Gauthier (aider): 2 tests/basic/test_sendchat.py: Paul Gauthier: 8 - Paul Gauthier (aider): 55 + Paul Gauthier (aider): 46 tests/scrape/test_scrape.py: Paul Gauthier: 1 grand_total: - Logan Attwood: 29 - Paul Gauthier: 285 - Paul Gauthier (aider): 385 + Logan Attwood: 13 + Paul Gauthier: 271 + Paul Gauthier (aider): 350 start_tag: v0.62.0 - total_lines: 699 -- aider_percentage: 73.15 - aider_total: 880 + total_lines: 634 +- aider_percentage: 73.55 + aider_total: 865 end_date: '2024-11-21' end_tag: v0.64.0 file_counts: @@ -3033,7 +3031,7 @@ Paul Gauthier (aider): 21 aider/args.py: Paul Gauthier: 2 - Paul Gauthier (aider): 10 + Paul Gauthier (aider): 9 aider/coders/base_coder.py: Paul Gauthier: 15 Paul Gauthier (aider): 3 @@ -3043,8 +3041,8 @@ Paul Gauthier: 5 Paul Gauthier (aider): 19 aider/editor.py: - Chad Phillips: 133 - Paul Gauthier (aider): 13 + Chad Phillips: 135 + Paul Gauthier (aider): 11 aider/exceptions.py: Paul Gauthier: 5 aider/help_pats.py: @@ -3054,22 +3052,22 @@ Paul Gauthier (aider): 41 mw: 21 aider/main.py: - Paul Gauthier: 21 - Paul Gauthier (aider): 41 + Paul Gauthier: 18 + Paul Gauthier (aider): 35 aider/models.py: - Paul Gauthier: 41 - Paul Gauthier (aider): 33 + Paul Gauthier: 31 + Paul Gauthier (aider): 34 aider/repo.py: Paul Gauthier (aider): 5 aider/urls.py: Paul Gauthier: 1 aider/website/_includes/edit-leaderboard.js: - Paul Gauthier (aider): 97 + Paul Gauthier (aider): 96 aider/website/_includes/quant-chart.js: Paul Gauthier: 3 - Paul Gauthier (aider): 66 + Paul Gauthier (aider): 65 aider/website/_includes/refactor-leaderboard.js: - Paul Gauthier (aider): 90 + Paul Gauthier (aider): 89 aider/website/docs/leaderboards/index.md: Paul Gauthier: 1 Paul Gauthier (aider): 10 @@ -3085,7 +3083,7 @@ Paul Gauthier: 5 Paul Gauthier (aider): 12 scripts/versionbump.py: - Paul Gauthier: 7 + Paul Gauthier: 5 tests/basic/test_analytics.py: Paul Gauthier: 12 Paul Gauthier (aider): 30 @@ -3094,20 +3092,20 @@ tests/basic/test_editor.py: Paul Gauthier (aider): 129 tests/basic/test_main.py: - Paul Gauthier (aider): 8 + Paul Gauthier (aider): 5 tests/basic/test_models.py: - Paul Gauthier: 3 - Paul Gauthier (aider): 55 + Paul Gauthier: 4 + Paul Gauthier (aider): 54 grand_total: - Chad Phillips: 146 - Paul Gauthier: 155 - Paul Gauthier (aider): 880 + Chad Phillips: 148 + Paul Gauthier: 141 + Paul Gauthier (aider): 865 caetanominuzzo: 1 mw: 21 start_tag: v0.63.0 - total_lines: 1203 -- aider_percentage: 81.11 - aider_total: 584 + total_lines: 1176 +- aider_percentage: 81.19 + aider_total: 544 end_date: '2024-11-26' end_tag: v0.65.0 file_counts: @@ -3117,7 +3115,7 @@ Paul Gauthier: 2 Paul Gauthier (aider): 5 aider/args.py: - Paul Gauthier (aider): 12 + Paul Gauthier (aider): 10 aider/coders/base_coder.py: Paul Gauthier: 1 Paul Gauthier (aider): 31 @@ -3127,13 +3125,13 @@ Paul Gauthier: 3 Paul Gauthier (aider): 9 aider/main.py: - Paul Gauthier: 15 + Paul Gauthier: 13 Paul Gauthier (aider): 19 aider/models.py: Paul Gauthier: 9 Paul Gauthier (aider): 17 aider/queries/tree-sitter-dart-tags.scm: - malkoG: 91 + malkoG: 83 aider/urls.py: Paul Gauthier (aider): 1 aider/website/_includes/quant-chart.js: @@ -3153,19 +3151,696 @@ Paul Gauthier: 8 Paul Gauthier (aider): 64 tests/basic/test_coder.py: - Paul Gauthier (aider): 81 + Paul Gauthier (aider): 70 tests/basic/test_editor.py: - Paul Gauthier (aider): 16 + Paul Gauthier (aider): 12 tests/basic/test_main.py: Paul Gauthier: 1 - Paul Gauthier (aider): 42 + Paul Gauthier (aider): 19 tests/basic/test_models.py: Paul Gauthier (aider): 30 tests/basic/test_repomap.py: Paul Gauthier (aider): 13 grand_total: - Paul Gauthier: 45 - Paul Gauthier (aider): 584 - malkoG: 91 + Paul Gauthier: 43 + Paul Gauthier (aider): 544 + malkoG: 83 start_tag: v0.64.0 - total_lines: 720 + total_lines: 670 +- aider_percentage: 86.17 + aider_total: 841 + end_date: '2024-12-01' + end_tag: v0.66.0 + file_counts: + .github/workflows/docker-build-test.yml: + Paul Gauthier (aider): 2 + .github/workflows/docker-release.yml: + Paul Gauthier (aider): 2 + .github/workflows/pages.yml: + Paul Gauthier (aider): 3 + .github/workflows/release.yml: + Paul Gauthier (aider): 2 + .github/workflows/ubuntu-tests.yml: + Paul Gauthier: 1 + Paul Gauthier (aider): 8 + .github/workflows/windows-tests.yml: + Paul Gauthier (aider): 4 + aider/__init__.py: + Paul Gauthier: 16 + aider/analytics.py: + Paul Gauthier (aider): 19 + aider/args.py: + Paul Gauthier: 1 + Paul Gauthier (aider): 6 + Philippe de Reynal: 6 + aider/coders/base_coder.py: + Paul Gauthier: 15 + Paul Gauthier (aider): 39 + aider/commands.py: + Paul Gauthier: 5 + Paul Gauthier (aider): 27 + aider/io.py: + Paul Gauthier (aider): 17 + aider/linter.py: + Paul Gauthier (aider): 2 + aider/main.py: + Paul Gauthier: 17 + Paul Gauthier (aider): 46 + aider/models.py: + Paul Gauthier: 7 + aider/run_cmd.py: + Paul Gauthier (aider): 8 + aider/utils.py: + Paul Gauthier: 1 + aider/voice.py: + Philippe de Reynal: 24 + aider/website/docs/leaderboards/index.md: + Paul Gauthier: 1 + benchmark/benchmark.py: + Paul Gauthier (aider): 38 + scripts/blame.py: + Paul Gauthier (aider): 26 + scripts/issues.py: + Paul Gauthier: 3 + scripts/update-history.py: + Paul Gauthier (aider): 58 + tests/basic/test_coder.py: + Paul Gauthier: 4 + tests/basic/test_commands.py: + Paul Gauthier: 10 + Paul Gauthier (aider): 64 + tests/basic/test_main.py: + Paul Gauthier (aider): 4 + tests/basic/test_models.py: + Paul Gauthier: 2 + tests/basic/test_repomap.py: + Paul Gauthier: 12 + Paul Gauthier (aider): 45 + tests/basic/test_voice.py: + Paul Gauthier (aider): 103 + tests/browser/test_browser.py: + Paul Gauthier: 1 + tests/fixtures/languages/c/test.c: + Paul Gauthier (aider): 6 + tests/fixtures/languages/cpp/test.cpp: + Paul Gauthier (aider): 6 + tests/fixtures/languages/csharp/test.cs: + Paul Gauthier (aider): 39 + tests/fixtures/languages/elisp/test.el: + Paul Gauthier (aider): 25 + tests/fixtures/languages/elixir/test.ex: + Paul Gauthier (aider): 5 + tests/fixtures/languages/elm/test.elm: + Paul Gauthier: 1 + Paul Gauthier (aider): 37 + tests/fixtures/languages/go/test.go: + Paul Gauthier: 1 + Paul Gauthier (aider): 41 + tests/fixtures/languages/java/test.java: + Paul Gauthier: 2 + Paul Gauthier (aider): 14 + tests/fixtures/languages/javascript/test.js: + Paul Gauthier: 1 + Paul Gauthier (aider): 25 + tests/fixtures/languages/ocaml/test.ml: + Paul Gauthier: 2 + Paul Gauthier (aider): 17 + tests/fixtures/languages/php/test.php: + Paul Gauthier (aider): 5 + tests/fixtures/languages/python/test.py: + Paul Gauthier: 2 + Paul Gauthier (aider): 26 + tests/fixtures/languages/ql/test.ql: + Paul Gauthier (aider): 3 + tests/fixtures/languages/ruby/test.rb: + Paul Gauthier (aider): 3 + tests/fixtures/languages/rust/test.rs: + Paul Gauthier (aider): 33 + tests/fixtures/languages/tsx/test.tsx: + Paul Gauthier (aider): 30 + tests/fixtures/languages/typescript/test.ts: + Paul Gauthier (aider): 3 + grand_total: + Paul Gauthier: 105 + Paul Gauthier (aider): 841 + Philippe de Reynal: 30 + start_tag: v0.65.0 + total_lines: 976 +- aider_percentage: 67.86 + aider_total: 437 + end_date: '2024-12-06' + end_tag: v0.67.0 + file_counts: + .github/workflows/issues.yml: + Paul Gauthier (aider): 29 + aider/__init__.py: + Paul Gauthier: 1 + aider/analytics.py: + Paul Gauthier: 13 + Paul Gauthier (aider): 7 + aider/args.py: + Paul Gauthier: 3 + Paul Gauthier (aider): 4 + aider/coders/base_coder.py: + Paul Gauthier: 15 + aider/commands.py: + Paul Gauthier: 11 + aider/io.py: + Paul Gauthier: 28 + Paul Gauthier (aider): 31 + aider/llm.py: + Paul Gauthier: 5 + aider/main.py: + Paul Gauthier: 7 + Paul Gauthier (aider): 5 + aider/models.py: + Paul Gauthier: 1 + aider/run_cmd.py: + Paul Gauthier: 1 + aider/utils.py: + Paul Gauthier: 7 + Paul Gauthier (aider): 22 + aider/watch.py: + Paul Gauthier: 51 + Paul Gauthier (aider): 221 + aider/website/_includes/qwq-chart.js: + Paul Gauthier: 30 + Paul Gauthier (aider): 47 + aider/website/docs/leaderboards/index.md: + Paul Gauthier: 1 + scripts/blame.py: + Paul Gauthier (aider): 26 + scripts/update-history.py: + Paul Gauthier: 5 + scripts/versionbump.py: + Paul Gauthier: 2 + tests/basic/test_analytics.py: + Paul Gauthier: 9 + Paul Gauthier (aider): 3 + tests/basic/test_main.py: + Paul Gauthier: 1 + tests/basic/test_models.py: + Paul Gauthier: 4 + Paul Gauthier (aider): 7 + tests/basic/test_watch.py: + Paul Gauthier: 10 + Paul Gauthier (aider): 34 + tests/browser/test_browser.py: + Paul Gauthier: 2 + Paul Gauthier (aider): 1 + grand_total: + Paul Gauthier: 207 + Paul Gauthier (aider): 437 + start_tag: v0.66.0 + total_lines: 644 +- aider_percentage: 71.57 + aider_total: 428 + end_date: '2024-12-10' + end_tag: v0.68.0 + file_counts: + .github/workflows/pages.yml: + Paul Gauthier (aider): 1 + aider/__init__.py: + Paul Gauthier: 1 + aider/analytics.py: + Paul Gauthier: 2 + aider/args.py: + Paul Gauthier: 30 + Paul Gauthier (aider): 15 + aider/coders/base_coder.py: + Paul Gauthier: 12 + Paul Gauthier (aider): 10 + aider/coders/editor_editblock_coder.py: + Paul Gauthier: 1 + aider/coders/editor_whole_coder.py: + Paul Gauthier: 1 + aider/commands.py: + Paul Gauthier: 24 + Paul Gauthier (aider): 25 + aider/copypaste.py: + Paul Gauthier: 4 + Paul Gauthier (aider): 68 + aider/exceptions.py: + Paul Gauthier: 9 + aider/history.py: + Paul Gauthier (aider): 1 + aider/io.py: + Paul Gauthier: 13 + aider/main.py: + Paul Gauthier: 17 + Paul Gauthier (aider): 29 + aider/models.py: + Paul Gauthier: 15 + aider/repo.py: + Paul Gauthier (aider): 1 + aider/run_cmd.py: + Paul Gauthier: 1 + aider/sendchat.py: + Paul Gauthier (aider): 4 + aider/utils.py: + Paul Gauthier: 1 + aider/voice.py: + Paul Gauthier: 9 + aider/watch.py: + Paul Gauthier: 6 + Paul Gauthier (aider): 35 + aider/website/_includes/edit-leaderboard.js: + Paul Gauthier: 2 + Paul Gauthier (aider): 90 + aider/website/_includes/head_custom.html: + Paul Gauthier: 7 + Paul Gauthier (aider): 53 + aider/website/docs/leaderboards/index.md: + Paul Gauthier: 1 + Paul Gauthier (aider): 2 + scripts/blame.py: + Paul Gauthier: 6 + Paul Gauthier (aider): 17 + scripts/pip-compile.sh: + Paul Gauthier: 2 + tests/basic/test_commands.py: + Paul Gauthier (aider): 24 + tests/basic/test_history.py: + Paul Gauthier (aider): 3 + tests/basic/test_main.py: + Paul Gauthier (aider): 46 + tests/basic/test_repo.py: + Paul Gauthier (aider): 3 + tests/basic/test_sendchat.py: + Paul Gauthier: 5 + Paul Gauthier (aider): 1 + tests/basic/test_watch.py: + Paul Gauthier: 1 + grand_total: + Paul Gauthier: 170 + Paul Gauthier (aider): 428 + start_tag: v0.67.0 + total_lines: 598 +- aider_percentage: 67.87 + aider_total: 207 + end_date: '2024-12-13' + end_tag: v0.69.0 + file_counts: + .github/workflows/pages.yml: + Paul Gauthier: 2 + aider/__init__.py: + Paul Gauthier: 1 + aider/analytics.py: + Paul Gauthier: 2 + aider/args.py: + Mir Adnan ALI: 3 + Paul Gauthier: 1 + aider/coders/base_coder.py: + JeongJuhyeon: 1 + Mir Adnan ALI: 3 + aider/commands.py: + Mir Adnan ALI: 4 + Paul Gauthier: 5 + Paul Gauthier (aider): 3 + aider/io.py: + Mir Adnan ALI: 37 + Paul Gauthier: 8 + Paul Gauthier (aider): 3 + aider/main.py: + Mir Adnan ALI: 1 + aider/models.py: + Paul Gauthier: 7 + aider/watch.py: + Paul Gauthier: 7 + Paul Gauthier (aider): 47 + aider/website/docs/leaderboards/index.md: + Paul Gauthier: 1 + benchmark/benchmark.py: + Paul Gauthier: 7 + Paul Gauthier (aider): 7 + scripts/blame.py: + Paul Gauthier (aider): 1 + scripts/issues.py: + Paul Gauthier (aider): 58 + scripts/update-history.py: + Paul Gauthier: 3 + tests/basic/test_io.py: + Paul Gauthier (aider): 20 + tests/basic/test_watch.py: + Paul Gauthier: 5 + Paul Gauthier (aider): 68 + grand_total: + JeongJuhyeon: 1 + Mir Adnan ALI: 48 + Paul Gauthier: 49 + Paul Gauthier (aider): 207 + start_tag: v0.68.0 + total_lines: 305 +- aider_percentage: 74.22 + aider_total: 875 + end_date: '2024-12-26' + end_tag: v0.70.0 + file_counts: + aider/__init__.py: + Paul Gauthier: 1 + aider/analytics.py: + Paul Gauthier: 6 + Paul Gauthier (aider): 41 + aider/args.py: + Evan Johnson: 2 + aider/coders/search_replace.py: + Paul Gauthier: 5 + aider/commands.py: + Paul Gauthier (aider): 41 + aider/help_pats.py: + Paul Gauthier: 3 + aider/io.py: + Paul Gauthier: 7 + Paul Gauthier (aider): 9 + aider/main.py: + Paul Gauthier: 15 + Paul Gauthier (aider): 5 + apaz-cli: 3 + mdk: 6 + aider/models.py: + Paul Gauthier: 29 + aider/repo.py: + Paul Gauthier: 14 + aider/utils.py: + Paul Gauthier: 2 + aider/watch.py: + Paul Gauthier: 13 + aider/website/_includes/head_custom.html: + Paul Gauthier (aider): 4 + aider/website/_includes/leaderboard.js: + Paul Gauthier (aider): 14 + aider/website/docs/leaderboards/index.md: + Paul Gauthier: 28 + Paul Gauthier (aider): 2 + benchmark/Dockerfile: + Paul Gauthier: 8 + Paul Gauthier (aider): 43 + benchmark/benchmark.py: + Paul Gauthier: 69 + Paul Gauthier (aider): 153 + benchmark/clone-exercism.sh: + Paul Gauthier: 2 + Paul Gauthier (aider): 18 + benchmark/cpp-test.sh: + Paul Gauthier: 10 + Paul Gauthier (aider): 1 + benchmark/docker.sh: + Paul Gauthier (aider): 4 + benchmark/install-docker-ubuntu.sh: + Paul Gauthier (aider): 63 + benchmark/npm-test.sh: + Paul Gauthier: 10 + Paul Gauthier (aider): 3 + benchmark/problem_stats.py: + Paul Gauthier: 35 + Paul Gauthier (aider): 318 + benchmark/rsync.sh: + Paul Gauthier: 7 + Paul Gauthier (aider): 26 + scripts/blame.py: + Paul Gauthier (aider): 6 + scripts/my_models.py: + Paul Gauthier (aider): 95 + scripts/update-blame.sh: + Paul Gauthier (aider): 3 + scripts/update-docs.sh: + Paul Gauthier: 1 + tests/basic/test_analytics.py: + Paul Gauthier (aider): 19 + tests/basic/test_main.py: + Paul Gauthier (aider): 7 + tests/basic/test_sanity_check_repo.py: + mdk: 28 + grand_total: + Evan Johnson: 2 + Paul Gauthier: 265 + Paul Gauthier (aider): 875 + apaz-cli: 3 + mdk: 34 + start_tag: v0.69.0 + total_lines: 1179 +- aider_percentage: 60.36 + aider_total: 236 + end_date: '2025-01-10' + end_tag: v0.71.0 + file_counts: + aider/__init__.py: + Paul Gauthier: 1 + aider/args.py: + Paul Gauthier: 2 + aider/coders/base_coder.py: + Paul Gauthier: 7 + Paul Gauthier (aider): 13 + aider/commands.py: + Paul Gauthier: 1 + Paul Gauthier (aider): 22 + aider/io.py: + Paul Gauthier: 3 + Paul Gauthier (aider): 16 + aider/linter.py: + Aaron Weisberg: 5 + aider/main.py: + Paul Gauthier: 7 + Paul Gauthier (aider): 13 + apaz-cli: 18 + aider/mdstream.py: + Paul Gauthier: 38 + Paul Gauthier (aider): 58 + aider/models.py: + Paul Gauthier: 11 + Paul Gauthier (aider): 2 + aider/repo.py: + Krazer: 10 + Paul Gauthier: 5 + aider/run_cmd.py: + Aaron Weisberg: 2 + aider/utils.py: + Paul Gauthier: 9 + aider/voice.py: + Paul Gauthier: 11 + Paul Gauthier (aider): 13 + aider/watch.py: + Paul Gauthier: 1 + benchmark/Dockerfile: + Josh Vera: 1 + Paul Maunders: 12 + benchmark/benchmark.py: + Nimesh Ghelani: 1 + Paul Gauthier: 6 + Paul Gauthier (aider): 30 + benchmark/problem_stats.py: + Paul Gauthier (aider): 5 + docker/Dockerfile: + Paul Gauthier (aider): 32 + scripts/update-history.py: + Paul Gauthier (aider): 1 + tests/basic/test_commands.py: + Paul Gauthier: 2 + tests/basic/test_io.py: + Paul Gauthier (aider): 6 + tests/basic/test_linter.py: + Aaron Weisberg: 2 + tests/basic/test_models.py: + Paul Gauthier (aider): 25 + grand_total: + Aaron Weisberg: 9 + Josh Vera: 1 + Krazer: 10 + Nimesh Ghelani: 1 + Paul Gauthier: 104 + Paul Gauthier (aider): 236 + Paul Maunders: 12 + apaz-cli: 18 + start_tag: v0.70.0 + total_lines: 391 +- aider_percentage: 48.76 + aider_total: 138 + end_date: '2025-01-20' + end_tag: v0.72.0 + file_counts: + .github/workflows/docker-build-test.yml: + Paul Gauthier (aider): 38 + .github/workflows/pages.yml: + Paul Gauthier: 3 + Paul Gauthier (aider): 1 + .github/workflows/ubuntu-tests.yml: + Paul Gauthier (aider): 8 + .github/workflows/windows-tests.yml: + Paul Gauthier (aider): 8 + aider/__init__.py: + Paul Gauthier: 1 + aider/args.py: + Titusz Pan: 6 + aider/coders/base_coder.py: + Paul Gauthier: 11 + aider/coders/single_wholefile_func_coder.py: + Paul Gauthier: 1 + aider/coders/wholefile_func_coder.py: + Paul Gauthier: 1 + aider/commands.py: + Paul Gauthier: 3 + aider/history.py: + Paul Gauthier: 7 + aider/io.py: + Paul Gauthier (aider): 14 + Titusz Pan: 2 + aider/main.py: + Titusz Pan: 1 + aider/models.py: + Paul Gauthier: 16 + aider/queries/tree-sitter-kotlin-tags.scm: + Paul Walker: 27 + aider/repomap.py: + Paul Gauthier (aider): 2 + aider/sendchat.py: + Paul Gauthier: 9 + Paul Gauthier (aider): 22 + aider/utils.py: + Paul Gauthier: 1 + aider/website/docs/leaderboards/index.md: + Paul Gauthier: 2 + benchmark/benchmark.py: + Paul Gauthier: 9 + benchmark/rsync.sh: + Paul Gauthier: 21 + docker/Dockerfile: + Paul Gauthier: 2 + Paul Gauthier (aider): 6 + scripts/my_models.py: + Paul Gauthier: 3 + scripts/update-docs.sh: + Paul Gauthier: 2 + tests/basic/test_io.py: + Paul Gauthier (aider): 39 + tests/basic/test_repomap.py: + Paul Walker: 1 + tests/fixtures/languages/kotlin/test.kt: + Paul Walker: 16 + grand_total: + Paul Gauthier: 92 + Paul Gauthier (aider): 138 + Paul Walker: 44 + Titusz Pan: 9 + start_tag: v0.71.0 + total_lines: 283 +- aider_percentage: 69.44 + aider_total: 284 + end_date: '2025-01-31' + end_tag: v0.73.0 + file_counts: + aider/__init__.py: + Paul Gauthier: 1 + aider/args.py: + Paul Gauthier: 3 + Paul Gauthier (aider): 2 + aider/coders/base_coder.py: + Paul Gauthier: 37 + Paul Gauthier (aider): 26 + aider/commands.py: + xqyz: 1 + aider/io.py: + Paul Gauthier: 7 + aider/main.py: + Paul Gauthier: 13 + Paul Gauthier (aider): 15 + aider/models.py: + Paul Gauthier: 8 + Paul Gauthier (aider): 33 + aider/sendchat.py: + Mir Adnan ALI: 28 + Paul Gauthier: 11 + Paul Gauthier (aider): 6 + aider/urls.py: + Paul Gauthier: 1 + aider/website/_includes/leaderboard.js: + Paul Gauthier (aider): 1 + aider/website/docs/leaderboards/index.md: + Paul Gauthier: 3 + Paul Gauthier (aider): 2 + benchmark/benchmark.py: + Paul Gauthier (aider): 21 + benchmark/rsync.sh: + Paul Gauthier: 2 + tests/basic/test_coder.py: + Paul Gauthier: 10 + Paul Gauthier (aider): 39 + tests/basic/test_main.py: + Paul Gauthier (aider): 62 + tests/basic/test_sendchat.py: + Paul Gauthier (aider): 77 + grand_total: + Mir Adnan ALI: 28 + Paul Gauthier: 96 + Paul Gauthier (aider): 284 + xqyz: 1 + start_tag: v0.72.0 + total_lines: 409 +- aider_percentage: 77.14 + aider_total: 604 + end_date: '2025-02-06' + end_tag: v0.74.0 + file_counts: + aider/__init__.py: + Paul Gauthier: 1 + aider/args.py: + Paul Gauthier: 1 + aider/coders/base_coder.py: + Paul Gauthier: 24 + Paul Gauthier (aider): 9 + aider/coders/editblock_coder.py: + Paul Gauthier: 5 + aider/coders/wholefile_coder.py: + Paul Gauthier: 2 + aider/commands.py: + Paul Gauthier: 1 + aider/exceptions.py: + Paul Gauthier: 4 + Paul Gauthier (aider): 6 + aider/history.py: + Paul Gauthier (aider): 1 + aider/io.py: + Paul Gauthier: 4 + Paul Gauthier (aider): 18 + aider/llm.py: + Paul Gauthier: 3 + aider/main.py: + Paul Gauthier: 21 + Paul Gauthier (aider): 25 + aider/models.py: + Paul Gauthier: 83 + Paul Gauthier (aider): 77 + aider/repo.py: + Paul Gauthier: 1 + Paul Gauthier (aider): 2 + "Viktor Sz\xE9pe": 3 + aider/watch.py: + Paul Gauthier (aider): 45 + benchmark/docker.sh: + Paul Gauthier: 2 + docker/Dockerfile: + Paul Gauthier: 5 + Paul Gauthier (aider): 4 + tests/basic/test_editblock.py: + Paul Gauthier: 7 + tests/basic/test_history.py: + Paul Gauthier (aider): 13 + tests/basic/test_io.py: + Paul Gauthier (aider): 46 + tests/basic/test_main.py: + Paul Gauthier: 8 + Paul Gauthier (aider): 1 + tests/basic/test_models.py: + Paul Gauthier (aider): 297 + tests/basic/test_repo.py: + Paul Gauthier (aider): 11 + tests/basic/test_sendchat.py: + Paul Gauthier (aider): 7 + tests/basic/test_watch.py: + Paul Gauthier: 4 + Paul Gauthier (aider): 42 + grand_total: + Paul Gauthier: 176 + Paul Gauthier (aider): 604 + "Viktor Sz\xE9pe": 3 + start_tag: v0.73.0 + total_lines: 783 diff --git a/aider/website/_data/deepseek-down.yml b/aider/website/_data/deepseek-down.yml new file mode 100644 index 000000000..75942a2e5 --- /dev/null +++ b/aider/website/_data/deepseek-down.yml @@ -0,0 +1,130 @@ +- dirname: 2024-12-25-13-31-51--deepseekv3preview-diff2 + test_cases: 225 + model: DeepSeek + edit_format: diff + commit_hash: 0a23c4a-dirty + pass_rate_1: 22.7 + pass_rate_2: 48.4 + pass_num_1: 51 + pass_num_2: 109 + percent_cases_well_formed: 98.7 + error_outputs: 7 + num_malformed_responses: 7 + num_with_malformed_responses: 3 + user_asks: 19 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 8 + total_tests: 225 + command: aider --model deepseek/deepseek-chat + date: 2024-12-25 + versions: 0.69.2.dev + seconds_per_case: 34.8 + total_cost: 0.3369 + + +- dirname: 2025-01-28-17-47-49--v3-fireworks + test_cases: 225 + model: Fireworks + edit_format: diff + commit_hash: 0336a98-dirty + pass_rate_1: 22.2 + pass_rate_2: 48.4 + pass_num_1: 50 + pass_num_2: 109 + percent_cases_well_formed: 96.9 + error_outputs: 18 + num_malformed_responses: 16 + num_with_malformed_responses: 7 + user_asks: 14 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 2 + test_timeouts: 9 + total_tests: 225 + command: aider --model fireworks_ai/accounts/fireworks/models/deepseek-v3 + date: 2025-01-28 + versions: 0.72.4.dev + seconds_per_case: 115.9 + total_cost: 2.1177 + +- dirname: 2025-01-28-19-25-32--or-v3-deepinfra-diff + test_cases: 222 + model: "OpenRouter: DeepInfra" + edit_format: diff + commit_hash: bfc5745, 77d2bc5-dirty + pass_rate_1: 23.9 + pass_rate_2: 48.0 + pass_num_1: 53 + pass_num_2: 108 + percent_cases_well_formed: 99.5 + error_outputs: 18 + num_malformed_responses: 1 + num_with_malformed_responses: 1 + user_asks: 17 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 2 + test_timeouts: 4 + total_tests: 225 + command: aider --model openrouter/deepseek/deepseek-chat + date: 2025-01-28 + versions: 0.72.4.dev + seconds_per_case: 187.0 + total_cost: 0.2733 + +- dirname: 2025-01-28-21-07-23--or-v3-novita-diff + test_cases: 225 + model: "OpenRouter: Novita" + edit_format: diff + commit_hash: 66025a0 + pass_rate_1: 20.4 + pass_rate_2: 42.7 + pass_num_1: 46 + pass_num_2: 96 + percent_cases_well_formed: 84.0 + error_outputs: 265 + num_malformed_responses: 67 + num_with_malformed_responses: 36 + user_asks: 5 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 8 + total_tests: 225 + command: aider --model openrouter/deepseek/deepseek-chat + date: 2025-01-28 + versions: 0.72.4.dev + seconds_per_case: 472.5 + total_cost: 0.0000 + +- dirname: 2025-01-29-00-36-49--v3-hyperolic-diff + test_cases: 224 + model: Hyperbolic + edit_format: diff + commit_hash: 298f713 + pass_rate_1: 20.5 + pass_rate_2: 48.4 + pass_num_1: 46 + pass_num_2: 109 + percent_cases_well_formed: 97.3 + error_outputs: 29 + num_malformed_responses: 6 + num_with_malformed_responses: 6 + user_asks: 7 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 7 + total_tests: 225 + command: OPENAI_API_BASE=https://api.hyperbolic.xyz/v1/ aider --model openai/deepseek-ai/DeepSeek-V3 + date: 2025-01-29 + versions: 0.72.4.dev + seconds_per_case: 365.4 + total_cost: 0.0000 \ No newline at end of file diff --git a/aider/website/_data/edit_leaderboard.yml b/aider/website/_data/edit_leaderboard.yml index 2ab3cee16..08e333889 100644 --- a/aider/website/_data/edit_leaderboard.yml +++ b/aider/website/_data/edit_leaderboard.yml @@ -644,7 +644,7 @@ - dirname: 2024-07-19-08-57-13--openrouter-deepseek-chat-v2-0628 test_cases: 133 - model: DeepSeek Chat V2 0628 (deprecated) + model: DeepSeek Chat V2 0628 edit_format: diff commit_hash: 96ff06e-dirty pass_rate_1: 60.9 @@ -716,7 +716,7 @@ - dirname: 2024-07-24-07-10-58--deepseek-coder2-0724-diff-direct test_cases: 133 - model: DeepSeek Coder V2 0724 (deprecated) + model: DeepSeek Coder V2 0724 edit_format: diff commit_hash: 89965bf pass_rate_1: 57.9 @@ -1232,7 +1232,7 @@ - dirname: 2024-09-24-16-33-23--gemini-1.5-flash-002-whole test_cases: 133 - model: gemini-1.5-flash-002 + model: gemini-1.5-flash-002 (0924) edit_format: whole commit_hash: 3edcd71 pass_rate_1: 37.6 @@ -1945,4 +1945,288 @@ command: aider --model gemini/gemini-exp-1114 date: 2024-11-15 versions: 0.63.2.dev - seconds_per_case: 38.6 \ No newline at end of file + seconds_per_case: 38.6 +- dirname: 2024-11-27-07-41-51--qwen2.5-coder-14b-whole-1 + test_cases: 133 + model: ollama/qwen2.5-coder:14b + edit_format: whole + commit_hash: 200295e + pass_rate_1: 53.4 + pass_rate_2: 61.7 + percent_cases_well_formed: 98.5 + error_outputs: 4 + num_malformed_responses: 4 + num_with_malformed_responses: 2 + user_asks: 48 + lazy_comments: 0 + syntax_errors: 2 + indentation_errors: 2 + exhausted_context_windows: 0 + test_timeouts: 2 + command: aider --model ollama/qwen2.5-coder:14b + date: 2024-11-27 + versions: 0.65.2.dev + seconds_per_case: 58.0 + total_cost: 0.0000 + +- dirname: 2024-11-28-07-42-56--qwen2.5-coder-32b-whole-4 + test_cases: 133 + model: ollama/qwen2.5-coder:32b + edit_format: whole + commit_hash: 200295e + pass_rate_1: 58.6 + pass_rate_2: 72.9 + percent_cases_well_formed: 100.0 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + command: aider --model ollama/qwen2.5-coder:32b + date: 2024-11-28 + versions: 0.65.2.dev + seconds_per_case: 147.5 + total_cost: 0.0000 +- dirname: 2024-11-28-13-14-00--tulu3-whole-2 + test_cases: 133 + model: ollama/tulu3 + edit_format: whole + commit_hash: 200295e + pass_rate_1: 21.8 + pass_rate_2: 26.3 + percent_cases_well_formed: 100.0 + error_outputs: 0 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + exhausted_context_windows: 0 + command: aider --model ollama/tulu3 + date: 2024-11-28 + versions: 0.65.2.dev + seconds_per_case: 35.8 + total_cost: 0.0000 + +- dirname: 2024-11-28-14-41-46--granite3-dense-8b-whole-1 + test_cases: 133 + model: ollama/granite3-dense:8b + edit_format: whole + commit_hash: 200295e + pass_rate_1: 17.3 + pass_rate_2: 20.3 + percent_cases_well_formed: 78.9 + exhausted_context_windows: 0 + command: aider --model ollama/granite3-dense:8b + date: 2024-11-28 + versions: 0.65.2.dev + seconds_per_case: 38.1 + total_cost: 0.0000 + +- dirname: 2024-12-04-13-53-03--nova-whole + test_cases: 133 + model: Nova Pro + edit_format: whole + commit_hash: 699e283 + pass_rate_1: 44.4 + pass_rate_2: 54.1 + percent_cases_well_formed: 100.0 + error_outputs: 0 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 7 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 4 + command: aider --model bedrock/us.amazon.nova-pro-v1:0 + date: 2024-12-04 + versions: 0.66.1.dev + seconds_per_case: 8.7 + total_cost: 0.0000 + +- dirname: 2024-12-06-18-27-47--llama33-diff + test_cases: 133 + model: llama-3.3-70b-instruct + edit_format: diff + commit_hash: 53e0d67 + pass_rate_1: 42.1 + pass_rate_2: 59.4 + percent_cases_well_formed: 88.7 + error_outputs: 33 + num_malformed_responses: 33 + num_with_malformed_responses: 15 + user_asks: 3 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 3 + command: aider --model openrouter/meta-llama/llama-3.3-70b-instruct + date: 2024-12-06 + versions: 0.67.1.dev + seconds_per_case: 20.2 + total_cost: 0.0000 + +- dirname: 2024-12-06-21-35-50--gemini-exp-1206-diff + test_cases: 133 + model: gemini-exp-1206 (diff) + edit_format: diff + commit_hash: f2d2ab5 + pass_rate_1: 55.6 + pass_rate_2: 69.2 + percent_cases_well_formed: 84.2 + error_outputs: 68 + num_malformed_responses: 68 + num_with_malformed_responses: 21 + user_asks: 5 + lazy_comments: 0 + syntax_errors: 2 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 0 + command: aider --model gemini/gemini-exp-1206 + date: 2024-12-06 + versions: 0.67.1.dev + seconds_per_case: 32.1 + total_cost: 0.0000 + +- dirname: 2024-12-08-21-39-06--gemini-exp-1206-whole + test_cases: 133 + model: gemini-exp-1206 (whole) + edit_format: whole + commit_hash: f2d2ab5 + pass_rate_1: 60.9 + pass_rate_2: 80.5 + percent_cases_well_formed: 100.0 + error_outputs: 0 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 1 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 3 + command: aider --model gemini/gemini-exp-1206 + date: 2024-12-08 + versions: 0.67.1.dev + seconds_per_case: 64.2 + total_cost: 0.0000 + +- dirname: 2024-12-10-14-45-21--deepseek-1210-diff + test_cases: 133 + model: DeepSeek-V2.5-1210 + edit_format: diff + commit_hash: 16332b2 + pass_rate_1: 58.6 + pass_rate_2: 72.2 + percent_cases_well_formed: 99.2 + error_outputs: 1 + num_malformed_responses: 1 + num_with_malformed_responses: 1 + user_asks: 2 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 2 + command: aider --model deepseek/deepseek-chat + date: 2024-12-10 + versions: 0.67.1.dev + seconds_per_case: 32.7 + total_cost: 0.1106 + +- dirname: 2024-12-11-00-37-08--yi-test + test_cases: 133 + model: yi-lightning + edit_format: whole + commit_hash: e909a3d-dirty + pass_rate_1: 49.6 + pass_rate_2: 65.4 + percent_cases_well_formed: 97.0 + error_outputs: 304 + num_malformed_responses: 5 + num_with_malformed_responses: 4 + user_asks: 34 + lazy_comments: 2 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 2 + command: aider --model openai/yi-lightning + date: 2024-12-11 + versions: 0.67.1.dev + seconds_per_case: 57.8 + total_cost: 0.0000 + +- dirname: 2024-12-11-21-07-00--gemini-2-flash-diff + test_cases: 133 + model: gemini-2.0-flash-exp + edit_format: diff + commit_hash: fcb2bac-dirty, 02e7e31-dirty + pass_rate_1: 56.4 + pass_rate_2: 69.9 + percent_cases_well_formed: 97.0 + error_outputs: 10 + num_malformed_responses: 6 + num_with_malformed_responses: 4 + user_asks: 8 + lazy_comments: 0 + syntax_errors: 1 + indentation_errors: 0 + exhausted_context_windows: 2 + test_timeouts: 1 + command: aider --model gemini/gemini-2.0-flash-exp + date: 2024-12-11 + versions: 0.68.1.dev + seconds_per_case: 7.3 + total_cost: 0.0000 + +- dirname: 2024-12-18-01-50-08--o1 + test_cases: 133 + model: o1 + edit_format: diff + commit_hash: 074c636-dirty + pass_rate_1: 65.4 + pass_rate_2: 84.2 + percent_cases_well_formed: 99.2 + error_outputs: 1 + num_malformed_responses: 1 + num_with_malformed_responses: 1 + user_asks: 0 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 2 + command: aider --model openrouter/openai/o1 + date: 2024-12-18 + versions: 0.69.2.dev + seconds_per_case: 29.9 + total_cost: 0.0000 + +- dirname: 2024-12-21-22-06-01--polyglot-o1-mini-whole + test_cases: 225 + model: o1-mini-2024-09-12 + edit_format: whole + commit_hash: a755079-dirty + pass_rate_1: 8.9 + pass_rate_2: 27.1 + pass_num_1: 20 + pass_num_2: 61 + percent_cases_well_formed: 95.6 + error_outputs: 15 + num_malformed_responses: 14 + num_with_malformed_responses: 10 + user_asks: 37 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 5 + total_tests: 225 + command: aider --model o1-mini + date: 2024-12-21 + versions: 0.69.2.dev + seconds_per_case: 34.3 + total_cost: 17.6270 \ No newline at end of file diff --git a/aider/website/_data/o1_polyglot_leaderboard.yml b/aider/website/_data/o1_polyglot_leaderboard.yml new file mode 100644 index 000000000..20e8102ad --- /dev/null +++ b/aider/website/_data/o1_polyglot_leaderboard.yml @@ -0,0 +1,259 @@ +- dirname: 2024-12-21-18-41-18--polyglot-gpt-4o-mini + test_cases: 225 + model: gpt-4o-mini-2024-07-18 + edit_format: whole + commit_hash: a755079-dirty + pass_rate_1: 0.9 + pass_rate_2: 3.6 + pass_num_1: 2 + pass_num_2: 8 + percent_cases_well_formed: 100.0 + error_outputs: 0 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 36 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 3 + total_tests: 225 + command: aider --model gpt-4o-mini-2024-07-18 + date: 2024-12-21 + versions: 0.69.2.dev + seconds_per_case: 17.3 + total_cost: 0.3236 + +- dirname: 2024-12-21-18-44-28--polyglot-sonnet + test_cases: 225 + model: claude-3-5-sonnet-20241022 + edit_format: diff + commit_hash: a755079-dirty + pass_rate_1: 18.7 + pass_rate_2: 45.3 + pass_num_1: 42 + pass_num_2: 102 + percent_cases_well_formed: 100.0 + error_outputs: 1 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 14 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 12 + total_tests: 225 + command: aider --model claude-3-5-sonnet-20241022 + date: 2024-12-21 + versions: 0.69.2.dev + seconds_per_case: 30.8 + total_cost: 13.4847 + +- dirname: 2024-12-21-18-52-34--polyglot-gpt-4o-diff + test_cases: 225 + model: gpt-4o-2024-11-20 + edit_format: diff + commit_hash: a755079-dirty + pass_rate_1: 4.9 + pass_rate_2: 15.1 + pass_num_1: 11 + pass_num_2: 34 + percent_cases_well_formed: 96.0 + error_outputs: 12 + num_malformed_responses: 11 + num_with_malformed_responses: 9 + user_asks: 34 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 19 + total_tests: 225 + command: aider --model gpt-4o-2024-11-20 + date: 2024-12-21 + versions: 0.69.2.dev + seconds_per_case: 22.2 + total_cost: 7.1835 + +- dirname: 2024-12-21-19-23-03--polyglot-o1-hard-diff + test_cases: 224 + model: o1-2024-12-17 (high) + edit_format: diff + commit_hash: a755079-dirty + pass_rate_1: 23.7 + pass_rate_2: 61.7 + pass_num_1: 53 + pass_num_2: 139 + percent_cases_well_formed: 91.5 + error_outputs: 25 + num_malformed_responses: 24 + num_with_malformed_responses: 19 + user_asks: 16 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 2 + total_tests: 225 + command: aider --model openrouter/openai/o1 + date: 2024-12-21 + versions: 0.69.2.dev + seconds_per_case: 133.2 + total_cost: 0.0000 + +- dirname: 2024-12-21-20-56-21--polyglot-deepseek-diff + test_cases: 225 + model: DeepSeek Chat V2.5 + edit_format: diff + commit_hash: a755079-dirty + pass_rate_1: 5.3 + pass_rate_2: 17.8 + pass_num_1: 12 + pass_num_2: 40 + percent_cases_well_formed: 92.9 + error_outputs: 42 + num_malformed_responses: 37 + num_with_malformed_responses: 16 + user_asks: 23 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 5 + test_timeouts: 5 + total_tests: 225 + command: aider --model deepseek/deepseek-chat + date: 2024-12-21 + versions: 0.69.2.dev + seconds_per_case: 184.0 + total_cost: 0.5101 + +- dirname: 2024-12-21-21-46-27--polyglot-haiku-diff + test_cases: 225 + model: claude-3-5-haiku-20241022 + edit_format: diff + commit_hash: a755079-dirty + pass_rate_1: 7.1 + pass_rate_2: 28.0 + pass_num_1: 16 + pass_num_2: 63 + percent_cases_well_formed: 91.1 + error_outputs: 31 + num_malformed_responses: 30 + num_with_malformed_responses: 20 + user_asks: 13 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 9 + total_tests: 225 + command: aider --model claude-3-5-haiku-20241022 + date: 2024-12-21 + versions: 0.69.2.dev + seconds_per_case: 31.8 + total_cost: 6.0583 + +- dirname: 2024-12-22-13-22-32--polyglot-qwen-diff + test_cases: 225 + model: Qwen2.5-Coder-32B-Instruct + edit_format: diff + commit_hash: 6d7e8be-dirty + pass_rate_1: 4.4 + pass_rate_2: 8.0 + pass_num_1: 10 + pass_num_2: 18 + percent_cases_well_formed: 71.6 + error_outputs: 158 + num_malformed_responses: 148 + num_with_malformed_responses: 64 + user_asks: 132 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 2 + total_tests: 225 + command: "aider --model openai/Qwen/Qwen2.5-Coder-32B-Instruct # via hyperbolic" + date: 2024-12-22 + versions: 0.69.2.dev + seconds_per_case: 84.4 + total_cost: 0.0000 + +- dirname: 2024-12-22-21-26-35--polyglot-o1mini-whole + test_cases: 225 + model: o1-mini-2024-09-12 + edit_format: whole + commit_hash: 37df899 + pass_rate_1: 5.8 + pass_rate_2: 32.9 + pass_num_1: 13 + pass_num_2: 74 + percent_cases_well_formed: 96.9 + error_outputs: 8 + num_malformed_responses: 8 + num_with_malformed_responses: 7 + user_asks: 27 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 3 + total_tests: 225 + command: aider --model o1-mini + date: 2024-12-22 + versions: 0.69.2.dev + seconds_per_case: 34.7 + total_cost: 18.5770 + +- dirname: 2024-12-22-18-43-25--gemini-exp-1206-polyglot-whole-2 + test_cases: 225 + model: gemini-exp-1206 + edit_format: whole + commit_hash: b1bc2f8 + pass_rate_1: 19.6 + pass_rate_2: 38.2 + pass_num_1: 44 + pass_num_2: 86 + percent_cases_well_formed: 98.2 + error_outputs: 8 + num_malformed_responses: 8 + num_with_malformed_responses: 4 + user_asks: 32 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 9 + total_tests: 225 + command: aider --model gemini/gemini-exp-1206 + date: 2024-12-22 + versions: 0.69.2.dev + seconds_per_case: 45.5 + total_cost: 0.0000 + +- dirname: 2024-12-22-20-08-13--gemini-2.0-flash-exp-polyglot-whole + test_cases: 225 + model: gemini-2.0-flash-exp + edit_format: whole + commit_hash: b1bc2f8 + pass_rate_1: 11.6 + pass_rate_2: 22.2 + pass_num_1: 26 + pass_num_2: 50 + percent_cases_well_formed: 100.0 + error_outputs: 1 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 9 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 8 + total_tests: 225 + command: aider --model gemini/gemini-2.0-flash-exp + date: 2024-12-22 + versions: 0.69.2.dev + seconds_per_case: 12.2 + total_cost: 0.0000 \ No newline at end of file diff --git a/aider/website/_data/polyglot_leaderboard.yml b/aider/website/_data/polyglot_leaderboard.yml new file mode 100644 index 000000000..7d8bd4494 --- /dev/null +++ b/aider/website/_data/polyglot_leaderboard.yml @@ -0,0 +1,546 @@ +- dirname: 2024-12-21-18-41-18--polyglot-gpt-4o-mini + test_cases: 225 + model: gpt-4o-mini-2024-07-18 + edit_format: whole + commit_hash: a755079-dirty + pass_rate_1: 0.9 + pass_rate_2: 3.6 + pass_num_1: 2 + pass_num_2: 8 + percent_cases_well_formed: 100.0 + error_outputs: 0 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 36 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 3 + total_tests: 225 + command: aider --model gpt-4o-mini-2024-07-18 + date: 2024-12-21 + versions: 0.69.2.dev + seconds_per_case: 17.3 + total_cost: 0.3236 + +- dirname: 2025-01-17-19-44-33--sonnet-baseline-jan-17 + test_cases: 225 + model: claude-3-5-sonnet-20241022 + edit_format: diff + commit_hash: 6451d59 + pass_rate_1: 22.2 + pass_rate_2: 51.6 + pass_num_1: 50 + pass_num_2: 116 + percent_cases_well_formed: 99.6 + error_outputs: 2 + num_malformed_responses: 1 + num_with_malformed_responses: 1 + user_asks: 11 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 8 + total_tests: 225 + command: aider --model claude-3-5-sonnet-20241022 + date: 2025-01-17 + versions: 0.71.2.dev + seconds_per_case: 21.4 + total_cost: 14.4063 + +- dirname: 2024-12-30-20-57-12--gpt-4o-2024-11-20-ex-as-sys + test_cases: 225 + model: gpt-4o-2024-11-20 + edit_format: diff + commit_hash: 09ee197-dirty + pass_rate_1: 4.9 + pass_rate_2: 18.2 + pass_num_1: 11 + pass_num_2: 41 + percent_cases_well_formed: 95.1 + error_outputs: 12 + num_malformed_responses: 12 + num_with_malformed_responses: 11 + user_asks: 53 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 12 + total_tests: 225 + command: aider --model gpt-4o-2024-11-20 + date: 2024-12-30 + versions: 0.70.1.dev + seconds_per_case: 12.1 + total_cost: 6.7351 + +- dirname: 2024-12-30-20-44-54--gpt4o-ex-as-sys-clean-prompt + test_cases: 225 + model: gpt-4o-2024-08-06 + edit_format: diff + commit_hash: 09ee197-dirty + pass_rate_1: 4.9 + pass_rate_2: 23.1 + pass_num_1: 11 + pass_num_2: 52 + percent_cases_well_formed: 94.2 + error_outputs: 21 + num_malformed_responses: 21 + num_with_malformed_responses: 13 + user_asks: 65 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 3 + total_tests: 225 + command: aider --model gpt-4o-2024-08-06 + date: 2024-12-30 + versions: 0.70.1.dev + seconds_per_case: 16.0 + total_cost: 7.0286 + +- dirname: 2024-12-21-19-23-03--polyglot-o1-hard-diff + test_cases: 224 + model: o1-2024-12-17 (high) + edit_format: diff + commit_hash: a755079-dirty + pass_rate_1: 23.7 + pass_rate_2: 61.7 + pass_num_1: 53 + pass_num_2: 139 + percent_cases_well_formed: 91.5 + error_outputs: 25 + num_malformed_responses: 24 + num_with_malformed_responses: 19 + user_asks: 16 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 2 + total_tests: 225 + command: aider --model openrouter/openai/o1 + date: 2024-12-21 + versions: 0.69.2.dev + seconds_per_case: 133.2 + total_cost: 186.4958 + +- dirname: 2024-12-21-20-56-21--polyglot-deepseek-diff + test_cases: 225 + model: DeepSeek Chat V2.5 + edit_format: diff + commit_hash: a755079-dirty + pass_rate_1: 5.3 + pass_rate_2: 17.8 + pass_num_1: 12 + pass_num_2: 40 + percent_cases_well_formed: 92.9 + error_outputs: 42 + num_malformed_responses: 37 + num_with_malformed_responses: 16 + user_asks: 23 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 5 + test_timeouts: 5 + total_tests: 225 + command: aider --model deepseek/deepseek-chat + date: 2024-12-21 + versions: 0.69.2.dev + seconds_per_case: 184.0 + total_cost: 0.5101 + +- dirname: 2024-12-21-21-46-27--polyglot-haiku-diff + test_cases: 225 + model: claude-3-5-haiku-20241022 + edit_format: diff + commit_hash: a755079-dirty + pass_rate_1: 7.1 + pass_rate_2: 28.0 + pass_num_1: 16 + pass_num_2: 63 + percent_cases_well_formed: 91.1 + error_outputs: 31 + num_malformed_responses: 30 + num_with_malformed_responses: 20 + user_asks: 13 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 9 + total_tests: 225 + command: aider --model claude-3-5-haiku-20241022 + date: 2024-12-21 + versions: 0.69.2.dev + seconds_per_case: 31.8 + total_cost: 6.0583 + +- dirname: 2024-12-22-13-22-32--polyglot-qwen-diff + test_cases: 225 + model: Qwen2.5-Coder-32B-Instruct + edit_format: diff + commit_hash: 6d7e8be-dirty + pass_rate_1: 4.4 + pass_rate_2: 8.0 + pass_num_1: 10 + pass_num_2: 18 + percent_cases_well_formed: 71.6 + error_outputs: 158 + num_malformed_responses: 148 + num_with_malformed_responses: 64 + user_asks: 132 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 2 + total_tests: 225 + command: "aider --model openai/Qwen/Qwen2.5-Coder-32B-Instruct # via hyperbolic" + date: 2024-12-22 + versions: 0.69.2.dev + seconds_per_case: 84.4 + total_cost: 0.0000 + +- dirname: 2024-12-22-21-26-35--polyglot-o1mini-whole + test_cases: 225 + model: o1-mini-2024-09-12 + edit_format: whole + commit_hash: 37df899 + pass_rate_1: 5.8 + pass_rate_2: 32.9 + pass_num_1: 13 + pass_num_2: 74 + percent_cases_well_formed: 96.9 + error_outputs: 8 + num_malformed_responses: 8 + num_with_malformed_responses: 7 + user_asks: 27 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 3 + total_tests: 225 + command: aider --model o1-mini + date: 2024-12-22 + versions: 0.69.2.dev + seconds_per_case: 34.7 + total_cost: 18.5770 + +- dirname: 2024-12-22-18-43-25--gemini-exp-1206-polyglot-whole-2 + test_cases: 225 + model: gemini-exp-1206 + edit_format: whole + commit_hash: b1bc2f8 + pass_rate_1: 19.6 + pass_rate_2: 38.2 + pass_num_1: 44 + pass_num_2: 86 + percent_cases_well_formed: 98.2 + error_outputs: 8 + num_malformed_responses: 8 + num_with_malformed_responses: 4 + user_asks: 32 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 9 + total_tests: 225 + command: aider --model gemini/gemini-exp-1206 + date: 2024-12-22 + versions: 0.69.2.dev + seconds_per_case: 45.5 + total_cost: 0.0000 + +- dirname: 2024-12-22-20-08-13--gemini-2.0-flash-exp-polyglot-whole + test_cases: 225 + model: gemini-2.0-flash-exp + edit_format: whole + commit_hash: b1bc2f8 + pass_rate_1: 11.6 + pass_rate_2: 22.2 + pass_num_1: 26 + pass_num_2: 50 + percent_cases_well_formed: 100.0 + error_outputs: 1 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 9 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 8 + total_tests: 225 + command: aider --model gemini/gemini-2.0-flash-exp + date: 2024-12-22 + versions: 0.69.2.dev + seconds_per_case: 12.2 + total_cost: 0.0000 + +- dirname: 2024-12-23-01-11-56--yi-test + test_cases: 225 + model: yi-lightning + edit_format: whole + commit_hash: 2b1625e + pass_rate_1: 5.8 + pass_rate_2: 12.9 + pass_num_1: 13 + pass_num_2: 29 + percent_cases_well_formed: 92.9 + error_outputs: 87 + num_malformed_responses: 72 + num_with_malformed_responses: 16 + user_asks: 107 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 6 + total_tests: 225 + command: aider --model openai/yi-lightning + date: 2024-12-23 + versions: 0.69.2.dev + seconds_per_case: 146.7 + total_cost: 0.0000 + +- dirname: 2024-12-25-13-31-51--deepseekv3preview-diff2 + test_cases: 225 + model: DeepSeek Chat V3 + edit_format: diff + commit_hash: 0a23c4a-dirty + pass_rate_1: 22.7 + pass_rate_2: 48.4 + pass_num_1: 51 + pass_num_2: 109 + percent_cases_well_formed: 98.7 + error_outputs: 7 + num_malformed_responses: 7 + num_with_malformed_responses: 3 + user_asks: 19 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 8 + total_tests: 225 + command: aider --model deepseek/deepseek-chat + date: 2024-12-25 + versions: 0.69.2.dev + seconds_per_case: 34.8 + total_cost: 0.3369 + +- dirname: 2024-12-26-00-55-20--Qwen2.5-Coder-32B-Instruct + test_cases: 225 + model: Qwen2.5-Coder-32B-Instruct + edit_format: whole + commit_hash: b51768b0 + pass_rate_1: 4.9 + pass_rate_2: 16.4 + pass_num_1: 11 + pass_num_2: 37 + percent_cases_well_formed: 99.6 + error_outputs: 1 + num_malformed_responses: 1 + num_with_malformed_responses: 1 + user_asks: 33 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 6 + total_tests: 225 + command: aider --model openai/Qwen2.5-Coder-32B-Instruct + date: 2024-12-26 + versions: 0.69.2.dev + seconds_per_case: 42.0 + total_cost: 0.0000 + +- dirname: 2025-01-13-18-17-25--codestral-whole2 + test_cases: 225 + model: Codestral 25.01 + edit_format: whole + commit_hash: 0cba898-dirty + pass_rate_1: 4.0 + pass_rate_2: 11.1 + pass_num_1: 9 + pass_num_2: 25 + percent_cases_well_formed: 100.0 + error_outputs: 0 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 47 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 4 + total_tests: 225 + command: aider --model mistral/codestral-latest + date: 2025-01-13 + versions: 0.71.2.dev + seconds_per_case: 9.3 + total_cost: 1.9834 + +- dirname: 2025-01-20-19-11-38--ds-turns-upd-cur-msgs-fix-with-summarizer + test_cases: 225 + model: DeepSeek R1 + edit_format: diff + commit_hash: 5650697-dirty + pass_rate_1: 26.7 + pass_rate_2: 56.9 + pass_num_1: 60 + pass_num_2: 128 + percent_cases_well_formed: 96.9 + error_outputs: 8 + num_malformed_responses: 7 + num_with_malformed_responses: 7 + user_asks: 15 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 5 + total_tests: 225 + command: aider --model deepseek/deepseek-reasoner + date: 2025-01-20 + versions: 0.71.2.dev + seconds_per_case: 113.7 + total_cost: 5.4193 + +- dirname: 2025-01-23-19-14-48--r1-architect-sonnet + test_cases: 225 + model: DeepSeek R1 + claude-3-5-sonnet-20241022 + edit_format: architect + commit_hash: 05a77c7 + editor_model: claude-3-5-sonnet-20241022 + editor_edit_format: editor-diff + pass_rate_1: 27.1 + pass_rate_2: 64.0 + pass_num_1: 61 + pass_num_2: 144 + percent_cases_well_formed: 100.0 + error_outputs: 2 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 392 + lazy_comments: 6 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 5 + total_tests: 225 + command: aider --architect --model r1 --editor-model sonnet + date: 2025-01-23 + versions: 0.72.3.dev + seconds_per_case: 251.6 + total_cost: 13.2933 + +- dirname: 2025-01-28-16-00-03--qwen-max-2025-01-25-polyglot-diff + test_cases: 225 + model: qwen-max-2025-01-25 + edit_format: diff + commit_hash: ae7d459 + pass_rate_1: 9.3 + pass_rate_2: 21.8 + pass_num_1: 21 + pass_num_2: 49 + percent_cases_well_formed: 90.2 + error_outputs: 46 + num_malformed_responses: 44 + num_with_malformed_responses: 22 + user_asks: 23 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 9 + total_tests: 225 + command: OPENAI_API_BASE=https://dashscope-intl.aliyuncs.com/compatible-mode/v1 aider --model openai/qwen-max-2025-01-25 + date: 2025-01-28 + versions: 0.72.4.dev + seconds_per_case: 39.5 + +- dirname: 2025-01-31-20-27-46--o3-mini-diff2 + test_cases: 225 + model: o3-mini (medium) + edit_format: diff + commit_hash: 2fb517b-dirty + pass_rate_1: 19.1 + pass_rate_2: 53.8 + pass_num_1: 43 + pass_num_2: 121 + percent_cases_well_formed: 95.1 + error_outputs: 28 + num_malformed_responses: 28 + num_with_malformed_responses: 11 + user_asks: 17 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 2 + total_tests: 225 + command: aider --model o3-mini + date: 2025-01-31 + versions: 0.72.4.dev + seconds_per_case: 47.2 + total_cost: 8.8599 + +- dirname: 2025-01-31-20-42-47--o3-mini-diff-high + test_cases: 224 + model: o3-mini (high) + edit_format: diff + commit_hash: b0d58d1-dirty + pass_rate_1: 21.0 + pass_rate_2: 60.4 + pass_num_1: 47 + pass_num_2: 136 + percent_cases_well_formed: 93.3 + error_outputs: 26 + num_malformed_responses: 24 + num_with_malformed_responses: 15 + user_asks: 19 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 7 + total_tests: 225 + command: aider --model o3-mini --reasoning-effort high + date: 2025-01-31 + versions: 0.72.4.dev + seconds_per_case: 124.6 + total_cost: 18.1584 + +- dirname: 2025-01-21-22-51-49--gemini-2.0-flash-thinking-exp-01-21-polyglot-diff + test_cases: 225 + model: gemini-2.0-flash-thinking-exp-01-21 + edit_format: diff + commit_hash: 843720a + pass_rate_1: 5.8 + pass_rate_2: 18.2 + pass_num_1: 13 + pass_num_2: 41 + percent_cases_well_formed: 77.8 + error_outputs: 182 + num_malformed_responses: 180 + num_with_malformed_responses: 50 + user_asks: 26 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 2 + test_timeouts: 7 + total_tests: 225 + command: aider --model gemini/gemini-2.0-flash-thinking-exp-01-21 + date: 2025-01-21 + versions: 0.72.2.dev + seconds_per_case: 24.2 + total_cost: 0.0000 \ No newline at end of file diff --git a/aider/website/_data/qwq.yml b/aider/website/_data/qwq.yml new file mode 100644 index 000000000..5e80639e4 --- /dev/null +++ b/aider/website/_data/qwq.yml @@ -0,0 +1,170 @@ + +- dirname: 2024-11-28-21-38-50--architect-qwq-haiku-whole + test_cases: 133 + model: QwQ + Haiku + edit_format: architect + commit_hash: e4a1d6f + editor_model: claude-3-5-haiku-20241022 + editor_edit_format: editor-whole + pass_rate_1: 54.1 + pass_rate_2: 71.4 + percent_cases_well_formed: 100.0 + error_outputs: 4 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 196 + lazy_comments: 4 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 0 + command: aider --model openrouter/qwen/qwq-32b-preview --editor-model claude-3-5-haiku-20241022 --edit-format editor-whole + date: 2024-11-28 + versions: 0.65.2.dev + seconds_per_case: 154.7 + total_cost: 1.4196 + +- dirname: 2024-11-28-19-24-35--architect-qwq-deepseek-whole + test_cases: 133 + model: QwQ + DeepSeek V2.5 + edit_format: architect + commit_hash: e4a1d6f + editor_model: deepseek/deepseek-chat + editor_edit_format: editor-whole + pass_rate_1: 55.6 + pass_rate_2: 67.7 + percent_cases_well_formed: 100.0 + error_outputs: 3 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 193 + lazy_comments: 2 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 0 + command: aider --model openrouter/qwen/qwq-32b-preview --editor-model deepseek/deepseek-chat --edit-format editor-whole + date: 2024-11-28 + versions: 0.65.2.dev + seconds_per_case: 170.3 + total_cost: 0.1558 + + +- dirname: 2024-11-09-11-09-15--Qwen2.5-Coder-32B-Instruct + test_cases: 133 + model: Qwen2.5 Coder 32B-I + released: 2024-11-12 + edit_format: diff + commit_hash: ec9982a + pass_rate_1: 59.4 + pass_rate_2: 71.4 + percent_cases_well_formed: 94.7 + error_outputs: 17 + num_malformed_responses: 17 + num_with_malformed_responses: 7 + user_asks: 1 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 3 + command: aider --model openai/hf:Qwen/Qwen2.5-Coder-32B-Instruct --openai-api-base https://glhf.chat/api/openai/v1 (via GLHF) + date: 2024-11-09 + versions: 0.59.2.dev + seconds_per_case: 22.5 + total_cost: 0.0000 + +- dirname: 2024-12-04-00-10-39--architect-qwq-qwen + test_cases: 132 + model: QwQ + Qwen2.5 Coder 32B-I + edit_format: architect + commit_hash: 51c02da + editor_model: openrouter/qwen/qwen-2.5-coder-32b-instruct + editor_edit_format: editor-whole + pass_rate_1: 58.3 + pass_rate_2: 73.6 + percent_cases_well_formed: 100.0 + error_outputs: 3 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 186 + lazy_comments: 5 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 0 + command: aider --model openrouter/qwen/qwq-32b-preview --editor-model openrouter/qwen/qwen-2.5-coder-32b-instruct --editor-edit-format editor-whole + date: 2024-12-04 + versions: 0.66.1.dev + seconds_per_case: 144.1 + total_cost: 0.1444 + +- dirname: 2024-12-04-00-42-05--qwq-alone-whole + test_cases: 133 + model: QwQ + edit_format: whole + commit_hash: 19004c0 + pass_rate_1: 33.1 + pass_rate_2: 42.1 + percent_cases_well_formed: 91.0 + error_outputs: 28 + num_malformed_responses: 12 + num_with_malformed_responses: 12 + user_asks: 119 + lazy_comments: 2 + syntax_errors: 22 + indentation_errors: 9 + exhausted_context_windows: 2 + test_timeouts: 1 + command: aider --model openrouter/qwen/qwq-32b-preview + date: 2024-12-04 + versions: 0.66.1.dev + seconds_per_case: 414.3 + total_cost: 0.0000 + +- dirname: 2024-09-12-19-57-35--o1-mini-whole + test_cases: 133 + model: o1-mini + edit_format: whole + commit_hash: 36fa773-dirty, 291b456 + pass_rate_1: 49.6 + pass_rate_2: 70.7 + percent_cases_well_formed: 90.0 + error_outputs: 0 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 17 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 1 + command: aider --model o1-mini + date: 2024-09-12 + versions: 0.56.1.dev + seconds_per_case: 103.0 + total_cost: 5.3725 + +- dirname: 2024-09-21-16-45-11--o1-preview-flex-sr-markers + test_cases: 133 + model: o1-preview + _released: 2024-09-12 + edit_format: diff + commit_hash: 5493654-dirty + pass_rate_1: 57.9 + pass_rate_2: 79.7 + percent_cases_well_formed: 93.2 + error_outputs: 11 + num_malformed_responses: 11 + num_with_malformed_responses: 9 + user_asks: 3 + lazy_comments: 0 + syntax_errors: 10 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 1 + command: aider --model o1-preview + date: 2024-09-21 + versions: 0.56.1.dev + seconds_per_case: 80.9 + total_cost: 63.9190 diff --git a/aider/website/_data/r1_architect.yml b/aider/website/_data/r1_architect.yml new file mode 100644 index 000000000..5467e0fc7 --- /dev/null +++ b/aider/website/_data/r1_architect.yml @@ -0,0 +1,138 @@ + + + +- dirname: 2025-01-23-19-14-48--r1-architect-sonnet + test_cases: 225 + model: R1+Sonnet + edit_format: architect + commit_hash: 05a77c7 + editor_model: claude-3-5-sonnet-20241022 + editor_edit_format: editor-diff + pass_rate_1: 27.1 + pass_rate_2: 64.0 + pass_num_1: 61 + pass_num_2: 144 + percent_cases_well_formed: 100.0 + error_outputs: 2 + num_malformed_responses: 0 + num_with_malformed_responses: 0 + user_asks: 392 + lazy_comments: 6 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 5 + total_tests: 225 + command: aider --architect --model r1 --editor-model sonnet + date: 2025-01-23 + versions: 0.72.3.dev + seconds_per_case: 251.6 + total_cost: 13.2933 + +- dirname: 2025-01-20-19-11-38--ds-turns-upd-cur-msgs-fix-with-summarizer + test_cases: 225 + model: R1 + edit_format: diff + commit_hash: 5650697-dirty + pass_rate_1: 26.7 + pass_rate_2: 56.9 + pass_num_1: 60 + pass_num_2: 128 + percent_cases_well_formed: 96.9 + error_outputs: 8 + num_malformed_responses: 7 + num_with_malformed_responses: 7 + user_asks: 15 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 5 + total_tests: 225 + command: aider --model r1 + date: 2025-01-20 + versions: 0.71.2.dev + seconds_per_case: 113.7 + total_cost: 5.4193 + + +- dirname: 2024-12-21-19-23-03--polyglot-o1-hard-diff + test_cases: 224 + model: o1 + edit_format: diff + commit_hash: a755079-dirty + pass_rate_1: 23.7 + pass_rate_2: 61.7 + pass_num_1: 53 + pass_num_2: 139 + percent_cases_well_formed: 91.5 + error_outputs: 25 + num_malformed_responses: 24 + num_with_malformed_responses: 19 + user_asks: 16 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 2 + total_tests: 225 + command: aider --model o1 + date: 2024-12-21 + versions: 0.69.2.dev + seconds_per_case: 133.2 + total_cost: 186.4958 + + +- dirname: 2024-12-25-13-31-51--deepseekv3preview-diff2 + test_cases: 225 + model: DeepSeek V3 + edit_format: diff + commit_hash: 0a23c4a-dirty + pass_rate_1: 22.7 + pass_rate_2: 48.4 + pass_num_1: 51 + pass_num_2: 109 + percent_cases_well_formed: 98.7 + error_outputs: 7 + num_malformed_responses: 7 + num_with_malformed_responses: 3 + user_asks: 19 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 0 + test_timeouts: 8 + total_tests: 225 + command: aider --model deepseek + date: 2024-12-25 + versions: 0.69.2.dev + seconds_per_case: 34.8 + total_cost: 0.3369 + + + +- dirname: 2025-01-17-19-44-33--sonnet-baseline-jan-17 + test_cases: 225 + model: Sonnet + edit_format: diff + commit_hash: 6451d59 + pass_rate_1: 22.2 + pass_rate_2: 51.6 + pass_num_1: 50 + pass_num_2: 116 + percent_cases_well_formed: 99.6 + error_outputs: 2 + num_malformed_responses: 1 + num_with_malformed_responses: 1 + user_asks: 11 + lazy_comments: 0 + syntax_errors: 0 + indentation_errors: 0 + exhausted_context_windows: 1 + test_timeouts: 8 + total_tests: 225 + command: aider --model sonnet + date: 2025-01-17 + versions: 0.71.2.dev + seconds_per_case: 21.4 + total_cost: 14.4063 diff --git a/aider/website/_includes/blame.md b/aider/website/_includes/blame.md index 3973ea812..61758a7db 100644 --- a/aider/website/_includes/blame.md +++ b/aider/website/_includes/blame.md @@ -1,5 +1,18 @@ - - +

+ +
+
+ +
+ + + @@ -24,10 +37,17 @@ document.addEventListener('DOMContentLoaded', function () { var linesData = { labels: labels, datasets: [{ - label: 'Aider\'s lines of new code', + label: 'Aider', data: [{% for row in site.data.blame %}{ x: '{{ row.end_tag }}', y: {{ row.aider_total }} },{% endfor %}], - backgroundColor: 'rgba(255, 99, 132, 0.8)', - borderColor: 'rgba(255, 99, 132, 1)', + backgroundColor: 'rgba(54, 162, 235, 0.8)', + borderColor: 'rgba(54, 162, 235, 1)', + borderWidth: 1 + }, + { + label: 'Human', + data: [{% for row in site.data.blame %}{ x: '{{ row.end_tag }}', y: {{ row.total_lines | minus: row.aider_total }} },{% endfor %}], + backgroundColor: 'rgba(200, 200, 200, 0.8)', + borderColor: 'rgba(200, 200, 200, 1)', borderWidth: 1 }] }; @@ -36,6 +56,7 @@ document.addEventListener('DOMContentLoaded', function () { type: 'bar', data: blameData, options: { + maintainAspectRatio: false, scales: { x: { type: 'category', @@ -85,9 +106,11 @@ document.addEventListener('DOMContentLoaded', function () { type: 'bar', data: linesData, options: { + maintainAspectRatio: false, scales: { x: { type: 'category', + stacked: true, title: { display: true, text: 'Version' @@ -98,6 +121,7 @@ document.addEventListener('DOMContentLoaded', function () { } }, y: { + stacked: true, title: { display: true, text: 'Lines of new code' @@ -107,12 +131,14 @@ document.addEventListener('DOMContentLoaded', function () { }, plugins: { legend: { - display: false + display: true, + position: 'chartArea', + reverse: true }, tooltip: { callbacks: { label: function(context) { - var label = 'New lines of code by aider'; + var label = context.dataset.label; var value = context.parsed.y || 0; return `${label}: ${value}`; } @@ -120,7 +146,7 @@ document.addEventListener('DOMContentLoaded', function () { }, title: { display: true, - text: 'Lines of new code written by aider, by release', + text: 'Lines of new code, by release', font: { size: 16 } diff --git a/aider/website/_includes/edit-leaderboard.js b/aider/website/_includes/edit-leaderboard.js deleted file mode 100644 index 7aeaac769..000000000 --- a/aider/website/_includes/edit-leaderboard.js +++ /dev/null @@ -1,97 +0,0 @@ -document.addEventListener('DOMContentLoaded', function () { - var ctx = document.getElementById('editChart').getContext('2d'); - const HIGHTLIGHT_MODEL = 'no no no no'; - var leaderboardData = { - labels: [], - datasets: [{ - label: 'Percent completed correctly', - data: [], - backgroundColor: function(context) { - const label = context.chart.data.labels[context.dataIndex] || ''; - return (label && label.includes(HIGHTLIGHT_MODEL)) ? 'rgba(255, 99, 132, 0.2)' : 'rgba(54, 162, 235, 0.2)'; - }, - borderColor: function(context) { - const label = context.chart.data.labels[context.dataIndex] || ''; - return (label && label.includes(HIGHTLIGHT_MODEL)) ? 'rgba(255, 99, 132, 1)' : 'rgba(54, 162, 235, 1)'; - }, - borderWidth: 1 - }] - }; - - var allData = []; - {% for row in edit_sorted %} - allData.push({ - model: '{{ row.model }}', - pass_rate_2: {{ row.pass_rate_2 }}, - percent_cases_well_formed: {{ row.percent_cases_well_formed }} - }); - {% endfor %} - - function updateChart() { - var selectedRows = document.querySelectorAll('tr.selected'); - var showAll = selectedRows.length === 0; - - leaderboardData.labels = []; - leaderboardData.datasets[0].data = []; - - allData.forEach(function(row, index) { - var rowElement = document.getElementById('edit-row-' + index); - if (showAll) { - rowElement.classList.remove('selected'); - } - if (showAll || rowElement.classList.contains('selected')) { - leaderboardData.labels.push(row.model); - leaderboardData.datasets[0].data.push(row.pass_rate_2); - } - }); - - leaderboardChart.update(); - } - - var tableBody = document.querySelector('table tbody'); - allData.forEach(function(row, index) { - var tr = tableBody.children[index]; - tr.id = 'edit-row-' + index; - tr.style.cursor = 'pointer'; - tr.onclick = function() { - this.classList.toggle('selected'); - updateChart(); - }; - }); - - var leaderboardChart = new Chart(ctx, { - type: 'bar', - data: leaderboardData, - options: { - scales: { - y: { - beginAtZero: true - } - } - } - }); - - updateChart(); - - // Add search functionality for edit table - document.getElementById('editSearchInput').addEventListener('keyup', function() { - var searchWords = this.value.toLowerCase().split(' ').filter(word => word.length > 0); - var tableBody = document.querySelector('table:first-of-type tbody'); - var rows = tableBody.getElementsByTagName('tr'); - - leaderboardData.labels = []; - leaderboardData.datasets[0].data = []; - - for (var i = 0; i < rows.length; i++) { - var rowText = rows[i].textContent; - if (searchWords.every(word => rowText.toLowerCase().includes(word))) { - rows[i].style.display = ''; - leaderboardData.labels.push(allData[i].model); - leaderboardData.datasets[0].data.push(allData[i].pass_rate_2); - } else { - rows[i].style.display = 'none'; - } - } - leaderboardChart.update(); - }); -}); diff --git a/aider/website/_includes/env-keys-tip.md b/aider/website/_includes/env-keys-tip.md deleted file mode 100644 index 0f2effb95..000000000 --- a/aider/website/_includes/env-keys-tip.md +++ /dev/null @@ -1,6 +0,0 @@ -{: .tip } -All API keys can be stored in a -[.env file](/docs/config/dotenv.html). -Only OpenAI and Anthropic keys can be stored in the -[YAML config file](/docs/config/aider_conf.html). - diff --git a/aider/website/_includes/get-started.md b/aider/website/_includes/get-started.md index 7fabb5cbd..07da34dab 100644 --- a/aider/website/_includes/get-started.md +++ b/aider/website/_includes/get-started.md @@ -1,17 +1,25 @@ -You can get started quickly like this: +If you already have python 3.8-3.13 installed, you can get started quickly like this: -``` -python -m pip install -U aider-chat - -# Change directory into a git repo -cd /to/your/git/repo - -# Work with Claude 3.5 Sonnet on your repo -export ANTHROPIC_API_KEY=your-key-goes-here -aider - -# Work with GPT-4o on your repo -export OPENAI_API_KEY=your-key-goes-here -aider +```bash +python -m pip install aider-install +aider-install + +# Change directory into your code base +cd /to/your/project + +# Work with DeepSeek via DeepSeek's API +aider --model deepseek --api-key deepseek=your-key-goes-here + +# Work with Claude 3.5 Sonnet via Anthropic's API +aider --model sonnet --api-key anthropic=your-key-goes-here + +# Work with GPT-4o via OpenAI's API +aider --model gpt-4o --api-key openai=your-key-goes-here + +# Work with Sonnet via OpenRouter's API +aider --model openrouter/anthropic/claude-3.5-sonnet --api-key openrouter=your-key-goes-here + +# Work with DeepSeek via OpenRouter's API +aider --model openrouter/deepseek/deepseek-chat --api-key openrouter=your-key-goes-here ``` diff --git a/aider/website/_includes/head_custom.html b/aider/website/_includes/head_custom.html index 95a83cf10..77533ab72 100644 --- a/aider/website/_includes/head_custom.html +++ b/aider/website/_includes/head_custom.html @@ -18,3 +18,65 @@ + +{% if site.analytics.enabled %} + + + + +{% endif %} diff --git a/aider/website/_includes/keys.md b/aider/website/_includes/keys.md new file mode 100644 index 000000000..5391c21dc --- /dev/null +++ b/aider/website/_includes/keys.md @@ -0,0 +1,4 @@ +{: .tip :} +See the +[API key configuration docs](/docs/config/api-keys.html) +for information on how to configure and store your API keys. diff --git a/aider/website/_includes/leaderboard.js b/aider/website/_includes/leaderboard.js index e69de29bb..f43dee7f9 100644 --- a/aider/website/_includes/leaderboard.js +++ b/aider/website/_includes/leaderboard.js @@ -0,0 +1,190 @@ +document.addEventListener('DOMContentLoaded', function () { + var ctx = document.getElementById('editChart').getContext('2d'); + const blueDiagonalPattern = pattern.draw('diagonal', 'rgba(54, 162, 235, 0.2)'); + const redDiagonalPattern = pattern.draw('diagonal', 'rgba(255, 99, 132, 0.2)'); + let displayedData = []; + + const HIGHLIGHT_MODEL = '{{ highlight_model | default: "no no no" }}'; + var leaderboardData = { + labels: [], + datasets: [{ + label: 'Percent completed correctly', + data: [], + backgroundColor: function(context) { + const row = allData[context.dataIndex]; + if (row && row.edit_format === 'whole') { + return diagonalPattern; + } + const label = leaderboardData.labels[context.dataIndex] || ''; + return (label && label.includes(HIGHLIGHT_MODEL)) ? 'rgba(255, 99, 132, 0.2)' : 'rgba(54, 162, 235, 0.2)'; + }, + borderColor: function(context) { + const label = context.chart.data.labels[context.dataIndex] || ''; + return (label && label.includes(HIGHLIGHT_MODEL)) ? 'rgba(255, 99, 132, 1)' : 'rgba(54, 162, 235, 1)'; + }, + borderWidth: 1 + }] + }; + + var allData = []; + {% for row in data_source %} + allData.push({ + model: '{{ row.model }}', + pass_rate: {{ row[pass_rate_field] }}, + percent_cases_well_formed: {{ row.percent_cases_well_formed }}, + edit_format: '{{ row.edit_format | default: "diff" }}' + }); + {% endfor %} + + function updateChart() { + var selectedRows = document.querySelectorAll('tr.selected'); + var showAll = selectedRows.length === 0; + + displayedData = []; + leaderboardData.labels = []; + leaderboardData.datasets[0].data = []; + + allData.forEach(function(row, index) { + var rowElement = document.getElementById('edit-row-' + index); + if (showAll) { + rowElement.classList.remove('selected'); + } + if (showAll || rowElement.classList.contains('selected')) { + displayedData.push(row); + leaderboardData.labels.push(row.model); + leaderboardData.datasets[0].data.push(row.pass_rate); + } + }); + + leaderboardChart.update(); + leaderboardChart.render(); + } + + // Use displayedData in the backgroundColor callback instead of allData + leaderboardData.datasets[0].backgroundColor = function(context) { + const row = displayedData[context.dataIndex]; + const label = leaderboardData.labels[context.dataIndex] || ''; + if (label && label.includes(HIGHLIGHT_MODEL)) { + if (row && row.edit_format === 'whole') return redDiagonalPattern; + else return 'rgba(255, 99, 132, 0.2)'; + } else if (row && row.edit_format === 'whole') { + return blueDiagonalPattern; + } else { + return 'rgba(54, 162, 235, 0.2)'; + } + }; + + var tableBody = document.querySelector('table tbody'); + allData.forEach(function(row, index) { + var tr = tableBody.children[index]; + if (!tr) { + // If the row doesn't exist, create it + tr = document.createElement('tr'); + tableBody.appendChild(tr); + } + tr.id = 'edit-row-' + index; + tr.style.cursor = 'pointer'; + tr.onclick = function() { + this.classList.toggle('selected'); + updateChart(); + }; + }); + + var leaderboardChart = new Chart(ctx, { + type: 'bar', + data: leaderboardData, + options: { + plugins: { + legend: { + display: {% if show_legend == false %}false{% else %}true{% endif %}, + labels: { + generateLabels: function(chart) { + return [ + { + text: 'Diff-like format', + fillStyle: 'rgba(54, 162, 235, 0.2)', + strokeStyle: 'rgba(54, 162, 235, 1)', + lineWidth: 1 + }, + { + text: 'Whole format', + fillStyle: blueDiagonalPattern, + strokeStyle: 'rgba(54, 162, 235, 1)', + lineWidth: 1 + } + ]; + } + } + } + }, + scales: { + y: { + beginAtZero: true, + title: { + display: true, + text: 'Percent completed correctly' + } + }, + x: { + ticks: { + callback: function(value, index) { + const label = this.getLabelForValue(value); + if (label.length <= "claude-3-5-sonnet".length) { + return label; + } + + // Find all possible split positions + const splitPositions = []; + for (let i = 0; i < label.length; i++) { + if (label[i] === '-' || label[i] === ' ') { + splitPositions.push(i); + } + } + + if (splitPositions.length === 0) { + return label; + } + + // Find split position closest to middle + const middle = label.length / 2; + const splitIndex = splitPositions.reduce((closest, current) => { + return Math.abs(current - middle) < Math.abs(closest - middle) ? current : closest; + }); + + return [ + label.slice(0, splitIndex), + label.slice(splitIndex + 1) + ]; + } + } + } + } + } + }); + + updateChart(); + + // Add search functionality for edit table + document.getElementById('editSearchInput').addEventListener('keyup', function() { + var searchWords = this.value.toLowerCase().split(' ').filter(word => word.length > 0); + var tableBody = document.querySelector('table:first-of-type tbody'); + var rows = tableBody.getElementsByTagName('tr'); + + displayedData = []; + leaderboardData.labels = []; + leaderboardData.datasets[0].data = []; + + for (var i = 0; i < rows.length; i++) { + var rowText = rows[i].textContent; + if (searchWords.every(word => rowText.toLowerCase().includes(word))) { + rows[i].style.display = ''; + displayedData.push(allData[i]); + leaderboardData.labels.push(allData[i].model); + leaderboardData.datasets[0].data.push(allData[i].pass_rate); + } else { + rows[i].style.display = 'none'; + } + } + leaderboardChart.update(); + }); +}); diff --git a/aider/website/_includes/multi-line.md b/aider/website/_includes/multi-line.md index 5a93562ca..b1fe74211 100644 --- a/aider/website/_includes/multi-line.md +++ b/aider/website/_includes/multi-line.md @@ -5,7 +5,10 @@ You can send long, multi-line messages in the chat in a few ways: - Use Meta-ENTER to start a new line without sending the message (Esc+ENTER in some environments). - Use `/paste` to paste text from the clipboard into the chat. - Use the `/editor` command to open your editor to create the next chat message. See [editor configuration docs](/docs/config/editor.html) for more info. - + - Use multiline-mode, which swaps the function of Meta-Enter and Enter, so that Enter inserts a newline, and Meta-Enter submits your command. To enable multiline mode: + - Use the `/multiline-mode` command to toggle it during a session. + - Use the `--multiline` switch. + Example with a tag: ``` {python diff --git a/aider/website/_includes/qwq-chart.js b/aider/website/_includes/qwq-chart.js new file mode 100644 index 000000000..e60648d60 --- /dev/null +++ b/aider/website/_includes/qwq-chart.js @@ -0,0 +1,120 @@ +document.addEventListener('DOMContentLoaded', function () { + var ctx = document.getElementById('qwqChart').getContext('2d'); + var allData = []; + {% for row in site.data.qwq %} + allData.push({ + model: '{{ row.model }}', + pass_rate_2: {{ row.pass_rate_2 }} + }); + {% endfor %} + + // Sort data by pass_rate_2 in descending order + allData.sort((a, b) => b.pass_rate_2 - a.pass_rate_2); + + var chart; + + function updateChart(filterText) { + var filteredData = allData.filter(row => + row.model.toLowerCase().includes(filterText.toLowerCase()) + ); + + var chartData = { + labels: filteredData.map(row => row.model), + datasets: [{ + data: filteredData.map(row => row.pass_rate_2), + backgroundColor: filteredData.map(row => + (row.model === 'Qwen2.5 Coder 32B-I' || row.model === 'Sonnet (SOTA)' || row.model === 'o1-mini' || row.model === 'o1-preview' || row.model === 'QwQ') + ? 'rgba(75, 192, 192, 0.2)' // Green for solo models + : 'rgba(54, 162, 235, 0.2)' // Blue for architect+editor + ), + borderColor: filteredData.map(row => + (row.model === 'Qwen2.5 Coder 32B-I' || row.model === 'Sonnet (SOTA)' || row.model === 'o1-mini' || row.model === 'o1-preview' || row.model === 'QwQ') + ? 'rgba(75, 192, 192, 1)' // Green border for solo models + : 'rgba(54, 162, 235, 1)' // Blue border for architect+editor + ), + borderWidth: 1 + }] + }; + + if (chart) { + chart.data = chartData; + chart.update(); + } else { + chart = new Chart(ctx, { + type: 'bar', + data: chartData, + options: { + plugins: { + legend: { + display: true, + position: 'top', + labels: { + font: { + size: 14 + }, + generateLabels: function(chart) { + return [ + { + text: 'Solo model', + fillStyle: 'rgba(75, 192, 192, 0.2)', + strokeStyle: 'rgba(75, 192, 192, 1)', + lineWidth: 1, + fontColor: '#666' + }, + { + text: 'Architect + Editor', + fillStyle: 'rgba(54, 162, 235, 0.2)', + strokeStyle: 'rgba(54, 162, 235, 1)', + lineWidth: 1, + fontColor: '#666' + } + ]; + } + } + } + }, + scales: { + y: { + beginAtZero: true, + title: { + display: true, + text: 'Aider code editing benchmark (%)', + font: { + size: 18 + } + }, + ticks: { + font: { + size: 16 + } + } + }, + x: { + ticks: { + font: { + size: 16 + }, + callback: function(value, index) { + const label = this.getLabelForValue(value); + if (label.includes(" + ")) { + const parts = label.split(" + "); + return [parts[0] + " +", parts[1]]; + } + return label; + } + } + } + } + } + }); + } + } + + // Initial chart render + updateChart(''); + + // Connect search input to chart filtering + document.getElementById('qwqSearchInput').addEventListener('keyup', function() { + updateChart(this.value); + }); +}); diff --git a/aider/website/_includes/refactor-leaderboard.js b/aider/website/_includes/refactor-leaderboard.js deleted file mode 100644 index d540bde65..000000000 --- a/aider/website/_includes/refactor-leaderboard.js +++ /dev/null @@ -1,90 +0,0 @@ -document.addEventListener('DOMContentLoaded', function () { - var ctx = document.getElementById('refacChart').getContext('2d'); - var leaderboardData = { - labels: [], - datasets: [{ - label: 'Percent completed correctly', - data: [], - backgroundColor: 'rgba(54, 162, 235, 0.2)', - borderColor: 'rgba(54, 162, 235, 1)', - borderWidth: 1 - }] - }; - - var allData = []; - {% for row in refac_sorted %} - allData.push({ - model: '{{ row.model }}', - pass_rate_1: {{ row.pass_rate_1 }}, - percent_cases_well_formed: {{ row.percent_cases_well_formed }} - }); - {% endfor %} - - function updateChart() { - var selectedRows = document.querySelectorAll('tr.selected'); - var showAll = selectedRows.length === 0; - - leaderboardData.labels = []; - leaderboardData.datasets[0].data = []; - - allData.forEach(function(row, index) { - var rowElement = document.getElementById('refac-row-' + index); - if (showAll) { - rowElement.classList.remove('selected'); - } - if (showAll || rowElement.classList.contains('selected')) { - leaderboardData.labels.push(row.model); - leaderboardData.datasets[0].data.push(row.pass_rate_1); - } - }); - - leaderboardChart.update(); - } - - var tableBody = document.querySelectorAll('table tbody')[1]; - allData.forEach(function(row, index) { - var tr = tableBody.children[index]; - tr.id = 'refac-row-' + index; - tr.style.cursor = 'pointer'; - tr.onclick = function() { - this.classList.toggle('selected'); - updateChart(); - }; - }); - - var leaderboardChart = new Chart(ctx, { - type: 'bar', - data: leaderboardData, - options: { - scales: { - y: { - beginAtZero: true - } - } - } - }); - - updateChart(); - - // Add search functionality for refactoring table - document.getElementById('refacSearchInput').addEventListener('keyup', function() { - var searchWords = this.value.toLowerCase().split(' ').filter(word => word.length > 0); - var tableBody = document.querySelectorAll('table tbody')[1]; - var rows = tableBody.getElementsByTagName('tr'); - - leaderboardData.labels = []; - leaderboardData.datasets[0].data = []; - - for (var i = 0; i < rows.length; i++) { - var rowText = rows[i].textContent; - if (searchWords.every(word => rowText.toLowerCase().includes(word))) { - rows[i].style.display = ''; - leaderboardData.labels.push(allData[i].model); - leaderboardData.datasets[0].data.push(allData[i].pass_rate_1); - } else { - rows[i].style.display = 'none'; - } - } - leaderboardChart.update(); - }); -}); diff --git a/aider/website/_includes/replit-pipx.md b/aider/website/_includes/replit-pipx.md index 12ca93f11..317489089 100644 --- a/aider/website/_includes/replit-pipx.md +++ b/aider/website/_includes/replit-pipx.md @@ -1,6 +1,6 @@ To use aider with pipx on replit, you can run these commands in the replit shell: -``` +```bash pip install pipx pipx run aider-chat ...normal aider args... ``` diff --git a/aider/website/_includes/special-keys.md b/aider/website/_includes/special-keys.md deleted file mode 100644 index dc7342916..000000000 --- a/aider/website/_includes/special-keys.md +++ /dev/null @@ -1,12 +0,0 @@ -Aider has special support for providing -OpenAI and Anthropic API keys -via -[command line switches](/docs/config/options.html) -and -[yaml config file](/docs/config/aider_conf.html). -*All other LLM providers* must -have their keys and settings -specified in environment variables. -This can be done in your shell, -or by using a -[.env file](/docs/config/dotenv.html). diff --git a/aider/website/_includes/venv-pipx.md b/aider/website/_includes/venv-pipx.md deleted file mode 100644 index 3b2d0fc00..000000000 --- a/aider/website/_includes/venv-pipx.md +++ /dev/null @@ -1,7 +0,0 @@ -{: .tip } -Using a Python -[virtual environment](https://docs.python.org/3/library/venv.html){:target="_blank"} -is recommended. -Or, you could -[use pipx to install aider](/docs/install/pipx.html) -once for your whole system. diff --git a/aider/website/_includes/works-best.md b/aider/website/_includes/works-best.md index 34d020ca9..1e7fc942d 100644 --- a/aider/website/_includes/works-best.md +++ b/aider/website/_includes/works-best.md @@ -1,2 +1 @@ -Aider works best with GPT-4o & Claude 3.5 Sonnet and can -[connect to almost any LLM](https://aider.chat/docs/llms.html). +Aider works best with Claude 3.5 Sonnet, DeepSeek V3, o1 & GPT-4o and can [connect to almost any LLM](https://aider.chat/docs/llms.html). diff --git a/aider/website/_posts/2024-05-24-self-assembly.md b/aider/website/_posts/2024-05-24-self-assembly.md index 4ccb9af96..31e2ec745 100644 --- a/aider/website/_posts/2024-05-24-self-assembly.md +++ b/aider/website/_posts/2024-05-24-self-assembly.md @@ -1,6 +1,6 @@ --- -title: Aider has written 7% of its own code -excerpt: Aider has written 7% of its own code, via 600+ commits that inserted 4.8K and deleted 1.5K lines of code. +title: Aider has written 7% of its own code (outdated, now 70%) +excerpt: This article is quite out dated. Aider is currently writing about 70% of the new code in each release. highlight_image: /assets/self-assembly.jpg nav_exclude: true --- @@ -8,13 +8,16 @@ nav_exclude: true {% endif %} -# Aider has written 7% of its own code +# Aider has written 7% of its own code (outdated, now 70%) [![self assembly](/assets/self-assembly.jpg)](https://aider.chat/assets/self-assembly.jpg) {: .note } -This article is quite out dated. For current statistics, see -[aider's release history](/HISTORY.html). +This article is quite old and outdated. +Aider is currently writing about 70% of the new code +in each release. +See +[aider's release history](/HISTORY.html) for the latest statistics. The [aider git repo](https://github.com/Aider-AI/aider) diff --git a/aider/website/_posts/2024-11-21-quantization.md b/aider/website/_posts/2024-11-21-quantization.md index a1d060edd..33677b5d8 100644 --- a/aider/website/_posts/2024-11-21-quantization.md +++ b/aider/website/_posts/2024-11-21-quantization.md @@ -12,6 +12,8 @@ nav_exclude: true # Details matter with open source models {: .no_toc } + + Open source models like Qwen 2.5 32B Instruct are performing very well on aider's code editing benchmark, rivaling closed source frontier models. @@ -21,44 +23,56 @@ Open source models are often available at a variety of quantizations, and can be served with different token limits. These details matter when working with code. -The graph and table below compares different versions of the Qwen 2.5 Coder 32B Instruct model, +The graph above and table below compares different versions of the Qwen 2.5 Coder 32B Instruct model, served both locally and from a variety of cloud providers. - The [HuggingFace BF16 weights](https://huggingface.co/Qwen/Qwen2.5-Coder-32B-Instruct) served via [glhf.chat](https://glhf.chat). - [4bit and 8bit quants for mlx](https://t.co/cwX3DYX35D). - The results from [OpenRouter's mix of providers](https://openrouter.ai/qwen/qwen-2.5-coder-32b-instruct/providers) which serve the model with different levels of quantization. -- Results from individual providers served via OpenRouter and directly to their own APIs. -- Ollama locally serving different quantizations from the [Ollama model library](https://ollama.com/library/qwen2.5-coder:32b-instruct-q4_K_M). +- Results from OpenRouter's providers, both served via OpenRouter and directly to their own APIs. +- Ollama locally serving different quantizations from the [Ollama model library](https://ollama.com/library/qwen2.5-coder:32b-instruct-q4_K_M) with 8k+ +context windows. +- An Ollama fp16 quantization served with Ollama's default 2k context window. -This benchmarking effort highlighted a number of pitfalls and details which -can have a significant impact on the model's ability to correctly edit code: +### Pitfalls and details + +This benchmarking effort highlighted a number of pitfalls and details specific to open source +models which +can have a significant impact on their ability to correctly edit code: - **Quantization** -- Open source models are often available at dozens of different quantizations. Most seem to only modestly decrease code editing skill, but stronger quantizations do have a real impact. - **Context window** -- Cloud providers can decide how large a context window to accept, -and they often choose differently. Ollama defaults to a tiny 2k context window, +and they often choose differently. Ollama's local API server +defaults to a tiny 2k context window, and silently discards data that exceeds it. Such a small window has -catastrophic effects on performance. +catastrophic effects on performance, without throwing obvious hard errors. - **Output token limits** -- Open source models are often served with wildly differing output token limits. This has a direct impact on how much code the model can write or edit in a response. -- **Buggy cloud providers** -- Between Qwen 2.5 Coder 32B Instruct -and DeepSeek V2.5, there were +- **Buggy cloud providers** -- While benchmarking Qwen 2.5 Coder 32B Instruct +and DeepSeek V2.5, I discovered multiple cloud providers with broken or buggy API endpoints. They seemed -to be returning result different from expected based on the advertised +to be returning results different from expected based on the advertised quantization and context sizes. The harm caused to the code editing benchmark varied from serious to catastrophic. +One provider scored 0.5% on the benchmark with DeepSeek V2.5, a highly capable model. -The best versions of the model rival GPT-4o, while the worst performing -quantization is more like the older GPT-4 Turbo. -Even an excellent fp16 quantization falls to GPT-3.5 Turbo levels of performance +Closed source, proprietary models don't typically have these issues. +They are owned and operated by the organization that created them, +and typically served with specific, predictable context window and output token limits. +Their quantization level is usually unknown, but fixed and unchanging for all users. + +### Conclusions + +The best versions of the Qwen model rival GPT-4o, while the worst performing +quantization is more like the older GPT-4 Turbo when served competently. +Even an otherwise excellent fp16 quantization falls to GPT-3.5 Turbo levels of performance if run with Ollama's default 2k context window. - - ### Sections {: .no_toc } @@ -67,7 +81,9 @@ if run with Ollama's default 2k context window. ## Benchmark results - +{: .note :} +These are results from single benchmark runs, so expect normal variance of +/- 1-2%. + + + + + + + + + + + + + + + {% assign qwq_sorted = site.data.qwq | sort: 'pass_rate_2' | reverse %} + {% for row in qwq_sorted %} + + + + + + + + {% endfor %} + +
ModelPercent completed correctlyPercent using correct edit formatCommandEdit format
{{ row.model }}{{ row.pass_rate_2 }}%{{ row.percent_cases_well_formed }}%{{ row.command }}{{ row.edit_format }}
+ + + + + +## Open source model caveats + +As discussed in a recent blog post, +[details matter with open source models](https://aider.chat/2024/11/21/quantization.html). +For clarity, new benchmark runs for this article were +performed against OpenRouter's endpoints for +QwQ 32B Preview and Qwen 2.5 Coder 32B Instruct. +For the other models, the benchmark was direct to their providers' APIs. + +Having recently done extensive testing of OpenRouter's Qwen 2.5 Coder 32B Instruct endpoint, +it seems reliable. +The provider Mancer was blocked due to the small context window it provides. + +For QwQ 32B Preview, Fireworks was blocked because of its small context window. diff --git a/aider/website/_posts/2024-12-21-polyglot.md b/aider/website/_posts/2024-12-21-polyglot.md new file mode 100644 index 000000000..4b2f9bdc7 --- /dev/null +++ b/aider/website/_posts/2024-12-21-polyglot.md @@ -0,0 +1,216 @@ +--- +title: o1 tops aider's new polyglot leaderboard +excerpt: o1 scores the top result on aider's new multi-language, more challenging coding benchmark. +highlight_image: /assets/o1-polyglot.jpg +draft: false +nav_exclude: true +--- +{% if page.date %} + +{% endif %} + +# o1 tops aider's new polyglot leaderboard +{: .no_toc } + + + +OpenAI's new o1 model with "high" reasoning effort +gets the top score on the +new +[aider polyglot leaderboard](/docs/leaderboards/), significantly ahead of +other top LLMs. +The new polyglot benchmark uses many popular coding languages +and was designed to be +*much more challenging* than aider's original +[code editing benchmark](/docs/leaderboards/edit.html). +This more clearly distinguishes +the performance of +today's strongest coding models and +leaves headroom for future LLMs. + +{: .note :} +See the main +[aider leaderboard](https://aider.chat/docs/leaderboards/) +for benchmark results from more models. +This article only contains a snapshot +of results at the time of publication. + +## The polyglot benchmark + +Like aider's original code editing benchmark, +the new polyglot benchmark is based on Exercism +coding exercises. + +The new polyglot benchmark: + +- Contains coding problems in C++, Go, Java, JavaScript, Python and Rust. +The old benchmark was solely based on Python exercises. +- Focuses on the *most difficult* 225 exercises out of the 697 that +Exercism provides for those languages. +The old benchmark simply included all 133 Python exercises, +regardless of difficulty. + +## Motivation and goals + +Aider's original code editing benchmark was +saturating as the top scores approached and then surpassed 80%. +Sonnet's score of 84.2% was based on solving 112 of the 133 +exercises, leaving only 21 unsolved exercises. +New champions were advancing the top score by +solving just 1-2 more problems than the previous record. +This made it hard to clearly +measure the +difference in code editing skill between these top models. + +Part of the problem is that many of the original +133 Python problems are very easy +and provide +little challenge to today's frontier LLMs. +Models as old as GPT 3.5 Turbo were able to solve half of the +133 problems. +Such easy problems simply inflate the benchmark scores +of modern LLMs without +providing any data about which models are better or worse. + +The main goal for a new benchmark +was to re-calibrate the scale so that +today's top coding LLMs +would occupy a wide range of scores between about 5% and 50%. +This should leave headroom for future LLMs and +make it possible to +more clearly compare the relative performance of top models. + +## Designing the polyglot benchmark + +The new benchmark: + +- Tests LLMs with more coding languages, to increase diversity and source a larger pool of problems. +- Includes just the most challenging coding problems and excludes easy problems that are solvable by most of today's top coding LLMs. +- Includes more total coding problems, to enable more granularity of comparison. + +The new benchmark is based on Exercism coding problems +from 6 of the most popular programming languages: + +- C++ +- Go +- Java +- JavaScript +- Python +- Rust + +Exercism provides a total of 697 coding problems in those 6 languages. +A set of 7 of today's top coding models each attempted all 697 of +the Exercism problems: + +- Sonnet +- Haiku +- o1 Mini +- DeepSeek +- GPT-4o +- Qwen 32B Coder Instruct +- GPT-4o Mini + +Depending on the difficulty of the problems, +a different number of solutions were found by the collection of +7 models: + +| Solutions
found | Number of
problems | Cumulative number
of problems | +|--------|-----------|------------| +| 0 | 66 | 66 | +| 1 | 61 | 127 | +| 2 | 50 | 177 | +| 3 | 48 | 225 | +| 4 | 53 | 278 | +| 5 | 71 | 349 | +| 6 | 90 | 439 | +| 7 | 258 | 697 | + +In the table above, you can see that 258 of the problems were solved +by all 7 LLMs. +These problems are far too easy, and wouldn't be good choices for the new benchmark. +Instead, we need hard problems like the +66 that none of the 7 models were able to solve. + +The new benchmark uses +the 225 problems that were solved by 3 or fewer models. +This achieves a balance between hard and moderate problems, +and provides a large but not excessive total pool of problems. +It also represents a good diversity of coding languages: + +| Language | Problems | +|-------------|----------| +| C++ | 26 | +| Go | 39 | +| Java | 47 | +| JavaScript | 49 | +| Python | 34 | +| Rust | 30 | +| **Total** | **225** | + +## o1 + +OpenAI's new o1 model established a very strong +top score of 62% on the new benchmark. +This still leaves 86 problems of headroom for future models +to solve. +Given the incredible pace of recent advancements, it +will be interesting to see +how long it will take for this new benchmark to saturate. + +## Benchmark problems + +The 225 coding problems are available in the +[aider polyglot benchmark repo](https://github.com/Aider-AI/polyglot-benchmark) +on GitHub. + + + +## Results + + + + + + + + + + + + + {% assign edit_sorted = site.data.o1_polyglot_leaderboard | sort: 'pass_rate_2' | reverse %} + {% for row in edit_sorted %} + + + + + + + + {% endfor %} + +
ModelPercent completed correctlyPercent using correct edit formatCommandEdit format
{{ row.model }}{{ row.pass_rate_2 }}%{{ row.percent_cases_well_formed }}%{{ row.command }}{{ row.edit_format }}
+ + + + + diff --git a/aider/website/_posts/2025-01-15-uv.md b/aider/website/_posts/2025-01-15-uv.md new file mode 100644 index 000000000..3f0d045c6 --- /dev/null +++ b/aider/website/_posts/2025-01-15-uv.md @@ -0,0 +1,102 @@ +--- +title: Using uv as an installer +excerpt: Reliably packaging & distributing python CLI tools is hard. Aider uses uv in novel ways to make it easy to install the aider CLI, its dependencies and python 3.12. All in an isolated env. +draft: false +nav_exclude: true +--- +{% if page.date %} + +{% endif %} + +# Using uv as an installer +{: .no_toc } + +It's hard to reliably +package and distribute python command line tools +to end users. +Users frequently encounter challenges: +dependency version conflicts, virtual environment management, +needing to install python or a specific version of python, etc. + +Aider employs [uv](https://github.com/astral-sh/uv) +in a couple of novel ways to streamline the installation process: + +1. Install aider with +`curl https://aider.chat/install.sh | sh` even if python isn't already installed. + +2. Users who have python 3.8+ installed can `pip install aider-install && aider-install`. + +Both methods use uv to **globally** install the `aider` command line program, +with all of its dependencies in an **isolated environment**. +They ensure that aider will run with **python 3.12**, and install that version +if it is not already available. + +These uv install methods are especially helpful for aider, because it +has a large set of very specific dependencies. +Since not all of aider's dependencies are available on all python versions, +it requires python 3.9-3.12. + +Most users don't want to worry about these details -- +they just want a quick way to install and run aider. + + +## One-liners + +Users can install aider with a shell one-liner, without even having python previously installed: + +```bash +curl -LsSf https://aider.chat/install.sh | sh +``` + +This installs uv, then uses it to install python 3.12, +install the `aider` command line tool +and update the user's shell path. +Under the hood, it is simply a copy of +uv's own install script `https://astral.sh/uv/install.sh` +with [one line added](https://github.com/Aider-AI/aider/blob/4251e976b3aa52c2a3af08da4b203d4d524c8e92/aider/website/install.sh#L1181), to install aider as a tool: + +``` +ensure "${_install_dir}/uv" tool install --force --python python3.12 aider-chat@latest +``` + + +## aider-install + +The aider-install python package allows quick global installation of aider +for users who already have python 3.8+ installed. +It simply provides the `aider-install` command line program, +which users just need to run once. + +```bash +pip install aider-install +aider-install +``` + +The `pip install aider-install` installs only two packages: +aider-install and the [uv python package](https://pypi.org/project/uv/). +This ensures that uv is available +in the user's environment. +Everything else is installed in a stand-alone environment created by uv. + +When the user runs `aider-install`, it runs uv +to install aider as a tool and update the user's shell path if needed: + +```bash +uv tool install --force --python python3.12 aider-chat +uv tool update-shell +``` + + +## Benefits + +These uv install methods have been popular with users, +providing a hassle free way to install aider and quickly get started. +Installs are also extremely fast, much faster than pip or pipx installs +even when uv is also installing python 3.12! + +There are also a number of benefits from the perspective of the tool developer/publisher. +Since providing these install methods, far fewer users report dependency problems and +version conflicts as compared to users who `pip install aider-chat`. +There is also less pressure to rapidly support the newest python versions, +since aider always installs with python 3.12. + diff --git a/aider/website/_posts/2025-01-24-r1-sonnet.md b/aider/website/_posts/2025-01-24-r1-sonnet.md new file mode 100644 index 000000000..909f69c23 --- /dev/null +++ b/aider/website/_posts/2025-01-24-r1-sonnet.md @@ -0,0 +1,118 @@ +--- +title: R1+Sonnet set SOTA on aider's polyglot benchmark +excerpt: R1+Sonnet has set a new SOTA on the aider polyglot benchmark. At 14X less cost compared to o1. +highlight_image: /assets/r1-sonnet-sota.jpg +draft: false +nav_exclude: true +--- +{% if page.date %} + +{% endif %} + +# R1+Sonnet set SOTA on aider's polyglot benchmark +{: .no_toc } + + + +Aider supports [using a pair of models for coding](https://aider.chat/2024/09/26/architect.html): + +- An Architect model is asked to describe how to solve the coding problem. Thinking/reasoning models often work well in this role. +- An Editor model is given the Architect's solution and asked to produce specific code editing instructions to apply those changes to existing source files. + +**R1 as architect with Sonnet as editor has set a new SOTA of 64.0%** on the +[aider polyglot benchmark](/2024/12/21/polyglot.html). +They achieve this at **14X less cost** compared to the previous o1 SOTA result. + +o1 paired with Sonnet didn't produce better results than just using o1 alone. +Using various other models as editor didn't seem to improve o1 or R1 versus their solo scores. +This is in contrast to the first wave of thinking models like o1-preview and o1-mini, +which improved when paired with many different editor models. + +o1 was set with reasoning effort high for these tests. + +## Try it + +Once you [install aider](https://aider.chat/docs/install.html), +you can use aider, R1 and Sonnet like this: + +```bash +export DEEPSEEK_API_KEY= +export ANTHROPIC_API_KEY= + +aider --architect --model r1 --editor-model sonnet +``` + +Or if you have an [OpenRouter](https://openrouter.ai) account: + +```bash +export OPENROUTER_API_KEY= + +aider --architect --model openrouter/deepseek/deepseek-r1 --editor-model openrouter/anthropic/claude-3.5-sonnet +``` + +## Thinking output + +There has been +[some recent discussion](https://github.com/Aider-AI/aider/pull/2973) +about extracting the `` tokens from R1's responses +and feeding them to Sonnet. +That was an interesting experiment, for sure. + +To be clear, the results above are *not* using R1's thinking tokens, just the normal +final output. +R1 is configured in aider's standard architect role with Sonnet as editor. +The benchmark results that used the thinking tokens appear to be worse than +the architect/editor results shared here. + +## Results + + + + + + + + + + + + + + {% assign edit_sorted = site.data.r1_architect | sort: 'pass_rate_2' | reverse %} + {% for row in edit_sorted %} + + + + + + + + + {% endfor %} + +
ModelPercent completed correctlyPercent using correct edit formatCommandEdit formatTotal Cost
{{ row.model }}{{ row.pass_rate_2 }}%{{ row.percent_cases_well_formed }}%{{ row.command }}{{ row.edit_format }}{% if row.total_cost == 0 %}?{% else %}${{ row.total_cost | times: 1.0 | round: 2 }}{% endif %}
+ + + + + diff --git a/aider/website/_posts/2025-01-28-deepseek-down.md b/aider/website/_posts/2025-01-28-deepseek-down.md new file mode 100644 index 000000000..b3145ce93 --- /dev/null +++ b/aider/website/_posts/2025-01-28-deepseek-down.md @@ -0,0 +1,257 @@ +--- +title: Alternative DeepSeek V3 providers +excerpt: DeepSeek's API has been experiencing reliability issues. Here are alternative providers you can use. +#highlight_image: /assets/deepseek-down.jpg +draft: false +nav_exclude: true +--- +{% if page.date %} + +{% endif %} + +# Alternative DeepSeek V3 providers +{: .no_toc } + + + +DeepSeek's API has been experiencing significant reliability issues for the past 24-48+ hours, with many users reporting downtime and overload problems. +Their [status page](https://status.deepseek.com) notes an ongoing incident. + +If you're affected by these issues, several alternative providers offer access to DeepSeek V3. This article compares their performance on aider's polyglot benchmark to help you choose a reliable alternative. + +## Providers +{: .no_toc } + +* TOC +{:toc} + +## OpenRouter + +[OpenRouter offers many DeepSeek providers](https://openrouter.ai/deepseek/deepseek-chat/providers) +through their unified API. +You can use aider with OpenRouter like this: + +```bash +# Set your API key using environment variables +export OPENROUTER_API_KEY= +aider --model openrouter/deepseek/deepseek-chat + +# Or use the --api-key command line option +aider --model openrouter/deepseek/deepseek-chat --api-key openrouter= + +# Or add it to .aider.conf.yml in your home directory or project root: +api-key: + - openrouter= +``` + +OpenRouter automatically monitors their providers and routes requests to stable +APIs and away from those experiencing unreliable performance. + +But not all providers serve the same version of open source models, and not +all have the same privacy guarantees. +You can control which OpenRouter providers are used to serve the model via +[aider's model settings](https://aider.chat/docs/config/adv-model-settings.html#model-settings). +Create a `.aider.model.settings.yml` file in your home directory or git project root with settings like this: + +```yaml +- name: openrouter/deepseek/deepseek-chat + extra_params: + extra_body: + provider: + # Only use these providers, in this order + order: ["Novita"] + # Don't fall back to other providers + allow_fallbacks: false +``` + +See [OpenRouter's provider routing docs](https://openrouter.ai/docs/provider-routing) for more details. + + +## Fireworks + +```bash +# Set your API key using environment variables +export FIREWORKS_API_KEY= +aider --model fireworks_ai/accounts/fireworks/models/deepseek-chat + +# Or use the --api-key command line option +aider --model fireworks_ai/accounts/fireworks/models/deepseek-chat --api-key fireworks= + +# Or add it to .aider.conf.yml in your home directory or project root: +api-key: + - fireworks= +``` + +Create a `.aider.model.settings.yml` file in your home directory or git project root with settings like this: + +```yaml +- name: fireworks_ai/accounts/fireworks/models/deepseek-chat + edit_format: diff + weak_model_name: null + use_repo_map: true + send_undo_reply: false + lazy: false + reminder: sys + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + cache_control: false + caches_by_default: true + use_system_prompt: true + use_temperature: true + streaming: true +``` + + +## Hyperbolic + +You can use [Hyperbolic's API](https://hyperbolic.xyz) as an OpenAI-compatible provider: + +```bash +# Set your API key using environment variables +export OPENAI_API_BASE=https://api.hyperbolic.xyz/v1/ +export OPENAI_API_KEY= +aider --model openai/deepseek-ai/DeepSeek-V3 + +# Or use the --api-key command line option +aider --model openai/deepseek-ai/DeepSeek-V3 --api-key openai= + +# Or add it to .aider.conf.yml in your home directory or project root: +api-key: + - openai= +``` + +Create a `.aider.model.settings.yml` file in your home directory or git project root with settings like this: + +```yaml +- name: openai/deepseek-ai/DeepSeek-V3 + edit_format: diff + weak_model_name: null + use_repo_map: true + send_undo_reply: false + lazy: false + reminder: sys + examples_as_sys_msg: true + cache_control: false + caches_by_default: true + use_system_prompt: true + use_temperature: true + streaming: true + editor_model_name: null + editor_edit_format: null + extra_params: + max_tokens: 65536 +``` + +## Ollama + +You can run [DeepSeek V3 via Ollama](https://ollama.com/library/deepseek-v3). + +```bash +# Pull the model +ollama pull deepseek-v3 + +# Start your ollama server +ollama serve + +# In another terminal window... +export OLLAMA_API_BASE=http://127.0.0.1:11434 # Mac/Linux +setx OLLAMA_API_BASE http://127.0.0.1:11434 # Windows, restart shell after setx + +aider --model ollama/deepseek-v3 +``` + +It's important to provide model settings, especially the `num_ctx` parameter to +set the context window. +Ollama uses a 2k context window by default, which is very small for working with aider. +Larger context windows will allow you to work with larger amounts of code, +but will use memory and increase latency. + +Unlike most other LLM servers, Ollama does not throw an error if you submit a request that exceeds the context window. Instead, it just silently truncates the request by discarding the “oldest” messages in the chat to make it fit within the context window. + +So if your context window is too small, you won’t get an explicit error. The biggest symptom will be that aider says it can’t see (some of) the files you added to the chat. That’s because ollama is silently discarding them because they exceed the context window. + +Create a `.aider.model.settings.yml` file in your home directory or git project root with settings like this: + +```yaml +- name: ollama/deepseek-v3 + edit_format: diff + weak_model_name: null + use_repo_map: true + send_undo_reply: false + lazy: false + reminder: sys + examples_as_sys_msg: true + cache_control: false + caches_by_default: true + use_system_prompt: true + use_temperature: true + streaming: true + extra_params: + num_ctx: 8192 # How large a context window? +``` + +## Other providers + +You will need to properly configure aider to work with DeepSeek V3 when served +via other providers: + +- Determine the `--model` name to use. +- Provide your API key to aider. +- Add model settings to `.aider.model.settings.yml`. + + +Adapt the `.aider.model.settings.yml` shown above for Fireworks. You will need to change the `name` field to match you chosen provider's model naming scheme. + +See [Advanced model settings](https://aider.chat/docs/config/adv-model-settings.html#model-settings) for details about all aider model settings + +## Results + + + + + + + + + + + + + + {% assign edit_sorted = site.data.deepseek-down | sort: 'pass_rate_2' | reverse %} + {% for row in edit_sorted %} + + + + + + + + {% endfor %} + +
ModelPercent completed correctlyPercent using correct edit formatCommandEdit format
{{ row.model }}{{ row.pass_rate_2 }}%{{ row.percent_cases_well_formed }}%{{ row.command }}{{ row.edit_format }}
+ + + + + diff --git a/aider/website/assets/copypaste.jpg b/aider/website/assets/copypaste.jpg new file mode 100644 index 000000000..0350492cc Binary files /dev/null and b/aider/website/assets/copypaste.jpg differ diff --git a/aider/website/assets/copypaste.mp4 b/aider/website/assets/copypaste.mp4 new file mode 100644 index 000000000..6e8ef4e83 Binary files /dev/null and b/aider/website/assets/copypaste.mp4 differ diff --git a/aider/website/assets/o1-polyglot.jpg b/aider/website/assets/o1-polyglot.jpg new file mode 100644 index 000000000..8945eb1af Binary files /dev/null and b/aider/website/assets/o1-polyglot.jpg differ diff --git a/aider/website/assets/qwq.jpg b/aider/website/assets/qwq.jpg new file mode 100644 index 000000000..8b7a71fcb Binary files /dev/null and b/aider/website/assets/qwq.jpg differ diff --git a/aider/website/assets/r1-sonnet-sota.jpg b/aider/website/assets/r1-sonnet-sota.jpg new file mode 100644 index 000000000..aba06f40f Binary files /dev/null and b/aider/website/assets/r1-sonnet-sota.jpg differ diff --git a/aider/website/assets/sample-analytics.jsonl b/aider/website/assets/sample-analytics.jsonl index bf186ae2a..8c68aa9b3 100644 --- a/aider/website/assets/sample-analytics.jsonl +++ b/aider/website/assets/sample-analytics.jsonl @@ -1,1000 +1,1000 @@ -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732214094} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 7539, "completion_tokens": 548, "total_tokens": 8087, "cost": 0.030837000000000003, "total_cost": 0.360738, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732214492} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 8172, "completion_tokens": 261, "total_tokens": 8433, "cost": 0.028430999999999998, "total_cost": 0.389169, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732214517} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732215325} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732215360} -{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732215363} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 9243, "completion_tokens": 507, "total_tokens": 9750, "cost": 0.035334, "total_cost": 0.42450299999999996, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732215394} -{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732215967} -{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732215970} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 5749, "completion_tokens": 189, "total_tokens": 5938, "cost": 0.020082000000000003, "total_cost": 0.44458499999999995, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732216011} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 6064, "completion_tokens": 161, "total_tokens": 6225, "cost": 0.020607, "total_cost": 0.46519199999999994, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732216101} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732216226} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 4261, "completion_tokens": 246, "total_tokens": 4507, "cost": 0.016473, "total_cost": 0.48166499999999995, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732216234} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 6639, "completion_tokens": 133, "total_tokens": 6772, "cost": 0.021912, "total_cost": 0.5035769999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732216280} -{"event": "command_undo", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732216317} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732216365} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 4722, "completion_tokens": 251, "total_tokens": 4973, "cost": 0.017931, "total_cost": 0.521508, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732216372} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 6949, "completion_tokens": 154, "total_tokens": 7103, "cost": 0.023157, "total_cost": 0.544665, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732216426} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 6028, "completion_tokens": 169, "total_tokens": 6197, "cost": 0.020619, "total_cost": 0.5652839999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732216439} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732217127} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 43, "total_tokens": 2246, "cost": 0.00040427999999999997, "total_cost": 0.00040427999999999997, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732217130} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732217171} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 6292, "completion_tokens": 309, "total_tokens": 6601, "cost": 0.023511, "total_cost": 0.5887949999999998, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732218000} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732218131} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732218131} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732218564} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732218564} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732218567} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.0"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732218756} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.0"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732218757} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.0"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732218961} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.0"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732218961} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219071} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219072} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219199} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219199} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219202} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219204} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219211} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219229} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219229} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219239} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 6845, "completion_tokens": 0, "total_tokens": 6845, "cost": 0.020535, "total_cost": 0.020535, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219240} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219254} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 6863, "completion_tokens": 0, "total_tokens": 6863, "cost": 0.020589, "total_cost": 0.041124, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219254} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219256} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219262} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219263} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219264} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 6862, "completion_tokens": 389, "total_tokens": 7251, "cost": 0.026421, "total_cost": 0.026421, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219278} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219286} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 7372, "completion_tokens": 291, "total_tokens": 7663, "cost": 0.026481, "total_cost": 0.052902000000000005, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219295} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219308} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 7678, "completion_tokens": 202, "total_tokens": 7880, "cost": 0.026064, "total_cost": 0.07896600000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219316} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219331} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219348} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 6872, "completion_tokens": 235, "total_tokens": 7107, "cost": 0.024141, "total_cost": 0.103107, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219357} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219429} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219429} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219451} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 6973, "completion_tokens": 513, "total_tokens": 7486, "cost": 0.028614, "total_cost": 0.028614, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219466} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219524} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219525} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219538} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219556} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 6151, "completion_tokens": 251, "total_tokens": 6402, "cost": 0.022218, "total_cost": 0.022218, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219607} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219616} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219628} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 6671, "completion_tokens": 429, "total_tokens": 7100, "cost": 0.026448, "total_cost": 0.048666, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219640} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732219765} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.0"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732220004} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.0"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732220004} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732220215} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732220215} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732220642} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732220642} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732221139} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732221215} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732221215} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732221304} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.63.3.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732221304} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.0"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732221402} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.0"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732221403} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732222469} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732222470} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732222562} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732222562} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.1"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732222680} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.1"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732222681} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732224618} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732224622} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732225984} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732225984} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226083} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226083} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226295} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 3577, "completion_tokens": 1518, "total_tokens": 5095, "cost": 0.033501, "total_cost": 0.033501, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226325} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 7097, "completion_tokens": 3651, "total_tokens": 10748, "cost": 0.076056, "total_cost": 0.109557, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226417} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226450} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226494} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226498} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226501} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226513} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 4603, "completion_tokens": 309, "total_tokens": 4912, "cost": 0.018444000000000002, "total_cost": 0.128001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226545} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226579} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226590} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 22736, "completion_tokens": 346, "total_tokens": 23082, "cost": 0.073398, "total_cost": 0.201399, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732226599} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732227043} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732227043} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732227522} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732227522} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732227527} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 4582, "completion_tokens": 118, "total_tokens": 4700, "cost": 0.015516, "total_cost": 0.015516, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732227542} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732227629} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732227629} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732231730} -{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732231732} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732231749} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732231957} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 63, "completion_tokens": 30, "total_tokens": 93, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732231970} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732236291} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732236292} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 4594, "completion_tokens": 173, "total_tokens": 4767, "cost": 0.016377000000000003, "total_cost": 0.016377000000000003, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732236306} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732236484} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242463} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242464} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242471} -{"event": "command_chat-mode", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242472} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 6967, "completion_tokens": 252, "total_tokens": 7219, "cost": 0.024680999999999998, "total_cost": 0.024680999999999998, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242510} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 7264, "completion_tokens": 391, "total_tokens": 7655, "cost": 0.027657, "total_cost": 0.052337999999999996, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242684} -{"event": "command_code", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242700} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 9810, "completion_tokens": 633, "total_tokens": 10443, "cost": 0.038925, "total_cost": 0.091263, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242715} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242751} -{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "gpt-4o-mini", "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242751} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 8528, "completion_tokens": 208, "total_tokens": 8736, "cost": 0.028704, "total_cost": 0.11996699999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242781} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242784} -{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "gpt-4o-mini", "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242784} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242806} -{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "gpt-4o-mini", "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242806} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242809} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242830} -{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "gpt-4o-mini", "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242830} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242833} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242840} -{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o-mini", "edit_format": "ask", "prompt_tokens": 68, "completion_tokens": 8, "total_tokens": 76, "cost": 1.4999999999999999e-05, "total_cost": 1.4999999999999999e-05, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242841} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242844} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242859} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242934} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732242934} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732243037} -{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "gpt-4o-mini", "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732243038} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732243040} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732243053} -{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "gpt-4o-mini", "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732243054} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732243054} -{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o-mini", "edit_format": "whole", "prompt_tokens": 682, "completion_tokens": 39, "total_tokens": 721, "cost": 0.0001257, "total_cost": 0.0001257, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732243061} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732243062} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732243067} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732283822} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732283823} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732287087} -{"event": "model warning", "properties": {"main_model": "openai/REDACTED", "weak_model": "openai/REDACTED", "editor_model": "openai/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732287089} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732287094} -{"event": "message_send", "properties": {"main_model": "openai/REDACTED", "weak_model": "openai/REDACTED", "editor_model": "openai/REDACTED", "edit_format": "diff", "prompt_tokens": 4704, "completion_tokens": 0, "total_tokens": 4704, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732287100} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732287115} -{"event": "message_send", "properties": {"main_model": "openai/REDACTED", "weak_model": "openai/REDACTED", "editor_model": "openai/REDACTED", "edit_format": "diff", "prompt_tokens": 3136, "completion_tokens": 0, "total_tokens": 3136, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732287120} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732288494} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732288494} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732288498} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732288506} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 6251, "completion_tokens": 320, "total_tokens": 6571, "cost": 0.023552999999999998, "total_cost": 0.023552999999999998, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732288559} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732288568} -{"event": "command_undo", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732288579} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732288583} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 7008, "completion_tokens": 244, "total_tokens": 7252, "cost": 0.024684, "total_cost": 0.048237, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732288598} -{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732288619} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732288622} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732288623} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 6851, "completion_tokens": 762, "total_tokens": 7613, "cost": 0.031983000000000004, "total_cost": 0.08022000000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732288641} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 8559, "completion_tokens": 527, "total_tokens": 9086, "cost": 0.033582, "total_cost": 0.11380200000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732289146} -{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732290032} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732290034} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 5682, "completion_tokens": 125, "total_tokens": 5807, "cost": 0.018921000000000004, "total_cost": 0.132723, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732290044} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732298794} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732298794} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732298844} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 1470, "completion_tokens": 267, "total_tokens": 1737, "cost": 0.008414999999999999, "total_cost": 0.008414999999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732298851} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 3814, "completion_tokens": 120, "total_tokens": 3934, "cost": 0.013242, "total_cost": 0.021657, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732298865} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301216} -{"event": "model warning", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301218} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 47, "total_tokens": 2250, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301225} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301235} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 47, "total_tokens": 2250, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301240} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301245} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 47, "total_tokens": 2250, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301250} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301280} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 0, "total_tokens": 2203, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301284} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301304} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 47, "total_tokens": 2250, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301309} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301462} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 0, "total_tokens": 2203, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301493} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301495} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 0, "total_tokens": 2203, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301505} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301509} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 0, "total_tokens": 2203, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301523} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301525} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 0, "total_tokens": 2203, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301535} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301537} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 38, "total_tokens": 2241, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301562} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301567} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 129, "total_tokens": 2332, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301589} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301669} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 60, "total_tokens": 2263, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301674} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301684} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 38, "total_tokens": 2241, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732301700} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732302442} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 38, "total_tokens": 2241, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732302454} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732302458} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 102, "total_tokens": 2305, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732302514} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732314005} -{"event": "model warning", "properties": {"main_model": "xai/REDACTED", "weak_model": "xai/REDACTED", "editor_model": "xai/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732314007} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732314019} -{"event": "model warning", "properties": {"main_model": "xai/grok-beta", "weak_model": "xai/grok-beta", "editor_model": "xai/grok-beta", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732314021} -{"event": "cli session", "properties": {"main_model": "xai/grok-beta", "weak_model": "xai/grok-beta", "editor_model": "xai/grok-beta", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732314024} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732314048} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732393998} -{"event": "model warning", "properties": {"main_model": "lm_studio/REDACTED", "weak_model": "lm_studio/REDACTED", "editor_model": "lm_studio/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394000} -{"event": "cli session", "properties": {"main_model": "lm_studio/REDACTED", "weak_model": "lm_studio/REDACTED", "editor_model": "lm_studio/REDACTED", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394003} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394005} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394043} -{"event": "cli session", "properties": {"main_model": "lm_studio/REDACTED", "weak_model": "lm_studio/REDACTED", "editor_model": "lm_studio/REDACTED", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394046} -{"event": "message_send", "properties": {"main_model": "lm_studio/REDACTED", "weak_model": "lm_studio/REDACTED", "editor_model": "lm_studio/REDACTED", "edit_format": "whole", "prompt_tokens": 406, "completion_tokens": 0, "total_tokens": 406, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394050} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394434} -{"event": "model warning", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394436} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394443} -{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394445} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394476} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394491} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394522} -{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394524} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 67, "completion_tokens": 24, "total_tokens": 91, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394530} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394534} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 165, "completion_tokens": 17, "total_tokens": 182, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394536} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394581} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394587} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394591} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394596} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394598} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 1856, "completion_tokens": 5, "total_tokens": 1861, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394602} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394605} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394612} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 3584, "completion_tokens": 21, "total_tokens": 3605, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394618} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394625} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 1856, "completion_tokens": 5, "total_tokens": 1861, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394628} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394635} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 2240, "completion_tokens": 21, "total_tokens": 2261, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394639} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394641} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394671} -{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394673} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394682} -{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394684} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394708} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394710} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394710} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394720} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394722} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394722} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 2240, "completion_tokens": 0, "total_tokens": 2240, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394732} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394739} -{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394741} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394742} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 2240, "completion_tokens": 0, "total_tokens": 2240, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394771} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 2257, "completion_tokens": 5, "total_tokens": 2262, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394782} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394796} -{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394798} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394799} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 4544, "completion_tokens": 33, "total_tokens": 4577, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394806} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394810} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394812} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 3968, "completion_tokens": 5, "total_tokens": 3973, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394817} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394833} -{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394835} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394837} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 3968, "completion_tokens": 5, "total_tokens": 3973, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394851} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394853} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394858} -{"event": "command_run", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394862} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394865} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394871} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 8000, "completion_tokens": 5, "total_tokens": 8005, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394878} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394885} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394887} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 8576, "completion_tokens": 33, "total_tokens": 8609, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394897} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732394899} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395028} -{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395030} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395030} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395037} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395046} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395052} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395060} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395068} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395075} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395086} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395089} -{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395091} -{"event": "command_tokens", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395093} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 64640, "completion_tokens": 5, "total_tokens": 64645, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395332} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395345} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395418} -{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395420} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395422} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732395439} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732396231} -{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732396233} -{"event": "message_send", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "ask", "prompt_tokens": 64636, "completion_tokens": 0, "total_tokens": 64636, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732396236} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732399992} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732399993} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732399995} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732399997} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732399997} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732400000} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 6446, "completion_tokens": 211, "total_tokens": 6657, "cost": 0.022503000000000002, "total_cost": 0.022503000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732400049} -{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732400102} -{"event": "command_lint", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732400103} -{"event": "command_commit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732400107} -{"event": "command_undo", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732400117} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732400477} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732400478} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732400552} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 2110, "completion_tokens": 276, "total_tokens": 2386, "cost": 0.01047, "total_cost": 0.01047, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732400560} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 3125, "completion_tokens": 371, "total_tokens": 3496, "cost": 0.01494, "total_cost": 0.025410000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732400580} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 5721, "completion_tokens": 520, "total_tokens": 6241, "cost": 0.024963000000000003, "total_cost": 0.050373, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732400603} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732400613} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732404392} -{"event": "cli session", "properties": {"main_model": "ollama_chat/REDACTED", "weak_model": "ollama_chat/REDACTED", "editor_model": "ollama_chat/REDACTED", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732404394} -{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732404395} -{"event": "message_send", "properties": {"main_model": "ollama_chat/REDACTED", "weak_model": "ollama_chat/REDACTED", "editor_model": "ollama_chat/REDACTED", "edit_format": "ask", "prompt_tokens": 63, "completion_tokens": 37, "total_tokens": 100, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732404400} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732404401} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732412885} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732412886} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732412890} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732412894} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732412898} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 7040, "completion_tokens": 170, "total_tokens": 7210, "cost": 0.02367, "total_cost": 0.02367, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732412913} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732413619} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732413620} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732413628} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 2322, "completion_tokens": 399, "total_tokens": 2721, "cost": 0.012951, "total_cost": 0.012951, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732413736} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732414921} -{"event": "model warning", "properties": {"main_model": "deepinfra/REDACTED", "weak_model": "deepinfra/REDACTED", "editor_model": "deepinfra/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732414923} -{"event": "cli session", "properties": {"main_model": "deepinfra/REDACTED", "weak_model": "deepinfra/REDACTED", "editor_model": "deepinfra/REDACTED", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732414926} -{"event": "message_send", "properties": {"main_model": "deepinfra/REDACTED", "weak_model": "deepinfra/REDACTED", "editor_model": "deepinfra/REDACTED", "edit_format": "diff", "prompt_tokens": 2870, "completion_tokens": 31, "total_tokens": 2901, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732414929} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732414930} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732415453} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 2175, "completion_tokens": 86, "total_tokens": 2261, "cost": 0.007815, "total_cost": 0.007815, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732415459} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732415495} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732415544} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732415556} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732415739} -{"event": "message_send", "properties": {"main_model": "openai/REDACTED", "weak_model": "openai/REDACTED", "editor_model": "openai/REDACTED", "edit_format": "diff", "prompt_tokens": 1568, "completion_tokens": 34, "total_tokens": 1602, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732415744} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732421525} -{"event": "model warning", "properties": {"main_model": "fireworks/REDACTED", "weak_model": "fireworks/REDACTED", "editor_model": "fireworks/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732421527} -{"event": "cli session", "properties": {"main_model": "fireworks/REDACTED", "weak_model": "fireworks/REDACTED", "editor_model": "fireworks/REDACTED", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732421528} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732421552} -{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/qwen2p5-coder-32b-instruct", "weak_model": "fireworks_ai/accounts/fireworks/models/qwen2p5-coder-32b-instruct", "editor_model": "fireworks_ai/accounts/fireworks/models/qwen2p5-coder-32b-instruct", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732421554} -{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/qwen2p5-coder-32b-instruct", "weak_model": "fireworks_ai/accounts/fireworks/models/qwen2p5-coder-32b-instruct", "editor_model": "fireworks_ai/accounts/fireworks/models/qwen2p5-coder-32b-instruct", "edit_format": "whole", "prompt_tokens": 593, "completion_tokens": 24, "total_tokens": 617, "cost": 0.0005553, "total_cost": 0.0005553, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732421557} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732460750} -{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732460751} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732460754} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732460768} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 4075, "completion_tokens": 254, "total_tokens": 4329, "cost": 0.016035, "total_cost": 0.016035, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732460779} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 6460, "completion_tokens": 556, "total_tokens": 7016, "cost": 0.02772, "total_cost": 0.043755, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732460798} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732461088} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732461091} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732461104} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 7239, "completion_tokens": 634, "total_tokens": 7873, "cost": 0.031227, "total_cost": 0.07498200000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732461120} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 9919, "completion_tokens": 956, "total_tokens": 10875, "cost": 0.044097000000000004, "total_cost": 0.11907900000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732461157} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 8685, "completion_tokens": 151, "total_tokens": 8836, "cost": 0.02832, "total_cost": 0.14739900000000003, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732461193} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732481168} -{"event": "model warning", "properties": {"main_model": "openai/REDACTED", "weak_model": "openai/REDACTED", "editor_model": "openai/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732481170} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732481179} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732481199} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483337} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483388} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 350, "completion_tokens": 392, "total_tokens": 742, "cost": 0.00013356000000000002, "total_cost": 0.00013356000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483400} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483488} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 350, "completion_tokens": 392, "total_tokens": 742, "cost": 0.00013356000000000002, "total_cost": 0.00013356000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483509} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 2752, "completion_tokens": 0, "total_tokens": 2752, "cost": 0.00049536, "total_cost": 0.00062892, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483519} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483529} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 350, "completion_tokens": 392, "total_tokens": 742, "cost": 0.00013356000000000002, "total_cost": 0.00013356000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483542} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483546} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 350, "completion_tokens": 392, "total_tokens": 742, "cost": 0.00013356000000000002, "total_cost": 0.00013356000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483559} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483578} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 350, "completion_tokens": 392, "total_tokens": 742, "cost": 0.00013356000000000002, "total_cost": 0.00013356000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483601} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483633} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483677} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 350, "completion_tokens": 392, "total_tokens": 742, "cost": 0.00013356000000000002, "total_cost": 0.00013356000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483691} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 752, "completion_tokens": 125, "total_tokens": 877, "cost": 0.00015786, "total_cost": 0.00029142, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483695} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483723} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 2203, "completion_tokens": 0, "total_tokens": 2203, "cost": 0.00039653999999999997, "total_cost": 0.00039653999999999997, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483735} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483751} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 350, "completion_tokens": 392, "total_tokens": 742, "cost": 0.00013356000000000002, "total_cost": 0.00013356000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483764} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 2629, "completion_tokens": 0, "total_tokens": 2629, "cost": 0.00047322, "total_cost": 0.00060678, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483766} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483797} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483833} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 350, "completion_tokens": 392, "total_tokens": 742, "cost": 0.00013356000000000002, "total_cost": 0.00013356000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483846} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483865} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 350, "completion_tokens": 392, "total_tokens": 742, "cost": 0.00013356000000000002, "total_cost": 0.00013356000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483878} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483948} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483969} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 350, "completion_tokens": 392, "total_tokens": 742, "cost": 0.00013356000000000002, "total_cost": 0.00013356000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732483985} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732484014} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 350, "completion_tokens": 392, "total_tokens": 742, "cost": 0.00013356000000000002, "total_cost": 0.00013356000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732484029} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732484034} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732484052} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732484089} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732484143} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732484158} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732484246} -{"event": "message_send", "properties": {"main_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "weak_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "editor_model": "openrouter/qwen/qwen-2.5-coder-32b-instruct", "edit_format": "diff", "prompt_tokens": 350, "completion_tokens": 392, "total_tokens": 742, "cost": 0.00013356000000000002, "total_cost": 0.00013356000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732484259} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732490410} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732490416} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 10329, "completion_tokens": 242, "total_tokens": 10571, "cost": 0.034617, "total_cost": 0.034617, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732490434} -{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 10735, "completion_tokens": 91, "total_tokens": 10826, "cost": 0.033569999999999996, "total_cost": 0.068187, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732490442} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732490681} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732490682} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732493670} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732493734} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732493735} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732496707} -{"event": "cli session", "properties": {"main_model": "ollama_chat/REDACTED", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "ollama_chat/REDACTED", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732496710} -{"event": "message_send", "properties": {"main_model": "ollama_chat/REDACTED", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "ollama_chat/REDACTED", "edit_format": "whole", "prompt_tokens": 593, "completion_tokens": 26, "total_tokens": 619, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732496715} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732496719} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732503219} -{"event": "message_send", "properties": {"main_model": "openrouter/deepseek/deepseek-coder", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "openrouter/deepseek/deepseek-coder", "edit_format": "diff", "prompt_tokens": 4519, "completion_tokens": 0, "total_tokens": 4519, "cost": 0.0006326600000000001, "total_cost": 0.0006326600000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732503223} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732503230} -{"event": "message_send", "properties": {"main_model": "openrouter/REDACTED", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "openrouter/REDACTED", "edit_format": "whole", "prompt_tokens": 593, "completion_tokens": 13, "total_tokens": 606, "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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732503234} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732504520} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732552179} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732552180} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732554412} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732554412} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732556336} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732556337} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732556340} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732556343} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588055} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588056} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588086} -{"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": 29685, "completion_tokens": 906, "total_tokens": 30591, "cost": 0.10264500000000001, "total_cost": 0.10264500000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588184} -{"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": 31058, "completion_tokens": 102, "total_tokens": 31160, "cost": 0.09470400000000001, "total_cost": 0.19734900000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588194} -{"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": 31234, "completion_tokens": 223, "total_tokens": 31457, "cost": 0.09704700000000001, "total_cost": 0.29439600000000005, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588245} -{"event": "command_undo", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588278} -{"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": 29910, "completion_tokens": 357, "total_tokens": 30267, "cost": 0.095085, "total_cost": 0.3894810000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588304} -{"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": 30906, "completion_tokens": 221, "total_tokens": 31127, "cost": 0.09603300000000001, "total_cost": 0.4855140000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588338} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588372} -{"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": 29683, "completion_tokens": 923, "total_tokens": 30606, "cost": 0.102894, "total_cost": 0.5884080000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588443} -{"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": 31065, "completion_tokens": 96, "total_tokens": 31161, "cost": 0.094635, "total_cost": 0.6830430000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588455} -{"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": 31303, "completion_tokens": 90, "total_tokens": 31393, "cost": 0.09525900000000001, "total_cost": 0.7783020000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588469} -{"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": 31551, "completion_tokens": 98, "total_tokens": 31649, "cost": 0.096123, "total_cost": 0.8744250000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588479} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588511} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588511} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588521} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588521} -{"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": 678, "completion_tokens": 0, "total_tokens": 678, "cost": 0.00010169999999999999, "total_cost": 0.00010169999999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588525} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588566} -{"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": 29783, "completion_tokens": 195, "total_tokens": 29978, "cost": 0.092274, "total_cost": 0.9666990000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588582} -{"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": 30164, "completion_tokens": 77, "total_tokens": 30241, "cost": 0.091647, "total_cost": 1.058346, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588593} -{"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": 30380, "completion_tokens": 75, "total_tokens": 30455, "cost": 0.092265, "total_cost": 1.150611, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588601} -{"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": 30594, "completion_tokens": 0, "total_tokens": 30594, "cost": 0.091782, "total_cost": 1.242393, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588606} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588636} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588647} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588647} -{"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": 678, "completion_tokens": 38, "total_tokens": 716, "cost": 0.0001245, "total_cost": 0.0001245, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588652} -{"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": 729, "completion_tokens": 36, "total_tokens": 765, "cost": 0.00013095, "total_cost": 0.00025545, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588659} -{"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": 776, "completion_tokens": 36, "total_tokens": 812, "cost": 0.000138, "total_cost": 0.00039345, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588669} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588678} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588679} -{"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": 2180, "completion_tokens": 165, "total_tokens": 2345, "cost": 0.009015, "total_cost": 0.009015, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588686} -{"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": 2357, "completion_tokens": 189, "total_tokens": 2546, "cost": 0.009906, "total_cost": 0.018921, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588695} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588696} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588708} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588718} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588718} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588724} -{"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": 15851, "completion_tokens": 465, "total_tokens": 16316, "cost": 0.054528, "total_cost": 0.054528, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588748} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588763} -{"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": 23325, "completion_tokens": 406, "total_tokens": 23731, "cost": 0.076065, "total_cost": 0.130593, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588786} -{"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": 24699, "completion_tokens": 185, "total_tokens": 24884, "cost": 0.076872, "total_cost": 0.20746499999999998, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588879} -{"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": 26276, "completion_tokens": 379, "total_tokens": 26655, "cost": 0.08451299999999999, "total_cost": 0.29197799999999996, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732588920} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732589001} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732589002} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732590455} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591034} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591034} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591041} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591045} -{"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": 18103, "completion_tokens": 323, "total_tokens": 18426, "cost": 0.059154000000000005, "total_cost": 0.059154000000000005, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591103} -{"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": 19254, "completion_tokens": 360, "total_tokens": 19614, "cost": 0.063162, "total_cost": 0.12231600000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591154} -{"event": "command_undo", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591167} -{"event": "command_undo", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591171} -{"event": "command_undo", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591176} -{"event": "command_undo", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591179} -{"event": "command_undo", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591186} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591219} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591219} -{"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": 18023, "completion_tokens": 377, "total_tokens": 18400, "cost": 0.059724, "total_cost": 0.059724, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591241} -{"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": 19227, "completion_tokens": 244, "total_tokens": 19471, "cost": 0.06134100000000001, "total_cost": 0.121065, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732591266} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732596150} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732596179} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732596380} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732596572} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732596572} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732596575} -{"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": 12696, "completion_tokens": 448, "total_tokens": 13144, "cost": 0.044808, "total_cost": 0.044808, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732596696} -{"event": "command_read-only", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732596803} -{"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": 18846, "completion_tokens": 1355, "total_tokens": 20201, "cost": 0.076863, "total_cost": 0.121671, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732596855} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732596895} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732596903} -{"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": 25551, "completion_tokens": 495, "total_tokens": 26046, "cost": 0.084078, "total_cost": 0.20574900000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732596962} -{"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": 26261, "completion_tokens": 286, "total_tokens": 26547, "cost": 0.08307300000000001, "total_cost": 0.288822, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597015} -{"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": 26903, "completion_tokens": 289, "total_tokens": 27192, "cost": 0.08504400000000001, "total_cost": 0.37386600000000003, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597025} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597042} -{"event": "model warning", "properties": {"main_model": "ollama/REDACTED", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "ollama/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597044} -{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "ollama/REDACTED", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597051} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597127} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597142} -{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597160} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597171} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597213} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597219} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597219} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597234} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597253} -{"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": 19776, "completion_tokens": 536, "total_tokens": 20312, "cost": 0.067368, "total_cost": 0.067368, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597269} -{"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": 20874, "completion_tokens": 396, "total_tokens": 21270, "cost": 0.068562, "total_cost": 0.13593, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597383} -{"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": 21299, "completion_tokens": 352, "total_tokens": 21651, "cost": 0.06917699999999999, "total_cost": 0.20510699999999998, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597412} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597565} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597565} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597569} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597572} -{"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": 14000, "completion_tokens": 403, "total_tokens": 14403, "cost": 0.048045000000000004, "total_cost": 0.048045000000000004, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597588} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597657} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732597657} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629182} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629183} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629208} -{"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": 1957, "completion_tokens": 190, "total_tokens": 2147, "cost": 0.008721, "total_cost": 0.008721, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629213} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629226} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629229} -{"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": 1856, "completion_tokens": 201, "total_tokens": 2057, "cost": 0.008583, "total_cost": 0.017304, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629234} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629247} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629498} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629498} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629506} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629522} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629528} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629534} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629534} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629536} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629537} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629566} -{"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": 1520, "completion_tokens": 257, "total_tokens": 1777, "cost": 0.008414999999999999, "total_cost": 0.008414999999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629572} -{"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": 3908, "completion_tokens": 178, "total_tokens": 4086, "cost": 0.014394, "total_cost": 0.022809, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629590} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629810} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629810} -{"event": "command_run", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629845} -{"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": 13799, "completion_tokens": 212, "total_tokens": 14011, "cost": 0.044577000000000006, "total_cost": 0.044577000000000006, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629908} -{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629926} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629930} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629933} -{"event": "command_run", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732629936} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630010} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630010} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630022} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630041} -{"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": 3438, "completion_tokens": 358, "total_tokens": 3796, "cost": 0.015684, "total_cost": 0.015684, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630177} -{"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": 4101, "completion_tokens": 307, "total_tokens": 4408, "cost": 0.016908, "total_cost": 0.032591999999999996, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630202} -{"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": 4604, "completion_tokens": 46, "total_tokens": 4650, "cost": 0.014502, "total_cost": 0.047094, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630254} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630259} -{"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": 23076, "completion_tokens": 198, "total_tokens": 23274, "cost": 0.072198, "total_cost": 0.072198, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630273} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630389} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630390} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630394} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630539} -{"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": 23226, "completion_tokens": 319, "total_tokens": 23545, "cost": 0.074463, "total_cost": 0.074463, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630567} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630788} -{"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": 23205, "completion_tokens": 183, "total_tokens": 23388, "cost": 0.07236, "total_cost": 0.07236, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630799} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630865} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630865} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630868} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630869} -{"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": 17486, "completion_tokens": 436, "total_tokens": 17922, "cost": 0.058998, "total_cost": 0.058998, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630974} -{"event": "command_diff", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732630980} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631019} -{"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": 24958, "completion_tokens": 1033, "total_tokens": 25991, "cost": 0.09036899999999999, "total_cost": 0.149367, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631050} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631055} -{"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": 23518, "completion_tokens": 1, "total_tokens": 23519, "cost": 0.070569, "total_cost": 0.070569, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631062} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631071} -{"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": 23501, "completion_tokens": 197, "total_tokens": 23698, "cost": 0.073458, "total_cost": 0.073458, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631086} -{"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": 30391, "completion_tokens": 502, "total_tokens": 30893, "cost": 0.098703, "total_cost": 0.24807, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631113} -{"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": 30342, "completion_tokens": 308, "total_tokens": 30650, "cost": 0.095646, "total_cost": 0.343716, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631184} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631548} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631548} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631572} -{"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": 22536, "completion_tokens": 496, "total_tokens": 23032, "cost": 0.075048, "total_cost": 0.075048, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631587} -{"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": 25163, "completion_tokens": 410, "total_tokens": 25573, "cost": 0.081639, "total_cost": 0.15668700000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631606} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631685} -{"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": 24886, "completion_tokens": 285, "total_tokens": 25171, "cost": 0.078933, "total_cost": 0.078933, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732631699} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732632227} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732632228} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732632258} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732632258} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732632261} -{"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": 17477, "completion_tokens": 820, "total_tokens": 18297, "cost": 0.064731, "total_cost": 0.064731, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732632359} -{"event": "command_diff", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732632370} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732632387} -{"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": 25098, "completion_tokens": 717, "total_tokens": 25815, "cost": 0.086049, "total_cost": 0.15078, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732632410} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732632516} -{"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": 25909, "completion_tokens": 431, "total_tokens": 26340, "cost": 0.084192, "total_cost": 0.084192, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732632538} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732632673} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732632674} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633005} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633005} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633011} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633022} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633153} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633153} -{"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": 2183, "completion_tokens": 93, "total_tokens": 2276, "cost": 0.007944, "total_cost": 0.007944, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633162} -{"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": 24729, "completion_tokens": 590, "total_tokens": 25319, "cost": 0.083037, "total_cost": 0.083037, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633163} -{"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": 25460, "completion_tokens": 309, "total_tokens": 25769, "cost": 0.081015, "total_cost": 0.164052, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633266} -{"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": 26399, "completion_tokens": 122, "total_tokens": 26521, "cost": 0.081027, "total_cost": 0.245079, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633314} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633320} -{"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": 26783, "completion_tokens": 246, "total_tokens": 27029, "cost": 0.084039, "total_cost": 0.329118, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633352} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633364} -{"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": 25924, "completion_tokens": 119, "total_tokens": 26043, "cost": 0.079557, "total_cost": 0.408675, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633386} -{"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": 26352, "completion_tokens": 0, "total_tokens": 26352, "cost": 0.079056, "total_cost": 0.487731, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633391} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633393} -{"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": 24862, "completion_tokens": 111, "total_tokens": 24973, "cost": 0.076251, "total_cost": 0.563982, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633405} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633407} -{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633424} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633428} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633452} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633453} -{"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": 31923, "completion_tokens": 575, "total_tokens": 32498, "cost": 0.10439400000000001, "total_cost": 0.668376, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633454} -{"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": 33758, "completion_tokens": 163, "total_tokens": 33921, "cost": 0.103719, "total_cost": 0.772095, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633482} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633494} -{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633497} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633500} -{"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": 31257, "completion_tokens": 559, "total_tokens": 31816, "cost": 0.10215600000000001, "total_cost": 0.874251, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633522} -{"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": 32320, "completion_tokens": 0, "total_tokens": 32320, "cost": 0.09696, "total_cost": 0.971211, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633540} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633541} -{"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": 30462, "completion_tokens": 356, "total_tokens": 30818, "cost": 0.096726, "total_cost": 1.0679370000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633586} -{"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": 31643, "completion_tokens": 391, "total_tokens": 32034, "cost": 0.100794, "total_cost": 1.1687310000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633629} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633738} -{"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": 27856, "completion_tokens": 483, "total_tokens": 28339, "cost": 0.090813, "total_cost": 0.090813, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633756} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633811} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633811} -{"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": 3756, "completion_tokens": 100, "total_tokens": 3856, "cost": 0.012768, "total_cost": 0.012768, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633831} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633840} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633916} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732633916} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732634837} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732634838} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732634847} -{"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": 7738, "completion_tokens": 178, "total_tokens": 7916, "cost": 0.025884, "total_cost": 0.025884, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732634876} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732634953} -{"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.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732634953} -{"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": 5392, "completion_tokens": 230, "total_tokens": 5622, "cost": 0.019625999999999998, "total_cost": 0.019625999999999998, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732635052} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732635055} -{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732635057} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732635062} -{"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": 5582, "completion_tokens": 540, "total_tokens": 6122, "cost": 0.024846, "total_cost": 0.044472, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732635080} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732635109} -{"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": 28745, "completion_tokens": 472, "total_tokens": 29217, "cost": 0.09331500000000001, "total_cost": 0.09331500000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732635133} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732635793} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732635794} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732639853} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.64.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732639854} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.0"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732640233} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.0"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732640233} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732640396} -{"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.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732640405} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732640491} -{"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": 3088, "completion_tokens": 139, "total_tokens": 3227, "cost": 0.011349, "total_cost": 0.011349, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732640496} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732640509} -{"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": 3178, "completion_tokens": 768, "total_tokens": 3946, "cost": 0.021054000000000003, "total_cost": 0.032403, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732640525} -{"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": 5955, "completion_tokens": 0, "total_tokens": 5955, "cost": 0.017865, "total_cost": 0.050268, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732640621} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732646529} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732646548} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732646648} -{"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": 3003, "completion_tokens": 851, "total_tokens": 3854, "cost": 0.021774, "total_cost": 0.072042, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732646668} -{"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": 6090, "completion_tokens": 425, "total_tokens": 6515, "cost": 0.024645, "total_cost": 0.096687, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732646705} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732647498} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652841} -{"event": "model warning", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_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.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652843} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652859} -{"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.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652859} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652878} -{"event": "cli session", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652879} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652897} -{"event": "model warning", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_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.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652898} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652933} -{"event": "model warning", "properties": {"main_model": "None", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "None", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652934} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652948} -{"event": "model warning", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_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.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652950} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652962} -{"event": "model warning", "properties": {"main_model": "gpt-4-0613", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4-0613", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652964} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652985} -{"event": "message_send", "properties": {"main_model": "gpt-4-0613", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4-0613", "edit_format": "diff", "prompt_tokens": 2206, "completion_tokens": 9, "total_tokens": 2215, "cost": 0.06672, "total_cost": 0.06672, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732652988} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732653075} -{"event": "message_send", "properties": {"main_model": "gpt-4-0613", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4-0613", "edit_format": "diff", "prompt_tokens": 2206, "completion_tokens": 9, "total_tokens": 2215, "cost": 0.06672, "total_cost": 0.06672, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732653077} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732653082} -{"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": 2175, "completion_tokens": 113, "total_tokens": 2288, "cost": 0.00822, "total_cost": 0.00822, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732653087} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732653095} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2175, "completion_tokens": 83, "total_tokens": 2258, "cost": 0.00259, "total_cost": 0.00259, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732653101} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732653110} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732653234} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732653313} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732653314} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732653421} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.1"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732653422} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661402} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661408} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661422} -{"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": 2034, "completion_tokens": 119, "total_tokens": 2153, "cost": 0.007887, "total_cost": 0.007887, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661433} -{"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": 9224, "completion_tokens": 385, "total_tokens": 9609, "cost": 0.033447000000000005, "total_cost": 0.041334, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661461} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661501} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661501} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661506} -{"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": 2027, "completion_tokens": 206, "total_tokens": 2233, "cost": 0.009171, "total_cost": 0.009171, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661526} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661575} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661576} -{"event": "command_web", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661577} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661586} -{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "ask", "prompt_tokens": 2506, "completion_tokens": 179, "total_tokens": 2685, "cost": 0.0004833, "total_cost": 0.0004833, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661589} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661770} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661771} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661773} -{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "ask", "prompt_tokens": 82, "completion_tokens": 310, "total_tokens": 392, "cost": 0.0001983, "total_cost": 0.0001983, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661786} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661850} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661851} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661851} -{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "ask", "prompt_tokens": 2512, "completion_tokens": 139, "total_tokens": 2651, "cost": 0.0004602, "total_cost": 0.0004602, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661863} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661866} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661867} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661870} -{"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": 4484, "completion_tokens": 221, "total_tokens": 4705, "cost": 0.016767, "total_cost": 0.016767, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661881} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661935} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661938} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661939} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661959} -{"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": 4500, "completion_tokens": 162, "total_tokens": 4662, "cost": 0.01593, "total_cost": 0.01593, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732661982} -{"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": 6899, "completion_tokens": 130, "total_tokens": 7029, "cost": 0.022647, "total_cost": 0.038577, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732662010} -{"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": 12865, "completion_tokens": 720, "total_tokens": 13585, "cost": 0.04939500000000001, "total_cost": 0.08797200000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732662031} -{"event": "command_diff", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732662040} -{"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": 10375, "completion_tokens": 480, "total_tokens": 10855, "cost": 0.038325, "total_cost": 0.126297, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732662108} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732662123} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732662254} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732662330} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732662330} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668587} -{"event": "cli session", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668587} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2177, "completion_tokens": 0, "total_tokens": 2177, "cost": 0.002177, "total_cost": 0.002177, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668590} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668617} -{"event": "cli session", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668617} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668627} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2225, "completion_tokens": 53, "total_tokens": 2278, "cost": 0.00249, "total_cost": 0.00249, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668632} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668784} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2225, "completion_tokens": 53, "total_tokens": 2278, "cost": 0.00249, "total_cost": 0.00249, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668789} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668799} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2225, "completion_tokens": 53, "total_tokens": 2278, "cost": 0.00249, "total_cost": 0.00249, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668804} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668829} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2225, "completion_tokens": 53, "total_tokens": 2278, "cost": 0.00249, "total_cost": 0.00249, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668834} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668859} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0, "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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668861} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668930} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2325, "completion_tokens": 0, "total_tokens": 2325, "cost": 0.002325, "total_cost": 0.002325, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732668933} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669007} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2325, "completion_tokens": 0, "total_tokens": 2325, "cost": 0.002325, "total_cost": 0.002325, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669009} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669063} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2325, "completion_tokens": 0, "total_tokens": 2325, "cost": 0.002325, "total_cost": 0.002325, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669065} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669111} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669122} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2235, "completion_tokens": 72, "total_tokens": 2307, "cost": 0.002595, "total_cost": 0.002595, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669127} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669143} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2241, "completion_tokens": 54, "total_tokens": 2295, "cost": 0.0025109999999999998, "total_cost": 0.0025109999999999998, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669147} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669153} -{"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": 2241, "completion_tokens": 47, "total_tokens": 2288, "cost": 0.007428, "total_cost": 0.007428, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669157} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669184} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2241, "completion_tokens": 56, "total_tokens": 2297, "cost": 0.002521, "total_cost": 0.002521, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669189} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669207} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2331, "completion_tokens": 0, "total_tokens": 2331, "cost": 0.0023309999999999997, "total_cost": 0.0023309999999999997, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669209} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669319} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2330, "completion_tokens": 0, "total_tokens": 2330, "cost": 0.00233, "total_cost": 0.00233, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669321} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669367} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2330, "completion_tokens": 0, "total_tokens": 2330, "cost": 0.00233, "total_cost": 0.00233, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669370} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669378} -{"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": 2330, "completion_tokens": 31, "total_tokens": 2361, "cost": 0.007455000000000001, "total_cost": 0.007455000000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669383} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669403} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2321, "completion_tokens": 0, "total_tokens": 2321, "cost": 0.0023209999999999997, "total_cost": 0.0023209999999999997, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669406} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669527} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2175, "completion_tokens": 83, "total_tokens": 2258, "cost": 0.00259, "total_cost": 0.00259, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732669534} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670104} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670105} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670112} -{"event": "command_git", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670117} -{"event": "command_editor", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670120} -{"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": 18049, "completion_tokens": 624, "total_tokens": 18673, "cost": 0.06350700000000001, "total_cost": 0.06350700000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670200} -{"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": 18845, "completion_tokens": 524, "total_tokens": 19369, "cost": 0.06439500000000001, "total_cost": 0.12790200000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670238} -{"event": "command_undo", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670268} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670362} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670410} -{"event": "message_send", "properties": {"main_model": "claude-3-5-haiku-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-haiku-20241022", "edit_format": "diff", "prompt_tokens": 2221, "completion_tokens": 56, "total_tokens": 2277, "cost": 0.0025009999999999998, "total_cost": 0.0025009999999999998, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670414} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670423} -{"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": 2230, "completion_tokens": 35, "total_tokens": 2265, "cost": 0.007215, "total_cost": 0.007215, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670426} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670482} -{"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": 2230, "completion_tokens": 35, "total_tokens": 2265, "cost": 0.007215, "total_cost": 0.007215, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670485} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670499} -{"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": 2230, "completion_tokens": 35, "total_tokens": 2265, "cost": 0.007215, "total_cost": 0.007215, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670503} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670603} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670762} -{"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": 2330, "completion_tokens": 31, "total_tokens": 2361, "cost": 0.007455000000000001, "total_cost": 0.007455000000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670766} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670811} -{"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": 2330, "completion_tokens": 31, "total_tokens": 2361, "cost": 0.007455000000000001, "total_cost": 0.007455000000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670815} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670821} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670951} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732670952} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678168} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678168} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678196} -{"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": 11571, "completion_tokens": 245, "total_tokens": 11816, "cost": 0.038388, "total_cost": 0.038388, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678205} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678221} -{"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": 11834, "completion_tokens": 673, "total_tokens": 12507, "cost": 0.045597, "total_cost": 0.083985, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678237} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678250} -{"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": 12392, "completion_tokens": 936, "total_tokens": 13328, "cost": 0.051216, "total_cost": 0.13520100000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678270} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678329} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678330} -{"event": "command_paste", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678331} -{"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": 4210, "completion_tokens": 64, "total_tokens": 4274, "cost": 0.013590000000000001, "total_cost": 0.013590000000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678345} -{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678366} -{"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": 15472, "completion_tokens": 1344, "total_tokens": 16816, "cost": 0.066576, "total_cost": 0.201777, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678393} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678639} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678639} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678648} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678648} -{"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": 226, "completion_tokens": 260, "total_tokens": 486, "cost": 0.0045780000000000005, "total_cost": 0.0045780000000000005, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678664} -{"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": 503, "completion_tokens": 240, "total_tokens": 743, "cost": 0.005109, "total_cost": 0.009687000000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678685} -{"event": "command_clear", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678708} -{"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": 225, "completion_tokens": 180, "total_tokens": 405, "cost": 0.0033750000000000004, "total_cost": 0.013062, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732678722} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679037} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679037} -{"event": "command_read-only", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679050} -{"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": 30601, "completion_tokens": 416, "total_tokens": 31017, "cost": 0.09804299999999999, "total_cost": 0.09804299999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679100} -{"event": "command_run", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679185} -{"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": 35687, "completion_tokens": 351, "total_tokens": 36038, "cost": 0.11232600000000001, "total_cost": 0.210369, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679210} -{"event": "command_run", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679218} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679233} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679253} -{"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": 36405, "completion_tokens": 512, "total_tokens": 36917, "cost": 0.11689500000000001, "total_cost": 0.327264, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679270} -{"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": 39001, "completion_tokens": 464, "total_tokens": 39465, "cost": 0.123963, "total_cost": 0.451227, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679320} -{"event": "command_run", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679332} -{"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": 34105, "completion_tokens": 404, "total_tokens": 34509, "cost": 0.108375, "total_cost": 0.5596019999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679362} -{"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": 34222, "completion_tokens": 835, "total_tokens": 35057, "cost": 0.115191, "total_cost": 0.674793, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679392} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679483} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679484} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679494} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679495} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679498} -{"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": 4198, "completion_tokens": 474, "total_tokens": 4672, "cost": 0.019704, "total_cost": 0.019704, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679525} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679543} -{"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": 19326, "completion_tokens": 118, "total_tokens": 19444, "cost": 0.059748, "total_cost": 0.079452, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679565} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679572} -{"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": 29776, "completion_tokens": 133, "total_tokens": 29909, "cost": 0.091323, "total_cost": 0.170775, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679587} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679614} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679615} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679621} -{"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": 14077, "completion_tokens": 219, "total_tokens": 14296, "cost": 0.045516, "total_cost": 0.045516, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679628} -{"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": 16430, "completion_tokens": 91, "total_tokens": 16521, "cost": 0.050655, "total_cost": 0.096171, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679648} -{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679677} -{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679679} -{"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": 7095, "completion_tokens": 311, "total_tokens": 7406, "cost": 0.02595, "total_cost": 0.196725, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679706} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679795} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732679795} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681092} -{"event": "model warning", "properties": {"main_model": "gemini/REDACTED", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681094} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681102} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-latest", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-latest", "edit_format": "diff-fenced", "prompt_tokens": 2256, "completion_tokens": 31, "total_tokens": 2287, "cost": 0.00792855, "total_cost": 0.00792855, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681105} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-latest", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-latest", "edit_format": "diff-fenced", "prompt_tokens": 2331, "completion_tokens": 63, "total_tokens": 2394, "cost": 0.008224649999999998, "total_cost": 0.0161532, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681108} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681148} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-latest", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-latest", "edit_format": "diff-fenced", "prompt_tokens": 2356, "completion_tokens": 5, "total_tokens": 2361, "cost": 0.00825125, "total_cost": 0.00825125, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681152} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681165} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-latest", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-latest", "edit_format": "diff-fenced", "prompt_tokens": 2361, "completion_tokens": 18, "total_tokens": 2379, "cost": 0.0082824, "total_cost": 0.0082824, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681169} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681230} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681244} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681271} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681274} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash", "edit_format": "whole", "prompt_tokens": 653, "completion_tokens": 31, "total_tokens": 684, "cost": 5.8274999999999993e-05, "total_cost": 5.8274999999999993e-05, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681277} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681279} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-001", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-001", "edit_format": "whole", "prompt_tokens": 653, "completion_tokens": 15, "total_tokens": 668, "cost": 5.3475e-05, "total_cost": 5.3475e-05, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681281} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681289} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681292} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 30, "total_tokens": 783, "cost": 6.547499999999999e-05, "total_cost": 6.547499999999999e-05, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681295} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681297} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-001", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-001", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 10, "total_tokens": 763, "cost": 5.9474999999999996e-05, "total_cost": 5.9474999999999996e-05, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681300} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681302} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-002", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-002", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 30, "total_tokens": 783, "cost": 6.547499999999999e-05, "total_cost": 6.547499999999999e-05, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681306} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681308} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-8b-exp-0827", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-8b-exp-0827", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 42, "total_tokens": 795, "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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681311} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681313} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-8b-exp-0924", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-8b-exp-0924", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 42, "total_tokens": 795, "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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681316} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681317} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-exp-0827", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-exp-0827", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 19, "total_tokens": 772, "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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681321} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681323} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-latest", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-latest", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 34, "total_tokens": 787, "cost": 6.6675e-05, "total_cost": 6.6675e-05, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681326} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681328} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro", "edit_format": "diff-fenced", "prompt_tokens": 2361, "completion_tokens": 18, "total_tokens": 2379, "cost": 0.0084525, "total_cost": 0.0084525, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681332} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681334} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-001", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-001", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 25, "total_tokens": 778, "cost": 0.002898, "total_cost": 0.002898, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681338} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681340} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-002", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-002", "edit_format": "diff", "prompt_tokens": 2363, "completion_tokens": 10, "total_tokens": 2373, "cost": 0.0083755, "total_cost": 0.0083755, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681345} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681347} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-exp-0801", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-exp-0801", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 37, "total_tokens": 790, "cost": 0.0030239999999999998, "total_cost": 0.0030239999999999998, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681352} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681354} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-exp-0827", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-exp-0827", "edit_format": "diff-fenced", "prompt_tokens": 2361, "completion_tokens": 19, "total_tokens": 2380, "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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681358} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681360} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-latest", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-latest", "edit_format": "diff-fenced", "prompt_tokens": 2361, "completion_tokens": 18, "total_tokens": 2379, "cost": 0.0082824, "total_cost": 0.0082824, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681364} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681366} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-exp-1114", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-exp-1114", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 10, "total_tokens": 763, "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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681372} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681374} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-gemma-2-27b-it", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-gemma-2-27b-it", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 0, "total_tokens": 753, "cost": 0.00026355, "total_cost": 0.00026355, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681376} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681378} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-gemma-2-9b-it", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-gemma-2-9b-it", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 0, "total_tokens": 753, "cost": 0.00026355, "total_cost": 0.00026355, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681380} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681383} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-pro", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-pro", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 0, "total_tokens": 753, "cost": 0.00026355, "total_cost": 0.00026355, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681385} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681387} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-pro-vision", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-pro-vision", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 0, "total_tokens": 753, "cost": 0.00026355, "total_cost": 0.00026355, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681389} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681485} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681488} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash", "edit_format": "whole", "prompt_tokens": 653, "completion_tokens": 32, "total_tokens": 685, "cost": 5.8575e-05, "total_cost": 5.8575e-05, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681491} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681493} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-001", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-001", "edit_format": "whole", "prompt_tokens": 653, "completion_tokens": 15, "total_tokens": 668, "cost": 5.3475e-05, "total_cost": 5.3475e-05, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681495} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681497} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681528} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681531} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 21, "total_tokens": 774, "cost": 6.2775e-05, "total_cost": 6.2775e-05, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681534} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681536} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-001", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-001", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 10, "total_tokens": 763, "cost": 5.9474999999999996e-05, "total_cost": 5.9474999999999996e-05, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681539} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681541} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-002", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-002", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 34, "total_tokens": 787, "cost": 6.6675e-05, "total_cost": 6.6675e-05, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681545} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681546} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-8b-exp-0827", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-8b-exp-0827", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 42, "total_tokens": 795, "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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681550} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681552} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-8b-exp-0924", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-8b-exp-0924", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 45, "total_tokens": 798, "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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681555} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681557} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-exp-0827", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-exp-0827", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 18, "total_tokens": 771, "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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681561} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681563} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-flash-latest", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-flash-latest", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 20, "total_tokens": 773, "cost": 6.2475e-05, "total_cost": 6.2475e-05, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681566} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681568} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro", "edit_format": "diff-fenced", "prompt_tokens": 2261, "completion_tokens": 37, "total_tokens": 2298, "cost": 0.008302, "total_cost": 0.008302, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681571} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681574} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-001", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-001", "edit_format": "whole", "prompt_tokens": 653, "completion_tokens": 24, "total_tokens": 677, "cost": 0.0025375, "total_cost": 0.0025375, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681577} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681579} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-002", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-002", "edit_format": "diff", "prompt_tokens": 2263, "completion_tokens": 28, "total_tokens": 2291, "cost": 0.0082145, "total_cost": 0.0082145, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681584} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681586} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-exp-0801", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-exp-0801", "edit_format": "whole", "prompt_tokens": 653, "completion_tokens": 49, "total_tokens": 702, "cost": 0.0027999999999999995, "total_cost": 0.0027999999999999995, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681590} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681592} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-exp-0827", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-exp-0827", "edit_format": "diff-fenced", "prompt_tokens": 2261, "completion_tokens": 45, "total_tokens": 2306, "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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681596} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681596} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681597} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-1.5-pro-latest", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-1.5-pro-latest", "edit_format": "diff-fenced", "prompt_tokens": 2261, "completion_tokens": 22, "total_tokens": 2283, "cost": 0.0079366, "total_cost": 0.0079366, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681600} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681602} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-exp-1114", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-exp-1114", "edit_format": "whole", "prompt_tokens": 753, "completion_tokens": 9, "total_tokens": 762, "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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681608} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681610} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-gemma-2-27b-it", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-gemma-2-27b-it", "edit_format": "whole", "prompt_tokens": 653, "completion_tokens": 0, "total_tokens": 653, "cost": 0.00022855, "total_cost": 0.00022855, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681612} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681614} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-gemma-2-9b-it", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-gemma-2-9b-it", "edit_format": "whole", "prompt_tokens": 653, "completion_tokens": 0, "total_tokens": 653, "cost": 0.00022855, "total_cost": 0.00022855, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681616} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681618} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-pro", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-pro", "edit_format": "whole", "prompt_tokens": 653, "completion_tokens": 23, "total_tokens": 676, "cost": 0.0002527, "total_cost": 0.0002527, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681621} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681623} -{"event": "message_send", "properties": {"main_model": "gemini/gemini-pro-vision", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gemini/gemini-pro-vision", "edit_format": "whole", "prompt_tokens": 653, "completion_tokens": 0, "total_tokens": 653, "cost": 0.00022855, "total_cost": 0.00022855, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681625} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681656} -{"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": 23213, "completion_tokens": 235, "total_tokens": 23448, "cost": 0.073164, "total_cost": 0.073164, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681667} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681679} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732681679} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682162} -{"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.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682162} -{"event": "command_ask", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682176} -{"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": 4762, "completion_tokens": 116, "total_tokens": 4878, "cost": 0.016026, "total_cost": 0.016026, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682188} -{"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": 5252, "completion_tokens": 472, "total_tokens": 5724, "cost": 0.022836, "total_cost": 0.038861999999999994, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682202} -{"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": 7910, "completion_tokens": 594, "total_tokens": 8504, "cost": 0.03264, "total_cost": 0.071502, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682247} -{"event": "command_diff", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682351} -{"event": "command_reset", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682448} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682462} -{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682462} -{"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": 7011, "completion_tokens": 71, "total_tokens": 7082, "cost": 0.022098, "total_cost": 0.09359999999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682475} -{"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": 11983, "completion_tokens": 296, "total_tokens": 12279, "cost": 0.040389, "total_cost": 0.133989, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682516} -{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682550} -{"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": 24248, "completion_tokens": 210, "total_tokens": 24458, "cost": 0.075894, "total_cost": 0.075894, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.65.2.dev"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1732682562} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/REDACTED", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 3651, "completion_tokens": 630, "total_tokens": 4281, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705096} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705096} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705158} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705159} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/REDACTED", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705159} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705160} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705183} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/REDACTED", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "ask", "prompt_tokens": 2445, "completion_tokens": 3376, "total_tokens": 5821, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705295} +{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705326} +{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705327} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705330} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "ask", "prompt_tokens": 2445, "completion_tokens": 255, "total_tokens": 2700, "cost": 0.0038115, "total_cost": 0.0038115}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705336} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705370} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705370} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705444} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705444} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705444} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705612} +{"event": "repo", "properties": {"num_files": 65}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705613} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/REDACTED", "weak_model": "fireworks_ai/REDACTED", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705613} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705617} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/REDACTED", "weak_model": "fireworks_ai/REDACTED", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 4359, "completion_tokens": 760, "total_tokens": 5119, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705643} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705643} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/REDACTED", "weak_model": "fireworks_ai/REDACTED", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 4982, "completion_tokens": 802, "total_tokens": 5784, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705670} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705694} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705937} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705937} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738705937} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706287} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706289} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706289} +{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706299} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706301} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706310} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706312} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706312} +{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706313} +{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706313} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706314} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 12716, "completion_tokens": 298, "total_tokens": 13014, "cost": 0.011712599999999998, "total_cost": 0.011712599999999998}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706331} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706340} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706340} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706343} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706345} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706345} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706374} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706376} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706377} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706377} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706379} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706379} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706391} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706411} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706412} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706426} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706489} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706489} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738706489} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712807} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712810} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712810} +{"event": "message_send", "properties": {"main_model": "deepseek/deepseek-reasoner", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "diff", "prompt_tokens": 10001, "completion_tokens": 92, "total_tokens": 10093, "cost": 0.00570203, "total_cost": 0.00570203}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712824} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712824} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712829} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712830} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712830} +{"event": "message_send", "properties": {"main_model": "deepseek/deepseek-reasoner", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "diff", "prompt_tokens": 10041, "completion_tokens": 89, "total_tokens": 10130, "cost": 0.005717460000000001, "total_cost": 0.005717460000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712844} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712844} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712935} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712937} +{"event": "cli session", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712937} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712941} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712952} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738712954} +{"event": "command_editor", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713005} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713044} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "ask", "prompt_tokens": 18678, "completion_tokens": 675, "total_tokens": 19353, "cost": 0.0235158, "total_cost": 0.0235158}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713069} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713093} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713096} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713096} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff", "prompt_tokens": 21712, "completion_tokens": 261, "total_tokens": 21973, "cost": 0.0250316, "total_cost": 0.048547400000000004}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713114} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713214} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "ask", "prompt_tokens": 19777, "completion_tokens": 689, "total_tokens": 20466, "cost": 0.0247863, "total_cost": 0.0733337}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713241} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713245} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713245} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff", "prompt_tokens": 22824, "completion_tokens": 203, "total_tokens": 23027, "cost": 0.0259996, "total_cost": 0.0993333}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713256} +{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713269} +{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713283} +{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713286} +{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713289} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713293} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/REDACTED", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "ask", "prompt_tokens": 18679, "completion_tokens": 1329, "total_tokens": 20008, "cost": 0, "total_cost": 0.0993333}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713339} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713497} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713497} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713497} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713562} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713562} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713569} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713571} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-r1", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713571} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713576} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713576} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713581} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713583} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713583} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713602} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713603} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713603} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713617} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713617} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713618} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713618} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713620} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713624} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713626} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713626} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713630} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713632} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713632} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713642} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713644} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713644} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713720} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713722} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713722} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713773} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713774} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713774} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713802} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713804} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713804} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713825} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713827} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713827} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713836} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713838} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713838} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713901} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713922} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713924} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738713924} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714167} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714168} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714168} +{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714238} +{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714238} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714238} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 12802, "completion_tokens": 179, "total_tokens": 12981, "cost": 0.041091, "total_cost": 0.041091}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714246} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714259} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714261} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714261} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714274} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714274} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714274} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714278} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714278} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714278} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714317} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714317} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714322} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714331} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714332} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714332} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714352} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714352} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714353} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714357} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714357} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714357} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714385} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714385} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-r1", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714385} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714388} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714396} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714397} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714397} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-r1", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714397} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714399} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714399} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714403} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714403} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714408} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714477} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714477} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714477} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714642} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714642} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714642} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714645} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714645} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714645} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714651} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714651} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714651} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714666} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714666} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714666} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714670} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714670} +{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714670} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714796} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714796} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714912} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714912} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738714916} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715000} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715000} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715000} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715043} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715045} +{"event": "cli session", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715045} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715046} +{"event": "command_editor", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715048} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715079} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "ask", "prompt_tokens": 11810, "completion_tokens": 352, "total_tokens": 12162, "cost": 0.0145398, "total_cost": 0.0145398}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715104} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715200} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715200} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715200} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715206} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715239} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "ask", "prompt_tokens": 18342, "completion_tokens": 854, "total_tokens": 19196, "cost": 0.0239338, "total_cost": 0.038473600000000004}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715252} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715274} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715274} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff", "prompt_tokens": 21493, "completion_tokens": 525, "total_tokens": 22018, "cost": 0.0259523, "total_cost": 0.06442590000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715289} +{"event": "command_diff", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715311} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715360} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715363} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715363} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715363} +{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715373} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715373} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff", "prompt_tokens": 20548, "completion_tokens": 148, "total_tokens": 20696, "cost": 0.023254000000000004, "total_cost": 0.0876799}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715391} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715393} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff", "prompt_tokens": 20894, "completion_tokens": 73, "total_tokens": 20967, "cost": 0.0233046, "total_cost": 0.11098450000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715400} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715550} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715551} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715551} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715635} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715642} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715642} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715647} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715721} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715721} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738715721} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717740} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717742} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717742} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717760} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717762} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717762} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717763} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717771} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717773} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717773} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717774} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717783} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717785} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717785} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717786} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717792} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717794} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717794} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717795} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717795} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717797} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717797} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717798} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717804} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717806} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717806} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717806} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717806} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717808} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717808} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738717809} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738787320} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738787322} +{"event": "cli session", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738787322} +{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738787323} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738787340} +{"event": "command_editor", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738787340} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738787414} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "ask", "prompt_tokens": 8828, "completion_tokens": 285, "total_tokens": 9113, "cost": 0.0109648, "total_cost": 0.0109648}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738787446} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738787609} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "ask", "prompt_tokens": 9152, "completion_tokens": 444, "total_tokens": 9596, "cost": 0.0120208, "total_cost": 0.022985600000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738787649} +{"event": "command_editor", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738787685} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738787877} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "ask", "prompt_tokens": 9672, "completion_tokens": 552, "total_tokens": 10224, "cost": 0.013068, "total_cost": 0.036053600000000005}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738787902} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738788233} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738788234} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738788234} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738788388} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738788555} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738788555} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738788555} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738788875} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738788876} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738788876} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789047} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789048} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789048} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789051} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789055} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789055} +{"event": "exit", "properties": {"reason": "Showed prompts"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789058} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789075} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789075} +{"event": "exit", "properties": {"reason": "Showed prompts"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789078} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789101} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789102} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789102} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789114} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789116} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789117} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789117} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789124} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789142} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789220} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789221} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789221} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789224} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789224} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789224} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789232} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789243} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 22069, "completion_tokens": 225, "total_tokens": 22294, "cost": 0.069582, "total_cost": 0.069582}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738789255} +{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738791922} +{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738791927} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738792251} +{"event": "exit", "properties": {"reason": "Listed models"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738792253} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738792268} +{"event": "model warning", "properties": {"main_model": "gemini/REDACTED", "weak_model": "gemini/REDACTED", "editor_model": "gemini/REDACTED"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738792269} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738792272} +{"event": "cli session", "properties": {"main_model": "gemini/REDACTED", "weak_model": "gemini/REDACTED", "editor_model": "gemini/REDACTED", "edit_format": "whole"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738792272} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738792273} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738792277} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738792277} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797794} +{"event": "model warning", "properties": {"main_model": "vertex_ai/REDACTED", "weak_model": "vertex_ai/REDACTED", "editor_model": "vertex_ai/REDACTED"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797796} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797798} +{"event": "cli session", "properties": {"main_model": "vertex_ai/REDACTED", "weak_model": "vertex_ai/REDACTED", "editor_model": "vertex_ai/REDACTED", "edit_format": "whole"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797798} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797799} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797810} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797810} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797841} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797841} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797844} +{"event": "model warning", "properties": {"main_model": "vertex_ai/REDACTED", "weak_model": "vertex_ai/REDACTED", "editor_model": "vertex_ai/REDACTED"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797846} +{"event": "exit", "properties": {"reason": "Keyboard interrupt during model warnings"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797848} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797851} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797853} +{"event": "cli session", "properties": {"main_model": "vertex_ai/REDACTED", "weak_model": "vertex_ai/REDACTED", "editor_model": "vertex_ai/REDACTED", "edit_format": "whole"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797853} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797854} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797864} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797864} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797870} +{"event": "exit", "properties": {"reason": "Listed models"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797872} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797886} +{"event": "exit", "properties": {"reason": "Listed models"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797888} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797894} +{"event": "exit", "properties": {"reason": "Listed models"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797895} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797912} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797913} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738797913} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738798659} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738798661} +{"event": "cli session", "properties": {"main_model": "gemini/REDACTED", "weak_model": "gemini/REDACTED", "editor_model": "gemini/REDACTED", "edit_format": "whole"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738798661} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738798663} +{"event": "message_send", "properties": {"main_model": "gemini/REDACTED", "weak_model": "gemini/REDACTED", "editor_model": "gemini/REDACTED", "edit_format": "whole", "prompt_tokens": 1844, "completion_tokens": 15, "total_tokens": 1859, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738798664} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738798686} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738798686} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738799240} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738799240} +{"event": "exit", "properties": {"reason": "Showed prompts"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738799243} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738799276} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738799276} +{"event": "exit", "properties": {"reason": "Showed prompts"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738799279} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857004} +{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857006} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857009} +{"event": "cli session", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None", "edit_format": "whole"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857009} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857012} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857012} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857015} +{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857016} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857018} +{"event": "cli session", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None", "edit_format": "whole"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857018} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857021} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857021} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857042} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857043} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857047} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857132} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857132} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738857132} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858467} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858467} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-r1", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858467} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858468} +{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858471} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858474} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858492} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-r1", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "ask", "prompt_tokens": 12098, "completion_tokens": 563, "total_tokens": 12661, "cost": 0.10128799999999999, "total_cost": 0.10128799999999999}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858523} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858545} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-r1", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "ask", "prompt_tokens": 12359, "completion_tokens": 2644, "total_tokens": 15003, "cost": 0.120024, "total_cost": 0.221312}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858682} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858692} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858692} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-r1", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 15224, "completion_tokens": 1181, "total_tokens": 16405, "cost": 0.13124, "total_cost": 0.352552}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858757} +{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858790} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858799} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 18938, "completion_tokens": 207, "total_tokens": 19145, "cost": 0.059919, "total_cost": 0.412471}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858806} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858809} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858809} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 21531, "completion_tokens": 382, "total_tokens": 21913, "cost": 0.070323, "total_cost": 0.48279399999999995}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858833} +{"event": "command_run", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858869} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858878} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 27025, "completion_tokens": 295, "total_tokens": 27320, "cost": 0.0855, "total_cost": 0.568294}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858887} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858891} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858891} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 29645, "completion_tokens": 152, "total_tokens": 29797, "cost": 0.091215, "total_cost": 0.659509}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858899} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858915} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 30526, "completion_tokens": 324, "total_tokens": 30850, "cost": 0.09643800000000001, "total_cost": 0.755947}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858926} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858927} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858927} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 33152, "completion_tokens": 151, "total_tokens": 33303, "cost": 0.101721, "total_cost": 0.8576680000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858935} +{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858945} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858962} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 12586, "completion_tokens": 988, "total_tokens": 13574, "cost": 0.052578, "total_cost": 0.9102460000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858984} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858994} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738858994} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 15786, "completion_tokens": 726, "total_tokens": 16512, "cost": 0.05824800000000001, "total_cost": 0.9684940000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859011} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859112} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 17801, "completion_tokens": 316, "total_tokens": 18117, "cost": 0.058143, "total_cost": 1.026637}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859120} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859125} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859126} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 20395, "completion_tokens": 257, "total_tokens": 20652, "cost": 0.06504, "total_cost": 1.091677}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859135} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859139} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 20947, "completion_tokens": 274, "total_tokens": 21221, "cost": 0.06695100000000001, "total_cost": 1.158628}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859147} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859147} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 21698, "completion_tokens": 349, "total_tokens": 22047, "cost": 0.070329, "total_cost": 1.228957}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859157} +{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859170} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859195} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 13317, "completion_tokens": 769, "total_tokens": 14086, "cost": 0.051486000000000004, "total_cost": 1.280443}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859211} +{"event": "command_reset", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859259} +{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859265} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859269} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859298} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 13760, "completion_tokens": 612, "total_tokens": 14372, "cost": 0.050460000000000005, "total_cost": 1.330903}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859310} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859323} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859323} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 16668, "completion_tokens": 655, "total_tokens": 17323, "cost": 0.059829, "total_cost": 1.3907319999999999}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859338} +{"event": "command_reset", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859358} +{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859362} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859366} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859371} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 13317, "completion_tokens": 860, "total_tokens": 14177, "cost": 0.052851, "total_cost": 1.4435829999999998}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859389} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859394} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859394} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 16471, "completion_tokens": 710, "total_tokens": 17181, "cost": 0.060063, "total_cost": 1.5036459999999998}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859413} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859447} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 19062, "completion_tokens": 157, "total_tokens": 19219, "cost": 0.059541000000000004, "total_cost": 1.5631869999999999}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859456} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859478} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 19230, "completion_tokens": 325, "total_tokens": 19555, "cost": 0.062565, "total_cost": 1.6257519999999999}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859487} +{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859716} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859755} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 13369, "completion_tokens": 579, "total_tokens": 13948, "cost": 0.048792, "total_cost": 1.6745439999999998}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859769} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859772} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859772} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 16136, "completion_tokens": 483, "total_tokens": 16619, "cost": 0.055653, "total_cost": 1.7301969999999998}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859783} +{"event": "command_reset", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859873} +{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859877} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859879} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859896} +{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859917} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859921} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 7130, "completion_tokens": 683, "total_tokens": 7813, "cost": 0.031634999999999996, "total_cost": 1.7618319999999998}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859936} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859941} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859941} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 10357, "completion_tokens": 525, "total_tokens": 10882, "cost": 0.038946, "total_cost": 1.8007779999999998}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859956} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859969} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 10680, "completion_tokens": 527, "total_tokens": 11207, "cost": 0.039945, "total_cost": 1.8407229999999997}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738859983} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860013} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860015} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860021} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860022} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 13549, "completion_tokens": 487, "total_tokens": 14036, "cost": 0.047952, "total_cost": 1.8886749999999997}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860034} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860054} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 13550, "completion_tokens": 509, "total_tokens": 14059, "cost": 0.048285, "total_cost": 1.9369599999999996}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860067} +{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860111} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860123} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 7091, "completion_tokens": 886, "total_tokens": 7977, "cost": 0.034562999999999997, "total_cost": 1.9715229999999995}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860143} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860151} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860151} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 10278, "completion_tokens": 1065, "total_tokens": 11343, "cost": 0.046809, "total_cost": 2.0183319999999996}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860174} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860192} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 12074, "completion_tokens": 343, "total_tokens": 12417, "cost": 0.041367, "total_cost": 2.0596989999999997}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860201} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860220} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 7636, "completion_tokens": 327, "total_tokens": 7963, "cost": 0.027813, "total_cost": 2.087512}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860231} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860244} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 7979, "completion_tokens": 358, "total_tokens": 8337, "cost": 0.029307, "total_cost": 2.116819}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860254} +{"event": "command_run", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860262} +{"event": "command_run", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860311} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860644} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860644} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860649} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860844} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860845} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738860845} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738862537} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738862950} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738862950} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738862950} +{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738862958} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738862962} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738862993} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863006} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863006} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863016} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863016} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863016} +{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863018} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863020} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863021} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 13873, "completion_tokens": 422, "total_tokens": 14295, "cost": 0.012865499999999998, "total_cost": 0.012865499999999998}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863060} +{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863124} +{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863128} +{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863131} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863137} +{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863138} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863141} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 15975, "completion_tokens": 753, "total_tokens": 16728, "cost": 0.0150552, "total_cost": 0.0279207}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863201} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863802} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863824} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863824} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863826} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863835} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863835} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863837} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863843} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863843} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863908} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863909} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863934} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863935} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863947} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863948} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863999} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738863999} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864001} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864101} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864101} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864102} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864104} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864108} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864108} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864108} +{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864118} +{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864118} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864118} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864138} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864138} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864151} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864151} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864151} +{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864158} +{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864158} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864158} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 7236, "completion_tokens": 340, "total_tokens": 7576, "cost": 0.0068184, "total_cost": 0.0068184}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864175} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864250} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 7600, "completion_tokens": 398, "total_tokens": 7998, "cost": 0.0071982, "total_cost": 0.0140166}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864289} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864416} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864416} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864422} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864430} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864430} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864433} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864433} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864433} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864578} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864578} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738864578} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868286} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868286} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868286} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868288} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 9941, "completion_tokens": 37, "total_tokens": 9978, "cost": 0.030378000000000002, "total_cost": 0.030378000000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868292} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868297} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868297} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868304} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868304} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-r1", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868304} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868305} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868437} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868437} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868484} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868484} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868485} +{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868509} +{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868509} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868509} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 15211, "completion_tokens": 246, "total_tokens": 15457, "cost": 0.0139113, "total_cost": 0.0139113}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868525} +{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868538} +{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868541} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868591} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868591} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868734} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868734} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868734} +{"event": "message_send", "properties": {"main_model": "deepseek/deepseek-chat", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "diff", "prompt_tokens": 9940, "completion_tokens": 43, "total_tokens": 9983, "cost": 0.00140363999999804, "total_cost": 0.00140363999999804}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868743} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868743} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868767} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868767} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868767} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868772} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868794} +{"event": "model warning", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868796} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868798} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868798} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868805} +{"event": "model warning", "properties": {"main_model": "ollama_chat/REDACTED", "weak_model": "ollama_chat/REDACTED", "editor_model": "ollama_chat/REDACTED"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868807} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868810} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868810} +{"event": "message_send_exception", "properties": {"exception": "[Errno 61] Connection refused"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868811} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868811} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868817} +{"event": "model warning", "properties": {"main_model": "ollama_chat/REDACTED", "weak_model": "ollama_chat/REDACTED", "editor_model": "ollama_chat/REDACTED"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868819} +{"event": "exit", "properties": {"reason": "Keyboard interrupt during model warnings"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868820} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868824} +{"event": "model warning", "properties": {"main_model": "ollama_chat/REDACTED", "weak_model": "ollama_chat/REDACTED", "editor_model": "ollama_chat/REDACTED"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868826} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868827} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868827} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868870} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868877} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868880} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868880} +{"event": "message_send_exception", "properties": {"exception": ""}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868882} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868882} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868896} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868912} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868915} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738868915} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869100} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869267} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869273} +{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869274} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869274} +{"event": "message_send", "properties": {"main_model": "ollama_chat/REDACTED", "weak_model": "ollama_chat/REDACTED", "editor_model": "ollama_chat/REDACTED", "edit_format": "ask", "prompt_tokens": 79, "completion_tokens": 24, "total_tokens": 103, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869283} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869283} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869289} +{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869291} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869291} +{"event": "message_send", "properties": {"main_model": "ollama_chat/REDACTED", "weak_model": "ollama_chat/REDACTED", "editor_model": "ollama_chat/REDACTED", "edit_format": "ask", "prompt_tokens": 79, "completion_tokens": 24, "total_tokens": 103, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869293} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869293} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869323} +{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869323} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869323} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869342} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869344} +{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869344} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869344} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869349} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869674} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869674} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738869678} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870016} +{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870016} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870016} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870023} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870029} +{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870030} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870030} +{"event": "message_send", "properties": {"main_model": "ollama_chat/REDACTED", "weak_model": "ollama_chat/REDACTED", "editor_model": "ollama_chat/REDACTED", "edit_format": "ask", "prompt_tokens": 79, "completion_tokens": 24, "total_tokens": 103, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870038} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870038} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870046} +{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870047} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870047} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870531} +{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870531} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870531} +{"event": "message_send", "properties": {"main_model": "deepseek/deepseek-chat", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "ask", "prompt_tokens": 79, "completion_tokens": 25, "total_tokens": 104, "cost": 1.8059999998040003e-05, "total_cost": 1.8059999998040003e-05}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870538} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870538} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870556} +{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870556} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870556} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870568} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870569} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870575} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870652} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870653} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870653} +{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870654} +{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870654} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870654} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 12793, "completion_tokens": 200, "total_tokens": 12993, "cost": 0.041379000000000006, "total_cost": 0.041379000000000006}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870662} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870822} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870822} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870826} +{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870826} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870826} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870831} +{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870831} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870831} +{"event": "message_send", "properties": {"main_model": "deepseek/deepseek-chat", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "ask", "prompt_tokens": 79, "completion_tokens": 36, "total_tokens": 115, "cost": 2.1139999998040004e-05, "total_cost": 2.1139999998040004e-05}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870839} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870839} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870880} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870881} +{"event": "cli session", "properties": {"main_model": "deepseek/deepseek-chat", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870881} +{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870884} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870887} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870913} +{"event": "message_send", "properties": {"main_model": "deepseek/deepseek-chat", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "diff", "prompt_tokens": 16364, "completion_tokens": 617, "total_tokens": 16981, "cost": 0.00246371999999804, "total_cost": 0.00246371999999804}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870944} +{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738870982} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871002} +{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871053} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871054} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 17017, "completion_tokens": 617, "total_tokens": 17634, "cost": 0.0158706, "total_cost": 0.018334319999998037}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871094} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871107} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871107} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871122} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871123} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871123} +{"event": "command_run", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871130} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871153} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 20195, "completion_tokens": 62, "total_tokens": 20257, "cost": 0.018231300000000002, "total_cost": 0.018231300000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871160} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871167} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 19777, "completion_tokens": 445, "total_tokens": 20222, "cost": 0.018199800000000002, "total_cost": 0.03643110000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871197} +{"event": "command_run", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871207} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871213} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 23881, "completion_tokens": 214, "total_tokens": 24095, "cost": 0.0216855, "total_cost": 0.058116600000000004}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871226} +{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871234} +{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871237} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871245} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 16424, "completion_tokens": 561, "total_tokens": 16985, "cost": 0.015286499999999998, "total_cost": 0.0734031}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871273} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871332} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871332} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871335} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871340} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871340} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871406} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871406} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738871406} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878138} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878138} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878138} +{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878142} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878160} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878160} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878160} +{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878162} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878180} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878182} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878182} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878182} +{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878183} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878229} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878229} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878234} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878234} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878238} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878309} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878310} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878310} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878659} +{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878659} +{"event": "cli session", "properties": {"main_model": "deepseek/deepseek-chat", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878659} +{"event": "command_multiline-mode", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878664} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878665} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878689} +{"event": "message_send", "properties": {"main_model": "deepseek/deepseek-chat", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "diff", "prompt_tokens": 2399, "completion_tokens": 67, "total_tokens": 2466, "cost": 0.00035461999999804, "total_cost": 0.00035461999999804}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878695} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878807} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878814} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878814} +{"event": "cli session", "properties": {"main_model": "deepseek/deepseek-chat", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878815} +{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878837} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878842} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878909} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878909} +{"event": "message_send", "properties": {"main_model": "deepseek/deepseek-chat", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "ask", "prompt_tokens": 13955, "completion_tokens": 438, "total_tokens": 14393, "cost": 0.0020763399999980396, "total_cost": 0.0020763399999980396}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878931} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878933} +{"event": "message_send", "properties": {"main_model": "deepseek/deepseek-chat", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "diff", "prompt_tokens": 16714, "completion_tokens": 853, "total_tokens": 17567, "cost": 0.0025787999999980406, "total_cost": 0.00465513999999608}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878967} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738878993} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879021} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879046} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879046} +{"event": "message_send", "properties": {"main_model": "deepseek/deepseek-chat", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "ask", "prompt_tokens": 16298, "completion_tokens": 618, "total_tokens": 16916, "cost": 0.00245475999999804, "total_cost": 0.00710989999999412}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879084} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879085} +{"event": "message_send", "properties": {"main_model": "deepseek/deepseek-chat", "weak_model": "deepseek/deepseek-chat", "editor_model": "deepseek/deepseek-chat", "edit_format": "diff", "prompt_tokens": 19220, "completion_tokens": 0, "total_tokens": 19220, "cost": 0.0026907999999980403, "total_cost": 0.00980069999999216}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879147} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879243} +{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879269} +{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879276} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879277} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "deepseek/deepseek-chat", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 19249, "completion_tokens": 599, "total_tokens": 19848, "cost": 0.0178632, "total_cost": 0.027663899999992157}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879325} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879395} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879408} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879409} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879409} +{"event": "command_run", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879411} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879443} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879475} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879475} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879497} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 17539, "completion_tokens": 302, "total_tokens": 17841, "cost": 0.0160569, "total_cost": 0.0160569}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879512} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879521} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 18166, "completion_tokens": 383, "total_tokens": 18549, "cost": 0.0166941, "total_cost": 0.032751}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879544} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879557} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 19898, "completion_tokens": 567, "total_tokens": 20465, "cost": 0.018418499999999997, "total_cost": 0.0511695}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879594} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879604} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 21582, "completion_tokens": 811, "total_tokens": 22393, "cost": 0.020153699999999997, "total_cost": 0.0713232}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879648} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879663} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879794} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879794} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879794} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879806} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879807} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879808} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879808} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879812} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879814} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879814} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879819} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879819} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879822} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879888} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879888} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738879888} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880039} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880039} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880039} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880045} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880048} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880048} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880089} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880089} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880109} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 22126, "completion_tokens": 87, "total_tokens": 22213, "cost": 0.06768300000000001, "total_cost": 0.06768300000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880115} +{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880119} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880471} +{"event": "model warning", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880473} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880475} +{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "whole"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880475} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880476} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880478} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880509} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880510} +{"event": "cli session", "properties": {"main_model": "ollama/REDACTED", "weak_model": "ollama/REDACTED", "editor_model": "ollama/REDACTED", "edit_format": "whole"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880510} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880512} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880514} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880524} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880524} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880524} +{"event": "message_send_exception", "properties": {"exception": "[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate (_ssl.c:1000)"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880525} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738880525} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738881386} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738881386} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738881386} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884252} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884252} +{"event": "cli session", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884252} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884254} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff", "prompt_tokens": 10012, "completion_tokens": 32, "total_tokens": 10044, "cost": 0.011154, "total_cost": 0.011154}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884259} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884260} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884263} +{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884263} +{"event": "cli session", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884263} +{"event": "exit", "properties": {"reason": "Completed main CLI coder.run"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884265} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884269} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884269} +{"event": "cli session", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884269} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884280} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff", "prompt_tokens": 9985, "completion_tokens": 180, "total_tokens": 10165, "cost": 0.0117755, "total_cost": 0.0117755}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884287} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884373} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884373} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884990} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884990} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738884990} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738888520} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738888520} +{"event": "cli session", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738888520} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738888521} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738888532} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "ask", "prompt_tokens": 4655, "completion_tokens": 159, "total_tokens": 4814, "cost": 0.0043326, "total_cost": 0.0043326}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738888540} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738888889} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738888889} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 7662, "completion_tokens": 186, "total_tokens": 7848, "cost": 0.0070631999999999995, "total_cost": 0.0113958}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738888903} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738888907} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738889683} +{"event": "repo", "properties": {"num_files": 436}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738889684} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738889684} +{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738889685} +{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738889685} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738889686} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 15460, "completion_tokens": 201, "total_tokens": 15661, "cost": 0.049395, "total_cost": 0.049395}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738889694} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738890195} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738890195} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738890350} +{"event": "repo", "properties": {"num_files": 436}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738890350} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738890350} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-r1", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 10008, "completion_tokens": 582, "total_tokens": 10590, "cost": 0.08471999999999999, "total_cost": 0.08471999999999999}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738890379} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738896839} +{"event": "repo", "properties": {"num_files": 436}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738896839} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738896839} +{"event": "message_send", "properties": {"main_model": "fireworks_ai/accounts/fireworks/models/deepseek-r1", "weak_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "editor_model": "fireworks_ai/accounts/fireworks/models/deepseek-v3", "edit_format": "diff", "prompt_tokens": 10044, "completion_tokens": 548, "total_tokens": 10592, "cost": 0.08473599999999999, "total_cost": 0.08473599999999999}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738896929} +{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738896929} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945606} +{"event": "repo", "properties": {"num_files": 436}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945606} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945606} +{"event": "command_multiline-mode", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945609} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945616} +{"event": "command_run", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945632} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945788} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945790} +{"event": "repo", "properties": {"num_files": 436}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945790} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945790} +{"event": "command_multiline-mode", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945792} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945826} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945828} +{"event": "repo", "properties": {"num_files": 436}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945828} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945828} +{"event": "command_multiline-mode", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945830} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945855} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945887} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945887} +{"event": "cli session", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945887} +{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945925} +{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945925} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945925} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945925} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "ask", "prompt_tokens": 11233, "completion_tokens": 383, "total_tokens": 11616, "cost": 0.0140415, "total_cost": 0.0140415}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945944} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945955} +{"event": "message_send", "properties": {"main_model": "o3-mini", "weak_model": "gpt-4o-mini", "editor_model": "gpt-4o", "edit_format": "diff", "prompt_tokens": 14522, "completion_tokens": 120, "total_tokens": 14642, "cost": 0.0165022, "total_cost": 0.0305437}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945971} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945979} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945979} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945979} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945992} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945998} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945998} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738945998} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946001} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946012} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946012} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946012} +{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946018} +{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946021} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946023} +{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946135} +{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946138} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946145} +{"event": "command_editor", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946146} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946178} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "gpt-4o-mini", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 10926, "completion_tokens": 327, "total_tokens": 11253, "cost": 0.037683, "total_cost": 0.0682267}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946189} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946203} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946203} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "gpt-4o-mini", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 13642, "completion_tokens": 208, "total_tokens": 13850, "cost": 0.044046, "total_cost": 0.1122727}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946210} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946215} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946215} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946215} +{"event": "command_run", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946228} +{"event": "command_run", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946243} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946251} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946253} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946253} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946253} +{"event": "command_run", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946259} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946266} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946306} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946306} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946328} +{"event": "repo", "properties": {"num_files": 435}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946328} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946328} +{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946332} +{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946336} +{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946343} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946346} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946346} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946346} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946351} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 35885, "completion_tokens": 866, "total_tokens": 36751, "cost": 0.120645, "total_cost": 0.120645}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946372} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946674} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946674} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 37097, "completion_tokens": 563, "total_tokens": 37660, "cost": 0.119736, "total_cost": 0.240381}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946691} +{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946817} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946817} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 37684, "completion_tokens": 451, "total_tokens": 38135, "cost": 0.119817, "total_cost": 0.360198}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946829} +{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946831} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946831} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 40543, "completion_tokens": 770, "total_tokens": 41313, "cost": 0.133179, "total_cost": 0.493377}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738946849} +{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738947046} +{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738947046} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738947160} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738947160} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738947160} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738947322} +{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738947323} +{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738947323} +{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738954379} +{"event": "repo", "properties": {"num_files": 436}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738954379} +{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738954379} +{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738954393} +{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-haiku-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 10183, "completion_tokens": 527, "total_tokens": 10710, "cost": 0.038454, "total_cost": 0.038454}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738954406} +{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1738954451} diff --git a/aider/website/assets/sample.aider.conf.yml b/aider/website/assets/sample.aider.conf.yml index 7d4d9fdb3..915bf8132 100644 --- a/aider/website/assets/sample.aider.conf.yml +++ b/aider/website/assets/sample.aider.conf.yml @@ -14,14 +14,8 @@ ## show this help message and exit #help: xxx -####### -# Main: - -## Specify the OpenAI API key -#openai-api-key: xxx - -## Specify the Anthropic API key -#anthropic-api-key: xxx +############# +# Main model: ## Specify the model to use for the main chat #model: xxx @@ -38,7 +32,7 @@ ## Use gpt-4-0613 model for the main chat #4: false -## Use gpt-4o-2024-08-06 model for the main chat +## Use gpt-4o model for the main chat #4o: false ## Use gpt-4o-mini model for the main chat @@ -50,7 +44,7 @@ ## Use gpt-3.5-turbo model for the main chat #35turbo: false -## Use deepseek/deepseek-coder model for the main chat +## Use deepseek/deepseek-chat model for the main chat #deepseek: false ## Use o1-mini model for the main chat @@ -59,27 +53,52 @@ ## Use o1-preview model for the main chat #o1-preview: false -################# -# Model Settings: +######################## +# API Keys and settings: -## List known models which match the (partial) MODEL name -#list-models: xxx +## Specify the OpenAI API key +#openai-api-key: xxx + +## Specify the Anthropic API key +#anthropic-api-key: xxx ## Specify the api base url #openai-api-base: xxx -## Specify the api_type +## (deprecated, use --set-env OPENAI_API_TYPE=) #openai-api-type: xxx -## Specify the api_version +## (deprecated, use --set-env OPENAI_API_VERSION=) #openai-api-version: xxx -## Specify the deployment_id +## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=) #openai-api-deployment-id: xxx -## Specify the OpenAI organization ID +## (deprecated, use --set-env OPENAI_ORGANIZATION=) #openai-organization-id: xxx +## Set an environment variable (to control API settings, can be used multiple times) +#set-env: xxx +## Specify multiple values like this: +#set-env: +# - xxx +# - yyy +# - zzz + +## Set an API key for a provider (eg: --api-key provider= sets PROVIDER_API_KEY=) +#api-key: xxx +## Specify multiple values like this: +#api-key: +# - xxx +# - yyy +# - zzz + +################# +# Model settings: + +## List known models which match the (partial) MODEL name +#list-models: xxx + ## Specify a file with aider model settings for unknown models #model-settings-file: .aider.model.settings.yml @@ -94,9 +113,15 @@ # - yyy # - zzz +## Set the reasoning_effort API parameter (default: not set) +#reasoning-effort: xxx + ## Verify the SSL cert when connecting to models (default: True) #verify-ssl: true +## Timeout in seconds for API calls (default: None) +#timeout: xxx + ## Specify what edit format the LLM should use (default depends on model) #edit-format: xxx @@ -118,11 +143,8 @@ ## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens. #max-chat-history-tokens: xxx -## Specify the .env file to load (default: .env in git root) -#env-file: .env - ################# -# Cache Settings: +# Cache settings: ## Enable caching of prompts (default: False) #cache-prompts: false @@ -131,9 +153,9 @@ #cache-keepalive-pings: false ################### -# Repomap Settings: +# Repomap settings: -## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024) +## Suggested number of tokens to use for repo map, use 0 to disable #map-tokens: xxx ## Control how often the repo map is refreshed. Options: auto, always, files, manual (default: auto) @@ -158,7 +180,7 @@ #llm-history-file: xxx ################## -# Output Settings: +# Output settings: ## Use colors suitable for a dark terminal background (default: False) #dark-mode: false @@ -199,14 +221,14 @@ ## Set the background color for the current item in the completion menu (default: terminal's default text color) #completion-menu-current-bg-color: xxx -## Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light) +## Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light, or a Pygments builtin style, see https://pygments.org/styles for available themes) #code-theme: default ## Show diffs when committing changes (default: False) #show-diffs: false ############### -# Git Settings: +# Git settings: ## Enable/disable looking for a git repo (default: True) #git: true @@ -250,6 +272,9 @@ ## Skip the sanity check for the git repository (default: False) #skip-sanity-check-repo: false +## Enable/disable watching files for ai coding comments (default: False) +#watch-files: false + ######################## # Fixing and committing: @@ -273,7 +298,7 @@ ## Enable/disable automatic testing after changes (default: False) #auto-test: false -## Run tests and fix problems found +## Run tests, fix problems found and then exit #test: false ############ @@ -288,8 +313,71 @@ ## Permanently disable analytics #analytics-disable: false +############ +# Upgrading: + +## Check for updates and return status in the exit code +#just-check-update: false + +## Check for new aider versions on launch +#check-update: true + +## Show release notes on first run of new version (default: None, ask user) +#show-release-notes: xxx + +## Install the latest version from the main branch +#install-main-branch: false + +## Upgrade aider to the latest version from PyPI +#upgrade: false + +## Show the version number and exit +#version: xxx + +######## +# Modes: + +## Specify a single message to send the LLM, process reply then exit (disables chat mode) +#message: xxx + +## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode) +#message-file: xxx + +## Run aider in your browser (default: False) +#gui: false + +## Enable automatic copy/paste of chat between aider and web UI (default: False) +#copy-paste: false + +## Apply the changes from the given file instead of running the chat (debug) +#apply: xxx + +## Apply clipboard contents as edits using the main model's editor format +#apply-clipboard-edits: false + +## Do all startup activities then exit before accepting user input (debug) +#exit: false + +## Print the repo map and exit (debug) +#show-repo-map: false + +## Print the system prompts and exit (debug) +#show-prompts: false + ################# -# Other Settings: +# Voice settings: + +## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg +#voice-format: wav + +## Specify the language for voice using ISO 639-1 code (default: auto) +#voice-language: en + +## Specify the input device name for voice recording +#voice-input-device: xxx + +################# +# Other settings: ## specify a file to edit (can be used multiple times) #file: xxx @@ -313,62 +401,26 @@ ## Specify the language to use in the chat (default: None, uses system settings) #chat-language: xxx -## Show the version number and exit -#version: xxx - -## Check for updates and return status in the exit code -#just-check-update: false - -## Check for new aider versions on launch -#check-update: true - -## Show release notes on first run of new version (default: None, ask user) -#show-release-notes: xxx - -## Install the latest version from the main branch -#install-main-branch: false - -## Upgrade aider to the latest version from PyPI -#upgrade: false - -## Apply the changes from the given file instead of running the chat (debug) -#apply: xxx - -## Apply clipboard contents as edits using the main model's editor format -#apply-clipboard-edits: false - ## Always say yes to every confirmation #yes-always: false ## Enable verbose output #verbose: false -## Print the repo map and exit (debug) -#show-repo-map: false - -## Print the system prompts and exit (debug) -#show-prompts: false - -## Do all startup activities then exit before accepting user input (debug) -#exit: false - -## Specify a single message to send the LLM, process reply then exit (disables chat mode) -#message: xxx - -## 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 +## Line endings to use when writing files (default: platform) +#line-endings: platform + ## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory) #config: xxx -## Run aider in your browser (default: False) -#gui: false +## Specify the .env file to load (default: .env in git root) +#env-file: .env ## Enable/disable suggesting shell commands (default: True) #suggest-shell-commands: true @@ -376,17 +428,11 @@ ## Enable/disable fancy input with history and completion (default: True) #fancy-input: true +## Enable/disable multi-line input mode with Meta-Enter to submit (default: False) +#multiline: false + ## Enable/disable detection and offering to add URLs to chat (default: True) #detect-urls: true ## Specify which editor to use for the /editor command #editor: xxx - -################# -# Voice Settings: - -## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg -#voice-format: wav - -## Specify the language for voice using ISO 639-1 code (default: auto) -#voice-language: en diff --git a/aider/website/assets/sample.env b/aider/website/assets/sample.env index 3642110af..ad3752823 100644 --- a/aider/website/assets/sample.env +++ b/aider/website/assets/sample.env @@ -18,14 +18,8 @@ ##... -####### -# Main: - -## Specify the OpenAI API key -#OPENAI_API_KEY= - -## Specify the Anthropic API key -#ANTHROPIC_API_KEY= +############# +# Main model: ## Specify the model to use for the main chat #AIDER_MODEL= @@ -42,7 +36,7 @@ ## Use gpt-4-0613 model for the main chat #AIDER_4= -## Use gpt-4o-2024-08-06 model for the main chat +## Use gpt-4o model for the main chat #AIDER_4O= ## Use gpt-4o-mini model for the main chat @@ -54,7 +48,7 @@ ## Use gpt-3.5-turbo model for the main chat #AIDER_35TURBO= -## Use deepseek/deepseek-coder model for the main chat +## Use deepseek/deepseek-chat model for the main chat #AIDER_DEEPSEEK= ## Use o1-mini model for the main chat @@ -63,27 +57,42 @@ ## Use o1-preview model for the main chat #AIDER_O1_PREVIEW= +######################## +# API Keys and settings: + +## Specify the OpenAI API key +#AIDER_OPENAI_API_KEY= + +## Specify the Anthropic API key +#AIDER_ANTHROPIC_API_KEY= + +## Specify the api base url +#AIDER_OPENAI_API_BASE= + +## (deprecated, use --set-env OPENAI_API_TYPE=) +#AIDER_OPENAI_API_TYPE= + +## (deprecated, use --set-env OPENAI_API_VERSION=) +#AIDER_OPENAI_API_VERSION= + +## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=) +#AIDER_OPENAI_API_DEPLOYMENT_ID= + +## (deprecated, use --set-env OPENAI_ORGANIZATION=) +#AIDER_OPENAI_ORGANIZATION_ID= + +## Set an environment variable (to control API settings, can be used multiple times) +#AIDER_SET_ENV= + +## Set an API key for a provider (eg: --api-key provider= sets PROVIDER_API_KEY=) +#AIDER_API_KEY= + ################# -# Model Settings: +# Model settings: ## List known models which match the (partial) MODEL name #AIDER_LIST_MODELS= -## Specify the api base url -#OPENAI_API_BASE= - -## Specify the api_type -#OPENAI_API_TYPE= - -## Specify the api_version -#OPENAI_API_VERSION= - -## Specify the deployment_id -#OPENAI_API_DEPLOYMENT_ID= - -## Specify the OpenAI organization ID -#OPENAI_ORGANIZATION_ID= - ## Specify a file with aider model settings for unknown models #AIDER_MODEL_SETTINGS_FILE=.aider.model.settings.yml @@ -93,9 +102,15 @@ ## Add a model alias (can be used multiple times) #AIDER_ALIAS= +## Set the reasoning_effort API parameter (default: not set) +#AIDER_REASONING_EFFORT= + ## Verify the SSL cert when connecting to models (default: True) #AIDER_VERIFY_SSL=true +## Timeout in seconds for API calls (default: None) +#AIDER_TIMEOUT= + ## Specify what edit format the LLM should use (default depends on model) #AIDER_EDIT_FORMAT= @@ -117,11 +132,8 @@ ## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens. #AIDER_MAX_CHAT_HISTORY_TOKENS= -## Specify the .env file to load (default: .env in git root) -#AIDER_ENV_FILE=.env - ################# -# Cache Settings: +# Cache settings: ## Enable caching of prompts (default: False) #AIDER_CACHE_PROMPTS=false @@ -130,9 +142,9 @@ #AIDER_CACHE_KEEPALIVE_PINGS=false ################### -# Repomap Settings: +# Repomap settings: -## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024) +## Suggested number of tokens to use for repo map, use 0 to disable #AIDER_MAP_TOKENS= ## Control how often the repo map is refreshed. Options: auto, always, files, manual (default: auto) @@ -157,7 +169,7 @@ #AIDER_LLM_HISTORY_FILE= ################## -# Output Settings: +# Output settings: ## Use colors suitable for a dark terminal background (default: False) #AIDER_DARK_MODE=false @@ -198,14 +210,14 @@ ## Set the background color for the current item in the completion menu (default: terminal's default text color) #AIDER_COMPLETION_MENU_CURRENT_BG_COLOR= -## Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light) +## Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light, or a Pygments builtin style, see https://pygments.org/styles for available themes) #AIDER_CODE_THEME=default ## Show diffs when committing changes (default: False) #AIDER_SHOW_DIFFS=false ############### -# Git Settings: +# Git settings: ## Enable/disable looking for a git repo (default: True) #AIDER_GIT=true @@ -249,6 +261,9 @@ ## Skip the sanity check for the git repository (default: False) #AIDER_SKIP_SANITY_CHECK_REPO=false +## Enable/disable watching files for ai coding comments (default: False) +#AIDER_WATCH_FILES=false + ######################## # Fixing and committing: @@ -267,7 +282,7 @@ ## Enable/disable automatic testing after changes (default: False) #AIDER_AUTO_TEST=false -## Run tests and fix problems found +## Run tests, fix problems found and then exit #AIDER_TEST=false ############ @@ -282,20 +297,8 @@ ## Permanently disable analytics #AIDER_ANALYTICS_DISABLE=false -################# -# Other Settings: - -## specify a file to edit (can be used multiple times) -#AIDER_FILE= - -## specify a read-only file (can be used multiple times) -#AIDER_READ= - -## Use VI editing mode in the terminal (default: False) -#AIDER_VIM=false - -## Specify the language to use in the chat (default: None, uses system settings) -#AIDER_CHAT_LANGUAGE= +############ +# Upgrading: ## Check for updates and return status in the exit code #AIDER_JUST_CHECK_UPDATE=false @@ -312,26 +315,8 @@ ## Upgrade aider to the latest version from PyPI #AIDER_UPGRADE=false -## Apply the changes from the given file instead of running the chat (debug) -#AIDER_APPLY= - -## Apply clipboard contents as edits using the main model's editor format -#AIDER_APPLY_CLIPBOARD_EDITS=false - -## Always say yes to every confirmation -#AIDER_YES_ALWAYS= - -## Enable verbose output -#AIDER_VERBOSE=false - -## Print the repo map and exit (debug) -#AIDER_SHOW_REPO_MAP=false - -## Print the system prompts and exit (debug) -#AIDER_SHOW_PROMPTS=false - -## Do all startup activities then exit before accepting user input (debug) -#AIDER_EXIT=false +######## +# Modes: ## Specify a single message to send the LLM, process reply then exit (disables chat mode) #AIDER_MESSAGE= @@ -339,14 +324,71 @@ ## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode) #AIDER_MESSAGE_FILE= +## Run aider in your browser (default: False) +#AIDER_GUI=false + +## Enable automatic copy/paste of chat between aider and web UI (default: False) +#AIDER_COPY_PASTE=false + +## Apply the changes from the given file instead of running the chat (debug) +#AIDER_APPLY= + +## Apply clipboard contents as edits using the main model's editor format +#AIDER_APPLY_CLIPBOARD_EDITS=false + +## Do all startup activities then exit before accepting user input (debug) +#AIDER_EXIT=false + +## Print the repo map and exit (debug) +#AIDER_SHOW_REPO_MAP=false + +## Print the system prompts and exit (debug) +#AIDER_SHOW_PROMPTS=false + +################# +# Voice settings: + +## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg +#AIDER_VOICE_FORMAT=wav + +## Specify the language for voice using ISO 639-1 code (default: auto) +#AIDER_VOICE_LANGUAGE=en + +## Specify the input device name for voice recording +#AIDER_VOICE_INPUT_DEVICE= + +################# +# Other settings: + +## specify a file to edit (can be used multiple times) +#AIDER_FILE= + +## specify a read-only file (can be used multiple times) +#AIDER_READ= + +## Use VI editing mode in the terminal (default: False) +#AIDER_VIM=false + +## Specify the language to use in the chat (default: None, uses system settings) +#AIDER_CHAT_LANGUAGE= + +## Always say yes to every confirmation +#AIDER_YES_ALWAYS= + +## Enable verbose output +#AIDER_VERBOSE=false + ## 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 (default: False) -#AIDER_GUI=false +## Line endings to use when writing files (default: platform) +#AIDER_LINE_ENDINGS=platform + +## Specify the .env file to load (default: .env in git root) +#AIDER_ENV_FILE=.env ## Enable/disable suggesting shell commands (default: True) #AIDER_SUGGEST_SHELL_COMMANDS=true @@ -354,17 +396,11 @@ ## Enable/disable fancy input with history and completion (default: True) #AIDER_FANCY_INPUT=true +## Enable/disable multi-line input mode with Meta-Enter to submit (default: False) +#AIDER_MULTILINE=false + ## Enable/disable detection and offering to add URLs to chat (default: True) #AIDER_DETECT_URLS=true ## Specify which editor to use for the /editor command #AIDER_EDITOR= - -################# -# Voice Settings: - -## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg -#AIDER_VOICE_FORMAT=wav - -## Specify the language for voice using ISO 639-1 code (default: auto) -#AIDER_VOICE_LANGUAGE=en diff --git a/aider/website/assets/watch.jpg b/aider/website/assets/watch.jpg new file mode 100644 index 000000000..9c3f5a3ba Binary files /dev/null and b/aider/website/assets/watch.jpg differ diff --git a/aider/website/assets/watch.mp4 b/aider/website/assets/watch.mp4 new file mode 100644 index 000000000..eb1e8c212 Binary files /dev/null and b/aider/website/assets/watch.mp4 differ diff --git a/aider/website/docs/config.md b/aider/website/docs/config.md index 3b192c432..299ec5979 100644 --- a/aider/website/docs/config.md +++ b/aider/website/docs/config.md @@ -40,5 +40,5 @@ Using an `.env` file: AIDER_DARK_MODE=true ``` -{% include env-keys-tip.md %} +{% include keys.md %} diff --git a/aider/website/docs/config/adv-model-settings.md b/aider/website/docs/config/adv-model-settings.md index 46715349d..212bdbae5 100644 --- a/aider/website/docs/config/adv-model-settings.md +++ b/aider/website/docs/config/adv-model-settings.md @@ -46,13 +46,19 @@ The json file should be a dictionary with an entry for each model, as follows: } ``` -See -[litellm's model_prices_and_context_window.json file](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) for more examples. - {: .tip } Use a fully qualified model name with a `provider/` at the front in the `.aider.model.metadata.json` file. For example, use `deepseek/deepseek-chat`, not just `deepseek-chat`. +That prefix should match the `litellm_provider` field. + +### Contribute model metadata + +Aider relies on +[litellm's model_prices_and_context_window.json file](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) +for model metadata. + +Consider submitting a PR to that file to add missing models. ## Model settings @@ -68,7 +74,7 @@ a model that aider doesn't know about. You can override or add settings for any model by creating a `.aider.model.settings.yml` file in one of these locations: - Your home directory. -- The root if your git repo. +- The root of your git repo. - The current directory where you launch aider. - Or specify a specific file with the `--model-settings-file ` switch. @@ -97,7 +103,41 @@ For example: These settings will be merged with any model-specific settings, with the `aider/extra_params` settings taking precedence for any direct conflicts. -### Example model settings +### Controlling o1 reasoning effort + +You need this chunk of yaml: + +``` + extra_params: + extra_body: + reasoning_effort: high +``` + +This is a full entry for o1 with that setting, obtained by finding the default +entry in the list below and adding the above `extra_params` entry: + +``` +- name: o1 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + send_undo_reply: false + lazy: false + reminder: user + examples_as_sys_msg: false + cache_control: false + caches_by_default: false + use_system_prompt: true + use_temperature: false + streaming: false + editor_model_name: gpt-4o + editor_edit_format: editor-diff + extra_params: + extra_body: + reasoning_effort: high +``` + +### Default model settings Below are all the pre-configured model settings to give a sense for the settings which are supported. @@ -105,6 +145,10 @@ You can also look at the `ModelSettings` class in [models.py](https://github.com/Aider-AI/aider/blob/main/aider/models.py) file for more details about all of the model setting that aider supports. +The first entry shows all the settings, with their default values. +For a real model, +you just need to include whichever fields that you want to override the defaults. + ```yaml -- cache_control: false - caches_by_default: false +- name: (default values) edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: gpt-3.5-turbo - reminder: sys - send_undo_reply: false - streaming: true + weak_model_name: null use_repo_map: false - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null + send_undo_reply: false lazy: false - name: gpt-3.5-turbo-0125 - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: gpt-3.5-turbo-1106 - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: gpt-3.5-turbo-0613 - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: gpt-3.5-turbo-16k-0613 - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: udiff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: true - name: gpt-4-turbo-2024-04-09 - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: udiff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: true - name: gpt-4-turbo - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: true - name: openai/gpt-4o - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: true - name: openai/gpt-4o-2024-08-06 - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: true - name: gpt-4o-2024-08-06 - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: true - name: gpt-4o-2024-11-20 - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: true - name: openai/gpt-4o-2024-11-20 - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: true - name: gpt-4o - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: true - name: gpt-4o-mini - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: true - name: openai/gpt-4o-mini - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true - weak_model_name: openai/gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: udiff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: true - extra_params: null - lazy: true - name: gpt-4-0125-preview - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: udiff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: true - name: gpt-4-1106-preview - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: gpt-4-vision-preview - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: true - extra_params: null - lazy: false - name: gpt-4-0314 - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: gpt-4-0613 - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: gpt-4-32k-0613 - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: claude-3-opus-20240229 reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: claude-3-5-haiku-20241022 -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null examples_as_sys_msg: false extra_params: null - lazy: false - name: openrouter/anthropic/claude-3-opus - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true + cache_control: false + caches_by_default: false use_system_prompt: true use_temperature: true - weak_model_name: openrouter/anthropic/claude-3-5-haiku -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: null + streaming: true editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: claude-3-sonnet-20240229 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true - weak_model_name: claude-3-5-haiku-20241022 -- cache_control: true - caches_by_default: false + editor_edit_format: null + remove_reasoning: null + system_prompt_prefix: null + +- name: anthropic/claude-3-5-haiku-20241022 edit_format: diff - editor_edit_format: editor-diff - editor_model_name: claude-3-5-sonnet-20240620 + weak_model_name: anthropic/claude-3-5-haiku-20241022 + use_repo_map: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + cache_control: true + +- name: anthropic/claude-3-5-sonnet-20240620 + edit_format: diff + weak_model_name: anthropic/claude-3-5-haiku-20241022 + use_repo_map: true examples_as_sys_msg: true extra_params: extra_headers: anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 max_tokens: 8192 - lazy: false - name: claude-3-5-sonnet-20240620 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: claude-3-5-haiku-20241022 -- cache_control: true - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff + cache_control: true editor_model_name: anthropic/claude-3-5-sonnet-20240620 + editor_edit_format: editor-diff + +- name: anthropic/claude-3-5-sonnet-20241022 + edit_format: diff + weak_model_name: anthropic/claude-3-5-haiku-20241022 + use_repo_map: true examples_as_sys_msg: true extra_params: extra_headers: anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 max_tokens: 8192 - lazy: false - name: anthropic/claude-3-5-sonnet-20240620 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: anthropic/claude-3-5-haiku-20241022 -- cache_control: true - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff + cache_control: true 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,pdfs-2024-09-25 - max_tokens: 8192 - lazy: false - name: anthropic/claude-3-5-sonnet-20241022 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true + editor_edit_format: editor-diff + +- name: anthropic/claude-3-5-sonnet-latest + edit_format: diff weak_model_name: anthropic/claude-3-5-haiku-20241022 -- cache_control: true - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff - editor_model_name: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0 + use_repo_map: true examples_as_sys_msg: true extra_params: extra_headers: anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 max_tokens: 8192 - lazy: false - name: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0 -- cache_control: true - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff + cache_control: true 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,pdfs-2024-09-25 - max_tokens: 8192 - lazy: false - name: anthropic/claude-3-5-sonnet-latest - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: anthropic/claude-3-5-haiku-20241022 -- cache_control: true - caches_by_default: false - edit_format: diff editor_edit_format: editor-diff - editor_model_name: claude-3-5-sonnet-20241022 - examples_as_sys_msg: true - extra_params: - extra_headers: - anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 - max_tokens: 8192 - lazy: false - name: claude-3-5-sonnet-20241022 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: claude-3-5-haiku-20241022 -- cache_control: true - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: true - extra_params: - extra_headers: - anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 - lazy: false - name: anthropic/claude-3-haiku-20240307 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true + +- name: anthropic/claude-3-haiku-20240307 weak_model_name: anthropic/claude-3-haiku-20240307 -- cache_control: true - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: - extra_headers: - anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 - lazy: false - name: anthropic/claude-3-5-haiku-20241022 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: anthropic/claude-3-5-haiku-20241022 -- cache_control: true - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: - extra_headers: - anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 - lazy: false - name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0 -- cache_control: true - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null examples_as_sys_msg: true extra_params: extra_headers: anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 - lazy: false - name: claude-3-5-haiku-20241022 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: claude-3-5-haiku-20241022 -- cache_control: false - caches_by_default: false + cache_control: true + +- name: azure/o1 edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false + weak_model_name: azure/gpt-4o-mini + use_repo_map: true + use_temperature: false + streaming: false + editor_model_name: azure/gpt-4o + editor_edit_format: editor-diff + +- name: azure/o1-mini + weak_model_name: azure/gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + editor_model_name: azure/gpt-4o + editor_edit_format: editor-diff + +- name: azure/o1-preview + edit_format: diff + weak_model_name: azure/gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + editor_model_name: azure/gpt-4o + editor_edit_format: editor-diff + +- name: azure/o3-mini + edit_format: diff + weak_model_name: azure/gpt-4o-mini + use_repo_map: true + use_temperature: false + editor_model_name: azure/gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: 'Formatting re-enabled. ' + +- name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0 + edit_format: diff + weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0 + use_repo_map: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + cache_control: true + +- name: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0 + edit_format: diff + weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0 + use_repo_map: true + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + max_tokens: 8192 + cache_control: true + editor_model_name: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0 + editor_edit_format: editor-diff + +- name: claude-3-5-haiku-20241022 + edit_format: diff + weak_model_name: claude-3-5-haiku-20241022 + use_repo_map: true + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + cache_control: true + +- name: claude-3-5-sonnet-20240620 + edit_format: diff + weak_model_name: claude-3-5-haiku-20241022 + use_repo_map: true + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + max_tokens: 8192 + cache_control: true + editor_model_name: claude-3-5-sonnet-20240620 + editor_edit_format: editor-diff + +- name: claude-3-5-sonnet-20241022 + edit_format: diff + weak_model_name: claude-3-5-haiku-20241022 + use_repo_map: true + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + max_tokens: 8192 + cache_control: true + editor_model_name: claude-3-5-sonnet-20241022 + editor_edit_format: editor-diff + +- name: claude-3-haiku-20240307 + weak_model_name: claude-3-haiku-20240307 + examples_as_sys_msg: true + extra_params: + extra_headers: + anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 + cache_control: true + +- name: claude-3-opus-20240229 + edit_format: diff + weak_model_name: claude-3-5-haiku-20241022 + use_repo_map: true + +- name: claude-3-sonnet-20240229 + weak_model_name: claude-3-5-haiku-20241022 + +- name: command-r-08-2024 + weak_model_name: command-r-08-2024 + use_repo_map: true + +- name: command-r-plus + weak_model_name: command-r-plus + use_repo_map: true + +- name: command-r-plus-08-2024 + weak_model_name: command-r-plus-08-2024 + use_repo_map: true + +- name: deepseek-chat + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + +- name: deepseek-coder + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + +- name: deepseek/deepseek-chat + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + +- name: deepseek/deepseek-coder + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + +- name: deepseek/deepseek-reasoner + edit_format: diff + weak_model_name: deepseek/deepseek-chat + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + use_temperature: false + editor_model_name: deepseek/deepseek-chat + editor_edit_format: editor-diff + +- name: fireworks_ai/accounts/fireworks/models/deepseek-r1 + edit_format: diff + weak_model_name: fireworks_ai/accounts/fireworks/models/deepseek-v3 + use_repo_map: true + extra_params: + max_tokens: 160000 + use_temperature: false + editor_model_name: fireworks_ai/accounts/fireworks/models/deepseek-v3 + editor_edit_format: editor-diff + remove_reasoning: think + +- name: fireworks_ai/accounts/fireworks/models/deepseek-v3 + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + extra_params: + max_tokens: 128000 + +- name: gemini/gemini-1.5-flash-002 + +- name: gemini/gemini-1.5-flash-exp-0827 + +- name: gemini/gemini-1.5-pro + edit_format: diff-fenced + use_repo_map: true + +- name: gemini/gemini-1.5-pro-002 + edit_format: diff + use_repo_map: true + +- name: gemini/gemini-1.5-pro-exp-0827 + edit_format: diff-fenced + use_repo_map: true + +- name: gemini/gemini-1.5-pro-latest + edit_format: diff-fenced + use_repo_map: true + +- name: gemini/gemini-2.0-flash + edit_format: diff + use_repo_map: true + +- name: gemini/gemini-2.0-flash-exp + edit_format: diff + use_repo_map: true + +- name: gemini/gemini-exp-1114 + edit_format: diff + use_repo_map: true + +- name: gemini/gemini-exp-1121 + edit_format: diff + use_repo_map: true + +- name: gemini/gemini-exp-1206 + edit_format: diff + use_repo_map: true + +- name: gpt-3.5-turbo + weak_model_name: gpt-4o-mini + reminder: sys + +- name: gpt-3.5-turbo-0125 + weak_model_name: gpt-4o-mini + reminder: sys + +- name: gpt-3.5-turbo-0613 + weak_model_name: gpt-4o-mini + reminder: sys + +- name: gpt-3.5-turbo-1106 + weak_model_name: gpt-4o-mini + reminder: sys + +- name: gpt-3.5-turbo-16k-0613 + weak_model_name: gpt-4o-mini + reminder: sys + +- name: gpt-4-0125-preview + edit_format: udiff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + +- name: gpt-4-0314 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + +- name: gpt-4-0613 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + reminder: sys + +- name: gpt-4-1106-preview + edit_format: udiff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + +- name: gpt-4-32k-0613 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + reminder: sys + +- name: gpt-4-turbo + edit_format: udiff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + +- name: gpt-4-turbo-2024-04-09 + edit_format: udiff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + +- name: gpt-4-vision-preview + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + reminder: sys + +- name: gpt-4o + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + editor_edit_format: editor-diff + +- name: gpt-4o-2024-08-06 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + +- name: gpt-4o-2024-11-20 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + +- name: gpt-4o-mini + weak_model_name: gpt-4o-mini + lazy: true + reminder: sys + +- name: groq/llama3-70b-8192 + edit_format: diff + weak_model_name: groq/llama3-8b-8192 + examples_as_sys_msg: true + +- name: o1 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + use_temperature: false + streaming: false + editor_model_name: gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: 'Formatting re-enabled. ' + +- name: o1-mini + weak_model_name: gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + editor_model_name: gpt-4o + editor_edit_format: editor-diff + +- name: o1-preview + edit_format: architect + weak_model_name: gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + editor_model_name: gpt-4o + editor_edit_format: editor-diff + +- name: o3-mini + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + use_temperature: false + editor_model_name: gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: 'Formatting re-enabled. ' + +- name: openai/gpt-4o + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + editor_edit_format: editor-diff + +- name: openai/gpt-4o-2024-08-06 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + +- name: openai/gpt-4o-2024-11-20 + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + +- name: openai/gpt-4o-mini + weak_model_name: openai/gpt-4o-mini + lazy: true + reminder: sys + +- name: openai/o1 + edit_format: diff + weak_model_name: openai/gpt-4o-mini + use_repo_map: true + use_temperature: false + streaming: false + editor_model_name: openai/gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: 'Formatting re-enabled. ' + +- name: openai/o1-mini + weak_model_name: openai/gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + editor_model_name: openai/gpt-4o + editor_edit_format: editor-diff + +- name: openai/o1-preview + edit_format: diff + weak_model_name: openai/gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + editor_model_name: openai/gpt-4o + editor_edit_format: editor-diff + +- name: openai/o3-mini + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + use_temperature: false + editor_model_name: gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: 'Formatting re-enabled. ' + +- name: openrouter/anthropic/claude-3-opus + edit_format: diff + weak_model_name: openrouter/anthropic/claude-3-5-haiku + use_repo_map: true + +- name: openrouter/anthropic/claude-3.5-sonnet + edit_format: diff + weak_model_name: openrouter/anthropic/claude-3-5-haiku + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + cache_control: true + editor_model_name: openrouter/anthropic/claude-3.5-sonnet + editor_edit_format: editor-diff + +- name: openrouter/anthropic/claude-3.5-sonnet:beta + edit_format: diff + weak_model_name: openrouter/anthropic/claude-3-5-haiku:beta + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + cache_control: true + editor_model_name: openrouter/anthropic/claude-3.5-sonnet:beta + editor_edit_format: editor-diff + +- name: openrouter/deepseek/deepseek-chat + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + +- name: openrouter/deepseek/deepseek-coder + edit_format: diff + use_repo_map: true + reminder: sys + examples_as_sys_msg: true + +- name: openrouter/deepseek/deepseek-r1 + edit_format: diff + weak_model_name: openrouter/deepseek/deepseek-chat + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + use_temperature: false + editor_model_name: openrouter/deepseek/deepseek-chat + editor_edit_format: editor-diff + +- name: openrouter/deepseek/deepseek-r1-distill-llama-70b + edit_format: diff + weak_model_name: openrouter/deepseek/deepseek-chat + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + use_temperature: false + editor_model_name: openrouter/deepseek/deepseek-chat + editor_edit_format: editor-diff + +- name: openrouter/deepseek/deepseek-r1:free + edit_format: diff + weak_model_name: openrouter/deepseek/deepseek-r1:free + use_repo_map: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + caches_by_default: true + use_temperature: false + editor_model_name: openrouter/deepseek/deepseek-r1:free + editor_edit_format: editor-diff + +- name: openrouter/meta-llama/llama-3-70b-instruct + edit_format: diff + weak_model_name: openrouter/meta-llama/llama-3-70b-instruct + examples_as_sys_msg: true + +- name: openrouter/openai/gpt-4o + edit_format: diff + weak_model_name: openrouter/openai/gpt-4o-mini + use_repo_map: true + lazy: true + reminder: sys + examples_as_sys_msg: true + editor_edit_format: editor-diff + +- name: openrouter/openai/o1 + edit_format: diff + weak_model_name: openrouter/openai/gpt-4o-mini + use_repo_map: true + use_temperature: false + streaming: false + editor_model_name: openrouter/openai/gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: 'Formatting re-enabled. ' + +- name: openrouter/openai/o1-mini + weak_model_name: openrouter/openai/gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + streaming: false + editor_model_name: openrouter/openai/gpt-4o + editor_edit_format: editor-diff + +- name: openrouter/openai/o1-preview + edit_format: diff + weak_model_name: openrouter/openai/gpt-4o-mini + use_repo_map: true + use_system_prompt: false + use_temperature: false + streaming: false + editor_model_name: openrouter/openai/gpt-4o + editor_edit_format: editor-diff + +- name: openrouter/openai/o3-mini + edit_format: diff + weak_model_name: openrouter/openai/gpt-4o-mini + use_repo_map: true + use_temperature: false + editor_model_name: openrouter/openai/gpt-4o + editor_edit_format: editor-diff + system_prompt_prefix: 'Formatting re-enabled. ' + +- name: openrouter/qwen/qwen-2.5-coder-32b-instruct + edit_format: diff + weak_model_name: openrouter/qwen/qwen-2.5-coder-32b-instruct + use_repo_map: true + editor_model_name: openrouter/qwen/qwen-2.5-coder-32b-instruct + editor_edit_format: editor-diff + +- name: vertex_ai/claude-3-5-haiku@20241022 + edit_format: diff + weak_model_name: vertex_ai/claude-3-5-haiku@20241022 + use_repo_map: true extra_params: max_tokens: 4096 - lazy: false - name: vertex_ai/claude-3-5-haiku@20241022 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true + +- name: vertex_ai/claude-3-5-sonnet-v2@20241022 + edit_format: diff weak_model_name: vertex_ai/claude-3-5-haiku@20241022 -- cache_control: true - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: true - extra_params: - extra_headers: - anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25 - lazy: false - name: claude-3-haiku-20240307 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true - weak_model_name: claude-3-haiku-20240307 -- cache_control: true - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff - editor_model_name: openrouter/anthropic/claude-3.5-sonnet + use_repo_map: true examples_as_sys_msg: true extra_params: max_tokens: 8192 - lazy: false - name: openrouter/anthropic/claude-3.5-sonnet - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: openrouter/anthropic/claude-3-5-haiku -- cache_control: true - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff - editor_model_name: openrouter/anthropic/claude-3.5-sonnet:beta - examples_as_sys_msg: true - extra_params: - max_tokens: 8192 - lazy: false - name: openrouter/anthropic/claude-3.5-sonnet:beta - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: openrouter/anthropic/claude-3-5-haiku:beta -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff - editor_model_name: vertex_ai/claude-3-5-sonnet@20240620 - examples_as_sys_msg: true - extra_params: - max_tokens: 8192 - lazy: false - name: vertex_ai/claude-3-5-sonnet@20240620 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: vertex_ai/claude-3-5-haiku@20241022 -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff editor_model_name: vertex_ai/claude-3-5-sonnet-v2@20241022 - examples_as_sys_msg: true - extra_params: - max_tokens: 8192 - lazy: false - name: vertex_ai/claude-3-5-sonnet-v2@20241022 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true + editor_edit_format: editor-diff + +- name: vertex_ai/claude-3-5-sonnet@20240620 + edit_format: diff weak_model_name: vertex_ai/claude-3-5-haiku@20241022 -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: vertex_ai/claude-3-opus@20240229 - reminder: user - send_undo_reply: false - streaming: true use_repo_map: true - use_system_prompt: true - use_temperature: true + examples_as_sys_msg: true + extra_params: + max_tokens: 8192 + editor_model_name: vertex_ai/claude-3-5-sonnet@20240620 + editor_edit_format: editor-diff + +- name: vertex_ai/claude-3-opus@20240229 + edit_format: diff weak_model_name: vertex_ai/claude-3-5-haiku@20241022 -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: vertex_ai/claude-3-sonnet@20240229 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true + use_repo_map: true + +- name: vertex_ai/claude-3-sonnet@20240229 weak_model_name: vertex_ai/claude-3-5-haiku@20241022 -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: command-r-plus - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: command-r-plus -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: command-r-08-2024 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: command-r-08-2024 -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: command-r-plus-08-2024 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: command-r-plus-08-2024 -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: true - extra_params: null - lazy: false - name: groq/llama3-70b-8192 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true - weak_model_name: groq/llama3-8b-8192 -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: true - extra_params: null - lazy: false - name: openrouter/meta-llama/llama-3-70b-instruct - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true - weak_model_name: openrouter/meta-llama/llama-3-70b-instruct -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: gemini/gemini-1.5-pro-002 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: null -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: gemini/gemini-1.5-flash-002 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true - weak_model_name: null -- cache_control: false - caches_by_default: false + +- name: vertex_ai/gemini-pro-experimental edit_format: diff-fenced - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: gemini/gemini-1.5-pro - reminder: user - send_undo_reply: false - streaming: true use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: null -- cache_control: false - caches_by_default: false - edit_format: diff-fenced - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: gemini/gemini-1.5-pro-latest - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: null -- cache_control: false - caches_by_default: false - edit_format: diff-fenced - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: gemini/gemini-1.5-pro-exp-0827 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: null -- cache_control: false - caches_by_default: false - edit_format: diff-fenced - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: vertex_ai/gemini-pro-experimental - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: null -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: false - name: gemini/gemini-1.5-flash-exp-0827 - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: false - use_system_prompt: true - use_temperature: true - weak_model_name: null -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: true - extra_params: - max_tokens: 8192 - lazy: false - name: deepseek/deepseek-chat - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: null -- cache_control: false - caches_by_default: true - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: true - extra_params: - max_tokens: 8192 - lazy: false - name: deepseek/deepseek-coder - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: null -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: true - extra_params: - max_tokens: 8192 - lazy: false - name: deepseek-chat - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: null -- cache_control: false - caches_by_default: true - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: true - extra_params: - max_tokens: 8192 - lazy: false - name: deepseek-coder - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: null -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: null - editor_model_name: null - examples_as_sys_msg: true - extra_params: null - lazy: false - name: openrouter/deepseek/deepseek-coder - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: null -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff - editor_model_name: null - examples_as_sys_msg: false - extra_params: null - lazy: true - name: openrouter/openai/gpt-4o - reminder: sys - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: openrouter/openai/gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: editor-diff - editor_model_name: openai/gpt-4o - examples_as_sys_msg: false - extra_params: null - lazy: false - name: openai/o1-mini - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: false - use_temperature: false - weak_model_name: openai/gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: editor-diff - editor_model_name: azure/gpt-4o - examples_as_sys_msg: false - extra_params: null - lazy: false - name: azure/o1-mini - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: false - use_temperature: false - weak_model_name: azure/gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: editor-diff - editor_model_name: gpt-4o - examples_as_sys_msg: false - extra_params: null - lazy: false - name: o1-mini - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: false - use_temperature: false - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff - editor_model_name: openai/gpt-4o - examples_as_sys_msg: false - extra_params: null - lazy: false - name: openai/o1-preview - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: false - use_temperature: false - weak_model_name: openai/gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff - editor_model_name: azure/gpt-4o - examples_as_sys_msg: false - extra_params: null - lazy: false - name: azure/o1-preview - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: false - use_temperature: false - weak_model_name: azure/gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: architect - editor_edit_format: editor-diff - editor_model_name: gpt-4o - examples_as_sys_msg: false - extra_params: null - lazy: false - name: o1-preview - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: false - use_temperature: false - weak_model_name: gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: whole - editor_edit_format: editor-diff - editor_model_name: openrouter/openai/gpt-4o - examples_as_sys_msg: false - extra_params: null - lazy: false - name: openrouter/openai/o1-mini - reminder: user - send_undo_reply: false - streaming: false - use_repo_map: true - use_system_prompt: false - use_temperature: false - weak_model_name: openrouter/openai/gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff - editor_model_name: openrouter/openai/gpt-4o - examples_as_sys_msg: false - extra_params: null - lazy: false - name: openrouter/openai/o1-preview - reminder: user - send_undo_reply: false - streaming: false - use_repo_map: true - use_system_prompt: false - use_temperature: false - weak_model_name: openrouter/openai/gpt-4o-mini -- cache_control: false - caches_by_default: false - edit_format: diff - editor_edit_format: editor-diff - editor_model_name: openrouter/qwen/qwen-2.5-coder-32b-instruct - examples_as_sys_msg: false - extra_params: null - lazy: false - name: openrouter/qwen/qwen-2.5-coder-32b-instruct - reminder: user - send_undo_reply: false - streaming: true - use_repo_map: true - use_system_prompt: true - use_temperature: true - weak_model_name: openrouter/qwen/qwen-2.5-coder-32b-instruct ``` diff --git a/aider/website/docs/config/aider_conf.md b/aider/website/docs/config/aider_conf.md index 2d931e54b..423c1a248 100644 --- a/aider/website/docs/config/aider_conf.md +++ b/aider/website/docs/config/aider_conf.md @@ -7,19 +7,17 @@ description: How to configure aider with a yaml config file. # YAML config file Most of aider's options can be set in an `.aider.conf.yml` file. -Aider will look for a this file in these locations and -load whichever is found first. +Aider will look for a this file in these locations: -- As specified with the `--config ` parameter. -- The current directory. -- The root of your git repo. - Your home directory. +- The root of your git repo. +- The current directory. -## Storing LLM keys +If the files above exist, they will be loaded in that order. Files loaded last will take priority. -{% include special-keys.md %} +You can also specify the `--config ` parameter, which will only load the one config file. -{% include env-keys-tip.md %} +{% include keys.md %} ## A note on lists @@ -70,14 +68,8 @@ cog.outl("```") ## show this help message and exit #help: xxx -####### -# Main: - -## Specify the OpenAI API key -#openai-api-key: xxx - -## Specify the Anthropic API key -#anthropic-api-key: xxx +############# +# Main model: ## Specify the model to use for the main chat #model: xxx @@ -94,7 +86,7 @@ cog.outl("```") ## Use gpt-4-0613 model for the main chat #4: false -## Use gpt-4o-2024-08-06 model for the main chat +## Use gpt-4o model for the main chat #4o: false ## Use gpt-4o-mini model for the main chat @@ -106,7 +98,7 @@ cog.outl("```") ## Use gpt-3.5-turbo model for the main chat #35turbo: false -## Use deepseek/deepseek-coder model for the main chat +## Use deepseek/deepseek-chat model for the main chat #deepseek: false ## Use o1-mini model for the main chat @@ -115,27 +107,52 @@ cog.outl("```") ## Use o1-preview model for the main chat #o1-preview: false -################# -# Model Settings: +######################## +# API Keys and settings: -## List known models which match the (partial) MODEL name -#list-models: xxx +## Specify the OpenAI API key +#openai-api-key: xxx + +## Specify the Anthropic API key +#anthropic-api-key: xxx ## Specify the api base url #openai-api-base: xxx -## Specify the api_type +## (deprecated, use --set-env OPENAI_API_TYPE=) #openai-api-type: xxx -## Specify the api_version +## (deprecated, use --set-env OPENAI_API_VERSION=) #openai-api-version: xxx -## Specify the deployment_id +## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=) #openai-api-deployment-id: xxx -## Specify the OpenAI organization ID +## (deprecated, use --set-env OPENAI_ORGANIZATION=) #openai-organization-id: xxx +## Set an environment variable (to control API settings, can be used multiple times) +#set-env: xxx +## Specify multiple values like this: +#set-env: +# - xxx +# - yyy +# - zzz + +## Set an API key for a provider (eg: --api-key provider= sets PROVIDER_API_KEY=) +#api-key: xxx +## Specify multiple values like this: +#api-key: +# - xxx +# - yyy +# - zzz + +################# +# Model settings: + +## List known models which match the (partial) MODEL name +#list-models: xxx + ## Specify a file with aider model settings for unknown models #model-settings-file: .aider.model.settings.yml @@ -150,9 +167,15 @@ cog.outl("```") # - yyy # - zzz +## Set the reasoning_effort API parameter (default: not set) +#reasoning-effort: xxx + ## Verify the SSL cert when connecting to models (default: True) #verify-ssl: true +## Timeout in seconds for API calls (default: None) +#timeout: xxx + ## Specify what edit format the LLM should use (default depends on model) #edit-format: xxx @@ -174,11 +197,8 @@ cog.outl("```") ## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens. #max-chat-history-tokens: xxx -## Specify the .env file to load (default: .env in git root) -#env-file: .env - ################# -# Cache Settings: +# Cache settings: ## Enable caching of prompts (default: False) #cache-prompts: false @@ -187,9 +207,9 @@ cog.outl("```") #cache-keepalive-pings: false ################### -# Repomap Settings: +# Repomap settings: -## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024) +## Suggested number of tokens to use for repo map, use 0 to disable #map-tokens: xxx ## Control how often the repo map is refreshed. Options: auto, always, files, manual (default: auto) @@ -214,7 +234,7 @@ cog.outl("```") #llm-history-file: xxx ################## -# Output Settings: +# Output settings: ## Use colors suitable for a dark terminal background (default: False) #dark-mode: false @@ -255,14 +275,14 @@ cog.outl("```") ## Set the background color for the current item in the completion menu (default: terminal's default text color) #completion-menu-current-bg-color: xxx -## Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light) +## Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light, or a Pygments builtin style, see https://pygments.org/styles for available themes) #code-theme: default ## Show diffs when committing changes (default: False) #show-diffs: false ############### -# Git Settings: +# Git settings: ## Enable/disable looking for a git repo (default: True) #git: true @@ -306,6 +326,9 @@ cog.outl("```") ## Skip the sanity check for the git repository (default: False) #skip-sanity-check-repo: false +## Enable/disable watching files for ai coding comments (default: False) +#watch-files: false + ######################## # Fixing and committing: @@ -329,7 +352,7 @@ cog.outl("```") ## Enable/disable automatic testing after changes (default: False) #auto-test: false -## Run tests and fix problems found +## Run tests, fix problems found and then exit #test: false ############ @@ -344,8 +367,71 @@ cog.outl("```") ## Permanently disable analytics #analytics-disable: false +############ +# Upgrading: + +## Check for updates and return status in the exit code +#just-check-update: false + +## Check for new aider versions on launch +#check-update: true + +## Show release notes on first run of new version (default: None, ask user) +#show-release-notes: xxx + +## Install the latest version from the main branch +#install-main-branch: false + +## Upgrade aider to the latest version from PyPI +#upgrade: false + +## Show the version number and exit +#version: xxx + +######## +# Modes: + +## Specify a single message to send the LLM, process reply then exit (disables chat mode) +#message: xxx + +## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode) +#message-file: xxx + +## Run aider in your browser (default: False) +#gui: false + +## Enable automatic copy/paste of chat between aider and web UI (default: False) +#copy-paste: false + +## Apply the changes from the given file instead of running the chat (debug) +#apply: xxx + +## Apply clipboard contents as edits using the main model's editor format +#apply-clipboard-edits: false + +## Do all startup activities then exit before accepting user input (debug) +#exit: false + +## Print the repo map and exit (debug) +#show-repo-map: false + +## Print the system prompts and exit (debug) +#show-prompts: false + ################# -# Other Settings: +# Voice settings: + +## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg +#voice-format: wav + +## Specify the language for voice using ISO 639-1 code (default: auto) +#voice-language: en + +## Specify the input device name for voice recording +#voice-input-device: xxx + +################# +# Other settings: ## specify a file to edit (can be used multiple times) #file: xxx @@ -369,62 +455,26 @@ cog.outl("```") ## Specify the language to use in the chat (default: None, uses system settings) #chat-language: xxx -## Show the version number and exit -#version: xxx - -## Check for updates and return status in the exit code -#just-check-update: false - -## Check for new aider versions on launch -#check-update: true - -## Show release notes on first run of new version (default: None, ask user) -#show-release-notes: xxx - -## Install the latest version from the main branch -#install-main-branch: false - -## Upgrade aider to the latest version from PyPI -#upgrade: false - -## Apply the changes from the given file instead of running the chat (debug) -#apply: xxx - -## Apply clipboard contents as edits using the main model's editor format -#apply-clipboard-edits: false - ## Always say yes to every confirmation #yes-always: false ## Enable verbose output #verbose: false -## Print the repo map and exit (debug) -#show-repo-map: false - -## Print the system prompts and exit (debug) -#show-prompts: false - -## Do all startup activities then exit before accepting user input (debug) -#exit: false - -## Specify a single message to send the LLM, process reply then exit (disables chat mode) -#message: xxx - -## 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 +## Line endings to use when writing files (default: platform) +#line-endings: platform + ## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory) #config: xxx -## Run aider in your browser (default: False) -#gui: false +## Specify the .env file to load (default: .env in git root) +#env-file: .env ## Enable/disable suggesting shell commands (default: True) #suggest-shell-commands: true @@ -432,19 +482,13 @@ cog.outl("```") ## Enable/disable fancy input with history and completion (default: True) #fancy-input: true +## Enable/disable multi-line input mode with Meta-Enter to submit (default: False) +#multiline: false + ## Enable/disable detection and offering to add URLs to chat (default: True) #detect-urls: true ## Specify which editor to use for the /editor command #editor: xxx - -################# -# Voice Settings: - -## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg -#voice-format: wav - -## Specify the language for voice using ISO 639-1 code (default: auto) -#voice-language: en ``` diff --git a/aider/website/docs/config/api-keys.md b/aider/website/docs/config/api-keys.md new file mode 100644 index 000000000..f353579f1 --- /dev/null +++ b/aider/website/docs/config/api-keys.md @@ -0,0 +1,90 @@ +--- +parent: Configuration +nav_order: 5 +description: Setting API keys for API providers. +--- + +# API Keys + +Aider lets you specify API keys in a few ways: + +- On the command line +- As environment variables +- In a `.env` file +- In your `.aider.conf.yml` config file + +--- + +## OpenAI and Anthropic + +Aider has special support for providing +OpenAI and Anthropic API keys +via dedicated switches and configuration options. +Settings keys for other providers works a bit differently, see below. + +#### Command line + +You can set OpenAI and Anthropic API keys via +[command line switches](/docs/config/options.html#api-keys-and-settings) +`--openai-api-key` and `--anthropic-api-key`. + + +#### Environment variables or .env file + +You can also store them in environment variables or a +[.env file](/docs/config/dotenv.html), which also works +for every API provider: + +``` +OPENAI_API_KEY= +ANTHROPIC_API_KEY= +``` + +#### Yaml config file +You can also set those API keys via special entries in the +[yaml config file](/docs/config/aider_conf.html), like this: + +```yaml +openai-api-key: +anthropic-api-key: +``` + + +--- + +## Other API providers + +All other LLM providers can use one of these other methods to set their API keys. + +#### Command line +{: .no_toc } + +Use `--api-key provider=` which has the effect of setting the environment variable `PROVIDER_API_KEY=`. So `--api-key gemini=xxx` would set `GEMINI_API_KEY=xxx`. + +#### Environment variables or .env file +{: .no_toc } + +You can set API keys in environment variables. +The [.env file](/docs/config/dotenv.html) +is a great place to store your API keys and other provider API environment variables: + +```bash +GEMINI_API_KEY=foo +OPENROUTER_API_KEY=bar +DEEPSEEK_API_KEY=baz +``` + +#### Yaml config file + + +You can also set API keys in the +[`.aider.conf.yml` file](/docs/config/aider_conf.html) +via the `api-key` entry: + +``` +api-key: +- gemini=foo # Sets env var GEMINI_API_KEY=foo +- openrouter=bar # Sets env var OPENROUTER_API_KEY=bar +- deepseek=baz # Sets env var DEEPSEEK_API_KEY=baz +``` + diff --git a/aider/website/docs/config/dotenv.md b/aider/website/docs/config/dotenv.md index 3dbec38dd..e69930792 100644 --- a/aider/website/docs/config/dotenv.md +++ b/aider/website/docs/config/dotenv.md @@ -1,6 +1,6 @@ --- parent: Configuration -nav_order: 900 +nav_order: 20 description: Using a .env file to store LLM API keys for aider. --- @@ -20,9 +20,7 @@ Aider will look for a `.env` file in these locations: If the files above exist, they will be loaded in that order. Files loaded last will take priority. -## Storing LLM keys - -{% include special-keys.md %} +{% include keys.md %} ## Sample .env file @@ -60,14 +58,8 @@ cog.outl("```") ##... -####### -# Main: - -## Specify the OpenAI API key -#OPENAI_API_KEY= - -## Specify the Anthropic API key -#ANTHROPIC_API_KEY= +############# +# Main model: ## Specify the model to use for the main chat #AIDER_MODEL= @@ -84,7 +76,7 @@ cog.outl("```") ## Use gpt-4-0613 model for the main chat #AIDER_4= -## Use gpt-4o-2024-08-06 model for the main chat +## Use gpt-4o model for the main chat #AIDER_4O= ## Use gpt-4o-mini model for the main chat @@ -96,7 +88,7 @@ cog.outl("```") ## Use gpt-3.5-turbo model for the main chat #AIDER_35TURBO= -## Use deepseek/deepseek-coder model for the main chat +## Use deepseek/deepseek-chat model for the main chat #AIDER_DEEPSEEK= ## Use o1-mini model for the main chat @@ -105,27 +97,42 @@ cog.outl("```") ## Use o1-preview model for the main chat #AIDER_O1_PREVIEW= +######################## +# API Keys and settings: + +## Specify the OpenAI API key +#AIDER_OPENAI_API_KEY= + +## Specify the Anthropic API key +#AIDER_ANTHROPIC_API_KEY= + +## Specify the api base url +#AIDER_OPENAI_API_BASE= + +## (deprecated, use --set-env OPENAI_API_TYPE=) +#AIDER_OPENAI_API_TYPE= + +## (deprecated, use --set-env OPENAI_API_VERSION=) +#AIDER_OPENAI_API_VERSION= + +## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=) +#AIDER_OPENAI_API_DEPLOYMENT_ID= + +## (deprecated, use --set-env OPENAI_ORGANIZATION=) +#AIDER_OPENAI_ORGANIZATION_ID= + +## Set an environment variable (to control API settings, can be used multiple times) +#AIDER_SET_ENV= + +## Set an API key for a provider (eg: --api-key provider= sets PROVIDER_API_KEY=) +#AIDER_API_KEY= + ################# -# Model Settings: +# Model settings: ## List known models which match the (partial) MODEL name #AIDER_LIST_MODELS= -## Specify the api base url -#OPENAI_API_BASE= - -## Specify the api_type -#OPENAI_API_TYPE= - -## Specify the api_version -#OPENAI_API_VERSION= - -## Specify the deployment_id -#OPENAI_API_DEPLOYMENT_ID= - -## Specify the OpenAI organization ID -#OPENAI_ORGANIZATION_ID= - ## Specify a file with aider model settings for unknown models #AIDER_MODEL_SETTINGS_FILE=.aider.model.settings.yml @@ -135,9 +142,15 @@ cog.outl("```") ## Add a model alias (can be used multiple times) #AIDER_ALIAS= +## Set the reasoning_effort API parameter (default: not set) +#AIDER_REASONING_EFFORT= + ## Verify the SSL cert when connecting to models (default: True) #AIDER_VERIFY_SSL=true +## Timeout in seconds for API calls (default: None) +#AIDER_TIMEOUT= + ## Specify what edit format the LLM should use (default depends on model) #AIDER_EDIT_FORMAT= @@ -159,11 +172,8 @@ cog.outl("```") ## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens. #AIDER_MAX_CHAT_HISTORY_TOKENS= -## Specify the .env file to load (default: .env in git root) -#AIDER_ENV_FILE=.env - ################# -# Cache Settings: +# Cache settings: ## Enable caching of prompts (default: False) #AIDER_CACHE_PROMPTS=false @@ -172,9 +182,9 @@ cog.outl("```") #AIDER_CACHE_KEEPALIVE_PINGS=false ################### -# Repomap Settings: +# Repomap settings: -## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024) +## Suggested number of tokens to use for repo map, use 0 to disable #AIDER_MAP_TOKENS= ## Control how often the repo map is refreshed. Options: auto, always, files, manual (default: auto) @@ -199,7 +209,7 @@ cog.outl("```") #AIDER_LLM_HISTORY_FILE= ################## -# Output Settings: +# Output settings: ## Use colors suitable for a dark terminal background (default: False) #AIDER_DARK_MODE=false @@ -240,14 +250,14 @@ cog.outl("```") ## Set the background color for the current item in the completion menu (default: terminal's default text color) #AIDER_COMPLETION_MENU_CURRENT_BG_COLOR= -## Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light) +## Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light, or a Pygments builtin style, see https://pygments.org/styles for available themes) #AIDER_CODE_THEME=default ## Show diffs when committing changes (default: False) #AIDER_SHOW_DIFFS=false ############### -# Git Settings: +# Git settings: ## Enable/disable looking for a git repo (default: True) #AIDER_GIT=true @@ -291,6 +301,9 @@ cog.outl("```") ## Skip the sanity check for the git repository (default: False) #AIDER_SKIP_SANITY_CHECK_REPO=false +## Enable/disable watching files for ai coding comments (default: False) +#AIDER_WATCH_FILES=false + ######################## # Fixing and committing: @@ -309,7 +322,7 @@ cog.outl("```") ## Enable/disable automatic testing after changes (default: False) #AIDER_AUTO_TEST=false -## Run tests and fix problems found +## Run tests, fix problems found and then exit #AIDER_TEST=false ############ @@ -324,20 +337,8 @@ cog.outl("```") ## Permanently disable analytics #AIDER_ANALYTICS_DISABLE=false -################# -# Other Settings: - -## specify a file to edit (can be used multiple times) -#AIDER_FILE= - -## specify a read-only file (can be used multiple times) -#AIDER_READ= - -## Use VI editing mode in the terminal (default: False) -#AIDER_VIM=false - -## Specify the language to use in the chat (default: None, uses system settings) -#AIDER_CHAT_LANGUAGE= +############ +# Upgrading: ## Check for updates and return status in the exit code #AIDER_JUST_CHECK_UPDATE=false @@ -354,26 +355,8 @@ cog.outl("```") ## Upgrade aider to the latest version from PyPI #AIDER_UPGRADE=false -## Apply the changes from the given file instead of running the chat (debug) -#AIDER_APPLY= - -## Apply clipboard contents as edits using the main model's editor format -#AIDER_APPLY_CLIPBOARD_EDITS=false - -## Always say yes to every confirmation -#AIDER_YES_ALWAYS= - -## Enable verbose output -#AIDER_VERBOSE=false - -## Print the repo map and exit (debug) -#AIDER_SHOW_REPO_MAP=false - -## Print the system prompts and exit (debug) -#AIDER_SHOW_PROMPTS=false - -## Do all startup activities then exit before accepting user input (debug) -#AIDER_EXIT=false +######## +# Modes: ## Specify a single message to send the LLM, process reply then exit (disables chat mode) #AIDER_MESSAGE= @@ -381,14 +364,71 @@ cog.outl("```") ## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode) #AIDER_MESSAGE_FILE= +## Run aider in your browser (default: False) +#AIDER_GUI=false + +## Enable automatic copy/paste of chat between aider and web UI (default: False) +#AIDER_COPY_PASTE=false + +## Apply the changes from the given file instead of running the chat (debug) +#AIDER_APPLY= + +## Apply clipboard contents as edits using the main model's editor format +#AIDER_APPLY_CLIPBOARD_EDITS=false + +## Do all startup activities then exit before accepting user input (debug) +#AIDER_EXIT=false + +## Print the repo map and exit (debug) +#AIDER_SHOW_REPO_MAP=false + +## Print the system prompts and exit (debug) +#AIDER_SHOW_PROMPTS=false + +################# +# Voice settings: + +## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg +#AIDER_VOICE_FORMAT=wav + +## Specify the language for voice using ISO 639-1 code (default: auto) +#AIDER_VOICE_LANGUAGE=en + +## Specify the input device name for voice recording +#AIDER_VOICE_INPUT_DEVICE= + +################# +# Other settings: + +## specify a file to edit (can be used multiple times) +#AIDER_FILE= + +## specify a read-only file (can be used multiple times) +#AIDER_READ= + +## Use VI editing mode in the terminal (default: False) +#AIDER_VIM=false + +## Specify the language to use in the chat (default: None, uses system settings) +#AIDER_CHAT_LANGUAGE= + +## Always say yes to every confirmation +#AIDER_YES_ALWAYS= + +## Enable verbose output +#AIDER_VERBOSE=false + ## 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 (default: False) -#AIDER_GUI=false +## Line endings to use when writing files (default: platform) +#AIDER_LINE_ENDINGS=platform + +## Specify the .env file to load (default: .env in git root) +#AIDER_ENV_FILE=.env ## Enable/disable suggesting shell commands (default: True) #AIDER_SUGGEST_SHELL_COMMANDS=true @@ -396,21 +436,13 @@ cog.outl("```") ## Enable/disable fancy input with history and completion (default: True) #AIDER_FANCY_INPUT=true +## Enable/disable multi-line input mode with Meta-Enter to submit (default: False) +#AIDER_MULTILINE=false + ## Enable/disable detection and offering to add URLs to chat (default: True) #AIDER_DETECT_URLS=true ## Specify which editor to use for the /editor command #AIDER_EDITOR= - -################# -# Voice Settings: - -## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg -#AIDER_VOICE_FORMAT=wav - -## Specify the language for voice using ISO 639-1 code (default: auto) -#AIDER_VOICE_LANGUAGE=en ``` - - diff --git a/aider/website/docs/config/editor.md b/aider/website/docs/config/editor.md index b09985c4e..aff3e376c 100644 --- a/aider/website/docs/config/editor.md +++ b/aider/website/docs/config/editor.md @@ -1,6 +1,6 @@ --- parent: Configuration -nav_order: 15 +nav_order: 100 description: How to configure a custom editor for aider's /editor command --- diff --git a/aider/website/docs/config/model-aliases.md b/aider/website/docs/config/model-aliases.md index a5e7b1260..471005c39 100644 --- a/aider/website/docs/config/model-aliases.md +++ b/aider/website/docs/config/model-aliases.md @@ -13,7 +13,7 @@ Model aliases allow you to create shorthand names for models you frequently use. You can define aliases when launching aider using the `--alias` option: ```bash -aider --alias "fast:gpt-3.5-turbo" --alias "smart:gpt-4" +aider --alias "fast:gpt-4o-mini" --alias "smart:o3-mini" ``` Multiple aliases can be defined by using the `--alias` option multiple times. Each alias definition should be in the format `alias:model-name`. @@ -24,8 +24,8 @@ You can also define aliases in your [`.aider.conf.yml` file](https://aider.chat/ ```yaml alias: - - "fast:gpt-3.5-turbo" - - "smart:gpt-4" + - "fast:gpt-4o-mini" + - "smart:o3-mini" - "hacker:claude-3-sonnet-20240229" ``` @@ -34,8 +34,8 @@ alias: Once defined, you can use the alias instead of the full model name: ```bash -aider --model fast # Uses gpt-3.5-turbo -aider --model smart # Uses gpt-4 +aider --model fast # Uses gpt-4o-mini +aider --model smart # Uses o3-mini ``` ## Built-in Aliases @@ -54,10 +54,12 @@ for alias, model in sorted(MODEL_ALIASES.items()): - `35turbo`: gpt-3.5-turbo - `4`: gpt-4-0613 - `4-turbo`: gpt-4-1106-preview -- `4o`: gpt-4o-2024-08-06 -- `deepseek`: deepseek/deepseek-coder +- `4o`: gpt-4o +- `deepseek`: deepseek/deepseek-chat +- `flash`: gemini/gemini-2.0-flash-exp - `haiku`: claude-3-5-haiku-20241022 - `opus`: claude-3-opus-20240229 +- `r1`: deepseek/deepseek-reasoner - `sonnet`: claude-3-5-sonnet-20241022 diff --git a/aider/website/docs/config/options.md b/aider/website/docs/config/options.md index abba8ff0f..af4abecaa 100644 --- a/aider/website/docs/config/options.md +++ b/aider/website/docs/config/options.md @@ -13,10 +13,7 @@ or review them below. - TOC {:toc} -## LLM keys -{: .no_toc } - -{% include special-keys.md %} +{% include keys.md %} ## Usage summary @@ -25,18 +22,20 @@ from aider.args import get_md_help cog.out(get_md_help()) ]]]--> ``` -usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model] - [--opus] [--sonnet] [--haiku] [--4] [--4o] [--mini] - [--4-turbo] [--35turbo] [--deepseek] [--o1-mini] - [--o1-preview] [--list-models] [--openai-api-base] +usage: aider [-h] [--model] [--opus] [--sonnet] [--haiku] [--4] + [--4o] [--mini] [--4-turbo] [--35turbo] [--deepseek] + [--o1-mini] [--o1-preview] [--openai-api-key] + [--anthropic-api-key] [--openai-api-base] [--openai-api-type] [--openai-api-version] [--openai-api-deployment-id] [--openai-organization-id] + [--set-env] [--api-key] [--list-models] [--model-settings-file] [--model-metadata-file] - [--alias] [--verify-ssl | --no-verify-ssl] + [--alias] [--reasoning-effort] + [--verify-ssl | --no-verify-ssl] [--timeout] [--edit-format] [--architect] [--weak-model] [--editor-model] [--editor-edit-format] [--show-model-warnings | --no-show-model-warnings] - [--max-chat-history-tokens] [--env-file] + [--max-chat-history-tokens] [--cache-prompts | --no-cache-prompts] [--cache-keepalive-pings] [--map-tokens] [--map-refresh] [--map-multiplier-no-files] @@ -59,23 +58,27 @@ usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model] [--attribute-commit-message-author | --no-attribute-commit-message-author] [--attribute-commit-message-committer | --no-attribute-commit-message-committer] [--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] + [--skip-sanity-check-repo] + [--watch-files | --no-watch-files] [--lint] + [--lint-cmd] [--auto-lint | --no-auto-lint] + [--test-cmd] [--auto-test | --no-auto-test] [--test] [--analytics | --no-analytics] [--analytics-log] - [--analytics-disable] [--file] [--read] [--vim] - [--chat-language] [--version] [--just-check-update] + [--analytics-disable] [--just-check-update] [--check-update | --no-check-update] [--show-release-notes | --no-show-release-notes] - [--install-main-branch] [--upgrade] [--apply] - [--apply-clipboard-edits] [--yes-always] [-v] - [--show-repo-map] [--show-prompts] [--exit] [--message] - [--message-file] [--load] [--encoding] [-c] + [--install-main-branch] [--upgrade] [--version] + [--message] [--message-file] [--gui | --no-gui | --browser | --no-browser] + [--copy-paste | --no-copy-paste] [--apply] + [--apply-clipboard-edits] [--exit] [--show-repo-map] + [--show-prompts] [--voice-format] [--voice-language] + [--voice-input-device] [--file] [--read] [--vim] + [--chat-language] [--yes-always] [-v] [--load] + [--encoding] [--line-endings] [-c] [--env-file] [--suggest-shell-commands | --no-suggest-shell-commands] [--fancy-input | --no-fancy-input] + [--multiline | --no-multiline] [--detect-urls | --no-detect-urls] [--editor] - [--voice-format] [--voice-language] ``` @@ -87,15 +90,7 @@ Aliases: - `-h` - `--help` -## Main: - -### `--openai-api-key OPENAI_API_KEY` -Specify the OpenAI API key -Environment variable: `OPENAI_API_KEY` - -### `--anthropic-api-key ANTHROPIC_API_KEY` -Specify the Anthropic API key -Environment variable: `ANTHROPIC_API_KEY` +## Main model: ### `--model MODEL` Specify the model to use for the main chat @@ -121,7 +116,7 @@ Aliases: - `-4` ### `--4o` -Use gpt-4o-2024-08-06 model for the main chat +Use gpt-4o model for the main chat Environment variable: `AIDER_4O` ### `--mini` @@ -142,7 +137,7 @@ Aliases: - `-3` ### `--deepseek` -Use deepseek/deepseek-coder model for the main chat +Use deepseek/deepseek-chat model for the main chat Environment variable: `AIDER_DEEPSEEK` ### `--o1-mini` @@ -153,7 +148,47 @@ Environment variable: `AIDER_O1_MINI` Use o1-preview model for the main chat Environment variable: `AIDER_O1_PREVIEW` -## Model Settings: +## API Keys and settings: + +### `--openai-api-key VALUE` +Specify the OpenAI API key +Environment variable: `AIDER_OPENAI_API_KEY` + +### `--anthropic-api-key VALUE` +Specify the Anthropic API key +Environment variable: `AIDER_ANTHROPIC_API_KEY` + +### `--openai-api-base VALUE` +Specify the api base url +Environment variable: `AIDER_OPENAI_API_BASE` + +### `--openai-api-type VALUE` +(deprecated, use --set-env OPENAI_API_TYPE=) +Environment variable: `AIDER_OPENAI_API_TYPE` + +### `--openai-api-version VALUE` +(deprecated, use --set-env OPENAI_API_VERSION=) +Environment variable: `AIDER_OPENAI_API_VERSION` + +### `--openai-api-deployment-id VALUE` +(deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=) +Environment variable: `AIDER_OPENAI_API_DEPLOYMENT_ID` + +### `--openai-organization-id VALUE` +(deprecated, use --set-env OPENAI_ORGANIZATION=) +Environment variable: `AIDER_OPENAI_ORGANIZATION_ID` + +### `--set-env ENV_VAR_NAME=value` +Set an environment variable (to control API settings, can be used multiple times) +Default: [] +Environment variable: `AIDER_SET_ENV` + +### `--api-key PROVIDER=KEY` +Set an API key for a provider (eg: --api-key provider= sets PROVIDER_API_KEY=) +Default: [] +Environment variable: `AIDER_API_KEY` + +## Model settings: ### `--list-models MODEL` List known models which match the (partial) MODEL name @@ -162,26 +197,6 @@ Aliases: - `--list-models MODEL` - `--models MODEL` -### `--openai-api-base OPENAI_API_BASE` -Specify the api base url -Environment variable: `OPENAI_API_BASE` - -### `--openai-api-type OPENAI_API_TYPE` -Specify the api_type -Environment variable: `OPENAI_API_TYPE` - -### `--openai-api-version OPENAI_API_VERSION` -Specify the api_version -Environment variable: `OPENAI_API_VERSION` - -### `--openai-api-deployment-id OPENAI_API_DEPLOYMENT_ID` -Specify the deployment_id -Environment variable: `OPENAI_API_DEPLOYMENT_ID` - -### `--openai-organization-id OPENAI_ORGANIZATION_ID` -Specify the OpenAI organization ID -Environment variable: `OPENAI_ORGANIZATION_ID` - ### `--model-settings-file MODEL_SETTINGS_FILE` Specify a file with aider model settings for unknown models Default: .aider.model.settings.yml @@ -196,6 +211,10 @@ Environment variable: `AIDER_MODEL_METADATA_FILE` Add a model alias (can be used multiple times) Environment variable: `AIDER_ALIAS` +### `--reasoning-effort VALUE` +Set the reasoning_effort API parameter (default: not set) +Environment variable: `AIDER_REASONING_EFFORT` + ### `--verify-ssl` Verify the SSL cert when connecting to models (default: True) Default: True @@ -204,6 +223,10 @@ Aliases: - `--verify-ssl` - `--no-verify-ssl` +### `--timeout VALUE` +Timeout in seconds for API calls (default: None) +Environment variable: `AIDER_TIMEOUT` + ### `--edit-format EDIT_FORMAT` Specify what edit format the LLM should use (default depends on model) Environment variable: `AIDER_EDIT_FORMAT` @@ -239,12 +262,7 @@ Aliases: Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens. Environment variable: `AIDER_MAX_CHAT_HISTORY_TOKENS` -### `--env-file ENV_FILE` -Specify the .env file to load (default: .env in git root) -Default: .env -Environment variable: `AIDER_ENV_FILE` - -## Cache Settings: +## Cache settings: ### `--cache-prompts` Enable caching of prompts (default: False) @@ -259,10 +277,10 @@ Number of times to ping at 5min intervals to keep prompt cache warm (default: 0) Default: 0 Environment variable: `AIDER_CACHE_KEEPALIVE_PINGS` -## Repomap Settings: +## Repomap settings: ### `--map-tokens VALUE` -Suggested number of tokens to use for repo map, use 0 to disable (default: 1024) +Suggested number of tokens to use for repo map, use 0 to disable Environment variable: `AIDER_MAP_TOKENS` ### `--map-refresh VALUE` @@ -299,7 +317,7 @@ Aliases: Log the conversation with the LLM to this file (for example, .aider.llm.history) Environment variable: `AIDER_LLM_HISTORY_FILE` -## Output Settings: +## Output settings: ### `--dark-mode` Use colors suitable for a dark terminal background (default: False) @@ -368,7 +386,7 @@ Set the background color for the current item in the completion menu (default: t Environment variable: `AIDER_COMPLETION_MENU_CURRENT_BG_COLOR` ### `--code-theme VALUE` -Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light) +Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light, or a Pygments builtin style, see https://pygments.org/styles for available themes) Default: default Environment variable: `AIDER_CODE_THEME` @@ -377,7 +395,7 @@ Show diffs when committing changes (default: False) Default: False Environment variable: `AIDER_SHOW_DIFFS` -## Git Settings: +## Git settings: ### `--git` Enable/disable looking for a git repo (default: True) @@ -475,6 +493,14 @@ Skip the sanity check for the git repository (default: False) Default: False Environment variable: `AIDER_SKIP_SANITY_CHECK_REPO` +### `--watch-files` +Enable/disable watching files for ai coding comments (default: False) +Default: False +Environment variable: `AIDER_WATCH_FILES` +Aliases: + - `--watch-files` + - `--no-watch-files` + ## Fixing and committing: ### `--lint` @@ -509,7 +535,7 @@ Aliases: - `--no-auto-test` ### `--test` -Run tests and fix problems found +Run tests, fix problems found and then exit Default: False Environment variable: `AIDER_TEST` @@ -531,27 +557,7 @@ Permanently disable analytics Default: False Environment variable: `AIDER_ANALYTICS_DISABLE` -## Other Settings: - -### `--file FILE` -specify a file to edit (can be used multiple times) -Environment variable: `AIDER_FILE` - -### `--read FILE` -specify a read-only file (can be used multiple times) -Environment variable: `AIDER_READ` - -### `--vim` -Use VI editing mode in the terminal (default: False) -Default: False -Environment variable: `AIDER_VIM` - -### `--chat-language CHAT_LANGUAGE` -Specify the language to use in the chat (default: None, uses system settings) -Environment variable: `AIDER_CHAT_LANGUAGE` - -### `--version` -Show the version number and exit +## Upgrading: ### `--just-check-update` Check for updates and return status in the exit code @@ -586,41 +592,10 @@ Aliases: - `--upgrade` - `--update` -### `--apply FILE` -Apply the changes from the given file instead of running the chat (debug) -Environment variable: `AIDER_APPLY` +### `--version` +Show the version number and exit -### `--apply-clipboard-edits` -Apply clipboard contents as edits using the main model's editor format -Default: False -Environment variable: `AIDER_APPLY_CLIPBOARD_EDITS` - -### `--yes-always` -Always say yes to every confirmation -Environment variable: `AIDER_YES_ALWAYS` - -### `--verbose` -Enable verbose output -Default: False -Environment variable: `AIDER_VERBOSE` -Aliases: - - `-v` - - `--verbose` - -### `--show-repo-map` -Print the repo map and exit (debug) -Default: False -Environment variable: `AIDER_SHOW_REPO_MAP` - -### `--show-prompts` -Print the system prompts and exit (debug) -Default: False -Environment variable: `AIDER_SHOW_PROMPTS` - -### `--exit` -Do all startup activities then exit before accepting user input (debug) -Default: False -Environment variable: `AIDER_EXIT` +## Modes: ### `--message COMMAND` Specify a single message to send the LLM, process reply then exit (disables chat mode) @@ -637,21 +612,6 @@ 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 -Environment variable: `AIDER_ENCODING` - -### `--config CONFIG_FILE` -Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory) -Aliases: - - `-c CONFIG_FILE` - - `--config CONFIG_FILE` - ### `--gui` Run aider in your browser (default: False) Default: False @@ -662,6 +622,110 @@ Aliases: - `--browser` - `--no-browser` +### `--copy-paste` +Enable automatic copy/paste of chat between aider and web UI (default: False) +Default: False +Environment variable: `AIDER_COPY_PASTE` +Aliases: + - `--copy-paste` + - `--no-copy-paste` + +### `--apply FILE` +Apply the changes from the given file instead of running the chat (debug) +Environment variable: `AIDER_APPLY` + +### `--apply-clipboard-edits` +Apply clipboard contents as edits using the main model's editor format +Default: False +Environment variable: `AIDER_APPLY_CLIPBOARD_EDITS` + +### `--exit` +Do all startup activities then exit before accepting user input (debug) +Default: False +Environment variable: `AIDER_EXIT` + +### `--show-repo-map` +Print the repo map and exit (debug) +Default: False +Environment variable: `AIDER_SHOW_REPO_MAP` + +### `--show-prompts` +Print the system prompts and exit (debug) +Default: False +Environment variable: `AIDER_SHOW_PROMPTS` + +## Voice settings: + +### `--voice-format VOICE_FORMAT` +Audio format for voice recording (default: wav). webm and mp3 require ffmpeg +Default: wav +Environment variable: `AIDER_VOICE_FORMAT` + +### `--voice-language VOICE_LANGUAGE` +Specify the language for voice using ISO 639-1 code (default: auto) +Default: en +Environment variable: `AIDER_VOICE_LANGUAGE` + +### `--voice-input-device VOICE_INPUT_DEVICE` +Specify the input device name for voice recording +Environment variable: `AIDER_VOICE_INPUT_DEVICE` + +## Other settings: + +### `--file FILE` +specify a file to edit (can be used multiple times) +Environment variable: `AIDER_FILE` + +### `--read FILE` +specify a read-only file (can be used multiple times) +Environment variable: `AIDER_READ` + +### `--vim` +Use VI editing mode in the terminal (default: False) +Default: False +Environment variable: `AIDER_VIM` + +### `--chat-language CHAT_LANGUAGE` +Specify the language to use in the chat (default: None, uses system settings) +Environment variable: `AIDER_CHAT_LANGUAGE` + +### `--yes-always` +Always say yes to every confirmation +Environment variable: `AIDER_YES_ALWAYS` + +### `--verbose` +Enable verbose output +Default: False +Environment variable: `AIDER_VERBOSE` +Aliases: + - `-v` + - `--verbose` + +### `--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 +Environment variable: `AIDER_ENCODING` + +### `--line-endings VALUE` +Line endings to use when writing files (default: platform) +Default: platform +Environment variable: `AIDER_LINE_ENDINGS` + +### `--config CONFIG_FILE` +Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory) +Aliases: + - `-c CONFIG_FILE` + - `--config CONFIG_FILE` + +### `--env-file ENV_FILE` +Specify the .env file to load (default: .env in git root) +Default: .env +Environment variable: `AIDER_ENV_FILE` + ### `--suggest-shell-commands` Enable/disable suggesting shell commands (default: True) Default: True @@ -678,6 +742,14 @@ Aliases: - `--fancy-input` - `--no-fancy-input` +### `--multiline` +Enable/disable multi-line input mode with Meta-Enter to submit (default: False) +Default: False +Environment variable: `AIDER_MULTILINE` +Aliases: + - `--multiline` + - `--no-multiline` + ### `--detect-urls` Enable/disable detection and offering to add URLs to chat (default: True) Default: True @@ -689,16 +761,4 @@ Aliases: ### `--editor VALUE` Specify which editor to use for the /editor command Environment variable: `AIDER_EDITOR` - -## Voice Settings: - -### `--voice-format VOICE_FORMAT` -Audio format for voice recording (default: wav). webm and mp3 require ffmpeg -Default: wav -Environment variable: `AIDER_VOICE_FORMAT` - -### `--voice-language VOICE_LANGUAGE` -Specify the language for voice using ISO 639-1 code (default: auto) -Default: en -Environment variable: `AIDER_VOICE_LANGUAGE` diff --git a/aider/website/docs/config/reasoning.md b/aider/website/docs/config/reasoning.md new file mode 100644 index 000000000..f34621d88 --- /dev/null +++ b/aider/website/docs/config/reasoning.md @@ -0,0 +1,83 @@ +--- +parent: Configuration +nav_order: 110 +description: How to configure reasoning model settings from secondary providers. +--- + +# Reasoning models + +Many +"reasoning" models have restrictions on how they can be used. +They sometimes prohibit streaming, use of temperature and/or the system prompt. +Aider is configured to work properly with these models +when served through major provider APIs. + +You may need to [configure model settings](/docs/config/adv-model-settings.html) +if you are using them through another provider +and see errors related to temperature or system prompt. + +Include settings for your new provider in `.aider.model.setting.yml` file +at the root of your project or in your home directory. + +## Temperature, streaming and system prompt + +You should find one of the existing model setting configuration entries +for the model you are interested in, say o3-mini: + +```yaml +- name: o3-mini + edit_format: diff + weak_model_name: gpt-4o-mini + use_repo_map: true + use_temperature: false # <--- + editor_model_name: gpt-4o + editor_edit_format: editor-diff +``` + +Pay attention to these settings, which must be set to `false` +for certain reasoning models: + +- `use_temperature` +- `streaming` +- `use_system_prompt` + +Here's an example of +the settings to use o3-mini via Azure. +Note that aider already has these settings pre-configured, but they +serve as a good example of how to adapt the main model +settings for a different provider. + +```yaml +- name: azure/o3-mini + edit_format: diff + weak_model_name: azure/gpt-4o-mini + use_repo_map: true + use_temperature: false # <--- + editor_model_name: azure/gpt-4o + editor_edit_format: editor-diff +``` + +## Thinking tokens + +There is also a `remove_reasoning` setting, which takes the name of a tag. +This is used to remove everything inside that XML tag pair. + +For example when using DeepSeek R1 from Fireworks, the reasoning comes back inside +`...` tags, so aider's settings +include `remove_reasoning: think` to remove that part of the response. + +Aider will still *display* think reasoning output, it just won't use it +to find file editing instructions, etc. + +```yaml +- name: fireworks_ai/accounts/fireworks/models/deepseek-r1 + edit_format: diff + weak_model_name: fireworks_ai/accounts/fireworks/models/deepseek-v3 + use_repo_map: true + extra_params: + max_tokens: 160000 + use_temperature: false + editor_model_name: fireworks_ai/accounts/fireworks/models/deepseek-v3 + editor_edit_format: editor-diff + remove_reasoning: think # <--- +``` diff --git a/aider/website/docs/faq.md b/aider/website/docs/faq.md index 4921f4326..d351538af 100644 --- a/aider/website/docs/faq.md +++ b/aider/website/docs/faq.md @@ -141,6 +141,18 @@ When starting a fresh aider session, you can include recent git history in the c Remember, the chat history already includes recent changes made during the current session, so this tip is most useful when starting a new aider session and you want to provide context about recent work. +You can also use aider to review PR branches: + +``` +/run git diff one-branch..another-branch + +... + +Add 6.9k tokens of command output to the chat? (Y)es/(N)o [Yes]: Yes + +/ask Are there any problems with the way this change works with the FooBar class? +``` + {: .tip } The `/git` command will not work for this purpose, as its output is not included in the chat. @@ -209,6 +221,49 @@ all the raw information being sent to/from the LLM in the conversation. You can also refer to the [instructions for installing a development version of aider](https://aider.chat/docs/install/optional.html#install-the-development-version-of-aider). +## What LLMs do you use to build aider? + +Aider writes a lot of its own code, usually about 70% of the new code in each +release. +People often ask which LLMs I use with aider, when writing aider. +Below is a table showing the models I have used recently, +extracted from the +[public log](https://github.com/aider-ai/aider/blob/main/aider/website/assets/sample-analytics.jsonl) +of my +[aider analytics](https://aider.chat/docs/more/analytics.html). + + + + + + + + + + + + + + +
Model NameTotal TokensPercent
claude-3-5-sonnet-20241022812,75751.3%
fireworks_ai/accounts/fireworks/models/deepseek-v3286,01918.1%
o3-mini257,95816.3%
deepseek/deepseek-chat97,7456.2%
fireworks_ai/accounts/fireworks/models/deepseek-r165,2514.1%
fireworks_ai/REDACTED41,0132.6%
deepseek/deepseek-reasoner20,2231.3%
gemini/REDACTED1,8590.1%
ollama_chat/REDACTED3090.0%
+ +{: .note :} +Some models show as REDACTED, because they are new or unpopular models. +Aider's analytics only records the names of "well known" LLMs. + ## How are the "aider wrote xx% of code" stats computed? @@ -220,6 +275,31 @@ by doing something like `git blame` on the repo, and counting up who wrote all the new lines of code in each release. Only lines in source code files are counted, not documentation or prompt files. +## Why does aider sometimes stop highlighting code in its replies? + +Aider displays the markdown responses that are coming back from the LLM. +Usually, the LLM will reply with code in a markdown "code block" with +triple backtick fences, like this: + +```` +Here's some code: + +``` +print("hello") +``` +```` + +But if you've added files to the chat that contain triple backticks, +aider needs to tell the LLM to use a different set of fences. +Otherwise, the LLM can't safely include your code's triple backticks +inside the code blocks that it returns with edits. +Aider will use fences like `...` in this case. + +A side effect of this is that the code that aider outputs may no +longer be properly highlighted. +You will most often notice this if you add markdown files +to you chats that contain code blocks. + ## Why is the LLM speaking to me in an unexpected language? Aider goes to some effort to prompt the model to use the language that is configured diff --git a/aider/website/docs/install.md b/aider/website/docs/install.md index df5358c89..eb18470e6 100644 --- a/aider/website/docs/install.md +++ b/aider/website/docs/install.md @@ -5,41 +5,118 @@ nav_order: 20 description: How to install and get started pair programming with aider. --- -# Quick start +# Installation +{: .no_toc } + + +## Get started quickly with aider-install {% include get-started.md %} -Or see the -[full installation instructions](/docs/install/install.html) -for more details, -or the -[usage instructions](https://aider.chat/docs/usage.html) to start coding with aider. +This will install aider in its own separate python environment. +If needed, +aider-install will also install a separate version of python 3.12 to use with aider. + +Once aider is installed, +there are also some [optional install steps](/docs/install/optional.html). + +See the [usage instructions](https://aider.chat/docs/usage.html) to start coding with aider. + +## One-liners + +These one-liners will install aider, along with python 3.12 if needed. +They are based on the +[uv installers](https://docs.astral.sh/uv/getting-started/installation/). + +#### Windows + +```powershell +powershell -ExecutionPolicy ByPass -c "irm https://aider.chat/install.ps1 | iex" +``` + +#### Mac & Linux + +Use curl to download the script and execute it with sh: + +```bash +curl -LsSf https://aider.chat/install.sh | sh +``` + +If your system doesn't have curl, you can use wget: + +```bash +wget -qO- https://aider.chat/install.sh | sh +``` + + +## Install with uv + +You can install aider with uv: + +```bash +python -m pip install uv # If you need to install uv +uv tool install --force --python python3.12 aider-chat@latest +``` + +This will install uv using your existing python version 3.8-3.13, +and use it to install aider. +If needed, +uv will automatically install a separate python 3.12 to use with aider. + +Also see the +[docs on other methods for installing uv itself](https://docs.astral.sh/uv/getting-started/installation/). + +## Install with pipx + +You can install aider with pipx: + +```bash +python -m pip install pipx # If you need to install pipx +pipx install aider-chat +``` + +You can use pipx to install aider with python versions 3.9-3.12. + +Also see the +[docs on other methods for installing pipx itself](https://pipx.pypa.io/stable/installation/). + +## Other install methods + +You can install aider with the methods described below, but one of the above +methods is usually safer. + +#### Install with pip + +If you install with pip, you should consider +using a +[virtual environment](https://docs.python.org/3/library/venv.html) +to keep aider's dependencies separated. + + +You can use pip to install aider with python versions 3.9-3.12. + +```bash +# Install aider +python -m pip install -U --upgrade-strategy only-if-needed aider-chat + +# To work with GPT-4o: +aider --4o --openai-api-key sk-xxx... + +# To work with Claude 3.5 Sonnet: +aider --sonnet --anthropic-api-key sk-xxx... +``` {% include python-m-aider.md %} -
- -
+#### Installing with package managers - +It's best to install aider using one of methods +recommended above. +While aider is available in a number of system package managers, +they often install aider with incorrect dependencies. +## Next steps... +There are some [optional install steps](/docs/install/optional.html) you could consider. +See the [usage instructions](https://aider.chat/docs/usage.html) to start coding with aider. diff --git a/aider/website/docs/install/codespaces.md b/aider/website/docs/install/codespaces.md index fd0146bcc..e99175c85 100644 --- a/aider/website/docs/install/codespaces.md +++ b/aider/website/docs/install/codespaces.md @@ -8,9 +8,9 @@ nav_order: 900 You can use aider in GitHub Codespaces via the built-in Terminal pane. See below for an example, -but you can see the +but you can just follow the [main install instructions](/docs/install.html) -for all the details. +inside your codespace terminal.
diff --git a/aider/website/docs/install/install.md b/aider/website/docs/install/install.md deleted file mode 100644 index f2dad3648..000000000 --- a/aider/website/docs/install/install.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -parent: Installation -nav_order: 10 ---- - -# Installing aider -{: .no_toc } - -- TOC -{:toc} - -## Python version - -Aider currently works with python 3.9-3.12. - -## Install git - -Make sure you have git installed. -Here are -[instructions for installing git in various environments](https://github.com/git-guides/install-git). - -## Get your API key - -To work with OpenAI's models like GPT-4o or GPT-3.5 you need a paid -[OpenAI API key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-secret-api-key). -Note that this is different than being a "ChatGPT Plus" subscriber. - -To work with Anthropic's models like Claude 3.5 Sonnet you need a paid -[Anthropic API key](https://docs.anthropic.com/claude/reference/getting-started-with-the-api). - - -{% include venv-pipx.md %} - -## Mac/Linux install - -``` -# Install aider -python -m pip install -U --upgrade-strategy only-if-needed aider-chat - -# To work with GPT-4o: -$ aider --4o --openai-api-key sk-xxx... - -# To work with Claude 3.5 Sonnet: -$ aider --sonnet --anthropic-api-key sk-xxx... -``` - -## Windows install - -``` -# Install aider -python -m pip install -U --upgrade-strategy only-if-needed aider-chat - -# To work with GPT-4o: -$ aider --4o --openai-api-key sk-xxx... - -# To work with Claude 3.5 Sonnet: -$ aider --sonnet --anthropic-api-key sk-xxx... -``` - -{% include python-m-aider.md %} - -## Working with other LLMs - -{% include works-best.md %} - -## You are done! - -There are some [optional install steps](/docs/install/optional.html) you could consider. -See the [usage instructions](https://aider.chat/docs/usage.html) to start coding with aider. - diff --git a/aider/website/docs/install/optional.md b/aider/website/docs/install/optional.md index 2bc62d201..818f9f2c3 100644 --- a/aider/website/docs/install/optional.md +++ b/aider/website/docs/install/optional.md @@ -11,10 +11,29 @@ The steps below are completely optional. - TOC {:toc} +## Install git -## Store your api keys +Aider works best if you have git installed. +Here are +[instructions for installing git in various environments](https://github.com/git-guides/install-git). -You can [store your api keys in a .env file](/docs/config/dotenv.html) +## Get your API key + +To work with OpenAI's models like GPT-4o or o1-preview you need a paid +[OpenAI API key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-secret-api-key). +Note that this is different than being a "ChatGPT Plus" subscriber. + +To work with Anthropic's models like Claude 3.5 Sonnet you need a paid +[Anthropic API key](https://docs.anthropic.com/claude/reference/getting-started-with-the-api). + + +### Working with other LLMs + +{% include works-best.md %} + +### Store your api keys + +You can [store your api keys in configuration or env files](/docs/config/api-keys.html) and they will be loaded automatically whenever you run aider. ## Enable Playwright @@ -53,14 +72,19 @@ Installing PortAudio is completely optional, but can usually be accomplished lik - For Windows, there is no need to install PortAudio. - For Mac, do `brew install portaudio` - For Linux, do `sudo apt-get install libportaudio2` + - Some linux environments may also need `sudo apt install libasound2-plugins` -## Add aider to your editor +## Add aider to your IDE/editor -Other projects have integrated aider into some IDE/editors. -It's not clear if they are tracking the latest +You can use +[aider's `--watch-files` mode](https://aider.chat/docs/usage/watch.html) +to integrate with any IDE or editor. + +There are a number of 3rd party aider plugins for various IDE/editors. +It's not clear how well they are tracking the latest versions of aider, so it may be best to just run the latest -aider in a terminal alongside your editor. +aider in a terminal alongside your editor and use `--watch-files`. ### NeoVim @@ -70,29 +94,22 @@ aider in a terminal alongside your editor. ### VS Code -joshuavial also confirmed that aider works inside a VS Code terminal window. -Aider detects if it is running inside VSCode and turns off pretty/color output, -since the VSCode terminal doesn't seem to support it well. +You can run aider inside a VS Code terminal window. +There are a number of 3rd party +[aider plugins for VSCode](https://marketplace.visualstudio.com/search?term=aider%20-kodu&target=VSCode&category=All%20categories&sortBy=Relevance). ### Other editors If you are interested in creating an aider plugin for your favorite editor, -please let me know by opening a +please let us know by opening a [GitHub issue](https://github.com/Aider-AI/aider/issues). ## Install the development version of aider If you want the very latest development version of aider -you can install directly from GitHub: +you can install it like this: ``` -python -m pip install --upgrade git+https://github.com/Aider-AI/aider.git +aider --install-main-branch ``` - -If you've git cloned the aider repository already, you can install "live" from your local copy. This is mostly useful if you are developing aider and want your current modifications to take effect immediately. - -``` -python -m pip install -e . -``` - diff --git a/aider/website/docs/install/pipx.md b/aider/website/docs/install/pipx.md deleted file mode 100644 index 85cd8abec..000000000 --- a/aider/website/docs/install/pipx.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -parent: Installation -nav_order: 100 ---- - -# Install with pipx - -If you are using aider to work on a python project, sometimes your project will require -specific versions of python packages which conflict with the versions that aider -requires. -If this happens, the `python -m pip install` command may return errors like these: - -``` -aider-chat 0.23.0 requires somepackage==X.Y.Z, but you have somepackage U.W.V which is incompatible. -``` - -You can avoid this problem by installing aider using `pipx`, -which will install it globally on your system -within its own python environment. -This way you can use aider to work on any python project, -even if that project has conflicting dependencies. - -Install [pipx](https://pipx.pypa.io/stable/) then just do: - -``` -pipx install aider-chat -``` - - -## pipx on replit - -{% include replit-pipx.md %} - diff --git a/aider/website/docs/install/replit.md b/aider/website/docs/install/replit.md new file mode 100644 index 000000000..cb277a86d --- /dev/null +++ b/aider/website/docs/install/replit.md @@ -0,0 +1,8 @@ +--- +parent: Installation +nav_order: 900 +--- + +### Replit + +{% include replit-pipx.md %} diff --git a/aider/website/docs/languages.md b/aider/website/docs/languages.md index 417850ff1..09eb1b4e0 100644 --- a/aider/website/docs/languages.md +++ b/aider/website/docs/languages.md @@ -62,7 +62,6 @@ cog.out(get_supported_languages_md()) | cpp | .cc | ✓ | ✓ | | cpp | .cpp | ✓ | ✓ | | css | .css | | ✓ | -| dart | .dart | ✓ | ✓ | | dockerfile | .dockerfile | | ✓ | | dot | .dot | | ✓ | | elisp | .el | ✓ | ✓ | @@ -74,7 +73,8 @@ cog.out(get_supported_languages_md()) | gomod | .gomod | | ✓ | | hack | .hack | | ✓ | | haskell | .hs | | ✓ | -| hcl | .hcl | | ✓ | +| hcl | .hcl | ✓ | ✓ | +| hcl | .tf | ✓ | ✓ | | html | .html | | ✓ | | java | .java | ✓ | ✓ | | javascript | .js | ✓ | ✓ | @@ -82,7 +82,7 @@ cog.out(get_supported_languages_md()) | jsdoc | .jsdoc | | ✓ | | json | .json | | ✓ | | julia | .jl | | ✓ | -| kotlin | .kt | | ✓ | +| kotlin | .kt | ✓ | ✓ | | lua | .lua | | ✓ | | make | .mk | | ✓ | | objc | .m | | ✓ | diff --git a/aider/website/docs/leaderboards/by-release-date.md b/aider/website/docs/leaderboards/by-release-date.md new file mode 100644 index 000000000..78cac1ae6 --- /dev/null +++ b/aider/website/docs/leaderboards/by-release-date.md @@ -0,0 +1,10 @@ +--- +title: Scores by release date +parent: Aider LLM Leaderboards +nav_order: 200 +--- + +## LLM code editing skill by model release date + +[![connecting to many LLMs](/assets/models-over-time.svg)](https://aider.chat/assets/models-over-time.svg) + diff --git a/aider/website/docs/leaderboards/contrib.md b/aider/website/docs/leaderboards/contrib.md new file mode 100644 index 000000000..02cc688a7 --- /dev/null +++ b/aider/website/docs/leaderboards/contrib.md @@ -0,0 +1,14 @@ +--- +parent: Aider LLM Leaderboards +nav_order: 900 +--- + +# Contributing results + +Contributions of benchmark results are welcome! +See the +[benchmark README](https://github.com/Aider-AI/aider/blob/main/benchmark/README.md) +for information on running aider's code editing benchmarks. +Submit results by opening a PR with edits to the +[benchmark results data files](https://github.com/Aider-AI/aider/blob/main/aider/website/_data/). + diff --git a/aider/website/docs/leaderboards/edit.md b/aider/website/docs/leaderboards/edit.md new file mode 100644 index 000000000..01a5dc57a --- /dev/null +++ b/aider/website/docs/leaderboards/edit.md @@ -0,0 +1,133 @@ +--- +parent: Aider LLM Leaderboards +highlight_image: /assets/leaderboard.jpg +nav_order: 50 +description: Quantitative benchmark of basic LLM code editing skill. +--- + +# Code editing leaderboard + + +{: .note :} +This old +[aider code editing leaderboard](edit.html) +has been replaced by the +new, much more challenging +[polyglot leaderboard](/docs/leaderboards/). + +[Aider's code editing benchmark](/docs/benchmarks.html#the-benchmark) asks the LLM to edit python source files to complete 133 small coding exercises +from Exercism. +This measures the LLM's coding ability, and whether it can +write new code that integrates into existing code. +The model also has to successfully apply all its changes to the source file without human intervention. + + + + + + + + + + + + + + + {% assign edit_sorted = site.data.edit_leaderboard | sort: 'pass_rate_2' | reverse %} + {% for row in edit_sorted %} + + + + + + + + {% endfor %} + +
ModelPercent completed correctlyPercent using correct edit formatCommandEdit format
{{ row.model }}{{ row.pass_rate_2 }}%{{ row.percent_cases_well_formed }}%{{ row.command }}{{ row.edit_format }}
+ + + + + + + + +## Notes on benchmarking results + +The key benchmarking results are: + +- **Percent completed correctly** - Measures what percentage of the coding tasks that the LLM completed successfully. To complete a task, the LLM must solve the programming assignment *and* edit the code to implement that solution. +- **Percent using correct edit format** - Measures the percent of coding tasks where the LLM complied with the edit format specified in the system prompt. If the LLM makes edit mistakes, aider will give it feedback and ask for a fixed copy of the edit. The best models can reliably conform to the edit format, without making errors. + + +## Notes on the edit format + +Aider uses different "edit formats" to collect code edits from different LLMs. +The "whole" format is the easiest for an LLM to use, but it uses a lot of tokens +and may limit how large a file can be edited. +Models which can use one of the diff formats are much more efficient, +using far fewer tokens. +Models that use a diff-like format are able to +edit larger files with less cost and without hitting token limits. + +Aider is configured to use the best edit format for the popular OpenAI and Anthropic models +and the [other models recommended on the LLM page](/docs/llms.html). +For lesser known models aider will default to using the "whole" editing format +since it is the easiest format for an LLM to use. + +## Contributing benchmark results + +Contributions of benchmark results are welcome! +See the +[benchmark README](https://github.com/Aider-AI/aider/blob/main/benchmark/README.md) +for information on running aider's code editing benchmarks. +Submit results by opening a PR with edits to the +[benchmark results data files](https://github.com/Aider-AI/aider/blob/main/aider/website/_data/). + + + diff --git a/aider/website/docs/leaderboards/index.md b/aider/website/docs/leaderboards/index.md index 6cf043378..e83088866 100644 --- a/aider/website/docs/leaderboards/index.md +++ b/aider/website/docs/leaderboards/index.md @@ -2,32 +2,36 @@ highlight_image: /assets/leaderboard.jpg nav_order: 950 description: Quantitative benchmarks of LLM code editing skill. +has_children: true --- # Aider LLM Leaderboards -{: .no_toc } Aider works best with LLMs which are good at *editing* code, not just good at writing code. -To evaluate an LLM's editing skill, aider uses a pair of benchmarks that +To evaluate an LLM's editing skill, aider uses benchmarks that assess a model's ability to consistently follow the system prompt to successfully edit code. -The leaderboards below report the results from a number of popular LLMs. +The leaderboards report the results from a number of popular LLMs. While [aider can connect to almost any LLM](/docs/llms.html), it works best with models that score well on the benchmarks. -See the following sections for benchmark -results and additional information: -- TOC -{:toc} -## Code editing leaderboard +## Polyglot leaderboard -[Aider's code editing benchmark](/docs/benchmarks.html#the-benchmark) asks the LLM to edit python source files to complete 133 small coding exercises +[Aider's polyglot benchmark](https://aider.chat/2024/12/21/polyglot.html#the-polyglot-benchmark) +asks the LLM to edit source files to complete 225 coding exercises from Exercism. -This measures the LLM's coding ability, and whether it can +It contains exercises in many popular programming languages: +C++, Go, Java, JavaScript, Python and Rust. +The 225 exercises were purposely selected to be the *hardest* +that Exercism offered in those languages, to provide +a strong coding challenge to LLMs. + +This benchmark measures the LLM's coding ability in popular languages, +and whether it can write new code that integrates into existing code. The model also has to successfully apply all its changes to the source file without human intervention. @@ -41,10 +45,11 @@ The model also has to successfully apply all its changes to the source file with Percent using correct edit format Command Edit format + Total Cost - {% assign edit_sorted = site.data.edit_leaderboard | sort: 'pass_rate_2' | reverse %} + {% assign edit_sorted = site.data.polyglot_leaderboard | sort: 'pass_rate_2' | reverse %} {% for row in edit_sorted %} {{ row.model }} @@ -52,15 +57,22 @@ The model also has to successfully apply all its changes to the source file with {{ row.percent_cases_well_formed }}% {{ row.command }} {{ row.edit_format }} + {% if row.total_cost == 0 %}?{% else %}${{ row.total_cost | times: 1.0 | round: 2 }}{% endif %} {% endfor %} +### Aider polyglot benchmark results + + -## Code refactoring leaderboard -[Aider's refactoring benchmark](https://github.com/Aider-AI/refactor-benchmark) asks the LLM to refactor 89 large methods from large python classes. This is a more challenging benchmark, which tests the model's ability to output long chunks of code without skipping sections or making mistakes. It was developed to provoke and measure [GPT-4 Turbo's "lazy coding" habit](/2023/12/21/unified-diffs.html). - -The refactoring benchmark requires a large context window to -work with large source files. -Therefore, results are available for fewer models. - - - - - - - - - - - - - - - {% assign refac_sorted = site.data.refactor_leaderboard | sort: 'pass_rate_1' | reverse %} - {% for row in refac_sorted %} - - - - - - - - {% endfor %} - -
ModelPercent completed correctlyPercent using correct edit formatCommandEdit format
{{ row.model }}{{ row.pass_rate_1 }}%{{ row.percent_cases_well_formed }}%{{ row.command }}{{ row.edit_format }}
- - - - - - -## LLM code editing skill by model release date - -[![connecting to many LLMs](/assets/models-over-time.svg)](https://aider.chat/assets/models-over-time.svg) - - -## Notes on benchmarking results - -The key benchmarking results are: - -- **Percent completed correctly** - Measures what percentage of the coding tasks that the LLM completed successfully. To complete a task, the LLM must solve the programming assignment *and* edit the code to implement that solution. -- **Percent using correct edit format** - Measures the percent of coding tasks where the LLM complied with the edit format specified in the system prompt. If the LLM makes edit mistakes, aider will give it feedback and ask for a fixed copy of the edit. The best models can reliably conform to the edit format, without making errors. - - -## Notes on the edit format - -Aider uses different "edit formats" to collect code edits from different LLMs. -The "whole" format is the easiest for an LLM to use, but it uses a lot of tokens -and may limit how large a file can be edited. -Models which can use one of the diff formats are much more efficient, -using far fewer tokens. -Models that use a diff-like format are able to -edit larger files with less cost and without hitting token limits. - -Aider is configured to use the best edit format for the popular OpenAI and Anthropic models -and the [other models recommended on the LLM page](/docs/llms.html). -For lesser known models aider will default to using the "whole" editing format -since it is the easiest format for an LLM to use. - -## Contributing benchmark results - -Contributions of benchmark results are welcome! -See the -[benchmark README](https://github.com/Aider-AI/aider/blob/main/benchmark/README.md) -for information on running aider's code editing benchmarks. -Submit results by opening a PR with edits to the -[benchmark results data files](https://github.com/Aider-AI/aider/blob/main/aider/website/_data/). diff --git a/aider/website/docs/leaderboards/notes.md b/aider/website/docs/leaderboards/notes.md new file mode 100644 index 000000000..01264a76e --- /dev/null +++ b/aider/website/docs/leaderboards/notes.md @@ -0,0 +1,29 @@ +--- +parent: Aider LLM Leaderboards +nav_order: 800 +--- + +# Benchmark notes + +## Notes on benchmarking results + +The key benchmarking results are: + +- **Percent completed correctly** - Measures what percentage of the coding tasks that the LLM completed successfully. To complete a task, the LLM must solve the programming assignment *and* edit the code to implement that solution. +- **Percent using correct edit format** - Measures the percent of coding tasks where the LLM complied with the edit format specified in the system prompt. If the LLM makes edit mistakes, aider will give it feedback and ask for a fixed copy of the edit. The best models can reliably conform to the edit format, without making errors. + + +## Notes on the edit format + +Aider uses different "edit formats" to collect code edits from different LLMs. +The "whole" format is the easiest for an LLM to use, but it uses a lot of tokens +and may limit how large a file can be edited. +Models which can use one of the diff formats are much more efficient, +using far fewer tokens. +Models that use a diff-like format are able to +edit larger files with less cost and without hitting token limits. + +Aider is configured to use the best edit format for the popular OpenAI and Anthropic models +and the [other models recommended on the LLM page](/docs/llms.html). +For lesser known models aider will default to using the "whole" editing format +since it is the easiest format for an LLM to use. diff --git a/aider/website/docs/leaderboards/refactor.md b/aider/website/docs/leaderboards/refactor.md new file mode 100644 index 000000000..96a7bea2b --- /dev/null +++ b/aider/website/docs/leaderboards/refactor.md @@ -0,0 +1,78 @@ +--- +parent: Aider LLM Leaderboards +highlight_image: /assets/leaderboard.jpg +nav_order: 100 +description: Quantitative benchmark of LLM code refactoring skill. +--- + + +## Refactoring leaderboard + +[Aider's refactoring benchmark](https://github.com/Aider-AI/refactor-benchmark) asks the LLM to refactor 89 large methods from large python classes. This is a more challenging benchmark, which tests the model's ability to output long chunks of code without skipping sections or making mistakes. It was developed to provoke and measure [GPT-4 Turbo's "lazy coding" habit](/2023/12/21/unified-diffs.html). + +The refactoring benchmark requires a large context window to +work with large source files. +Therefore, results are available for fewer models. + + + + + + + + + + + + + + + {% assign refac_sorted = site.data.refactor_leaderboard | sort: 'pass_rate_1' | reverse %} + {% for row in refac_sorted %} + + + + + + + + {% endfor %} + +
ModelPercent completed correctlyPercent using correct edit formatCommandEdit format
{{ row.model }}{{ row.pass_rate_1 }}%{{ row.percent_cases_well_formed }}%{{ row.command }}{{ row.edit_format }}
+ + + + + + + + diff --git a/aider/website/docs/legal/privacy.md b/aider/website/docs/legal/privacy.md index 01b80db59..1d1a2192a 100644 --- a/aider/website/docs/legal/privacy.md +++ b/aider/website/docs/legal/privacy.md @@ -69,7 +69,7 @@ We make reasonable efforts to protect your information by using physical and ele ### Children’s 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]. +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 privacy@aider.chat. ### International Visitors @@ -98,7 +98,7 @@ if result.returncode == 0: date = datetime.datetime.fromtimestamp(timestamp) cog.out(f"{date.strftime('%B %d, %Y.')}") ]]]--> -October 31, 2024. +December 06, 2024.

diff --git a/aider/website/docs/llms.md b/aider/website/docs/llms.md index 939bbef87..1e30795f8 100644 --- a/aider/website/docs/llms.md +++ b/aider/website/docs/llms.md @@ -19,7 +19,7 @@ Aider works best with these models, which are skilled at editing code: - [GPT-4o](/docs/llms/openai.html) - [Claude 3.5 Sonnet](/docs/llms/anthropic.html) - [Claude 3 Opus](/docs/llms/anthropic.html) -- [DeepSeek Coder V2](/docs/llms/deepseek.html) +- [DeepSeek V3](/docs/llms/deepseek.html) ## Free models diff --git a/aider/website/docs/llms/bedrock.md b/aider/website/docs/llms/bedrock.md index 677b050b8..64a95c8dd 100644 --- a/aider/website/docs/llms/bedrock.md +++ b/aider/website/docs/llms/bedrock.md @@ -39,12 +39,24 @@ export AWS_PROFILE=your-profile You can add these to your [.env file](/docs/config/dotenv.html). -## Bedrock with `pipx` installation +## Install boto3 -The AWS Bedrock provider requires the `boto3` package in order to function correctly. To use aider installed via `pipx` with AWS Bedrock, you must add the `boto3` dependency to aider's virtual environment by running +The AWS Bedrock provider requires the `boto3` package in order to function correctly: +```bash +pip install boto3 ``` -pipx inject aider boto3 + +To use aider installed via `pipx` with AWS Bedrock, you must add the `boto3` dependency to aider's virtual environment by running + +```bash +pipx inject aider-chat boto3 +``` + +You must install `boto3` dependency to aider's virtual environment installed via one-liner or uv by running + +```bash +uv tool run --from aider-chat pip install boto3 ``` @@ -56,12 +68,18 @@ Once your AWS credentials are set up, you can run Aider with the `--model` comma aider --model bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0 ``` +Sometimes it seems to help if you prefix the model name with "us.": + +```bash +aider --model bedrock/us.anthropic.claude-3-5-sonnet-20240620-v1:0 +``` + ## Available Models To see some models available via Bedrock, run: -``` +```bash aider --list-models bedrock/ ``` diff --git a/aider/website/docs/llms/deepseek.md b/aider/website/docs/llms/deepseek.md index 361758427..c49c49c7e 100644 --- a/aider/website/docs/llms/deepseek.md +++ b/aider/website/docs/llms/deepseek.md @@ -6,7 +6,8 @@ nav_order: 500 # DeepSeek Aider can connect to the DeepSeek.com API. -The DeepSeek Coder V2 model has a top score on aider's code editing benchmark. +To work with DeepSeek's models, you need to set the `DEEPSEEK_API_KEY` environment variable with your [DeepSeek API key](https://platform.deepseek.com/api_keys). +The DeepSeek Chat V3 model has a top score on aider's code editing benchmark. ``` python -m pip install -U aider-chat @@ -14,7 +15,7 @@ python -m pip install -U aider-chat export DEEPSEEK_API_KEY= # Mac/Linux setx DEEPSEEK_API_KEY # Windows, restart shell after setx -# Use DeepSeek Coder V2 +# Use DeepSeek Chat v3 aider --deepseek ``` diff --git a/aider/website/docs/llms/gemini.md b/aider/website/docs/llms/gemini.md index c8f045ac3..8d8234d88 100644 --- a/aider/website/docs/llms/gemini.md +++ b/aider/website/docs/llms/gemini.md @@ -5,15 +5,17 @@ nav_order: 300 # Gemini -Google currently offers -[*free* API access to the Gemini 1.5 Pro model](https://ai.google.dev/pricing). -This is the most capable free model to use with aider, -with code editing capability that's comparable to GPT-3.5. You'll need a [Gemini API key](https://aistudio.google.com/app/u/2/apikey). ``` python -m pip install -U aider-chat +# You may need to install google-generativeai +pip install -U google-generativeai + +# Or with pipx... +pipx inject aider-chat google-generativeai + export GEMINI_API_KEY= # Mac/Linux setx GEMINI_API_KEY # Windows, restart shell after setx diff --git a/aider/website/docs/llms/ollama.md b/aider/website/docs/llms/ollama.md index 3e42648ed..014baa175 100644 --- a/aider/website/docs/llms/ollama.md +++ b/aider/website/docs/llms/ollama.md @@ -44,25 +44,22 @@ setx OLLAMA_API_KEY # Windows, restart shell after setx [Ollama uses a 2k context window by default](https://github.com/ollama/ollama/blob/main/docs/faq.md#how-can-i-specify-the-context-window-size), which is very small for working with aider. +It also **silently** discards context that exceeds the window. +This is especially dangerous because many users don't even realize that most of their data +is being discarded by Ollama. + +By default, aider sets Ollama's context window +to be large enough for each request you send plus 8k tokens for the reply. +This ensures data isn't silently discarded by Ollama. -Aider sets Ollama's context window to 8k by default. -If you would like -a larger context window -you can use a +If you'd like you can configure a fixed sized context window instead +with an [`.aider.model.settings.yml` file](https://aider.chat/docs/config/adv-model-settings.html#model-settings) like this: ``` - name: ollama/qwen2.5-coder:32b-instruct-fp16 extra_params: - num_ctx: 8192 + num_ctx: 65536 ``` -Unlike most other LLM servers, Ollama does not throw an error if you submit -a request that exceeds the context window. -Instead, it just silently truncates the request by discarding the "oldest" messages -in the chat to make it fit within the context window. -So if your context window is too small, you won't get an error. -Aider will probably just fail to work well and experience -a lot of -[file editing problems](https://aider.chat/docs/troubleshooting/edit-errors.html). diff --git a/aider/website/docs/llms/openai-compat.md b/aider/website/docs/llms/openai-compat.md index d35070ed7..e1b2a73f2 100644 --- a/aider/website/docs/llms/openai-compat.md +++ b/aider/website/docs/llms/openai-compat.md @@ -8,7 +8,8 @@ nav_order: 500 Aider can connect to any LLM which is accessible via an OpenAI compatible API endpoint. ``` -python -m pip install -U aider-chat +python -m pip install aider-install +aider-install # Mac/Linux: export OPENAI_API_BASE= diff --git a/aider/website/docs/llms/openai.md b/aider/website/docs/llms/openai.md index 4be98041d..f39d3927f 100644 --- a/aider/website/docs/llms/openai.md +++ b/aider/website/docs/llms/openai.md @@ -8,7 +8,7 @@ nav_order: 100 To work with OpenAI's models, you need to provide your [OpenAI API key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-secret-api-key) either in the `OPENAI_API_KEY` environment variable or -via the `--openai-api-key` command line switch. +via the `--api-key openai=` command line switch. Aider has some built in shortcuts for the most popular OpenAI models and has been tested and benchmarked to work well with them: @@ -16,28 +16,34 @@ has been tested and benchmarked to work well with them: ``` python -m pip install -U aider-chat -export OPENAI_API_KEY= # Mac/Linux -setx OPENAI_API_KEY # Windows, restart shell after setx - -# Aider uses gpt-4o by default (or use --4o) -aider - -# GPT-4o -aider --4o - -# GPT-3.5 Turbo -aider --35-turbo +# o3-mini +aider --model o3-mini --api-key openai= # o1-mini -aider --model o1-mini +aider --model o1-mini --api-key openai= -# o1-preview -aider --model o1-preview +# GPT-4o +aider --4o --api-key openai= # List models available from OpenAI aider --list-models openai/ + +# You can also store you API key in environment variables (or .env) +export OPENAI_API_KEY= # Mac/Linux +setx OPENAI_API_KEY # Windows, restart shell after setx ``` You can use `aider --model ` to use any other OpenAI model. For example, if you want to use a specific version of GPT-4 Turbo you could do `aider --model gpt-4-0125-preview`. + +## o1 models from other providers + +Many of OpenAI's o1 +"reasoning" models have restrictions on streaming and setting the temperature parameter. +Aider is configured to work properly with these models +when served through major provider APIs. + +You may need to [configure reasoning model settings](/docs/config/reasoning.html) +if you are using them through another provider +and see errors related to temperature or system prompt. diff --git a/aider/website/docs/llms/openrouter.md b/aider/website/docs/llms/openrouter.md index 20888a33c..9d561bf1c 100644 --- a/aider/website/docs/llms/openrouter.md +++ b/aider/website/docs/llms/openrouter.md @@ -39,5 +39,39 @@ If you get errors, check your Be sure to "enable providers that may train on inputs" to allow use of all models. +## Controlling provider selection + +OpenRouter often has multiple providers serving each model. +You can control which OpenRouter providers are used for your requests in two ways: + +1. By "ignoring" certain providers in your +[OpenRouter account settings](https://openrouter.ai/settings/preferences). +This disables those named providers across all the models that you access via OpenRouter. + +2. By configuring "provider routing" in a `.aider.model.settings.yml` file. + +Place that file in your home directory or the root if your git project, with +entries like this: + +```yaml +- name: openrouter/anthropic/claude-3.5-sonnet + extra_params: + extra_body: + provider: + # Only use these providers, in this order + order: ["Anthropic", "Together"] + # Don't fall back to other providers + allow_fallbacks: false + # Skip providers that may train on inputs + data_collection: "deny" + # Only use providers supporting all parameters + require_parameters: true +``` + +See [OpenRouter's provider routing docs](https://openrouter.ai/docs/provider-routing) for full details on these settings. + +See [Advanced model settings](https://aider.chat/docs/config/adv-model-settings.html#model-settings) +for more details about model settings files. + diff --git a/aider/website/docs/llms/other.md b/aider/website/docs/llms/other.md index 84fb3006a..c77c8ff54 100644 --- a/aider/website/docs/llms/other.md +++ b/aider/website/docs/llms/other.md @@ -95,6 +95,8 @@ cog.out(''.join(lines)) - TOGETHERAI_API_KEY - VOLCENGINE_API_KEY - VOYAGE_API_KEY +- WATSONX_API_KEY +- WX_API_KEY - XAI_API_KEY - XINFERENCE_API_KEY diff --git a/aider/website/docs/more/edit-formats.md b/aider/website/docs/more/edit-formats.md index 870284cc4..cabf6cc94 100644 --- a/aider/website/docs/more/edit-formats.md +++ b/aider/website/docs/more/edit-formats.md @@ -20,7 +20,7 @@ copy of each source file that needs changes. While simple, it can be slow and costly because the LLM has to return the *entire file* even if just a few lines are edited. -The format expects the file path just before the fenced file content: +The whole format expects the file path just before the fenced file content: ```` show_greeting.py @@ -28,7 +28,7 @@ show_greeting.py import sys def greeting(name): - print(f"Hey {{name}}") + print("Hey", name) if __name__ == '__main__': greeting(sys.argv[1]) @@ -42,7 +42,7 @@ The "diff" edit format asks the LLM to specify file edits as a series of search/ This is an efficient format, because the model only needs to return parts of the file which have changes. -They are formatted using a syntax similar to the git merge conflict resolution markings, +Edits are formatted using a syntax similar to the git merge conflict resolution markings, with the file path right before a fenced block: ```` @@ -62,7 +62,7 @@ from flask import Flask The "diff-fenced" edit format is based on the diff format, but the file path is placed inside the fence. It is primarily used with the Gemini family of models, -which often fail to conform to fencing approach specified in the diff format. +which often fail to conform to the fencing approach specified in the diff format. ```` ``` @@ -84,7 +84,10 @@ This is an efficient format, because the model only needs to return parts of the which have changes. It was mainly used to the GPT-4 Turbo family of models, -to reduce their "lazy coding" tendencies with other edit formats. +because it reduced their "lazy coding" tendencies. +With other edit formats the GPT-4 Turbo models tended to elide +large sections of code and replace them with "# ... original code here ..." +style comments. ```` @@ -104,3 +107,10 @@ to reduce their "lazy coding" tendencies with other edit formats. These are streamlined versions of the diff and whole formats, intended to be used with `--editor-edit-format` when using [architect mode](/docs/usage/modes.html). +The actual edit format is the same, but aider uses a simpler prompt that +is more narrowly focused on just editing the file as opposed to +solving the coding task. +The architect model resolves the coding task and +provides plain text instructions about which file changes need to be made. +The editor interprets those instructions to produce the +syntactically correct diff or whole edits. diff --git a/aider/website/docs/more/infinite-output.md b/aider/website/docs/more/infinite-output.md index 33e84188b..4e046fbf3 100644 --- a/aider/website/docs/more/infinite-output.md +++ b/aider/website/docs/more/infinite-output.md @@ -65,14 +65,17 @@ cog.out(model_list) - claude-3-sonnet-20240229 - codestral/codestral-2405 - codestral/codestral-latest -- deepseek-chat -- deepseek-coder +- deepseek/deepseek-chat +- deepseek/deepseek-coder +- deepseek/deepseek-reasoner +- eu.anthropic.claude-3-5-haiku-20241022-v1:0 - eu.anthropic.claude-3-5-sonnet-20241022-v2:0 - mistral/codestral-2405 - mistral/codestral-latest - mistral/codestral-mamba-latest - mistral/mistral-large-2402 - mistral/mistral-large-2407 +- mistral/mistral-large-2411 - mistral/mistral-large-latest - mistral/mistral-medium - mistral/mistral-medium-2312 @@ -87,7 +90,10 @@ cog.out(model_list) - mistral/open-mixtral-8x22b - mistral/open-mixtral-8x7b - mistral/pixtral-12b-2409 +- mistral/pixtral-large-2411 +- mistral/pixtral-large-latest - openrouter/anthropic/claude-3.5-sonnet +- openrouter/deepseek/deepseek-r1 - us.anthropic.claude-3-5-haiku-20241022-v1:0 - us.anthropic.claude-3-5-sonnet-20241022-v2:0 - vertex_ai/claude-3-5-haiku diff --git a/aider/website/docs/troubleshooting/aider-not-found.md b/aider/website/docs/troubleshooting/aider-not-found.md index 12a610340..29ef7c3aa 100644 --- a/aider/website/docs/troubleshooting/aider-not-found.md +++ b/aider/website/docs/troubleshooting/aider-not-found.md @@ -14,12 +14,11 @@ You may see an error message like this: > aider: The term 'aider' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. -Below is the most fail safe way to install and run aider in these situations: +Below is the most fail safe way to run aider in these situations: ``` -python -m pip install -U aider-chat python -m aider ``` - -{% include venv-pipx.md %} +You should also consider +[installing aider using aider-install, uv or pipx](/docs/install.html). diff --git a/aider/website/docs/troubleshooting/edit-errors.md b/aider/website/docs/troubleshooting/edit-errors.md index 7aab589b1..a6de214e3 100644 --- a/aider/website/docs/troubleshooting/edit-errors.md +++ b/aider/website/docs/troubleshooting/edit-errors.md @@ -24,6 +24,8 @@ In these cases, here are some things you might try. Many LLMs now have very large context windows, but filling them with irrelevant code or conversation can confuse the model. +Above about 25k tokens of context, most models start to become distracted and become less likely +to conform to their system prompt. - Don't add too many files to the chat, *just* add the files you think need to be edited. Aider also sends the LLM a [map of your entire git repo](https://aider.chat/docs/repomap.html), so other relevant code will be included automatically. @@ -33,8 +35,8 @@ Aider also sends the LLM a [map of your entire git repo](https://aider.chat/docs ## Use a more capable model -If possible try using GPT-4o, Claude 3.5 Sonnet or Claude 3 Opus, -as they are the strongest and most capable models. +If possible try using GPT-4o, Claude 3.5 Sonnet, DeepSeek V3 or DeepSeek R1. +They are the strongest and most capable models. Weaker models are more prone to @@ -62,6 +64,12 @@ Aider v0.50.2-dev Models: claude-3-5-sonnet-20240620 with ♾️ diff edit format ``` +## Try architect mode + +Run aider with `--architect` or `/chat-mode architect` to enable [architect mode](../usage/modes.md#architect-mode-and-the-editor-model). +This mode first proposes changes, then uses a separate model to handle the file edits. +This two-step process often produces more reliable edits, especially with models that have trouble +following edit format instructions. ## More help diff --git a/aider/website/docs/troubleshooting/imports.md b/aider/website/docs/troubleshooting/imports.md index ac9e96791..c512b9725 100644 --- a/aider/website/docs/troubleshooting/imports.md +++ b/aider/website/docs/troubleshooting/imports.md @@ -5,7 +5,7 @@ nav_order: 28 # Dependency versions -Aider expects to be installed via `pip` or `pipx`, which will install +Aider expects to be installed with the correct versions of all of its required dependencies. If you've been linked to this doc from a GitHub issue, @@ -13,43 +13,38 @@ or if aider is reporting `ImportErrors` it is likely that your aider install is using incorrect dependencies. -## Install with pipx + +## Avoid package conflicts + +If you are using aider to work on a python project, sometimes your project will require +specific versions of python packages which conflict with the versions that aider +requires. +If this happens, you may see errors like these when running pip installs: + +``` +aider-chat 0.23.0 requires somepackage==X.Y.Z, but you have somepackage U.W.V which is incompatible. +``` + +## Install with aider-install, uv or pipx If you are having dependency problems you should consider -[installing aider using pipx](/docs/install/pipx.html). +[installing aider using aider-install, uv or pipx](/docs/install.html). This will ensure that aider is installed in its own python environment, with the correct set of dependencies. -Try re-installing cleanly: - -``` -pipx uninstall aider-chat -pipx install aider-chat -``` - ## Package managers like Homebrew, AUR, ports Package managers often install aider with the wrong dependencies, leading to import errors and other problems. -The recommended way to -install aider is with -[pip](/docs/install/install.html). -Be sure to use the `--upgrade-strategy only-if-needed` switch so that the correct -versions of dependencies will be installed. +It is recommended to +[install aider using aider-install, uv or pipx](/docs/install.html). -``` -python -m pip install -U --upgrade-strategy only-if-needed aider-chat -``` - -A very safe way is to -[install aider using pipx](/docs/install/pipx.html), -which will ensure it is installed in a stand alone virtual environment. ## Dependency versions matter Aider pins its dependencies and is tested to work with those specific versions. -If you are installing aider with pip (rather than pipx), +If you are installing aider directly with pip you should be careful about upgrading or downgrading the python packages that aider uses. @@ -64,9 +59,4 @@ and sometimes introduces bugs or backwards incompatible changes. ## Replit -You can `pip install -U aider-chat` on replit. - -Or you can install aider with -pipx as follows: - {% include replit-pipx.md %} diff --git a/aider/website/docs/troubleshooting/models-and-keys.md b/aider/website/docs/troubleshooting/models-and-keys.md new file mode 100644 index 000000000..1ee24733c --- /dev/null +++ b/aider/website/docs/troubleshooting/models-and-keys.md @@ -0,0 +1,32 @@ +--- +parent: Troubleshooting +nav_order: 28 +--- + +# Models and API keys + +You need to tell aider which LLM to use and provide an API key. +The easiest way is to use the `--model` and `--api-key` +command line arguments, like this: + +``` +# Work with DeepSeek via DeepSeek's API +aider --model deepseek --api-key deepseek=your-key-goes-here + +# Work with Claude 3.5 Sonnet via Anthropic's API +aider --model sonnet --api-key anthropic=your-key-goes-here + +# Work with o3-mini via OpenAI's API +aider --model o3-mini --api-key openai=your-key-goes-here + +# Work with Sonnet via OpenRouter's API +aider --model openrouter/anthropic/claude-3.5-sonnet --api-key openrouter=your-key-goes-here + +# Work with DeepSeek Chat V3 via OpenRouter's API +aider --model openrouter/deepseek/deepseek-chat --api-key openrouter=your-key-goes-here +``` + +For more information, see the documentation sections: + +- [Connecting to LLMs](https://aider.chat/docs/llms.html) +- [Configuring API keys](https://aider.chat/docs/config/api-keys.html) diff --git a/aider/website/docs/troubleshooting/token-limits.md b/aider/website/docs/troubleshooting/token-limits.md index a3812475c..31e12e224 100644 --- a/aider/website/docs/troubleshooting/token-limits.md +++ b/aider/website/docs/troubleshooting/token-limits.md @@ -12,11 +12,12 @@ Every LLM has limits on how many tokens it can process for each request: - Each model has limit on how many **output tokens** it can produce. -Aider will report an error if a model responds indicating that +Aider will report an error **if a model responds** indicating that it has exceeded a token limit. The error will include suggested actions to try and avoid hitting token limits. -Here's an example error: + +Here's an example error: ``` Model gpt-3.5-turbo has hit a token limit! @@ -28,7 +29,7 @@ Total tokens: 4864 of 16385 To reduce output tokens: - Ask for smaller changes in each request. - Break your code into smaller source files. -- Try using a stronger model like gpt-4o or opus that can return diffs. +- Try using a stronger model like DeepSeek V3 or Sonnet that can return diffs. For more info: https://aider.chat/docs/token-limits.html ``` @@ -36,9 +37,7 @@ For more info: https://aider.chat/docs/token-limits.html {: .note } Aider never *enforces* token limits, it only *reports* token limit errors from the API provider. -You probably don't need to -[configure aider with the proper token limits](http://0.0.0.0:4000/docs/config/adv-model-settings.html#context-window-size-and-token-costs) -for unusual models. +The token counts that aider reports are *estimates*. ## Input tokens & context window size @@ -48,7 +47,7 @@ overflowing its context window. Technically you can exhaust the context window if the input is too large or if the input plus output are too large. -Strong models like GPT-4o and Opus have quite +Strong models like GPT-4o and Sonnet have quite large context windows, so this sort of error is typically only an issue when working with weaker models. @@ -74,7 +73,7 @@ To avoid hitting output token limits: - Ask for smaller changes in each request. - Break your code into smaller source files. -- Use a strong model like gpt-4o, sonnet or opus that can return diffs. +- Use a strong model like gpt-4o, sonnet or DeepSeek V3 that can return diffs. - Use a model that supports [infinite output](/docs/more/infinite-output.html). ## Other causes diff --git a/aider/website/docs/usage.md b/aider/website/docs/usage.md index 2c15cadf6..76f0ac980 100644 --- a/aider/website/docs/usage.md +++ b/aider/website/docs/usage.md @@ -68,11 +68,11 @@ relevant context from the rest of your repo. {% include works-best.md %} ``` -# GPT-4o -$ aider --4o +# o3-mini +$ aider --model o3-mini --api-key openai= # Claude 3.5 Sonnet -$ aider --sonnet +$ aider --model sonnet --api-key anthropic= ``` Or you can run `aider --model XXX` to launch aider with diff --git a/aider/website/docs/usage/caching.md b/aider/website/docs/usage/caching.md index f79bc6d9c..3173a3e83 100644 --- a/aider/website/docs/usage/caching.md +++ b/aider/website/docs/usage/caching.md @@ -4,14 +4,13 @@ highlight_image: /assets/prompt-caching.jpg parent: Usage nav_order: 750 description: Aider supports prompt caching for cost savings and faster coding. - --- # Prompt caching Aider supports prompt caching for cost savings and faster coding. Currently Anthropic provides caching for Sonnet and Haiku, -and DeepSeek provides caching for Coder. +and DeepSeek provides caching for Chat. Aider organizes the chat history to try and cache: @@ -48,4 +47,3 @@ every 5 minutes to keep the cache warm. Aider will ping up to `N` times over a period of `N*5` minutes after each message you send. - diff --git a/aider/website/docs/usage/commands.md b/aider/website/docs/usage/commands.md index 8f445afb9..b73d82ac8 100644 --- a/aider/website/docs/usage/commands.md +++ b/aider/website/docs/usage/commands.md @@ -22,13 +22,14 @@ cog.out(get_help_md()) |Command|Description| |:------|:----------| | **/add** | Add files to the chat so aider can edit them or review them in detail | -| **/architect** | Enter architect mode to discuss high-level design and architecture | -| **/ask** | Ask questions about the code base without editing any files | +| **/architect** | Enter architect/editor mode using 2 different models. If no prompt provided, switches to architect/editor mode. | +| **/ask** | Ask questions about the code base without editing any files. If no prompt provided, switches to ask mode. | | **/chat-mode** | Switch to a new chat mode | | **/clear** | Clear the chat history | -| **/code** | Ask for changes to your code | +| **/code** | Ask for changes to your code. If no prompt provided, switches to code mode. | | **/commit** | Commit edits to the repo made outside the chat (commit message optional) | | **/copy** | Copy the last assistant message to the clipboard | +| **/copy-context** | Copy the current chat context as markdown, suitable to paste into a web UI | | **/diff** | Display the diff of changes since the last message | | **/drop** | Remove files from the chat session to free up context space | | **/editor** | Open an editor to write a prompt | @@ -42,9 +43,10 @@ cog.out(get_help_md()) | **/map-refresh** | Force a refresh of the repository map | | **/model** | Switch to a new LLM | | **/models** | Search the list of available models | +| **/multiline-mode** | Toggle multiline mode (swaps behavior of Enter and Meta+Enter) | | **/paste** | Paste image/text from the clipboard into the chat. Optionally provide a name for the image. | | **/quit** | Exit the application | -| **/read-only** | Add files to the chat that are for reference, not to be edited | +| **/read-only** | Add files to the chat that are for reference only, or turn added files to read-only | | **/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: !) | @@ -77,8 +79,10 @@ 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. +- `Up Arrow` : Move up one line in the current message. +- `Down Arrow` : Move down one line in the current message. +- `Ctrl-Up` : Scroll back through previously sent messages. +- `Ctrl-Down` : 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. @@ -95,8 +99,10 @@ 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. +- `Up Arrow` : Move up one line in the current message. +- `Down Arrow` : Move down one line in the current message. +- `Ctrl-Up` : Scroll back through previously sent messages. +- `Ctrl-Down` : 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. diff --git a/aider/website/docs/usage/conventions.md b/aider/website/docs/usage/conventions.md index 2778694a4..e32feb5ef 100644 --- a/aider/website/docs/usage/conventions.md +++ b/aider/website/docs/usage/conventions.md @@ -28,6 +28,11 @@ or `aider --read CONVENTIONS.md`. This way it is marked as read-only, and cached if prompt caching is enabled. +## Community contributed conventions + +You can check the [aider conventions repository](https://github.com/Aider-AI/conventions) +to find or contribute conventions files. + ## Always load conventions You can also configure aider to always load your conventions file diff --git a/aider/website/docs/usage/copypaste.md b/aider/website/docs/usage/copypaste.md new file mode 100644 index 000000000..c1864d507 --- /dev/null +++ b/aider/website/docs/usage/copypaste.md @@ -0,0 +1,121 @@ +--- +title: Copy/paste with web chat +#highlight_image: /assets/browser.jpg +parent: Usage +nav_order: 850 +description: Aider works with LLM web chat UIs +--- + +# Copy/paste with web chat + + + + + +## Working with an LLM web chat + +[Aider can connect to most LLMs via API](https://aider.chat/docs/llms.html) and works best that way. +But there are times when you may want to work with an LLM via its web chat interface: + +- Workplace policies may limit your LLM usage to a proprietary web chat system. +- The web chat LLM may have access to unique context or may have been specially fine tuned for your task. +- It may be cost prohibitive to use some models via API. +- There may not be an API available. + +Aider has features for working with an LLM via its web chat interface. +This allows you to use the web chat LLM as the "big brain code architect" +while running aider with a smaller, cheaper LLM to actually make changes +to your local files. + +For this "file editor" part of the process +you can run aider with many open source, free or very inexpensive LLMs. +For example, the demo video above shows aider using DeepSeek to apply the changes +that o1-preview is suggesting in the web chat. + +### Copy aider's code context to your clipboard, paste into the web UI + +The `/copy-context ` command can be used in chat to copy aider's code context to your clipboard. +It will include: + +- All the files which have been added to the chat via `/add`. +- Any read only files which have been added via `/read`. +- Aider's [repository map](https://aider.chat/docs/repomap.html) that brings in code context related to the above files from elsewhere in your git repo. +- Some instructions to the LLM that ask it to output change instructions concisely. +- If you include ``, they will be copied too. + +You can paste the context into your browser, and start interacting with the LLM web chat to +ask for code changes. + +### Paste the LLM's reply back into aider to edit your files + +Once the LLM has replied, you can use the "copy response" button in the web UI to copy +the LLM's response. +Back in aider, you can run `/paste` and aider will edit your files +to implement the changes suggested by the LLM. + +You can use a cheap, efficient model like GPT-4o Mini, DeepSeek or Qwen to do these edits. +This works best if you run aider with `--edit-format editor-diff` or `--edit-format editor-whole`. + +### Copy/paste mode + +Aider has a `--copy-paste` mode that streamlines this entire process: + +- Whenever you `/add` or `/read` files, aider will automatically copy the entire, updated +code context to your clipboard. +You'll see "Copied code context to clipboard" whenever this happens. +- When you copy the LLM reply to your clipboard outside aider, aider will automatically notice +and load it into the aider chat. +Just press ENTER to send the message +and aider will apply the LLMs changes to your local files. +- Aider will automatically select the best edit format for this copy/paste functionality. +Depending on the LLM you have aider use, it will be either `editor-whole` or `editor-diff`. + +## Terms of service + +Be sure to review the Terms Of Service of any LLM web chat service you use with +these features. +These features are not intended to be used in violation of any service's Terms Of Service (TOS). + +Aider's web chat features have been designed to be compliant with the +terms of service of most LLM web chats. + +There are 4 copy/paste steps involved when coding with an LLM web chat: + +1. Copy code and context from aider. +2. Paste the code and context into the LLM web chat. +3. Copy the reply from the LLM web chat. +4. Paste the LLM reply into aider. + +Most LLM web chat TOS prohibit automating steps (2) and (3) where code +is copied from and pasted into the web chat. +Aider's `--copy-paste` mode leaves those as 100% manual steps for the user to complete. +It simply streamlines steps (1) and (4) that are interactions with aider, +and which should not be under the scope of an LLM web chat TOS. + +If you are concerned that +the automatic interactions with aider in steps (1) and (4) may be problematic with respect to +your LLM web chat provider's TOS, you can forego `--copy-paste` mode. +Instead, manually use the `/copy-context` and `/paste` commands if that +will keep you in compliance. + +Again, do not use these features in violation of any service's Terms Of Service. diff --git a/aider/website/docs/usage/modes.md b/aider/website/docs/usage/modes.md index 1818a9589..f3d9a3359 100644 --- a/aider/website/docs/usage/modes.md +++ b/aider/website/docs/usage/modes.md @@ -29,6 +29,14 @@ with the `/chat-mode ` command: /chat-mode help ``` +Or you can switch between coding modes using these commands without arguments: + +``` +/code +/architect +/ask +``` + Or you can launch aider in one of the modes with the `--chat-mode ` switch. There is also a special shortcut `--architect` to launch in `--chat-mode architect`. diff --git a/aider/website/docs/usage/not-code.md b/aider/website/docs/usage/not-code.md new file mode 100644 index 000000000..6a0bd8158 --- /dev/null +++ b/aider/website/docs/usage/not-code.md @@ -0,0 +1,179 @@ +--- +parent: Usage +nav_order: 901 +description: Use aider to edit configuration files, documentation, and other text-based formats. +--- + + +# Editing config & text files + +Aider isn't just for code, it can be very helpful when editing +almost any text file. +You can use aider to make changes to your shell & ssh settings, +Dockerfiles +or pretty much any configuration or documentation file. + +Here are some practical examples of modifying common config/text files: + +## Shell Configuration + +
+$ aider .bashrc + +Added .bashrc to the chat. + + +#### Add an alias 'll' that lists all files, with all details in human readable format. And update PATH to include uv installed tools. + +``` ++ alias ll='ls -alh' ++ export PATH="$PATH:$HOME/.local/bin:$PATH" +``` +
+ +## SSH Configurations + +
+$ aider ~/.ssh/config + +Added config to the chat. + +#### Create a Host entry 'my-server' using bastion.example.com as JumpHost + +``` ++ Host my-server ++ HostName 192.168.1.100 ++ User deploy ++ Port 2222 ++ IdentityFile ~/.ssh/deploy_key ++ ProxyJump bastion.example.com +``` +
+ +## Docker Setup + +
+$ aider Dockerfile docker-compose.yml + +Added Dockerfile and docker-compose.yml to the chat. + +#### Set non-root user and enable healthchecks + +``` ++ USER appuser ++ HEALTHCHECK --interval=30s --timeout=3s \ ++ CMD curl -f http://localhost:8000/health || exit 1 +``` + +#### Expose port 5432 and add volume for postgres data + +``` + services: + postgres: + image: postgres:15 ++ ports: ++ - "5432:5432" ++ volumes: ++ - pgdata:/var/lib/postgresql/data +``` +
+ +## Git Configuration + +
+$ aider .gitconfig + +Added .gitconfig to the chat. + +#### Set default push behavior to current branch and enable color UI + +``` ++ [push] ++ default = current ++ [color] ++ ui = auto +``` +
+ +## System Configuration +
+$ aider /etc/hosts # May need sudo + +Added hosts to the chat. + +#### Block tracking domains by pointing them to 127.0.0.1 + +``` ++ 127.0.0.1 ads.example.com ++ 127.0.0.1 track.analytics.co +``` +
+ + +## Editor Configs +
+$ aider .vimrc + +Added .vimrc to the chat. + +#### Enable line numbers and set 4-space tabs for Python + +``` ++ set number ++ autocmd FileType python set tabstop=4 shiftwidth=4 expandtab +``` +
+ +## VSCode Configuration +
+$ aider settings.json + +Added settings.json to the chat. + +#### Enable auto-format on save and set default formatter + +``` ++ "editor.formatOnSave": true, ++ "editor.defaultFormatter": "esbenp.prettier-vscode" +``` +
+ +## Markdown Documentation +
+$ aider README.md + +Added README.md to the chat. + + +#### Add installation section with brew and pip options + +``` ++ ## Installation ++ ``` ++ # Homebrew ++ brew install cool-app-10k ++ ++ # PyPI ++ pipx install cool-app-10k ++ ``` +``` +
+ +## XML Configuration +
+$ aider pom.xml + +Added pom.xml to the chat. +#### Add JUnit 5 dependency with test scope + +``` ++ ++ org.junit.jupiter ++ junit-jupiter-api ++ 5.9.2 ++ test ++ +``` +
+ + diff --git a/aider/website/docs/usage/watch.md b/aider/website/docs/usage/watch.md new file mode 100644 index 000000000..f46be1dbc --- /dev/null +++ b/aider/website/docs/usage/watch.md @@ -0,0 +1,294 @@ +--- +title: Aider in your IDE +#highlight_image: /assets/browser.jpg +parent: Usage +nav_order: 750 +description: Aider can watch your files and respond to AI comments you add in your favorite IDE or text editor. +--- + +# Aider in your IDE + + + + + +## AI comments + +If you run aider with `--watch-files`, it will watch all files in your repo +and look for any AI coding instructions you add using your favorite IDE or text editor. + +Specifically, aider looks for one-liner comments (# ... or // ...) that either start or end with `AI`, `AI!` or `AI?` like these: + +```python +# Make a snake game. AI! +# What is the purpose of this method AI? +``` + +Or in `//` comment languages... + +```js +// Write a protein folding prediction engine. AI! +``` + +Aider will take note of all the comments that start or end with `AI`. +Comments that include `AI!` with an exclamation point or `AI?` with a question +mark are special. +They trigger aider to take action to collect *all* the AI comments and use them +as your instructions. + +- `AI!` triggers aider to make changes to your code. +- `AI?` triggers aider to answer your question. + +See the demo video above that shows aider working with AI comments in VSCode. + + +## Example + +For example, if you included this AI comment in your code: + +```js +function factorial(n) // Implement this. AI! +``` + +Then aider would update the file and implement the function: + +```js +function factorial(n) { + if (n === 0 || n === 1) { + return 1; + } else { + return n * factorial(n - 1); + } +} +``` + +## Comment styles + +Aider only watches for these types of **one-liner** comments: + +``` +# Python and bash style +// Javascript style +-- SQL style +``` + +Aider will look for those comment types in all files. +You can use them into any code file you're editing, even if they aren't the +correct comment syntax for that language. + +## Multiple uses + +This capability is quite flexible and powerful, and can be used in many ways. + +### In-context instructions + +You can add an AI comment in the function you want changed, +explaining the change request in-context right where you want the changes. + +```javascript +app.get('/sqrt/:n', (req, res) => { + const n = parseFloat(req.params.n); + + // Add error handling for NaN and less than zero. AI! + + const result = math.sqrt(n); + res.json({ result: result }); +}); +``` + +### Multiple comments + +You can add multiple `AI` comments without the `!`, +before triggering aider with a final `AI!`. +Also keep in mind that you can spread the AI comments across +multiple files, if you want to coordinate changes in multiple places. +Just use `AI!` last, to trigger aider. + +```python +@app.route('/factorial/') +def factorial(n): + if n < 0: + return jsonify(error="Factorial is not defined for negative numbers"), 400 + + # AI: Refactor this code... + + result = 1 + for i in range(1, n + 1): + result *= i + + # ... into to a compute_factorial() function. AI! + + return jsonify(result=result) +``` + +### Long form instructions + +You can add a block of comments, with longer instructions. +Just be sure to start or end one of the lines with `AI` or `AI!` to draw +aider's attention to the block. + +```python +# Make these changes: AI! +# - Add a proper main() function +# - Use Click to process cmd line args +# - Accept --host and --port args +# - Print a welcome message that includes the listening url + +if __name__ == "__main__": + app.run(debug=True) +``` + +### Add a file to the aider chat + +Rather than using `/add` to add a file inside the aider chat, you can +simply put an `#AI` comment in it and save the file. +You can undo/remove the comment immediately if you like, the file +will still be added to the aider chat. + +## Also use aider chat in the terminal + +It can be really helpful to get a change started with AI comments. +But sometimes you want to build on or refine those changes. +You can of course continue to do that with AI comments, +but it can sometimes be effective to switch over to the aider terminal chat. +The chat has the history of the AI comments you just made, +so you can continue on naturally from there. + +You can also use the normal aider chat in your terminal to work with +many of aider's more advanced features: + +- Use `/undo` to revert changes you don't like. Although you may also be able to use your IDE's undo function to step back in the file history. +- Use [chat modes](https://aider.chat/docs/usage/modes.html) to ask questions or get help. +- Manage the chat context with `/tokens`, `/clear`, `/drop`, `/reset`. +Adding an AI comment will add the file to the chat. +Periodically, you may want remove extra context that is no longer needed. +- [Fix lint and test errors](https://aider.chat/docs/usage/lint-test.html). +- Run shell commands. +- Etc. + + +## You can be lazy + +The examples above all show AI +comments with full sentences, proper capitalization, punctuation, etc. +This was done to help explain how AI comments work, but is not needed in practice. + +Most LLMs are perfectly capable of dealing with ambiguity and +inferring implied intent. +This often allows you to be quite lazy with your AI comments. +In particular, you can start and end comments with lowercase `ai` and `ai!`, +but you can also be much more terse with the request itself. +Below are simpler versions of some of the examples given above. + +When the context clearly implies the needed action, `ai!` might be all you +need. For example, to implement a factorial function +in a program full of other math functions either of these +approaches would probably work: + +```js +function factorial(n) // ai! +``` + +Or... + +```js +// add factorial() ai! +``` + +Rather than a long, explicit comment like "Add error handling for NaN and less than zero," +you can let aider infer more about the request. +This simpler comment may be sufficient: + +```javascript +app.get('/sqrt/:n', (req, res) => { + const n = parseFloat(req.params.n); + + // add error handling ai! + + const result = math.sqrt(n); + res.json({ result: result }); +}); +``` + +Similarly, this refactor probably could have been requested with fewer words, like this: + +```python +@app.route('/factorial/') +def factorial(n): + if n < 0: + return jsonify(error="Factorial is not defined for negative numbers"), 400 + + # ai refactor... + + result = 1 + for i in range(1, n + 1): + result *= i + + # ... to compute_factorial() ai! + + return jsonify(result=result) +``` + +As you use aider with your chosen LLM, you can develop a sense for how +explicit you need to make your AI comments. + +## Behind the scenes + +Aider sends your AI comments to the LLM with the +[repo map](https://aider.chat/docs/repomap.html) +and all the other code context you've added to the chat. + +It also pulls out and highlights the AI comments with specific context, showing the LLM +exactly how they fit into the code base. + +``` +The "AI" comments below marked with █ can be found in the code files I've shared with you. +They contain your instructions. +Make the requested changes. +Be sure to remove all these "AI" comments from the code! + +todo_app.py: +⋮... +│class TodoList: +⋮... +│ def __init__(self): +│ """Initialize an empty todo list""" +⋮... +│ +│ def list_tasks(self): +│ """Display all tasks""" +█ # Implement this. AI! +│ +│def main(): +│ todo = TodoList() +│ +⋮... +``` + +-------- + +#### Credits + +*This feature was inspired by +the way [Override](https://github.com/oi-overide) watches for file changes +to find prompts embedded within `//> a specific set of delimiters @@ -70,28 +70,36 @@ Aider works best with GPT-4o & Claude 3.5 Sonnet and can cog.out(open("aider/website/_includes/get-started.md").read()) --> -You can get started quickly like this: +If you already have python 3.8-3.13 installed, you can get started quickly like this: -``` -python -m pip install -U aider-chat +```bash +python -m pip install aider-install +aider-install -# Change directory into a git repo -cd /to/your/git/repo +# Change directory into your code base +cd /to/your/project -# Work with Claude 3.5 Sonnet on your repo -export ANTHROPIC_API_KEY=your-key-goes-here -aider +# Work with DeepSeek via DeepSeek's API +aider --model deepseek --api-key deepseek=your-key-goes-here -# Work with GPT-4o on your repo -export OPENAI_API_KEY=your-key-goes-here -aider +# Work with Claude 3.5 Sonnet via Anthropic's API +aider --model sonnet --api-key anthropic=your-key-goes-here + +# Work with GPT-4o via OpenAI's API +aider --model gpt-4o --api-key openai=your-key-goes-here + +# Work with Sonnet via OpenRouter's API +aider --model openrouter/anthropic/claude-3.5-sonnet --api-key openrouter=your-key-goes-here + +# Work with DeepSeek via OpenRouter's API +aider --model openrouter/deepseek/deepseek-chat --api-key openrouter=your-key-goes-here ``` See the [installation instructions](https://aider.chat/docs/install.html) -and other -[documentation](https://aider.chat/docs/usage.html) +and +[usage documentation](https://aider.chat/docs/usage.html) for more details. ## Features @@ -100,21 +108,22 @@ for more details. - Ask for changes: - Add new features or test cases. - Describe a bug. - - Paste in an error message or or GitHub issue URL. + - Paste in an error message or GitHub issue URL. - Refactor code. - Update docs. - Aider will edit your files to complete your request. - Aider [automatically git commits](https://aider.chat/docs/git.html) changes with a sensible commit message. +- [Use aider inside your favorite editor or IDE](https://aider.chat/docs/usage/watch.html). - Aider works with [most popular languages](https://aider.chat/docs/languages.html): python, javascript, typescript, php, html, css, and more... -- Aider works best with GPT-4o & Claude 3.5 Sonnet and can [connect to almost any LLM](https://aider.chat/docs/llms.html). - Aider can edit multiple files at once for complex requests. - Aider uses a [map of your entire git repo](https://aider.chat/docs/repomap.html), which helps it work well in larger codebases. -- Edit files in your editor while chatting with aider, +- Edit files in your editor or IDE while chatting with aider, and it will always use the latest version. Pair program with AI. - [Add images to the chat](https://aider.chat/docs/usage/images-urls.html) (GPT-4o, Claude 3.5 Sonnet, etc). - [Add URLs to the chat](https://aider.chat/docs/usage/images-urls.html) and aider will read their content. - [Code with your voice](https://aider.chat/docs/usage/voice.html). +- Aider works best with Claude 3.5 Sonnet, DeepSeek V3, o1 & GPT-4o and can [connect to almost any LLM](https://aider.chat/docs/llms.html). ## Top tier performance diff --git a/aider/website/install.ps1 b/aider/website/install.ps1 new file mode 100644 index 000000000..116b5e118 --- /dev/null +++ b/aider/website/install.ps1 @@ -0,0 +1,559 @@ +# Licensed under the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +<# +.SYNOPSIS + +The installer for uv 0.5.9 + +.DESCRIPTION + +This script detects what platform you're on and fetches an appropriate archive from +https://github.com/astral-sh/uv/releases/download/0.5.9 +then unpacks the binaries and installs them to the first of the following locations + + $env:XDG_BIN_HOME + $env:XDG_DATA_HOME/../bin + $HOME/.local/bin + +It will then add that dir to PATH by editing your Environment.Path registry key + +.PARAMETER ArtifactDownloadUrl +The URL of the directory where artifacts can be fetched from + +.PARAMETER NoModifyPath +Don't add the install directory to PATH + +.PARAMETER Help +Print help + +#> + +param ( + [Parameter(HelpMessage = "The URL of the directory where artifacts can be fetched from")] + [string]$ArtifactDownloadUrl = 'https://github.com/astral-sh/uv/releases/download/0.5.9', + [Parameter(HelpMessage = "Don't add the install directory to PATH")] + [switch]$NoModifyPath, + [Parameter(HelpMessage = "Print Help")] + [switch]$Help +) + +$app_name = 'uv' +$app_version = '0.5.9' +if ($env:UV_INSTALLER_GHE_BASE_URL) { + $installer_base_url = $env:UV_INSTALLER_GHE_BASE_URL +} elseif ($env:UV_INSTALLER_GITHUB_BASE_URL) { + $installer_base_url = $env:UV_INSTALLER_GITHUB_BASE_URL +} else { + $installer_base_url = "https://github.com" +} +if ($env:INSTALLER_DOWNLOAD_URL) { + $ArtifactDownloadUrl = $env:INSTALLER_DOWNLOAD_URL +} else { + $ArtifactDownloadUrl = "$installer_base_url/astral-sh/uv/releases/download/0.5.9" +} + +$receipt = @" +{"binaries":["CARGO_DIST_BINS"],"binary_aliases":{},"cdylibs":["CARGO_DIST_DYLIBS"],"cstaticlibs":["CARGO_DIST_STATICLIBS"],"install_layout":"unspecified","install_prefix":"AXO_INSTALL_PREFIX","modify_path":true,"provider":{"source":"cargo-dist","version":"0.25.2-prerelease.3"},"source":{"app_name":"uv","name":"uv","owner":"astral-sh","release_type":"github"},"version":"0.5.9"} +"@ +$receipt_home = "${env:LOCALAPPDATA}\uv" + +if ($env:UV_DISABLE_UPDATE) { + $install_updater = $false +} else { + $install_updater = $true +} + +if ($NoModifyPath) { + Write-Information "-NoModifyPath has been deprecated; please set UV_NO_MODIFY_PATH=1 in the environment" +} + +if ($env:UV_NO_MODIFY_PATH) { + $NoModifyPath = $true +} + +$unmanaged_install = $env:UV_UNMANAGED_INSTALL + +if ($unmanaged_install) { + $NoModifyPath = $true + $install_updater = $false +} + +function Install-Binary($install_args) { + if ($Help) { + Get-Help $PSCommandPath -Detailed + Exit + } + + Initialize-Environment + + # Platform info injected by dist + $platforms = @{ + "aarch64-pc-windows-msvc" = @{ + "artifact_name" = "uv-x86_64-pc-windows-msvc.zip" + "bins" = @("uv.exe", "uvx.exe") + "libs" = @() + "staticlibs" = @() + "zip_ext" = ".zip" + "aliases" = @{ + } + "aliases_json" = '{}' + } + "i686-pc-windows-msvc" = @{ + "artifact_name" = "uv-i686-pc-windows-msvc.zip" + "bins" = @("uv.exe", "uvx.exe") + "libs" = @() + "staticlibs" = @() + "zip_ext" = ".zip" + "aliases" = @{ + } + "aliases_json" = '{}' + } + "x86_64-pc-windows-msvc" = @{ + "artifact_name" = "uv-x86_64-pc-windows-msvc.zip" + "bins" = @("uv.exe", "uvx.exe") + "libs" = @() + "staticlibs" = @() + "zip_ext" = ".zip" + "aliases" = @{ + } + "aliases_json" = '{}' + } + } + + $fetched = Download "$ArtifactDownloadUrl" $platforms + # FIXME: add a flag that lets the user not do this step + try { + Invoke-Installer -artifacts $fetched -platforms $platforms "$install_args" + } catch { + throw @" +We encountered an error trying to perform the installation; +please review the error messages below. + +$_ +"@ + } +} + +function Get-TargetTriple() { + try { + # NOTE: this might return X64 on ARM64 Windows, which is OK since emulation is available. + # It works correctly starting in PowerShell Core 7.3 and Windows PowerShell in Win 11 22H2. + # Ideally this would just be + # [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture + # but that gets a type from the wrong assembly on Windows PowerShell (i.e. not Core) + $a = [System.Reflection.Assembly]::LoadWithPartialName("System.Runtime.InteropServices.RuntimeInformation") + $t = $a.GetType("System.Runtime.InteropServices.RuntimeInformation") + $p = $t.GetProperty("OSArchitecture") + # Possible OSArchitecture Values: https://learn.microsoft.com/dotnet/api/system.runtime.interopservices.architecture + # Rust supported platforms: https://doc.rust-lang.org/stable/rustc/platform-support.html + switch ($p.GetValue($null).ToString()) + { + "X86" { return "i686-pc-windows-msvc" } + "X64" { return "x86_64-pc-windows-msvc" } + "Arm" { return "thumbv7a-pc-windows-msvc" } + "Arm64" { return "aarch64-pc-windows-msvc" } + } + } catch { + # The above was added in .NET 4.7.1, so Windows PowerShell in versions of Windows + # prior to Windows 10 v1709 may not have this API. + Write-Verbose "Get-TargetTriple: Exception when trying to determine OS architecture." + Write-Verbose $_ + } + + # This is available in .NET 4.0. We already checked for PS 5, which requires .NET 4.5. + Write-Verbose("Get-TargetTriple: falling back to Is64BitOperatingSystem.") + if ([System.Environment]::Is64BitOperatingSystem) { + return "x86_64-pc-windows-msvc" + } else { + return "i686-pc-windows-msvc" + } +} + +function Download($download_url, $platforms) { + $arch = Get-TargetTriple + + if (-not $platforms.ContainsKey($arch)) { + $platforms_json = ConvertTo-Json $platforms + throw "ERROR: could not find binaries for this platform. Last platform tried: $arch platform info: $platforms_json" + } + + # Lookup what we expect this platform to look like + $info = $platforms[$arch] + $zip_ext = $info["zip_ext"] + $bin_names = $info["bins"] + $lib_names = $info["libs"] + $staticlib_names = $info["staticlibs"] + $artifact_name = $info["artifact_name"] + + # Make a new temp dir to unpack things to + $tmp = New-Temp-Dir + $dir_path = "$tmp\$app_name$zip_ext" + + # Download and unpack! + $url = "$download_url/$artifact_name" + Write-Information "Downloading $app_name $app_version ($arch)" + Write-Verbose " from $url" + Write-Verbose " to $dir_path" + $wc = New-Object Net.Webclient + $wc.downloadFile($url, $dir_path) + + Write-Verbose "Unpacking to $tmp" + + # Select the tool to unpack the files with. + # + # As of windows 10(?), powershell comes with tar preinstalled, but in practice + # it only seems to support .tar.gz, and not xz/zstd. Still, we should try to + # forward all tars to it in case the user has a machine that can handle it! + switch -Wildcard ($zip_ext) { + ".zip" { + Expand-Archive -Path $dir_path -DestinationPath "$tmp"; + Break + } + ".tar.*" { + tar xf $dir_path --strip-components 1 -C "$tmp"; + Break + } + Default { + throw "ERROR: unknown archive format $zip_ext" + } + } + + # Let the next step know what to copy + $bin_paths = @() + foreach ($bin_name in $bin_names) { + Write-Verbose " Unpacked $bin_name" + $bin_paths += "$tmp\$bin_name" + } + $lib_paths = @() + foreach ($lib_name in $lib_names) { + Write-Verbose " Unpacked $lib_name" + $lib_paths += "$tmp\$lib_name" + } + $staticlib_paths = @() + foreach ($lib_name in $staticlib_names) { + Write-Verbose " Unpacked $lib_name" + $staticlib_paths += "$tmp\$lib_name" + } + + if (($null -ne $info["updater"]) -and $install_updater) { + $updater_id = $info["updater"]["artifact_name"] + $updater_url = "$download_url/$updater_id" + $out_name = "$tmp\uv-update.exe" + + $wc.downloadFile($updater_url, $out_name) + $bin_paths += $out_name + } + + return @{ + "bin_paths" = $bin_paths + "lib_paths" = $lib_paths + "staticlib_paths" = $staticlib_paths + } +} + +function Invoke-Installer($artifacts, $platforms) { + # Replaces the placeholder binary entry with the actual list of binaries + $arch = Get-TargetTriple + + if (-not $platforms.ContainsKey($arch)) { + $platforms_json = ConvertTo-Json $platforms + throw "ERROR: could not find binaries for this platform. Last platform tried: $arch platform info: $platforms_json" + } + + $info = $platforms[$arch] + + # Forces the install to occur at this path, not the default + $force_install_dir = $null + $install_layout = "unspecified" + # Check the newer app-specific variable before falling back + # to the older generic one + if (($env:UV_INSTALL_DIR)) { + $force_install_dir = $env:UV_INSTALL_DIR + $install_layout = "flat" + } elseif (($env:CARGO_DIST_FORCE_INSTALL_DIR)) { + $force_install_dir = $env:CARGO_DIST_FORCE_INSTALL_DIR + $install_layout = "flat" + } elseif ($unmanaged_install) { + $force_install_dir = $unmanaged_install + $install_layout = "flat" + } + + # Check if the install layout should be changed from `flat` to `cargo-home` + # for backwards compatible updates of applications that switched layouts. + if (($force_install_dir) -and ($install_layout -eq "flat")) { + # If the install directory is targeting the Cargo home directory, then + # we assume this application was previously installed that layout + # Note the installer passes the path with `\\` separators, but here they are + # `\` so we normalize for comparison. We don't use `Resolve-Path` because they + # may not exist. + $cargo_home = if ($env:CARGO_HOME) { $env:CARGO_HOME } else { + Join-Path $(if ($HOME) { $HOME } else { "." }) ".cargo" + } + if ($force_install_dir.Replace('\\', '\') -eq $cargo_home) { + $install_layout = "cargo-home" + } + } + + # The actual path we're going to install to + $dest_dir = $null + $dest_dir_lib = $null + # The install prefix we write to the receipt. + # For organized install methods like CargoHome, which have + # subdirectories, this is the root without `/bin`. For other + # methods, this is the same as `_install_dir`. + $receipt_dest_dir = $null + # Before actually consulting the configured install strategy, see + # if we're overriding it. + if (($force_install_dir)) { + switch ($install_layout) { + "hierarchical" { + $dest_dir = Join-Path $force_install_dir "bin" + $dest_dir_lib = Join-Path $force_install_dir "lib" + } + "cargo-home" { + $dest_dir = Join-Path $force_install_dir "bin" + $dest_dir_lib = $dest_dir + } + "flat" { + $dest_dir = $force_install_dir + $dest_dir_lib = $dest_dir + } + Default { + throw "Error: unrecognized installation layout: $install_layout" + } + } + $receipt_dest_dir = $force_install_dir + } + if (-Not $dest_dir) { + # Install to $env:XDG_BIN_HOME + $dest_dir = if (($base_dir = $env:XDG_BIN_HOME)) { + Join-Path $base_dir "" + } + $dest_dir_lib = $dest_dir + $receipt_dest_dir = $dest_dir + $install_layout = "flat" + } + if (-Not $dest_dir) { + # Install to $env:XDG_DATA_HOME/../bin + $dest_dir = if (($base_dir = $env:XDG_DATA_HOME)) { + Join-Path $base_dir "../bin" + } + $dest_dir_lib = $dest_dir + $receipt_dest_dir = $dest_dir + $install_layout = "flat" + } + if (-Not $dest_dir) { + # Install to $HOME/.local/bin + $dest_dir = if (($base_dir = $HOME)) { + Join-Path $base_dir ".local/bin" + } + $dest_dir_lib = $dest_dir + $receipt_dest_dir = $dest_dir + $install_layout = "flat" + } + + # Looks like all of the above assignments failed + if (-Not $dest_dir) { + throw "ERROR: could not find a valid path to install to; please check the installation instructions" + } + + # The replace call here ensures proper escaping is inlined into the receipt + $receipt = $receipt.Replace('AXO_INSTALL_PREFIX', $receipt_dest_dir.replace("\", "\\")) + $receipt = $receipt.Replace('"install_layout":"unspecified"', -join('"install_layout":"', $install_layout, '"')) + + $dest_dir = New-Item -Force -ItemType Directory -Path $dest_dir + $dest_dir_lib = New-Item -Force -ItemType Directory -Path $dest_dir_lib + Write-Information "Installing to $dest_dir" + # Just copy the binaries from the temp location to the install dir + foreach ($bin_path in $artifacts["bin_paths"]) { + $installed_file = Split-Path -Path "$bin_path" -Leaf + Copy-Item "$bin_path" -Destination "$dest_dir" -ErrorAction Stop + Remove-Item "$bin_path" -Recurse -Force -ErrorAction Stop + Write-Information " $installed_file" + + if (($dests = $info["aliases"][$installed_file])) { + $source = Join-Path "$dest_dir" "$installed_file" + foreach ($dest_name in $dests) { + $dest = Join-Path $dest_dir $dest_name + $null = New-Item -ItemType HardLink -Target "$source" -Path "$dest" -Force -ErrorAction Stop + } + } + } + foreach ($lib_path in $artifacts["lib_paths"]) { + $installed_file = Split-Path -Path "$lib_path" -Leaf + Copy-Item "$lib_path" -Destination "$dest_dir_lib" -ErrorAction Stop + Remove-Item "$lib_path" -Recurse -Force -ErrorAction Stop + Write-Information " $installed_file" + } + foreach ($lib_path in $artifacts["staticlib_paths"]) { + $installed_file = Split-Path -Path "$lib_path" -Leaf + Copy-Item "$lib_path" -Destination "$dest_dir_lib" -ErrorAction Stop + Remove-Item "$lib_path" -Recurse -Force -ErrorAction Stop + Write-Information " $installed_file" + } + + $formatted_bins = ($info["bins"] | ForEach-Object { '"' + $_ + '"' }) -join "," + $receipt = $receipt.Replace('"CARGO_DIST_BINS"', $formatted_bins) + $formatted_libs = ($info["libs"] | ForEach-Object { '"' + $_ + '"' }) -join "," + $receipt = $receipt.Replace('"CARGO_DIST_DYLIBS"', $formatted_libs) + $formatted_staticlibs = ($info["staticlibs"] | ForEach-Object { '"' + $_ + '"' }) -join "," + $receipt = $receipt.Replace('"CARGO_DIST_STATICLIBS"', $formatted_staticlibs) + # Also replace the aliases with the arch-specific one + $receipt = $receipt.Replace('"binary_aliases":{}', -join('"binary_aliases":', $info['aliases_json'])) + if ($NoModifyPath) { + $receipt = $receipt.Replace('"modify_path":true', '"modify_path":false') + } + + # Write the install receipt + if ($install_updater) { + $null = New-Item -Path $receipt_home -ItemType "directory" -ErrorAction SilentlyContinue + # Trying to get Powershell 5.1 (not 6+, which is fake and lies) to write utf8 is a crime + # because "Out-File -Encoding utf8" actually still means utf8BOM, so we need to pull out + # .NET's APIs which actually do what you tell them (also apparently utf8NoBOM is the + # default in newer .NETs but I'd rather not rely on that at this point). + $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False + [IO.File]::WriteAllLines("$receipt_home/uv-receipt.json", "$receipt", $Utf8NoBomEncoding) + } + + # Respect the environment, but CLI takes precedence + if ($null -eq $NoModifyPath) { + $NoModifyPath = $env:INSTALLER_NO_MODIFY_PATH + } + + Write-Information "" + Write-Information "Installing aider-chat..." + & "$dest_dir\uv.exe" tool install --force --python python3.12 aider-chat@latest + + if (-not $NoModifyPath) { + Add-Ci-Path $dest_dir + if (Add-Path $dest_dir) { + Write-Information "" + Write-Information "You need to add $dest_dir to your PATH. Either restart your system or run:" + Write-Information "" + Write-Information " set Path=$dest_dir;%Path% (cmd)" + Write-Information " `$env:Path = `"$dest_dir;`$env:Path`" (powershell)" + } + } +} + +# Attempt to do CI-specific rituals to get the install-dir on PATH faster +function Add-Ci-Path($OrigPathToAdd) { + # If GITHUB_PATH is present, then write install_dir to the file it refs. + # After each GitHub Action, the contents will be added to PATH. + # So if you put a curl | sh for this script in its own "run" step, + # the next step will have this dir on PATH. + # + # Note that GITHUB_PATH will not resolve any variables, so we in fact + # want to write the install dir and not an expression that evals to it + if (($gh_path = $env:GITHUB_PATH)) { + Write-Output "$OrigPathToAdd" | Out-File -FilePath "$gh_path" -Encoding utf8 -Append + } +} + +# Try to add the given path to PATH via the registry +# +# Returns true if the registry was modified, otherwise returns false +# (indicating it was already on PATH) +function Add-Path($OrigPathToAdd) { + Write-Verbose "Adding $OrigPathToAdd to your PATH" + $RegistryPath = "HKCU:\Environment" + $PropertyName = "Path" + $PathToAdd = $OrigPathToAdd + + $Item = if (Test-Path $RegistryPath) { + # If the registry key exists, get it + Get-Item -Path $RegistryPath + } else { + # If the registry key doesn't exist, create it + Write-Verbose "Creating $RegistryPath" + New-Item -Path $RegistryPath -Force + } + + $OldPath = "" + try { + # Try to get the old PATH value. If that fails, assume we're making it from scratch. + # Otherwise assume there's already paths in here and use a ; separator + $OldPath = $Item | Get-ItemPropertyValue -Name $PropertyName + $PathToAdd = "$PathToAdd;" + } catch { + # We'll be creating the PATH from scratch + Write-Verbose "No $PropertyName Property exists on $RegistryPath (we'll make one)" + } + + # Check if the path is already there + # + # We don't want to incorrectly match "C:\blah\" to "C:\blah\blah\", so we include the semicolon + # delimiters when searching, ensuring exact matches. To avoid corner cases we add semicolons to + # both sides of the input, allowing us to pretend we're always in the middle of a list. + Write-Verbose "Old $PropertyName Property is $OldPath" + if (";$OldPath;" -like "*;$OrigPathToAdd;*") { + # Already on path, nothing to do + Write-Verbose "install dir already on PATH, all done!" + return $false + } else { + # Actually update PATH + Write-Verbose "Actually mutating $PropertyName Property" + $NewPath = $PathToAdd + $OldPath + # We use -Force here to make the value already existing not be an error + $Item | New-ItemProperty -Name $PropertyName -Value $NewPath -PropertyType String -Force | Out-Null + return $true + } +} + +function Initialize-Environment() { + If (($PSVersionTable.PSVersion.Major) -lt 5) { + throw @" +Error: PowerShell 5 or later is required to install $app_name. +Upgrade PowerShell: + + https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell + +"@ + } + + # show notification to change execution policy: + $allowedExecutionPolicy = @('Unrestricted', 'RemoteSigned', 'ByPass') + If ((Get-ExecutionPolicy).ToString() -notin $allowedExecutionPolicy) { + throw @" +Error: PowerShell requires an execution policy in [$($allowedExecutionPolicy -join ", ")] to run $app_name. For example, to set the execution policy to 'RemoteSigned' please run: + + Set-ExecutionPolicy RemoteSigned -scope CurrentUser + +"@ + } + + # GitHub requires TLS 1.2 + If ([System.Enum]::GetNames([System.Net.SecurityProtocolType]) -notcontains 'Tls12') { + throw @" +Error: Installing $app_name requires at least .NET Framework 4.5 +Please download and install it first: + + https://www.microsoft.com/net/download + +"@ + } +} + +function New-Temp-Dir() { + [CmdletBinding(SupportsShouldProcess)] + param() + $parent = [System.IO.Path]::GetTempPath() + [string] $name = [System.Guid]::NewGuid() + New-Item -ItemType Directory -Path (Join-Path $parent $name) +} + +# PSScriptAnalyzer doesn't like how we use our params as globals, this calms it +$Null = $ArtifactDownloadUrl, $NoModifyPath, $Help +# Make Write-Information statements be visible +$InformationPreference = "Continue" + +# The default interactive handler +try { + Install-Binary "$Args" +} catch { + Write-Information $_ + exit 1 +} diff --git a/aider/website/install.sh b/aider/website/install.sh new file mode 100644 index 000000000..e0e234826 --- /dev/null +++ b/aider/website/install.sh @@ -0,0 +1,1832 @@ +#!/bin/sh +# shellcheck shell=dash +# +# Licensed under the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +if [ "$KSH_VERSION" = 'Version JM 93t+ 2010-03-05' ]; then + # The version of ksh93 that ships with many illumos systems does not + # support the "local" extension. Print a message rather than fail in + # subtle ways later on: + echo 'this installer does not work with this ksh93 version; please try bash!' >&2 + exit 1 +fi + +set -u + +APP_NAME="uv" +APP_VERSION="0.5.9" +# Look for GitHub Enterprise-style base URL first +if [ -n "${UV_INSTALLER_GHE_BASE_URL:-}" ]; then + INSTALLER_BASE_URL="$UV_INSTALLER_GHE_BASE_URL" +else + INSTALLER_BASE_URL="${UV_INSTALLER_GITHUB_BASE_URL:-https://github.com}" +fi +if [ -n "${INSTALLER_DOWNLOAD_URL:-}" ]; then + ARTIFACT_DOWNLOAD_URL="$INSTALLER_DOWNLOAD_URL" +else + ARTIFACT_DOWNLOAD_URL="${INSTALLER_BASE_URL}/astral-sh/uv/releases/download/0.5.9" +fi +PRINT_VERBOSE=${INSTALLER_PRINT_VERBOSE:-0} +PRINT_QUIET=${INSTALLER_PRINT_QUIET:-0} +if [ -n "${UV_NO_MODIFY_PATH:-}" ]; then + NO_MODIFY_PATH="$UV_NO_MODIFY_PATH" +else + NO_MODIFY_PATH=${INSTALLER_NO_MODIFY_PATH:-0} +fi +if [ "${UV_DISABLE_UPDATE:-0}" = "1" ]; then + INSTALL_UPDATER=0 +else + INSTALL_UPDATER=1 +fi +UNMANAGED_INSTALL="${UV_UNMANAGED_INSTALL:-}" +if [ -n "${UNMANAGED_INSTALL}" ]; then + NO_MODIFY_PATH=1 + INSTALL_UPDATER=0 +fi + +read -r RECEIPT <&2 + say_verbose " from $_url" 1>&2 + say_verbose " to $_file" 1>&2 + + ensure mkdir -p "$_dir" + + if ! downloader "$_url" "$_file"; then + say "failed to download $_url" + say "this may be a standard network error, but it may also indicate" + say "that $APP_NAME's release process is not working. When in doubt" + say "please feel free to open an issue!" + exit 1 + fi + + if [ -n "${_checksum_style:-}" ]; then + verify_checksum "$_file" "$_checksum_style" "$_checksum_value" + else + say "no checksums to verify" + fi + + # ...and then the updater, if it exists + if [ -n "$_updater_name" ] && [ "$INSTALL_UPDATER" = "1" ]; then + local _updater_url="$ARTIFACT_DOWNLOAD_URL/$_updater_name" + # This renames the artifact while doing the download, removing the + # target triple and leaving just the appname-update format + local _updater_file="$_dir/$APP_NAME-update" + + if ! downloader "$_updater_url" "$_updater_file"; then + say "failed to download $_updater_url" + say "this may be a standard network error, but it may also indicate" + say "that $APP_NAME's release process is not working. When in doubt" + say "please feel free to open an issue!" + exit 1 + fi + + # Add the updater to the list of binaries to install + _bins="$_bins $APP_NAME-update" + fi + + # unpack the archive + case "$_zip_ext" in + ".zip") + ensure unzip -q "$_file" -d "$_dir" + ;; + + ".tar."*) + ensure tar xf "$_file" --strip-components 1 -C "$_dir" + ;; + *) + err "unknown archive format: $_zip_ext" + ;; + esac + + install "$_dir" "$_bins" "$_libs" "$_staticlibs" "$_arch" "$@" + local _retval=$? + if [ "$_retval" != 0 ]; then + return "$_retval" + fi + + ignore rm -rf "$_dir" + + # Install the install receipt + if [ "$INSTALL_UPDATER" = "1" ]; then + if ! mkdir -p "$RECEIPT_HOME"; then + err "unable to create receipt directory at $RECEIPT_HOME" + else + echo "$RECEIPT" > "$RECEIPT_HOME/$APP_NAME-receipt.json" + # shellcheck disable=SC2320 + local _retval=$? + fi + else + local _retval=0 + fi + + return "$_retval" +} + +# Replaces $HOME with the variable name for display to the user, +# only if $HOME is defined. +replace_home() { + local _str="$1" + + if [ -n "${HOME:-}" ]; then + echo "$_str" | sed "s,$HOME,\$HOME," + else + echo "$_str" + fi +} + +json_binary_aliases() { + local _arch="$1" + + case "$_arch" in + "aarch64-apple-darwin") + echo '{}' + ;; + "aarch64-unknown-linux-gnu") + echo '{}' + ;; + "aarch64-unknown-linux-musl-dynamic") + echo '{}' + ;; + "aarch64-unknown-linux-musl-static") + echo '{}' + ;; + "arm-unknown-linux-gnueabihf") + echo '{}' + ;; + "arm-unknown-linux-musl-dynamiceabihf") + echo '{}' + ;; + "arm-unknown-linux-musl-staticeabihf") + echo '{}' + ;; + "armv7-unknown-linux-gnueabihf") + echo '{}' + ;; + "armv7-unknown-linux-musl-dynamiceabihf") + echo '{}' + ;; + "armv7-unknown-linux-musl-staticeabihf") + echo '{}' + ;; + "i686-pc-windows-gnu") + echo '{}' + ;; + "i686-unknown-linux-gnu") + echo '{}' + ;; + "i686-unknown-linux-musl-dynamic") + echo '{}' + ;; + "i686-unknown-linux-musl-static") + echo '{}' + ;; + "powerpc64-unknown-linux-gnu") + echo '{}' + ;; + "powerpc64le-unknown-linux-gnu") + echo '{}' + ;; + "s390x-unknown-linux-gnu") + echo '{}' + ;; + "x86_64-apple-darwin") + echo '{}' + ;; + "x86_64-pc-windows-gnu") + echo '{}' + ;; + "x86_64-unknown-linux-gnu") + echo '{}' + ;; + "x86_64-unknown-linux-musl-dynamic") + echo '{}' + ;; + "x86_64-unknown-linux-musl-static") + echo '{}' + ;; + *) + echo '{}' + ;; + esac +} + +aliases_for_binary() { + local _bin="$1" + local _arch="$2" + + case "$_arch" in + "aarch64-apple-darwin") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "aarch64-unknown-linux-gnu") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "aarch64-unknown-linux-musl-dynamic") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "aarch64-unknown-linux-musl-static") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "arm-unknown-linux-gnueabihf") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "arm-unknown-linux-musl-dynamiceabihf") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "arm-unknown-linux-musl-staticeabihf") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "armv7-unknown-linux-gnueabihf") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "armv7-unknown-linux-musl-dynamiceabihf") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "armv7-unknown-linux-musl-staticeabihf") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "i686-pc-windows-gnu") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "i686-unknown-linux-gnu") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "i686-unknown-linux-musl-dynamic") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "i686-unknown-linux-musl-static") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "powerpc64-unknown-linux-gnu") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "powerpc64le-unknown-linux-gnu") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "s390x-unknown-linux-gnu") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "x86_64-apple-darwin") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "x86_64-pc-windows-gnu") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "x86_64-unknown-linux-gnu") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "x86_64-unknown-linux-musl-dynamic") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + "x86_64-unknown-linux-musl-static") + case "$_bin" in + *) + echo "" + ;; + esac + ;; + *) + echo "" + ;; + esac +} + +select_archive_for_arch() { + local _true_arch="$1" + local _archive + + # try each archive, checking runtime conditions like libc versions + # accepting the first one that matches, as it's the best match + case "$_true_arch" in + "aarch64-apple-darwin") + _archive="uv-aarch64-apple-darwin.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + _archive="uv-x86_64-apple-darwin.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "aarch64-pc-windows-msvc") + _archive="uv-x86_64-pc-windows-msvc.zip" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + _archive="uv-i686-pc-windows-msvc.zip" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "aarch64-unknown-linux-gnu") + _archive="uv-aarch64-unknown-linux-gnu.tar.gz" + if ! check_glibc "2" "31"; then + _archive="" + fi + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + _archive="uv-aarch64-unknown-linux-musl.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "aarch64-unknown-linux-musl-dynamic") + _archive="uv-aarch64-unknown-linux-musl.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "aarch64-unknown-linux-musl-static") + _archive="uv-aarch64-unknown-linux-musl.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "arm-unknown-linux-gnueabihf") + _archive="uv-arm-unknown-linux-musleabihf.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "arm-unknown-linux-musl-dynamiceabihf") + _archive="uv-arm-unknown-linux-musleabihf.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "arm-unknown-linux-musl-staticeabihf") + _archive="uv-arm-unknown-linux-musleabihf.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "armv7-unknown-linux-gnueabihf") + _archive="uv-armv7-unknown-linux-gnueabihf.tar.gz" + if ! check_glibc "2" "31"; then + _archive="" + fi + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + _archive="uv-armv7-unknown-linux-musleabihf.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "armv7-unknown-linux-musl-dynamiceabihf") + _archive="uv-armv7-unknown-linux-musleabihf.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "armv7-unknown-linux-musl-staticeabihf") + _archive="uv-armv7-unknown-linux-musleabihf.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "i686-pc-windows-gnu") + _archive="uv-i686-pc-windows-msvc.zip" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "i686-pc-windows-msvc") + _archive="uv-i686-pc-windows-msvc.zip" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "i686-unknown-linux-gnu") + _archive="uv-i686-unknown-linux-gnu.tar.gz" + if ! check_glibc "2" "31"; then + _archive="" + fi + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + _archive="uv-i686-unknown-linux-musl.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "i686-unknown-linux-musl-dynamic") + _archive="uv-i686-unknown-linux-musl.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "i686-unknown-linux-musl-static") + _archive="uv-i686-unknown-linux-musl.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "powerpc64-unknown-linux-gnu") + _archive="uv-powerpc64-unknown-linux-gnu.tar.gz" + if ! check_glibc "2" "31"; then + _archive="" + fi + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "powerpc64le-unknown-linux-gnu") + _archive="uv-powerpc64le-unknown-linux-gnu.tar.gz" + if ! check_glibc "2" "31"; then + _archive="" + fi + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "s390x-unknown-linux-gnu") + _archive="uv-s390x-unknown-linux-gnu.tar.gz" + if ! check_glibc "2" "31"; then + _archive="" + fi + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "x86_64-apple-darwin") + _archive="uv-x86_64-apple-darwin.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "x86_64-pc-windows-gnu") + _archive="uv-x86_64-pc-windows-msvc.zip" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "x86_64-pc-windows-msvc") + _archive="uv-x86_64-pc-windows-msvc.zip" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + _archive="uv-i686-pc-windows-msvc.zip" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "x86_64-unknown-linux-gnu") + _archive="uv-x86_64-unknown-linux-gnu.tar.gz" + if ! check_glibc "2" "31"; then + _archive="" + fi + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + _archive="uv-x86_64-unknown-linux-musl.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "x86_64-unknown-linux-musl-dynamic") + _archive="uv-x86_64-unknown-linux-musl.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + "x86_64-unknown-linux-musl-static") + _archive="uv-x86_64-unknown-linux-musl.tar.gz" + if [ -n "$_archive" ]; then + echo "$_archive" + return 0 + fi + ;; + *) + err "there isn't a download for your platform $_true_arch" + ;; + esac + err "no compatible downloads were found for your platform $_true_arch" +} + +check_glibc() { + local _min_glibc_major="$1" + local _min_glibc_series="$2" + + # Parsing version out from line 1 like: + # ldd (Ubuntu GLIBC 2.35-0ubuntu3.1) 2.35 + _local_glibc="$(ldd --version | awk -F' ' '{ if (FNR<=1) print $NF }')" + + if [ "$(echo "${_local_glibc}" | awk -F. '{ print $1 }')" = "$_min_glibc_major" ] && [ "$(echo "${_local_glibc}" | awk -F. '{ print $2 }')" -ge "$_min_glibc_series" ]; then + return 0 + else + say "System glibc version (\`${_local_glibc}') is too old; checking alternatives" >&2 + return 1 + fi +} + +# See discussion of late-bound vs early-bound for why we use single-quotes with env vars +# shellcheck disable=SC2016 +install() { + # This code needs to both compute certain paths for itself to write to, and + # also write them to shell/rc files so that they can look them up to e.g. + # add them to PATH. This requires an active distinction between paths + # and expressions that can compute them. + # + # The distinction lies in when we want env-vars to be evaluated. For instance + # if we determine that we want to install to $HOME/.myapp, which do we add + # to e.g. $HOME/.profile: + # + # * early-bound: export PATH="/home/myuser/.myapp:$PATH" + # * late-bound: export PATH="$HOME/.myapp:$PATH" + # + # In this case most people would prefer the late-bound version, but in other + # cases the early-bound version might be a better idea. In particular when using + # other env-vars than $HOME, they are more likely to be only set temporarily + # for the duration of this install script, so it's more advisable to erase their + # existence with early-bounding. + # + # This distinction is handled by "double-quotes" (early) vs 'single-quotes' (late). + # + # However if we detect that "$SOME_VAR/..." is a subdir of $HOME, we try to rewrite + # it to be '$HOME/...' to get the best of both worlds. + # + # This script has a few different variants, the most complex one being the + # CARGO_HOME version which attempts to install things to Cargo's bin dir, + # potentially setting up a minimal version if the user hasn't ever installed Cargo. + # + # In this case we need to: + # + # * Install to $HOME/.cargo/bin/ + # * Create a shell script at $HOME/.cargo/env that: + # * Checks if $HOME/.cargo/bin/ is on PATH + # * and if not prepends it to PATH + # * Edits $HOME/.profile to run $HOME/.cargo/env (if the line doesn't exist) + # + # To do this we need these 4 values: + + # The actual path we're going to install to + local _install_dir + # The directory C dynamic/static libraries install to + local _lib_install_dir + # The install prefix we write to the receipt. + # For organized install methods like CargoHome, which have + # subdirectories, this is the root without `/bin`. For other + # methods, this is the same as `_install_dir`. + local _receipt_install_dir + # Path to the an shell script that adds install_dir to PATH + local _env_script_path + # Potentially-late-bound version of install_dir to write env_script + local _install_dir_expr + # Potentially-late-bound version of env_script_path to write to rcfiles like $HOME/.profile + local _env_script_path_expr + # Forces the install to occur at this path, not the default + local _force_install_dir + # Which install layout to use - "flat" or "hierarchical" + local _install_layout="unspecified" + + # Check the newer app-specific variable before falling back + # to the older generic one + if [ -n "${UV_INSTALL_DIR:-}" ]; then + _force_install_dir="$UV_INSTALL_DIR" + _install_layout="flat" + elif [ -n "${CARGO_DIST_FORCE_INSTALL_DIR:-}" ]; then + _force_install_dir="$CARGO_DIST_FORCE_INSTALL_DIR" + _install_layout="flat" + elif [ -n "$UNMANAGED_INSTALL" ]; then + _force_install_dir="$UNMANAGED_INSTALL" + _install_layout="flat" + fi + + # Check if the install layout should be changed from `flat` to `cargo-home` + # for backwards compatible updates of applications that switched layouts. + if [ -n "${_force_install_dir:-}" ]; then + if [ "$_install_layout" = "flat" ]; then + # If the install directory is targeting the Cargo home directory, then + # we assume this application was previously installed that layout + if [ "$_force_install_dir" = "${CARGO_HOME:-${HOME:-}/.cargo}" ]; then + _install_layout="cargo-home" + fi + fi + fi + + # Before actually consulting the configured install strategy, see + # if we're overriding it. + if [ -n "${_force_install_dir:-}" ]; then + case "$_install_layout" in + "hierarchical") + _install_dir="$_force_install_dir/bin" + _lib_install_dir="$_force_install_dir/lib" + _receipt_install_dir="$_force_install_dir" + _env_script_path="$_force_install_dir/env" + _install_dir_expr="$(replace_home "$_force_install_dir/bin")" + _env_script_path_expr="$(replace_home "$_force_install_dir/env")" + ;; + "cargo-home") + _install_dir="$_force_install_dir/bin" + _lib_install_dir="$_force_install_dir/bin" + _receipt_install_dir="$_force_install_dir" + _env_script_path="$_force_install_dir/env" + _install_dir_expr="$(replace_home "$_force_install_dir/bin")" + _env_script_path_expr="$(replace_home "$_force_install_dir/env")" + ;; + "flat") + _install_dir="$_force_install_dir" + _lib_install_dir="$_force_install_dir" + _receipt_install_dir="$_install_dir" + _env_script_path="$_force_install_dir/env" + _install_dir_expr="$(replace_home "$_force_install_dir")" + _env_script_path_expr="$(replace_home "$_force_install_dir/env")" + ;; + *) + err "Unrecognized install layout: $_install_layout" + ;; + esac + fi + if [ -z "${_install_dir:-}" ]; then + _install_layout="flat" + # Install to $XDG_BIN_HOME + if [ -n "${XDG_BIN_HOME:-}" ]; then + _install_dir="$XDG_BIN_HOME" + _lib_install_dir="$_install_dir" + _receipt_install_dir="$_install_dir" + _env_script_path="$XDG_BIN_HOME/env" + _install_dir_expr="$(replace_home "$_install_dir")" + _env_script_path_expr="$(replace_home "$_env_script_path")" + fi + fi + if [ -z "${_install_dir:-}" ]; then + _install_layout="flat" + # Install to $XDG_DATA_HOME/../bin + if [ -n "${XDG_DATA_HOME:-}" ]; then + _install_dir="$XDG_DATA_HOME/../bin" + _lib_install_dir="$_install_dir" + _receipt_install_dir="$_install_dir" + _env_script_path="$XDG_DATA_HOME/../bin/env" + _install_dir_expr="$(replace_home "$_install_dir")" + _env_script_path_expr="$(replace_home "$_env_script_path")" + fi + fi + if [ -z "${_install_dir:-}" ]; then + _install_layout="flat" + # Install to $HOME/.local/bin + if [ -n "${HOME:-}" ]; then + _install_dir="$HOME/.local/bin" + _lib_install_dir="$HOME/.local/bin" + _receipt_install_dir="$_install_dir" + _env_script_path="$HOME/.local/bin/env" + _install_dir_expr='$HOME/.local/bin' + _env_script_path_expr='$HOME/.local/bin/env' + fi + fi + + if [ -z "$_install_dir_expr" ]; then + err "could not find a valid path to install to!" + fi + + # Identical to the sh version, just with a .fish file extension + # We place it down here to wait until it's been assigned in every + # path. + _fish_env_script_path="${_env_script_path}.fish" + _fish_env_script_path_expr="${_env_script_path_expr}.fish" + + # Replace the temporary cargo home with the calculated one + RECEIPT=$(echo "$RECEIPT" | sed "s,AXO_INSTALL_PREFIX,$_receipt_install_dir,") + # Also replace the aliases with the arch-specific one + RECEIPT=$(echo "$RECEIPT" | sed "s'\"binary_aliases\":{}'\"binary_aliases\":$(json_binary_aliases "$_arch")'") + # And replace the install layout + RECEIPT=$(echo "$RECEIPT" | sed "s'\"install_layout\":\"unspecified\"'\"install_layout\":\"$_install_layout\"'") + if [ "$NO_MODIFY_PATH" = "1" ]; then + RECEIPT=$(echo "$RECEIPT" | sed "s'\"modify_path\":true'\"modify_path\":false'") + fi + + say "installing to $_install_dir" + ensure mkdir -p "$_install_dir" + ensure mkdir -p "$_lib_install_dir" + + # copy all the binaries to the install dir + local _src_dir="$1" + local _bins="$2" + local _libs="$3" + local _staticlibs="$4" + local _arch="$5" + for _bin_name in $_bins; do + local _bin="$_src_dir/$_bin_name" + ensure mv "$_bin" "$_install_dir" + # unzip seems to need this chmod + ensure chmod +x "$_install_dir/$_bin_name" + for _dest in $(aliases_for_binary "$_bin_name" "$_arch"); do + ln -sf "$_install_dir/$_bin_name" "$_install_dir/$_dest" + done + say " $_bin_name" + done + # Like the above, but no aliases + for _lib_name in $_libs; do + local _lib="$_src_dir/$_lib_name" + ensure mv "$_lib" "$_lib_install_dir" + # unzip seems to need this chmod + ensure chmod +x "$_lib_install_dir/$_lib_name" + say " $_lib_name" + done + for _lib_name in $_staticlibs; do + local _lib="$_src_dir/$_lib_name" + ensure mv "$_lib" "$_lib_install_dir" + # unzip seems to need this chmod + ensure chmod +x "$_lib_install_dir/$_lib_name" + say " $_lib_name" + done + + say "uv is installed!" + + say "" + say "Installing aider..." + say "" + # Install aider-chat using the newly installed uv + ensure "${_install_dir}/uv" tool install --force --python python3.12 aider-chat@latest + + # Avoid modifying the users PATH if they are managing their PATH manually + case :$PATH: + in *:$_install_dir:*) NO_MODIFY_PATH=1 ;; + *) ;; + esac + + if [ "0" = "$NO_MODIFY_PATH" ]; then + add_install_dir_to_ci_path "$_install_dir" + add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".profile" "sh" + exit1=$? + shotgun_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".profile .bashrc .bash_profile .bash_login" "sh" + exit2=$? + add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".zshrc .zshenv" "sh" + exit3=$? + # This path may not exist by default + ensure mkdir -p "$HOME/.config/fish/conf.d" + exit4=$? + add_install_dir_to_path "$_install_dir_expr" "$_fish_env_script_path" "$_fish_env_script_path_expr" ".config/fish/conf.d/$APP_NAME.env.fish" "fish" + exit5=$? + + if [ "${exit1:-0}" = 1 ] || [ "${exit2:-0}" = 1 ] || [ "${exit3:-0}" = 1 ] || [ "${exit4:-0}" = 1 ] || [ "${exit5:-0}" = 1 ]; then + say "" + say "To add $_install_dir_expr to your PATH, either restart your shell or run:" + say "" + say " source $_env_script_path_expr (sh, bash, zsh)" + say " source $_fish_env_script_path_expr (fish)" + fi + fi + +} + +print_home_for_script() { + local script="$1" + + local _home + case "$script" in + # zsh has a special ZDOTDIR directory, which if set + # should be considered instead of $HOME + .zsh*) + if [ -n "${ZDOTDIR:-}" ]; then + _home="$ZDOTDIR" + else + _home="$HOME" + fi + ;; + *) + _home="$HOME" + ;; + esac + + echo "$_home" +} + +add_install_dir_to_ci_path() { + # Attempt to do CI-specific rituals to get the install-dir on PATH faster + local _install_dir="$1" + + # If GITHUB_PATH is present, then write install_dir to the file it refs. + # After each GitHub Action, the contents will be added to PATH. + # So if you put a curl | sh for this script in its own "run" step, + # the next step will have this dir on PATH. + # + # Note that GITHUB_PATH will not resolve any variables, so we in fact + # want to write install_dir and not install_dir_expr + if [ -n "${GITHUB_PATH:-}" ]; then + ensure echo "$_install_dir" >> "$GITHUB_PATH" + fi +} + +add_install_dir_to_path() { + # Edit rcfiles ($HOME/.profile) to add install_dir to $PATH + # + # We do this slightly indirectly by creating an "env" shell script which checks if install_dir + # is on $PATH already, and prepends it if not. The actual line we then add to rcfiles + # is to just source that script. This allows us to blast it into lots of different rcfiles and + # have it run multiple times without causing problems. It's also specifically compatible + # with the system rustup uses, so that we don't conflict with it. + local _install_dir_expr="$1" + local _env_script_path="$2" + local _env_script_path_expr="$3" + local _rcfiles="$4" + local _shell="$5" + + if [ -n "${HOME:-}" ]; then + local _target + local _home + + # Find the first file in the array that exists and choose + # that as our target to write to + for _rcfile_relative in $_rcfiles; do + _home="$(print_home_for_script "$_rcfile_relative")" + local _rcfile="$_home/$_rcfile_relative" + + if [ -f "$_rcfile" ]; then + _target="$_rcfile" + break + fi + done + + # If we didn't find anything, pick the first entry in the + # list as the default to create and write to + if [ -z "${_target:-}" ]; then + local _rcfile_relative + _rcfile_relative="$(echo "$_rcfiles" | awk '{ print $1 }')" + _home="$(print_home_for_script "$_rcfile_relative")" + _target="$_home/$_rcfile_relative" + fi + + # `source x` is an alias for `. x`, and the latter is more portable/actually-posix. + # This apparently comes up a lot on freebsd. It's easy enough to always add + # the more robust line to rcfiles, but when telling the user to apply the change + # to their current shell ". x" is pretty easy to misread/miscopy, so we use the + # prettier "source x" line there. Hopefully people with Weird Shells are aware + # this is a thing and know to tweak it (or just restart their shell). + local _robust_line=". \"$_env_script_path_expr\"" + local _pretty_line="source \"$_env_script_path_expr\"" + + # Add the env script if it doesn't already exist + if [ ! -f "$_env_script_path" ]; then + say_verbose "creating $_env_script_path" + if [ "$_shell" = "sh" ]; then + write_env_script_sh "$_install_dir_expr" "$_env_script_path" + else + write_env_script_fish "$_install_dir_expr" "$_env_script_path" + fi + else + say_verbose "$_env_script_path already exists" + fi + + # Check if the line is already in the rcfile + # grep: 0 if matched, 1 if no match, and 2 if an error occurred + # + # Ideally we could use quiet grep (-q), but that makes "match" and "error" + # have the same behaviour, when we want "no match" and "error" to be the same + # (on error we want to create the file, which >> conveniently does) + # + # We search for both kinds of line here just to do the right thing in more cases. + if ! grep -F "$_robust_line" "$_target" > /dev/null 2>/dev/null && \ + ! grep -F "$_pretty_line" "$_target" > /dev/null 2>/dev/null + then + # If the script now exists, add the line to source it to the rcfile + # (This will also create the rcfile if it doesn't exist) + if [ -f "$_env_script_path" ]; then + local _line + # Fish has deprecated `.` as an alias for `source` and + # it will be removed in a later version. + # https://fishshell.com/docs/current/cmds/source.html + # By contrast, `.` is the traditional syntax in sh and + # `source` isn't always supported in all circumstances. + if [ "$_shell" = "fish" ]; then + _line="$_pretty_line" + else + _line="$_robust_line" + fi + say_verbose "adding $_line to $_target" + # prepend an extra newline in case the user's file is missing a trailing one + ensure echo "" >> "$_target" + ensure echo "$_line" >> "$_target" + return 1 + fi + else + say_verbose "$_install_dir already on PATH" + fi + fi +} + +shotgun_install_dir_to_path() { + # Edit rcfiles ($HOME/.profile) to add install_dir to $PATH + # (Shotgun edition - write to all provided files that exist rather than just the first) + local _install_dir_expr="$1" + local _env_script_path="$2" + local _env_script_path_expr="$3" + local _rcfiles="$4" + local _shell="$5" + + if [ -n "${HOME:-}" ]; then + local _found=false + local _home + + for _rcfile_relative in $_rcfiles; do + _home="$(print_home_for_script "$_rcfile_relative")" + local _rcfile_abs="$_home/$_rcfile_relative" + + if [ -f "$_rcfile_abs" ]; then + _found=true + add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" "$_rcfile_relative" "$_shell" + fi + done + + # Fall through to previous "create + write to first file in list" behavior + if [ "$_found" = false ]; then + add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" "$_rcfiles" "$_shell" + fi + fi +} + +write_env_script_sh() { + # write this env script to the given path (this cat/EOF stuff is a "heredoc" string) + local _install_dir_expr="$1" + local _env_script_path="$2" + ensure cat < "$_env_script_path" +#!/bin/sh +# add binaries to PATH if they aren't added yet +# affix colons on either side of \$PATH to simplify matching +case ":\${PATH}:" in + *:"$_install_dir_expr":*) + ;; + *) + # Prepending path in case a system-installed binary needs to be overridden + export PATH="$_install_dir_expr:\$PATH" + ;; +esac +EOF +} + +write_env_script_fish() { + # write this env script to the given path (this cat/EOF stuff is a "heredoc" string) + local _install_dir_expr="$1" + local _env_script_path="$2" + ensure cat < "$_env_script_path" +if not contains "$_install_dir_expr" \$PATH + # Prepending path in case a system-installed binary needs to be overridden + set -x PATH "$_install_dir_expr" \$PATH +end +EOF +} + +check_proc() { + # Check for /proc by looking for the /proc/self/exe link + # This is only run on Linux + if ! test -L /proc/self/exe ; then + err "fatal: Unable to find /proc/self/exe. Is /proc mounted? Installation cannot proceed without /proc." + fi +} + +get_bitness() { + need_cmd head + # Architecture detection without dependencies beyond coreutils. + # ELF files start out "\x7fELF", and the following byte is + # 0x01 for 32-bit and + # 0x02 for 64-bit. + # The printf builtin on some shells like dash only supports octal + # escape sequences, so we use those. + local _current_exe_head + _current_exe_head=$(head -c 5 /proc/self/exe ) + if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then + echo 32 + elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then + echo 64 + else + err "unknown platform bitness" + fi +} + +is_host_amd64_elf() { + need_cmd head + need_cmd tail + # ELF e_machine detection without dependencies beyond coreutils. + # Two-byte field at offset 0x12 indicates the CPU, + # but we're interested in it being 0x3E to indicate amd64, or not that. + local _current_exe_machine + _current_exe_machine=$(head -c 19 /proc/self/exe | tail -c 1) + [ "$_current_exe_machine" = "$(printf '\076')" ] +} + +get_endianness() { + local cputype=$1 + local suffix_eb=$2 + local suffix_el=$3 + + # detect endianness without od/hexdump, like get_bitness() does. + need_cmd head + need_cmd tail + + local _current_exe_endianness + _current_exe_endianness="$(head -c 6 /proc/self/exe | tail -c 1)" + if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then + echo "${cputype}${suffix_el}" + elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then + echo "${cputype}${suffix_eb}" + else + err "unknown platform endianness" + fi +} + +get_architecture() { + local _ostype + local _cputype + _ostype="$(uname -s)" + _cputype="$(uname -m)" + local _clibtype="gnu" + local _local_glibc + + if [ "$_ostype" = Linux ]; then + if [ "$(uname -o)" = Android ]; then + _ostype=Android + fi + if ldd --version 2>&1 | grep -q 'musl'; then + _clibtype="musl-dynamic" + else + # Assume all other linuxes are glibc (even if wrong, static libc fallback will apply) + _clibtype="gnu" + fi + fi + + if [ "$_ostype" = Darwin ] && [ "$_cputype" = i386 ]; then + # Darwin `uname -m` lies + if sysctl hw.optional.x86_64 | grep -q ': 1'; then + _cputype=x86_64 + fi + fi + + if [ "$_ostype" = Darwin ] && [ "$_cputype" = x86_64 ]; then + # Rosetta on aarch64 + if [ "$(sysctl -n hw.optional.arm64 2>/dev/null)" = "1" ]; then + _cputype=aarch64 + fi + fi + + if [ "$_ostype" = SunOS ]; then + # Both Solaris and illumos presently announce as "SunOS" in "uname -s" + # so use "uname -o" to disambiguate. We use the full path to the + # system uname in case the user has coreutils uname first in PATH, + # which has historically sometimes printed the wrong value here. + if [ "$(/usr/bin/uname -o)" = illumos ]; then + _ostype=illumos + fi + + # illumos systems have multi-arch userlands, and "uname -m" reports the + # machine hardware name; e.g., "i86pc" on both 32- and 64-bit x86 + # systems. Check for the native (widest) instruction set on the + # running kernel: + if [ "$_cputype" = i86pc ]; then + _cputype="$(isainfo -n)" + fi + fi + + case "$_ostype" in + + Android) + _ostype=linux-android + ;; + + Linux) + check_proc + _ostype=unknown-linux-$_clibtype + _bitness=$(get_bitness) + ;; + + FreeBSD) + _ostype=unknown-freebsd + ;; + + NetBSD) + _ostype=unknown-netbsd + ;; + + DragonFly) + _ostype=unknown-dragonfly + ;; + + Darwin) + _ostype=apple-darwin + ;; + + illumos) + _ostype=unknown-illumos + ;; + + MINGW* | MSYS* | CYGWIN* | Windows_NT) + _ostype=pc-windows-gnu + ;; + + *) + err "unrecognized OS type: $_ostype" + ;; + + esac + + case "$_cputype" in + + i386 | i486 | i686 | i786 | x86) + _cputype=i686 + ;; + + xscale | arm) + _cputype=arm + if [ "$_ostype" = "linux-android" ]; then + _ostype=linux-androideabi + fi + ;; + + armv6l) + _cputype=arm + if [ "$_ostype" = "linux-android" ]; then + _ostype=linux-androideabi + else + _ostype="${_ostype}eabihf" + fi + ;; + + armv7l | armv8l) + _cputype=armv7 + if [ "$_ostype" = "linux-android" ]; then + _ostype=linux-androideabi + else + _ostype="${_ostype}eabihf" + fi + ;; + + aarch64 | arm64) + _cputype=aarch64 + ;; + + x86_64 | x86-64 | x64 | amd64) + _cputype=x86_64 + ;; + + mips) + _cputype=$(get_endianness mips '' el) + ;; + + mips64) + if [ "$_bitness" -eq 64 ]; then + # only n64 ABI is supported for now + _ostype="${_ostype}abi64" + _cputype=$(get_endianness mips64 '' el) + fi + ;; + + ppc) + _cputype=powerpc + ;; + + ppc64) + _cputype=powerpc64 + ;; + + ppc64le) + _cputype=powerpc64le + ;; + + s390x) + _cputype=s390x + ;; + riscv64) + _cputype=riscv64gc + ;; + loongarch64) + _cputype=loongarch64 + ;; + *) + err "unknown CPU type: $_cputype" + + esac + + # Detect 64-bit linux with 32-bit userland + if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then + case $_cputype in + x86_64) + # 32-bit executable for amd64 = x32 + if is_host_amd64_elf; then { + err "x32 linux unsupported" + }; else + _cputype=i686 + fi + ;; + mips64) + _cputype=$(get_endianness mips '' el) + ;; + powerpc64) + _cputype=powerpc + ;; + aarch64) + _cputype=armv7 + if [ "$_ostype" = "linux-android" ]; then + _ostype=linux-androideabi + else + _ostype="${_ostype}eabihf" + fi + ;; + riscv64gc) + err "riscv64 with 32-bit userland unsupported" + ;; + esac + fi + + # treat armv7 systems without neon as plain arm + if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then + if ensure grep '^Features' /proc/cpuinfo | grep -q -v neon; then + # At least one processor does not have NEON. + _cputype=arm + fi + fi + + _arch="${_cputype}-${_ostype}" + + RETVAL="$_arch" +} + +say() { + if [ "0" = "$PRINT_QUIET" ]; then + echo "$1" + fi +} + +say_verbose() { + if [ "1" = "$PRINT_VERBOSE" ]; then + echo "$1" + fi +} + +err() { + if [ "0" = "$PRINT_QUIET" ]; then + local red + local reset + red=$(tput setaf 1 2>/dev/null || echo '') + reset=$(tput sgr0 2>/dev/null || echo '') + say "${red}ERROR${reset}: $1" >&2 + fi + exit 1 +} + +need_cmd() { + if ! check_cmd "$1" + then err "need '$1' (command not found)" + fi +} + +check_cmd() { + command -v "$1" > /dev/null 2>&1 + return $? +} + +assert_nz() { + if [ -z "$1" ]; then err "assert_nz $2"; fi +} + +# Run a command that should never fail. If the command fails execution +# will immediately terminate with an error showing the failing +# command. +ensure() { + if ! "$@"; then err "command failed: $*"; fi +} + +# This is just for indicating that commands' results are being +# intentionally ignored. Usually, because it's being executed +# as part of error handling. +ignore() { + "$@" +} + +# This wraps curl or wget. Try curl first, if not installed, +# use wget instead. +downloader() { + if check_cmd curl + then _dld=curl + elif check_cmd wget + then _dld=wget + else _dld='curl or wget' # to be used in error message of need_cmd + fi + + if [ "$1" = --check ] + then need_cmd "$_dld" + elif [ "$_dld" = curl ] + then curl -sSfL "$1" -o "$2" + elif [ "$_dld" = wget ] + then wget "$1" -O "$2" + else err "Unknown downloader" # should not reach here + fi +} + +verify_checksum() { + local _file="$1" + local _checksum_style="$2" + local _checksum_value="$3" + local _calculated_checksum + + if [ -z "$_checksum_value" ]; then + return 0 + fi + case "$_checksum_style" in + sha256) + if ! check_cmd sha256sum; then + say "skipping sha256 checksum verification (it requires the 'sha256sum' command)" + return 0 + fi + _calculated_checksum="$(sha256sum -b "$_file" | awk '{printf $1}')" + ;; + sha512) + if ! check_cmd sha512sum; then + say "skipping sha512 checksum verification (it requires the 'sha512sum' command)" + return 0 + fi + _calculated_checksum="$(sha512sum -b "$_file" | awk '{printf $1}')" + ;; + sha3-256) + if ! check_cmd openssl; then + say "skipping sha3-256 checksum verification (it requires the 'openssl' command)" + return 0 + fi + _calculated_checksum="$(openssl dgst -sha3-256 "$_file" | awk '{printf $NF}')" + ;; + sha3-512) + if ! check_cmd openssl; then + say "skipping sha3-512 checksum verification (it requires the 'openssl' command)" + return 0 + fi + _calculated_checksum="$(openssl dgst -sha3-512 "$_file" | awk '{printf $NF}')" + ;; + blake2s) + if ! check_cmd b2sum; then + say "skipping blake2s checksum verification (it requires the 'b2sum' command)" + return 0 + fi + # Test if we have official b2sum with blake2s support + local _well_known_blake2s_checksum="93314a61f470985a40f8da62df10ba0546dc5216e1d45847bf1dbaa42a0e97af" + local _test_blake2s + _test_blake2s="$(printf "can do blake2s" | b2sum -a blake2s | awk '{printf $1}')" || _test_blake2s="" + + if [ "X$_test_blake2s" = "X$_well_known_blake2s_checksum" ]; then + _calculated_checksum="$(b2sum -a blake2s "$_file" | awk '{printf $1}')" || _calculated_checksum="" + else + say "skipping blake2s checksum verification (installed b2sum doesn't support blake2s)" + return 0 + fi + ;; + blake2b) + if ! check_cmd b2sum; then + say "skipping blake2b checksum verification (it requires the 'b2sum' command)" + return 0 + fi + _calculated_checksum="$(b2sum "$_file" | awk '{printf $1}')" + ;; + false) + ;; + *) + say "skipping unknown checksum style: $_checksum_style" + return 0 + ;; + esac + + if [ "$_calculated_checksum" != "$_checksum_value" ]; then + err "checksum mismatch + want: $_checksum_value + got: $_calculated_checksum" + fi +} + +download_binary_and_run_installer "$@" || exit 1 diff --git a/benchmark/Dockerfile b/benchmark/Dockerfile index f9eacd6a6..a5926dab7 100644 --- a/benchmark/Dockerfile +++ b/benchmark/Dockerfile @@ -1,8 +1,64 @@ -FROM python:3.10-slim -RUN apt-get update -RUN apt-get install -y less git build-essential +FROM buildpack-deps:jammy + +# Install Python 3.11 +RUN apt-get update && apt-get install -y \ + software-properties-common \ + cmake \ + libboost-all-dev \ + && add-apt-repository ppa:deadsnakes/ppa \ + && apt-get update \ + && apt-get install -y \ + python3.11 \ + python3.11-venv \ + python3.11-dev \ + python3-pip \ + ca-certificates-java \ + openjdk-21-jdk \ + libtbb-dev \ + && rm -rf /var/lib/apt/lists/* + +# Make python3.11 the default python3 +RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1 + +# Install Go with architecture detection +RUN ARCH=$(uname -m) && \ + if [ "$ARCH" = "x86_64" ]; then \ + GOARCH="amd64"; \ + elif [ "$ARCH" = "aarch64" ]; then \ + GOARCH="arm64"; \ + else \ + false; \ + fi && \ + curl -L "https://golang.org/dl/go1.21.5.linux-$GOARCH.tar.gz" -o go.tar.gz && \ + tar -C /usr/local -xzf go.tar.gz && \ + rm go.tar.gz +ENV PATH="/usr/local/go/bin:${PATH}" + +# Install Rust +ADD https://sh.rustup.rs /tmp/rustup.sh +RUN chmod +x /tmp/rustup.sh && /tmp/rustup.sh -y && rm /tmp/rustup.sh +ENV PATH="/root/.cargo/bin:${PATH}" + +# Install Node.js and dependencies +RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ + apt-get install -y nodejs && \ + rm -rf /var/lib/apt/lists/* && \ + mkdir -p /npm-install && \ + cd /npm-install && \ + npm init -y && \ + npm install \ + jest \ + @babel/core@7.25.2 \ + @exercism/babel-preset-javascript@0.2.1 \ + @exercism/eslint-config-javascript@0.6.0 \ + @types/jest@29.5.12 \ + @types/node@20.12.12 \ + babel-jest@29.6.4 \ + core-js@3.37.1 \ + eslint@8.49.0 + COPY . /aider -RUN pip install --no-cache-dir --upgrade pip -RUN pip install --no-cache-dir -e /aider[dev] +RUN pip3 install --no-cache-dir --upgrade pip uv +RUN uv pip install --system --no-cache-dir -e /aider[dev] RUN git config --global --add safe.directory /aider WORKDIR /aider diff --git a/benchmark/README.md b/benchmark/README.md index 494806823..b9e1b1e43 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -1,24 +1,23 @@ -# Aider code editing benchmark harness +# Aider benchmark harness -Aider uses a "code editing" benchmark to quantitatively measure how well it works -with the GPT-3.5 and GPT-4 models. +Aider uses benchmarks to quantitatively measure how well it works +with various LLMs. This directory holds the harness and tools needed to run the benchmarking suite. ## Background -The benchmark is based on the [Exercism -python](https://github.com/exercism/python) coding exercises. +The benchmark is based on the [Exercism](https://github.com/exercism/python) coding exercises. This -benchmark evaluates how effectively aider and GPT can translate a +benchmark evaluates how effectively aider and LLMs can translate a natural language coding request into executable code saved into files that pass unit tests. It provides an end-to-end evaluation of not just -GPT's coding ability, but also its capacity to *edit existing code* +the LLM's coding ability, but also its capacity to *edit existing code* and *format those code edits* so that aider can save the edits to the local source files. -See [this writeup for a longer discussion about the benchmark and how to interpret the results](https://aider.chat/docs/benchmarks.html). +See [this writeup for a longer discussion about the benchmark](https://aider.chat/2024/12/21/polyglot.html). The benchmark is intended to be run *inside a docker container*. This is because the benchmarking harness will be @@ -33,7 +32,7 @@ There are 3 main tasks involved in benchmarking aider: 1. Install and setup for benchmarking. -2. Run the benchmark to measure performance across the 133 exercises. +2. Run the benchmark to measure performance across all the exercises. 3. Generate a summary report of how many of the exercises succeeded or failed. @@ -50,11 +49,8 @@ git clone git@github.com:Aider-AI/aider.git cd aider mkdir tmp.benchmarks -# Clone the exercism repo -git clone git@github.com:exercism/python.git - -# Copy the practice exercises into the benchmark scratch dir -cp -rp python/exercises/practice tmp.benchmarks/exercism-python +# Clone the repo with the exercises +git clone https://github.com/Aider-AI/polyglot-benchmark tmp.benchmarks/polyglot-benchmark # Build the docker container ./benchmark/docker_build.sh @@ -70,21 +66,21 @@ Launch the docker container and run the benchmark inside it: # Inside the container, install aider as a development build. # This way you're running the code that you cloned above, including any local changes. -pip install -e . +pip install -e .[dev] # Run the benchmark: -./benchmark/benchmark.py a-helpful-name-for-this-run --model gpt-3.5-turbo --edit-format whole --threads 10 +./benchmark/benchmark.py a-helpful-name-for-this-run --model gpt-3.5-turbo --edit-format whole --threads 10 --exercises-dir polyglot-benchmark ``` The above will create a folder `tmp.benchmarks/YYYY-MM-DD-HH-MM-SS--a-helpful-name-for-this-run` with benchmarking results. -Run like this, the script will run all 133 exercises in a random order. +Run like this, the script will run all the exercises in a random order. You can run `./benchmark/benchmark.py --help` for a list of all the arguments, but here are the most useful to keep in mind: - `--model` is the name of the model, same as you would pass directly to `aider`. - `--edit-format` is the name of the edit format, same as you would pass directly to `aider`. When working with an experimental LLM, I recommend starting with `whole` - `--threads` specifies how many exercises to benchmark in parallel. Start with a single thread if you are working out the kinks on your benchmarking setup or working with a new model, etc. Once you are getting reliable results, you can speed up the process by running with more threads. 10 works well against the OpenAI APIs. -- `--num-tests` specifies how many of the 133 tests to run before stopping. This is another way to start gently as you debug your benchmarking setup. +- `--num-tests` specifies how many of the tests to run before stopping. This is another way to start gently as you debug your benchmarking setup. - `--keywords` filters the tests to run to only the ones whose name match the supplied argument (similar to `pytest -k xxxx`). ### Benchmark report @@ -102,7 +98,7 @@ The benchmark report is a yaml record with statistics about the run: ```yaml - dirname: 2024-07-04-14-32-08--claude-3.5-sonnet-diff-continue - test_cases: 133 + test_cases: 225 model: claude-3.5-sonnet edit_format: diff commit_hash: 35f21b5 @@ -143,7 +139,6 @@ You can see examples of the benchmark report yaml in the ## Limitations, notes -- Benchmarking all 133 exercises against Claude 3.5 Sonnet will cost about $4. - Contributions of benchmark results are welcome! Submit results by opening a PR with edits to the [aider leaderboard data files](https://github.com/Aider-AI/aider/blob/main/aider/website/_data/). - These scripts are not intended for use by typical aider end users. diff --git a/benchmark/benchmark.py b/benchmark/benchmark.py index 78db4403a..66b187df5 100755 --- a/benchmark/benchmark.py +++ b/benchmark/benchmark.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import datetime import json import os @@ -16,6 +16,7 @@ from types import SimpleNamespace from typing import List, Optional import git +import importlib_resources import lox import pandas as pd import prompts @@ -24,20 +25,18 @@ from dotenv import load_dotenv from plots import plot_refactoring from rich.console import Console -from aider import models -from aider.coders import Coder +from aider import models, sendchat +from aider.coders import Coder, base_coder from aider.dump import dump # noqa: F401 from aider.io import InputOutput BENCHMARK_DNAME = Path(os.environ.get("AIDER_BENCHMARK_DIR", "tmp.benchmarks")) -EXERCISES_DIR_DEFAULT = "exercism-python" +EXERCISES_DIR_DEFAULT = "polyglot-benchmark" app = typer.Typer(add_completion=False, pretty_exceptions_enable=False) -NUM_TESTS = (89, 133) - load_dotenv(override=True) @@ -47,18 +46,52 @@ def find_latest_benchmark_dir(): print("Error: No benchmark directories found under tmp.benchmarks.") sys.exit(1) - latest_dir = max( - benchmark_dirs, - key=lambda d: next((f.stat().st_mtime for f in d.rglob("*.md") if f.is_file()), 0), - ) + # Get current time and 24 hours ago + now = datetime.datetime.now() + day_ago = now - datetime.timedelta(days=1) + + # Filter directories by name pattern YYYY-MM-DD-HH-MM-SS-- + recent_dirs = [] + for d in benchmark_dirs: + try: + # Extract datetime from directory name + date_str = d.name[:19] # Takes YYYY-MM-DD-HH-MM-SS + dir_date = datetime.datetime.strptime(date_str, "%Y-%m-%d-%H-%M-%S") + if dir_date >= day_ago: + recent_dirs.append(d) + except ValueError: + # Skip directories that don't match the expected format + continue + + if not recent_dirs: + print("Error: No benchmark directories found from the last 24 hours.") + sys.exit(1) + + # Find directory with most recently modified .md file + latest_dir = None + latest_time = 0 + + for d in recent_dirs: + # Look for .md files in subdirectories + for md_file in d.glob("*/exercises/practice/*/.*.md"): + if md_file.is_file(): + mtime = md_file.stat().st_mtime + if mtime > latest_time: + latest_time = mtime + latest_dir = d + + if not latest_dir: + print("Error: No .md files found in recent benchmark directories.") + sys.exit(1) + print(f"Using the most recently updated benchmark directory: {latest_dir.name}") return latest_dir -def show_stats(dirnames, graphs): +def show_stats(dirnames, graphs, stats_languages=None): raw_rows = [] for dirname in dirnames: - row = summarize_results(dirname) + row = summarize_results(dirname, stats_languages) raw_rows.append(row) # return @@ -69,10 +102,16 @@ def show_stats(dirnames, graphs): if not row: continue - if row.completed_tests not in NUM_TESTS: - print(f"Warning: {row.dir_name} is incomplete: {row.completed_tests}") + if row.completed_tests != row.total_tests: + print( + f"Warning: {row.dir_name} is incomplete: {row.completed_tests} of {row.total_tests}" + ) + + try: + kind = (row.model, row.edit_format) + except AttributeError: + return - kind = (row.model, row.edit_format) if kind in seen: dump(row.dir_name) dump(seen[kind]) @@ -124,6 +163,12 @@ def main( dirnames: Optional[List[str]] = typer.Argument(None, help="Directory names"), graphs: bool = typer.Option(False, "--graphs", help="Generate graphs"), model: str = typer.Option("gpt-3.5-turbo", "--model", "-m", help="Model name"), + sleep: float = typer.Option( + 0, "--sleep", help="Sleep seconds between tests when single threaded" + ), + languages: str = typer.Option( + None, "--languages", "-l", help="Only run tests for specific languages (comma separated)" + ), edit_format: str = typer.Option(None, "--edit-format", "-e", help="Edit format"), editor_model: str = typer.Option(None, "--editor-model", help="Editor model name"), editor_edit_format: str = typer.Option(None, "--editor-edit-format", help="Editor edit format"), @@ -132,11 +177,6 @@ def main( "--replay", help="Replay previous .aider.chat.history.md responses from previous benchmark run", ), - max_apply_update_errors: int = typer.Option( - 3, - "--max-apply-update-errors", - help="Maximum number of apply update errors before stopping the test", - ), keywords: str = typer.Option( None, "--keywords", "-k", help="Only run tests that contain keywords (comma sep)" ), @@ -151,6 +191,11 @@ def main( stats_only: bool = typer.Option( False, "--stats", "-s", help="Do not run tests, just collect stats on completed tests" ), + stats_languages: str = typer.Option( + None, + "--stats-languages", + help="Only include stats for specific languages (comma separated)", + ), diffs_only: bool = typer.Option(False, "--diffs", help="Just diff the provided stats dirs"), tries: int = typer.Option(2, "--tries", "-r", help="Number of tries for running tests"), threads: int = typer.Option(1, "--threads", "-t", help="Number of threads to run in parallel"), @@ -158,6 +203,9 @@ def main( num_ctx: Optional[int] = typer.Option( None, "--num-ctx", help="Override model context window size" ), + read_model_settings: str = typer.Option( + None, "--read-model-settings", help="Load aider model settings from YAML file" + ), exercises_dir: str = typer.Option( EXERCISES_DIR_DEFAULT, "--exercises-dir", help="Directory with exercise files" ), @@ -187,7 +235,7 @@ def main( updated_dirnames.append(dirname) if stats_only: - return show_stats(updated_dirnames, graphs) + return show_stats(updated_dirnames, graphs, stats_languages) if diffs_only: return show_diffs(updated_dirnames) @@ -200,9 +248,41 @@ def main( return assert BENCHMARK_DNAME.exists() and BENCHMARK_DNAME.is_dir(), BENCHMARK_DNAME + + def get_exercise_dirs(base_dir, languages=None): + """Get all exercise directories for specified languages (or all if none specified)""" + base_dir = Path(base_dir) + + # Get available language dirs + lang_dirs = [d for d in base_dir.iterdir() if d.is_dir()] + + # Filter to requested languages if specified + if languages: + requested = set(lang.strip().lower() for lang in languages.split(",")) + lang_dirs = [d for d in lang_dirs if d.name.lower() in requested] + dump(lang_dirs) + if not lang_dirs: + print(f"No matching language directories found for: {languages}") + return [] + + # Get all exercise dirs under exercises/practice for each language + exercise_dirs = [] + for lang_dir in lang_dirs: + practice_dir = lang_dir / "exercises" / "practice" + if practice_dir.exists(): + exercise_dirs.extend(d for d in practice_dir.iterdir() if d.is_dir()) + + return exercise_dirs + original_dname = BENCHMARK_DNAME / exercises_dir assert original_dname.exists() and original_dname.is_dir(), original_dname + exercise_dirs = get_exercise_dirs(original_dname, languages) + + if not exercise_dirs: + print("No exercise directories found") + return 1 + if clean and dirname.exists(): print("Cleaning up and replacing", dirname) dir_files = set(fn.name for fn in dirname.glob("*")) @@ -220,10 +300,35 @@ def main( if not dirname.exists(): print(f"Copying {original_dname} -> {dirname} ...") - shutil.copytree(original_dname, dirname) + # Only copy the practice subdirs with exercises + os.makedirs(dirname, exist_ok=True) + for lang_dir in original_dname.iterdir(): + if not lang_dir.is_dir(): + continue + practice_dir = lang_dir / "exercises" / "practice" + if practice_dir.exists(): + dest_lang_dir = dirname / lang_dir.name / "exercises" / "practice" + os.makedirs(dest_lang_dir.parent, exist_ok=True) + shutil.copytree(practice_dir, dest_lang_dir) print("...done") - test_dnames = sorted(os.listdir(dirname)) + test_dnames = sorted(str(d.relative_to(original_dname)) for d in exercise_dirs) + + resource_metadata = importlib_resources.files("aider.resources").joinpath("model-metadata.json") + model_metadata_files_loaded = models.register_litellm_models([resource_metadata]) + dump(model_metadata_files_loaded) + + if read_model_settings: + try: + files_loaded = models.register_models([read_model_settings]) + if verbose: + if files_loaded: + print(f"Loaded model settings from: {files_loaded[0]}") + else: + print(f"No model settings loaded from: {read_model_settings}") + except Exception as e: + print(f"Error loading model settings: {e}") + return 1 if keywords: keywords = keywords.split(",") @@ -233,12 +338,17 @@ def main( if num_tests > 0: test_dnames = test_dnames[:num_tests] + # Don't give up when benchmarking + LONG_TIMEOUT = 24 * 60 * 60 + sendchat.RETRY_TIMEOUT = LONG_TIMEOUT + base_coder.RETRY_TIMEOUT = LONG_TIMEOUT + if threads == 1: all_results = [] - for testname in test_dnames: + for test_path in test_dnames: results = run_test( original_dname, - dirname / testname, + dirname / test_path, model, edit_format, tries, @@ -247,20 +357,22 @@ def main( verbose, commit_hash, replay, - max_apply_update_errors, editor_model, editor_edit_format, num_ctx, + sleep, ) all_results.append(results) summarize_results(dirname) + if sleep: + time.sleep(sleep) else: run_test_threaded = lox.thread(threads)(run_test) - for testname in test_dnames: + for test_path in test_dnames: run_test_threaded.scatter( original_dname, - dirname / testname, + dirname / test_path, model, edit_format, tries, @@ -269,7 +381,6 @@ def main( verbose, commit_hash, replay, - max_apply_update_errors, editor_model, editor_edit_format, ) @@ -320,17 +431,32 @@ def show_diffs(dirnames): print("unchanged:", len(unchanged), ",".join(sorted(unchanged))) -def load_results(dirname): +def load_results(dirname, stats_languages=None): dirname = Path(dirname) - all_results = [json.loads(fname.read_text()) for fname in dirname.glob("*/.aider.results.json")] + all_results = [] + + if stats_languages: + languages = [lang.strip().lower() for lang in stats_languages.split(",")] + glob_patterns = [f"{lang}/exercises/practice/*/.aider.results.json" for lang in languages] + else: + glob_patterns = ["*/exercises/practice/*/.aider.results.json"] + + for pattern in glob_patterns: + for fname in dirname.glob(pattern): + try: + results = json.loads(fname.read_text()) + all_results.append(results) + except json.JSONDecodeError: + print("json.JSONDecodeError", fname) + continue return all_results -def summarize_results(dirname): - all_results = load_results(dirname) +def summarize_results(dirname, stats_languages=None): + all_results = load_results(dirname, stats_languages) res = SimpleNamespace() - res.total_tests = len(list(Path(dirname).glob("*"))) + res.total_tests = len(list(Path(dirname).glob("*/exercises/practice/*"))) try: tries = max(len(results.get("tests_outcomes", [])) for results in all_results if results) @@ -411,9 +537,10 @@ def summarize_results(dirname): percents[i] = pass_rate # console.print(f"{pass_rate:.1f}% correct after try {i+1}") setattr(res, f"pass_rate_{i + 1}", f"{pass_rate:.1f}") + setattr(res, f"pass_num_{i + 1}", passed_tests[i]) print(f"- dirname: {dirname.name}") - style = None if res.completed_tests in NUM_TESTS else "red" + style = None if res.completed_tests == res.total_tests else "red" console.print(f" test_cases: {res.completed_tests}", style=style) for key, val in variants.items(): if len(val) > 1: @@ -426,6 +553,8 @@ def summarize_results(dirname): for i in range(tries): print(f" pass_rate_{i + 1}: {percents[i]:.1f}") + for i in range(tries): + print(f" pass_num_{i + 1}: {passed_tests[i]}") pct_well_formed = 1.0 - res.num_with_malformed_responses / res.completed_tests print(f" percent_cases_well_formed: {pct_well_formed * 100:.1f}") @@ -439,10 +568,12 @@ def summarize_results(dirname): show("indentation_errors") show("exhausted_context_windows") show("test_timeouts") + print(f" total_tests: {res.total_tests}") - a_model = set(variants["model"]).pop() - command = f"aider --model {a_model}" - print(f" command: {command}") + if variants["model"]: + a_model = set(variants["model"]).pop() + command = f"aider --model {a_model}" + print(f" command: {command}") print(f" date: {date}") print(" versions:", ",".join(versions)) @@ -527,10 +658,11 @@ def run_test_real( verbose, commit_hash, replay, - max_apply_update_errors, editor_model, editor_edit_format, num_ctx=None, + sleep=0, + read_model_settings=None, ): if not os.path.isdir(testdir): print("Not a dir:", testdir) @@ -544,25 +676,67 @@ def run_test_real( if results_fname.exists(): try: res = json.loads(results_fname.read_text()) + # if res.get("test_timeouts", 0) > 0: + # print(f"{results_fname} test timeouts, redoing...") + # else: return res except JSONDecodeError: - print(f"{results_fname} failed to parse, skipping") - return + print(f"{results_fname} failed to parse, redoing...") + # Read solution and test files from config fnames = [] - for fname in testdir.glob("*"): - if ( - "test" not in fname.name - and fname.is_file() - and fname.name[0] != "." - and fname.suffix == ".py" - ): - fnames.append(fname) + config_file = testdir / ".meta/config.json" + if not config_file.exists(): + raise ValueError(f"No config file found: {config_file}") + with open(config_file) as f: + config = json.loads(f.read()) + + # Get file sets from config + test_files = config.get("files", {}).get("test", []) + example_files = config.get("files", {}).get("example", []) + solution_files = set(config.get("files", {}).get("solution", [])) + + # Forcibly ignore certain files not covered by test_files and example_files + ignore_files = set( + [ + "CMakeLists.txt", + "Cargo.toml", + ] + ) + + # Add all files under .meta and .docs directories + ignore_files.update(str(p.relative_to(testdir)) for p in testdir.glob(".meta/**/*")) + ignore_files.update(str(p.relative_to(testdir)) for p in testdir.glob(".docs/**/*")) + + # Also ignore test & example files + ignore_files.update(test_files) + ignore_files.update(example_files) + + # Remove any ignore files from the solution set that LLM will edit + solution_files.difference_update(ignore_files) + + # Copy all solution files + for file_path in solution_files: + src = testdir / Path(file_path) + if src.exists(): + fnames.append(src) # restore the original file, in case we interrupted a prev run - # after it had saved changes - original_fname = original_dname / testdir.name / fname.name - shutil.copy(original_fname, fname) + # Find the original file in the language-specific practice dir + lang_part = str(testdir).split("/exercises/practice/")[0] + original_fname = ( + original_dname + / Path(lang_part).name + / "exercises" + / "practice" + / testdir.name + / file_path + ) + if original_fname.exists(): + os.makedirs(src.parent, exist_ok=True) + shutil.copy(original_fname, src) + else: + print(f"Warning: Solution file not found: {src}") file_list = " ".join(fname.name for fname in fnames) @@ -594,6 +768,8 @@ def run_test_real( editor_edit_format=editor_edit_format, ) + dump(main_model.max_chat_history_tokens) + if num_ctx: if not main_model.extra_params: main_model.extra_params = {} @@ -616,9 +792,12 @@ def run_test_real( # auto_lint=False, # disabled for code-in-json experiments cache_prompts=True, suggest_shell_commands=False, + ignore_mentions=ignore_files, ) - coder.max_apply_update_errors = max_apply_update_errors + dump(coder.ignore_mentions) + coder.show_announcements() + coder.get_file_mentions = lambda x: set() # No loading of any other files timeouts = 0 @@ -630,6 +809,7 @@ def run_test_real( test_outcomes = [] for i in range(tries): start = time.time() + if no_aider: pass elif replay: @@ -643,6 +823,7 @@ def run_test_real( coder.apply_updates() else: response = coder.run(with_message=instructions, preproc=False) + dur += time.time() - start if not no_aider: @@ -659,8 +840,11 @@ def run_test_real( break try: - errors = run_unit_tests(testdir, history_fname) + errors = run_unit_tests(original_dname, testdir, history_fname, test_files) except subprocess.TimeoutExpired: + # try: + # errors = run_unit_tests(original_dname, testdir, history_fname, test_files) + # except subprocess.TimeoutExpired: errors = "Tests timed out!" timeouts += 1 @@ -679,11 +863,44 @@ def run_test_real( indentation_errors += sum(1 for line in errors if line.startswith("IndentationError")) print(errors[-1]) - errors = errors[:50] errors = "\n".join(errors) instructions = errors instructions += prompts.test_failures.format(file_list=file_list) + # Clean up build directories after all attempts + # Rust target/debug + target_dir = testdir / "target" / "debug" + if target_dir.exists(): + try: + shutil.rmtree(target_dir) + if verbose: + print(f"Cleaned up Rust target/debug directory: {target_dir}") + except (OSError, shutil.Error, PermissionError) as e: + if verbose: + print(f"Failed to clean up Rust target/debug directory: {e}") + + # Java build directories + java_build_dir = testdir / "build" + if java_build_dir.exists(): + try: + shutil.rmtree(java_build_dir) + if verbose: + print(f"Cleaned up Java build directory: {java_build_dir}") + except (OSError, shutil.Error, PermissionError) as e: + if verbose: + print(f"Failed to clean up Java build directory: {e}") + + # Node.js node_modules directories + node_modules_dir = testdir / "node_modules" + if node_modules_dir.exists(): + try: + shutil.rmtree(node_modules_dir) + if verbose: + print(f"Cleaned up Node.js node_modules directory: {node_modules_dir}") + except (OSError, shutil.Error, PermissionError) as e: + if verbose: + print(f"Failed to clean up Node.js node_modules directory: {e}") + results = dict( testdir=str(testdir), testcase=testdir.name, @@ -719,22 +936,51 @@ def run_test_real( return results -def run_unit_tests(testdir, history_fname): - command = [ - "python", - "-m", - "unittest", - "discover", - "-s", - str(testdir), - "-t", - str(testdir), - "-p", - "*_test.py", - ] - print(" ".join(command)) +def run_unit_tests(original_dname, testdir, history_fname, test_files): + timeout = 60 * 3 - timeout = 60 + # Map of file extensions to test commands + TEST_COMMANDS = { + ".py": ["pytest"], + ".rs": ["cargo", "test", "--", "--include-ignored"], + ".go": ["go", "test", "./..."], + ".js": ["/aider/benchmark/npm-test.sh"], + ".cpp": ["/aider/benchmark/cpp-test.sh"], + ".java": ["./gradlew", "test"], + } + + # Get unique file extensions from test files + extensions = {Path(f).suffix for f in test_files} + + # Find matching test command + command = None + for ext in extensions: + if ext in TEST_COMMANDS: + command = TEST_COMMANDS[ext] + break + + if not command: + raise ValueError(f"No test command found for files with extensions: {extensions}") + + # Copy test files from original directory + for file_path in test_files: + src = original_dname / Path(*testdir.parts[-4:]) / file_path + dst = testdir / file_path + if src.exists(): + print("copying", src, dst) + os.makedirs(dst.parent, exist_ok=True) + shutil.copy(src, dst) + + # Remove @Disabled annotations from Java test files + for file_path in test_files: + if file_path.endswith(".java"): + test_file = testdir / file_path + if test_file.exists(): + content = test_file.read_text() + content = re.sub(r"@Disabled\([^)]*\)\s*\n", "", content) + test_file.write_text(content) + + print(" ".join(command)) result = subprocess.run( command, @@ -742,11 +988,15 @@ def run_unit_tests(testdir, history_fname): stderr=subprocess.STDOUT, text=True, timeout=timeout, + cwd=testdir, + encoding="utf-8", + errors="replace", ) success = result.returncode == 0 res = result.stdout res = cleanup_test_output(res, testdir) + dump(res) with history_fname.open("a") as fh: fh.write(f"```\n{res}\n```") @@ -758,25 +1008,7 @@ def run_unit_tests(testdir, history_fname): def cleanup_test_output(output, testdir): # remove timing info, to avoid randomizing the response to GPT - res = re.sub( - r"^Ran \d+ tests in \d+\.\d+s$", - "", - output, - flags=re.MULTILINE, - ) - res = re.sub( - r"^====*$", - "====", - res, - flags=re.MULTILINE, - ) - res = re.sub( - r"^----*$", - "----", - res, - flags=re.MULTILINE, - ) - + res = re.sub(r"\bin \d+\.\d+s\b", "", output) res = res.replace(str(testdir), str(testdir.name)) return res diff --git a/benchmark/clone-exercism.sh b/benchmark/clone-exercism.sh new file mode 100755 index 000000000..a4dc79269 --- /dev/null +++ b/benchmark/clone-exercism.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Create directories if they don't exist +mkdir -p tmp.benchmarks/exercism + +# Change to the exercism directory +cd tmp.benchmarks/exercism + +# List of languages to clone +languages=("cpp" "go" "java" "javascript" "python" "rust") + +# Clone each repository +for lang in "${languages[@]}"; do + if [ ! -d "$lang" ]; then + echo "Cloning $lang repository..." + git clone "https://github.com/exercism/$lang" + else + echo "$lang repository already exists" + fi +done diff --git a/benchmark/cpp-test.sh b/benchmark/cpp-test.sh new file mode 100755 index 000000000..7dcbfabee --- /dev/null +++ b/benchmark/cpp-test.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# exit when any command fails +set -e + +[ ! -d "build" ] && mkdir build +cd build +cmake -DEXERCISM_RUN_ALL_TESTS=1 -G "Unix Makefiles" .. +make + + diff --git a/benchmark/docker.sh b/benchmark/docker.sh index 205552619..3edde7c66 100755 --- a/benchmark/docker.sh +++ b/benchmark/docker.sh @@ -2,11 +2,17 @@ docker run \ -it --rm \ + --memory=25g \ + --memory-swap=25g \ --add-host=host.docker.internal:host-gateway \ -v `pwd`:/aider \ -v `pwd`/tmp.benchmarks/.:/benchmarks \ -e OPENAI_API_KEY=$OPENAI_API_KEY \ -e HISTFILE=/aider/.bash_history \ + -e PROMPT_COMMAND='history -a' \ + -e HISTCONTROL=ignoredups \ + -e HISTSIZE=10000 \ + -e HISTFILESIZE=20000 \ -e AIDER_DOCKER=1 \ -e AIDER_BENCHMARK_DIR=/benchmarks \ aider-benchmark \ diff --git a/benchmark/install-docker-ubuntu.sh b/benchmark/install-docker-ubuntu.sh new file mode 100755 index 000000000..3f163d8c1 --- /dev/null +++ b/benchmark/install-docker-ubuntu.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# Exit on error +set -e + +# Update package index +echo "Updating package index..." +sudo apt-get update + +# Install prerequisites +echo "Installing prerequisites..." +sudo apt-get install -y \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg \ + lsb-release + +# Add Docker's official GPG key +echo "Adding Docker's GPG key..." +sudo mkdir -p /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg + +# Set up the repository +echo "Setting up Docker repository..." +echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ + $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + +# Update package index again +sudo apt-get update + +# Install Docker Engine +echo "Installing Docker Engine..." +sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin + +# Add current user to docker group and verify +echo "Adding current user to docker group..." +sudo usermod -aG docker $USER + +# Verify group addition +if getent group docker | grep -q "\b${USER}\b"; then + echo "Successfully added $USER to docker group" +else + echo "Failed to add $USER to docker group. Retrying..." + # Force group addition + sudo gpasswd -a $USER docker +fi + +# Print success message and instructions +echo "Docker installation completed successfully!" + +# Start Docker service +echo "Starting Docker service..." +sudo systemctl start docker +sudo systemctl enable docker + +# Verify Docker installation and service status +echo "Docker version:" +docker --version + +echo "Docker Compose version:" +docker compose version diff --git a/benchmark/npm-test.sh b/benchmark/npm-test.sh new file mode 100755 index 000000000..063730076 --- /dev/null +++ b/benchmark/npm-test.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# exit when any command fails +set -e + +# Create symlinks if they don't exist +[ ! -e node_modules ] && ln -s /npm-install/node_modules . +[ ! -e package-lock.json ] && ln -s /npm-install/package-lock.json . + + +sed -i 's/\bxtest(/test(/g' *.spec.js +npm run test + diff --git a/benchmark/problem_stats.py b/benchmark/problem_stats.py new file mode 100755 index 000000000..2ee8a0890 --- /dev/null +++ b/benchmark/problem_stats.py @@ -0,0 +1,355 @@ +#!/usr/bin/env python + +import argparse +import json +import shutil +from collections import defaultdict +from pathlib import Path + +import yaml + +from aider.dump import dump # noqa + +HARD_SET_NUM = 3 # Number of models that defines the hard set threshold + + +def get_dirs_from_leaderboard(): + # Load the leaderboard data + with open("aider/website/_data/edit_leaderboard.yml") as f: + leaderboard = yaml.safe_load(f) + return [(entry["dirname"], entry["model"]) for entry in leaderboard] + + +def load_results(dirname): + """Load all result files from a benchmark directory""" + dirname = Path(dirname) + + benchmark_dir = dirname + if not benchmark_dir.exists(): + benchmark_dir = Path("tmp.benchmarks") / dirname + if not benchmark_dir.exists(): + return None + + all_results = [] + parse_errors = [] # Track which exercises had parse errors for this model + + # Look in language subdirectories under exercises/practice + for fname in benchmark_dir.glob("*/exercises/practice/*/.aider.results.json"): + error = False + try: + results = json.loads(fname.read_text()) + error = "testcase" not in results + if not error: + # Add language info to results + lang = fname.parts[-5] # Get language from path + results["language"] = lang + all_results.append(results) + + except json.JSONDecodeError: + error = True + + if error: + # Track the parse error for this exercise/model combination + lang = fname.parts[-5] + exercise = f"{fname.parts[-2]}/{lang}" # Use directory name as testcase + parse_errors.append(exercise) + print(f"Bad results file {fname}") + continue + + return all_results, parse_errors + + +def analyze_exercise_solutions(dirs=None, topn=None, copy_hard_set=False): + PARSE_ERROR_M = 4 # Threshold for number of parse errors to DQ an exercise + + if dirs is None: + # Use leaderboard data if no directories specified + dir_entries = get_dirs_from_leaderboard() + else: + # Use provided directories, with dirname as model name + dir_entries = [(d, d) for d in dirs] + + # Filter out entries that don't load and sort by pass rate + valid_entries = [] + parse_errors_by_model = {} # Track which exercises had parse errors for each model + + dump(dir_entries) + + for dirname, model in dir_entries: + results_data = load_results(dirname) + + if results_data: + results, model_parse_errors = results_data + parse_errors_by_model[model] = set(model_parse_errors) + # Calculate pass rate for sorting when using custom dirs + if dirs is not None: + pass_rate = sum( + 1 for r in results if r.get("tests_outcomes", []) and r["tests_outcomes"][-1] + ) / len(results) + else: + # Use existing pass rate from leaderboard + pass_rate = next( + ( + entry["pass_rate_2"] + for entry in yaml.safe_load( + open("aider/website/_data/edit_leaderboard.yml") + ) + if entry["dirname"] == dirname + ), + 0, + ) + valid_entries.append(((dirname, model), results, float(pass_rate))) + + # Sort by pass rate and take top N if specified + valid_entries.sort(key=lambda x: x[2], reverse=True) + if topn: + valid_entries = valid_entries[:topn] + + # Get all exercise names from a complete run + all_exercises = set() + exercise_solutions = defaultdict(list) + + # Get all unique exercise names from all results + all_exercises = set() + for (dirname, model), results, _ in valid_entries: + if results: + for result in results: + try: + all_exercises.add(result["testcase"] + "/" + result["language"]) + except KeyError: + print(f"Warning: Missing testcase in {dirname}", json.dumps(result, indent=4)) + + for (dirname, model), results, _ in valid_entries: + if not results: + print(f"Could not load results for {dirname}") + continue + + for result in results: + testcase = result.get("testcase") + if not testcase: + continue + lang = result.get("language") + if not lang: + continue + + testcase = f"{testcase}/{lang}" + # Consider it solved if the last test attempt passed + tests_outcomes = result.get("tests_outcomes", []) + if tests_outcomes and tests_outcomes[-1]: + exercise_solutions[testcase].append(model) + + # Calculate never solved exercises + never_solved = len(all_exercises - set(exercise_solutions.keys())) + + # Print per-exercise statistics + print("\nExercise Solution Statistics:") + print("-" * 40) + + # Add exercises that were never solved + for exercise in all_exercises: + if exercise not in exercise_solutions: + exercise_solutions[exercise] = [] + + # Create list of (language, exercise) pairs with solution stats + exercise_stats = [] + total_models = len(valid_entries) + + for testcase in all_exercises: + # Language is already in the testcase string + lang = testcase.split("/")[0] # First part is the language + models = exercise_solutions[testcase] + num_solved = len(models) + percent = (num_solved / total_models) * 100 + testcase = testcase.replace("exercises/", "") # Remove the exercises/ prefix + # Remove duplicate language prefix (e.g. javascript/javascript/ -> javascript/) + if testcase.startswith(f"{lang}/{lang}/"): + testcase = testcase[len(lang) + 1 :] + exercise_stats.append((lang, testcase, num_solved, percent)) + + # Sort all exercises by solve rate, then by exercise name + exercise_stats.sort( + key=lambda x: (-x[2], x[1]) + ) # -x[2] for descending solve rate, x[1] for ascending exercise name + + # Calculate max lengths for alignment after cleaning up paths + max_name_len = max(len(f"{lang}/{testcase}") for lang, testcase, _, _ in exercise_stats) + + # Print all exercises sorted by solve rate + print("\nAll Exercises (sorted by solve rate):") + for i, (lang, testcase, num_solved, percent) in enumerate(exercise_stats, 1): + print(f"{i:>3}. {testcase:<{max_name_len}} : {num_solved:>3} solved ({percent:>5.1f}%)") + + print("\nSummary:") + solved_at_least_once = len([ex for ex, models in exercise_solutions.items() if models]) + solved_by_none = never_solved + solved_by_all = len( + [ex for ex, models in exercise_solutions.items() if len(models) == total_models] + ) + + print(f"Total exercises solved at least once: {solved_at_least_once}") + print(f"Never solved by any model: {solved_by_none}") + if solved_by_none > 0: + print("\nExercises never solved by any model:") + unsolved = [ex for ex, models in exercise_solutions.items() if not models] + for ex in sorted(unsolved): + # Split into language and exercise parts + lang, exercise = ex.split("/") + # Reconstruct path in desired format + formatted_path = f"{lang}/exercises/practice/{exercise}" + print(f" {formatted_path}") + print(f"\nSolved by all models: {solved_by_all}") + print( + f"Total exercises: {len(all_exercises)} = {solved_by_none} (none) + {solved_by_all} (all) +" + f" {len(all_exercises) - solved_by_none - solved_by_all} (some)" + ) + + # Distribution table of how many models solved each exercise + print("\nDistribution of solutions:") + print("Models Exercises Cumulative RevCumulative") + print("-" * 50) + counts = [0] * (total_models + 1) + for ex, models in exercise_solutions.items(): + counts[len(models)] += 1 + + cumsum = 0 + revcumsum = sum(counts) # Start with total number of exercises + for i, count in enumerate(counts): + cumsum += count + print(f"{i:>6d} {count:>9d} {cumsum:>10d} {revcumsum:>12d}") + revcumsum -= count # Decrement the reverse cumulative sum + + # Count parse errors per exercise + parse_error_counts = defaultdict(int) + for model_errors in parse_errors_by_model.values(): + for exercise in model_errors: + parse_error_counts[exercise] += 1 + + # Find exercises to disqualify based on parse error threshold + disqualified_exercises = { + exercise for exercise, count in parse_error_counts.items() if count >= PARSE_ERROR_M + } + + if disqualified_exercises: + print( + f"\nDisqualified {len(disqualified_exercises)} exercises with {PARSE_ERROR_M}+ parse" + " errors:" + ) + for ex in sorted(disqualified_exercises): + print(f" {ex} ({parse_error_counts[ex]} parse errors)") + + # Collect the hard set (exercises solved by HARD_SET_NUM or fewer models) + print(f"\nHard Set Analysis (exercises solved by ≤{HARD_SET_NUM} models):") + print("-" * 60) + hard_set = { + ex + for ex, models in exercise_solutions.items() + if len(models) <= HARD_SET_NUM and ex not in disqualified_exercises + } + print(f"Total hard set exercises: {len(hard_set)}") + + # Count total problems, unsolved problems, and hard set problems by language + lang_totals = defaultdict(int) + lang_unsolved = defaultdict(int) + lang_hard_set = defaultdict(int) + + for exercise in all_exercises: + lang = exercise.split("/")[1] # Get language from path + lang_totals[lang] += 1 + if not exercise_solutions[exercise]: # No models solved this exercise + lang_unsolved[lang] += 1 + if exercise in hard_set: # Exercise is in the hard set + lang_hard_set[lang] += 1 + + print("\nUnsolved and hard set problems by language:") + print(f"{'Language':<12} {'Unsolved':>8} {'Hard Set':>9} {'Total':>7} {'%hardUnsolved':>8}") + print("-" * 47) + for lang in sorted(lang_totals.keys()): + count = lang_unsolved[lang] + hard = lang_hard_set[lang] + total = lang_totals[lang] + pct = (count / hard) * 100 if hard else -1 + print(f"{lang:<12} {count:>8} {hard:>9} {total:>7} {pct:>7.1f}%") + print() + + # For each model, compute performance on hard set + model_hard_stats = [] + for (dirname, model), results, _ in valid_entries: + if not results: + continue + + solved_hard = 0 + for result in results: + testcase = result.get("testcase") + if not testcase: + continue + lang = result.get("language") + if not lang: + continue + + testcase = f"{testcase}/{lang}" + if testcase in hard_set: + tests_outcomes = result.get("tests_outcomes", []) + if tests_outcomes and tests_outcomes[-1]: + solved_hard += 1 + + pct = (solved_hard / len(hard_set)) * 100 + model_hard_stats.append((model, solved_hard, pct)) + + # Sort by number solved + model_hard_stats.sort(key=lambda x: x[1], reverse=True) + + print("\nModel performance on hard set:") + print(f"{'Model':<55} {'Solved':<8} {'Percent':>7}") + print("-" * 50) + for model, solved, pct in model_hard_stats: + print(f"{model:<55} {solved:>6d} {pct:>6.1f}%") + + if copy_hard_set: + # Create hard set directory + src_dir = Path("tmp.benchmarks/exercism") + dst_dir = Path("tmp.benchmarks/exercism-polyglot") + + if dst_dir.exists(): + print(f"\nError: Destination directory {dst_dir} already exists") + return + + print(f"\nCopying hard set problems to {dst_dir}...") + + # Create a set of (exercise, language) pairs from hard_set + hard_set_pairs = {tuple(exercise.split("/")) for exercise in hard_set} + + # Copy each hard set problem's directory + copied_by_lang = defaultdict(int) + for lang_dir in src_dir.glob("*/exercises/practice"): + if not lang_dir.is_dir(): + continue + + lang = lang_dir.parts[-3] # Get language from path + for problem_dir in lang_dir.glob("*"): + if (problem_dir.name, lang) in hard_set_pairs: + rel_path = problem_dir.relative_to(src_dir) + dst_path = dst_dir / rel_path + dst_path.parent.mkdir(parents=True, exist_ok=True) + shutil.copytree(problem_dir, dst_path) + copied_by_lang[lang] += 1 + + total_copied = sum(copied_by_lang.values()) + print(f"\nCopied {total_copied} hard set problems:") + for lang in sorted(copied_by_lang): + print(f" {lang}: {copied_by_lang[lang]}") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--topn", type=int, help="Only consider top N models by pass rate") + parser.add_argument( + "dirs", nargs="*", help="Directories to analyze (optional, defaults to leaderboard entries)" + ) + parser.add_argument( + "--copy-hard-set", + action="store_true", + help="Copy hard set problems to tmp.benchmarks/exercism-polygot", + ) + args = parser.parse_args() + + analyze_exercise_solutions(args.dirs if args.dirs else None, args.topn, args.copy_hard_set) diff --git a/benchmark/prompts.py b/benchmark/prompts.py index 13511d023..4fb3c387e 100644 --- a/benchmark/prompts.py +++ b/benchmark/prompts.py @@ -3,7 +3,7 @@ instructions_addendum = """ Use the above instructions to modify the supplied files: {file_list} Don't change the names of existing functions or classes, as they may be referenced from other code like unit tests, etc. -Only use standard python libraries, don't suggest installing any packages. +Only use standard libraries, don't suggest installing any packages. """ # noqa: E501 @@ -11,6 +11,6 @@ test_failures = """ #### See the testing errors above. -The tests are correct. +The tests are correct, don't try and change them. Fix the code in {file_list} to resolve the errors. """ diff --git a/benchmark/rsync.sh b/benchmark/rsync.sh new file mode 100755 index 000000000..3960f2cd7 --- /dev/null +++ b/benchmark/rsync.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +set -e + +if [ $# -ne 1 ]; then + echo "Usage: $0 user@host" + exit 1 +fi + +DEST="$1" +REPO_ROOT="$(git rev-parse --show-toplevel)" + +# Create a temporary file for rsync exclude patterns +EXCLUDE_FILE=$(mktemp) + +# Convert .gitignore patterns to rsync exclude patterns +git -C "$REPO_ROOT" ls-files --exclude-standard --others --ignored --directory > "$EXCLUDE_FILE" + +# Create remote directory if needed +ssh "$DEST" "mkdir -p ~/aider" + +sync_repo() { + # Sync the repository + rsync -avz --delete \ + --exclude-from="$EXCLUDE_FILE" \ + "$REPO_ROOT/" \ + "$DEST:~/aider/" || sleep 0.1 + + rsync -av .env .gitignore .aider.model.settings.yml "$DEST:~/aider/." || sleep 0.1 + + echo Done syncing, waiting. +} + +sync_repo + +while true; do + fswatch -o $REPO_ROOT | while read ; do + sync_repo + done +done + + +# Clean up +rm "$EXCLUDE_FILE" + diff --git a/docker/Dockerfile b/docker/Dockerfile index 4cf7ceeb1..72ea5ce19 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,41 +1,58 @@ FROM python:3.10-slim AS base +# Install system dependencies RUN apt-get update && \ apt-get install --no-install-recommends -y build-essential git libportaudio2 pandoc && \ rm -rf /var/lib/apt/lists/* +# Create app user with UID 1000 +RUN useradd -m -u 1000 -s /bin/bash appuser + WORKDIR /app +# Create virtual environment RUN python -m venv /venv ENV PATH="/venv/bin:$PATH" -# https://playwright.dev/python/docs/browsers -ENV PLAYWRIGHT_BROWSERS_PATH=/pw-browsers +# Playwright browser settings +ENV PLAYWRIGHT_BROWSERS_PATH=/home/appuser/pw-browsers ENV PLAYWRIGHT_SKIP_BROWSER_GC=1 -# Permission kludges to support `docker run --user xxx` -RUN chmod a+rwx /venv /venv/bin /venv/include /venv/lib /venv/lib/python3.10/site-packages - -RUN mkdir /.aider /.cache /pw-browsers -RUN chmod a+rwx /.aider /.cache /pw-browsers +# Create directories with proper permissions +RUN mkdir -p /home/appuser/.aider /home/appuser/.cache /home/appuser/pw-browsers && \ + chown -R appuser:appuser /home/appuser /app /venv && \ + chmod -R 777 /home/appuser/.aider /home/appuser/.cache /home/appuser/pw-browsers # So git doesn't complain about unusual permissions RUN git config --system --add safe.directory /app +# This puts the container's ~/.aider into the host's project directory (usually host's cwd). +# That way caches, version checks, etc get stored in the host filesystem not +# simply discarded every time the container exits. +ENV HOME=/app + ######################### FROM base AS aider-full ENV AIDER_DOCKER_IMAGE=paulgauthier/aider-full COPY . /tmp/aider -RUN /venv/bin/python -m pip install --upgrade --no-cache-dir pip \ - && /venv/bin/python -m pip install --no-cache-dir /tmp/aider[help,browser,playwright] \ - --extra-index-url https://download.pytorch.org/whl/cpu \ - && rm -rf /tmp/aider +# Install dependencies as root +RUN /venv/bin/python -m pip install --upgrade --no-cache-dir pip && \ + /venv/bin/python -m pip install --no-cache-dir /tmp/aider[help,browser,playwright] boto3 \ + --extra-index-url https://download.pytorch.org/whl/cpu && \ + rm -rf /tmp/aider + +# Install playwright browsers RUN /venv/bin/python -m playwright install --with-deps chromium + +# Fix site-packages permissions RUN find /venv/lib/python3.10/site-packages \( -type d -exec chmod a+rwx {} + \) -o \( -type f -exec chmod a+rw {} + \) +# Switch to appuser +USER appuser + ENTRYPOINT ["/venv/bin/aider"] ######################### @@ -44,12 +61,20 @@ FROM base AS aider ENV AIDER_DOCKER_IMAGE=paulgauthier/aider COPY . /tmp/aider -RUN /venv/bin/python -m pip install --upgrade --no-cache-dir pip \ - && /venv/bin/python -m pip install --no-cache-dir /tmp/aider[playwright] \ - --extra-index-url https://download.pytorch.org/whl/cpu \ - && rm -rf /tmp/aider +# Install dependencies as root +RUN /venv/bin/python -m pip install --upgrade --no-cache-dir pip && \ + /venv/bin/python -m pip install --no-cache-dir /tmp/aider[playwright] boto3 \ + --extra-index-url https://download.pytorch.org/whl/cpu && \ + rm -rf /tmp/aider + +# Install playwright browsers RUN /venv/bin/python -m playwright install --with-deps chromium + +# Fix site-packages permissions RUN find /venv/lib/python3.10/site-packages \( -type d -exec chmod a+rwx {} + \) -o \( -type f -exec chmod a+rw {} + \) +# Switch to appuser +USER appuser + ENTRYPOINT ["/venv/bin/aider"] diff --git a/pyproject.toml b/pyproject.toml index 0d0ef3eae..f7b25eee8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,3 @@ -# [[[cog -# from aider.help_pats import exclude_website_pats -# ]]] -# [[[end]]] [project] name = "aider-chat" @@ -38,36 +34,18 @@ help = { file = "requirements/requirements-help.txt" } browser = { file = "requirements/requirements-browser.txt" } playwright = { file = "requirements/requirements-playwright.txt" } +[tool.setuptools] +include-package-data = true + [tool.setuptools.packages.find] -include = ["aider*", "aider.website"] - -[tool.setuptools.package-data] -"aider" = ["queries/*.scm"] -"aider.website" = ["**/*.md"] - -[tool.setuptools.exclude-package-data] -"aider.website" = [ -# [[[cog -# cog.out("\n".join(f' "{pat}",' for pat in exclude_website_pats)) -# ]]] -"examples/**", -"_posts/**", -"HISTORY.md", -"docs/benchmarks*md", -"docs/ctags.md", -"docs/unified-diffs.md", -"docs/leaderboards/index.md", -"assets/**", -"**/.DS_Store", -# [[[end]]] -] +include = ["aider"] [build-system] requires = ["setuptools>=68", "setuptools_scm[toml]>=8"] build-backend = "setuptools.build_meta" [tool.setuptools_scm] -write_to = "aider/__version__.py" +write_to = "aider/_version.py" [tool.codespell] skip = "*.svg,Gemfile.lock" diff --git a/pytest.ini b/pytest.ini index ab9d6d15d..7e37e1779 100644 --- a/pytest.ini +++ b/pytest.ini @@ -6,5 +6,7 @@ testpaths = tests/help tests/browser tests/scrape - + +env = + AIDER_ANALYTICS=false diff --git a/requirements.txt b/requirements.txt index cdc67ae97..b1933f406 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,21 +2,22 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile --output-file=requirements.txt requirements/requirements.in +# pip-compile --allow-unsafe --output-file=requirements.txt requirements/requirements.in # -aiohappyeyeballs==2.4.3 +aiohappyeyeballs==2.4.6 # via aiohttp -aiohttp==3.11.7 +aiohttp==3.11.12 # via litellm -aiosignal==1.3.1 +aiosignal==1.3.2 # via aiohttp annotated-types==0.7.0 # via pydantic -anyio==4.6.2.post1 +anyio==4.8.0 # via # httpx # openai -attrs==24.2.0 + # watchfiles +attrs==25.1.0 # via # aiohttp # jsonschema @@ -25,9 +26,9 @@ backoff==2.2.1 # via # -r requirements/requirements.in # posthog -beautifulsoup4==4.12.3 +beautifulsoup4==4.13.3 # via -r requirements/requirements.in -certifi==2024.8.30 +certifi==2025.1.31 # via # httpcore # httpx @@ -36,9 +37,9 @@ cffi==1.17.1 # via # sounddevice # soundfile -charset-normalizer==3.4.0 +charset-normalizer==3.4.1 # via requests -click==8.1.7 +click==8.1.8 # via litellm configargparse==1.7 # via -r requirements/requirements.in @@ -48,7 +49,7 @@ diskcache==5.6.3 # via -r requirements/requirements.in distro==1.9.0 # via openai -filelock==3.16.1 +filelock==3.17.0 # via huggingface-hub flake8==7.1.1 # via -r requirements/requirements.in @@ -56,21 +57,23 @@ frozenlist==1.5.0 # via # aiohttp # aiosignal -fsspec==2024.10.0 +fsspec==2025.2.0 # via huggingface-hub -gitdb==4.0.11 +gitdb==4.0.12 # via gitpython -gitpython==3.1.43 +gitpython==3.1.44 # via -r requirements/requirements.in -grep-ast==0.4.0 +grep-ast==0.5.0 # via -r requirements/requirements.in h11==0.14.0 # via httpcore httpcore==1.0.7 # via httpx -httpx==0.27.2 - # via openai -huggingface-hub==0.26.2 +httpx==0.28.1 + # via + # litellm + # openai +huggingface-hub==0.28.1 # via tokenizers idna==3.10 # via @@ -82,13 +85,13 @@ importlib-metadata==7.2.1 # via # -r requirements/requirements.in # litellm -importlib-resources==6.4.5 +importlib-resources==6.5.2 # via -r requirements/requirements.in -jinja2==3.1.4 +jinja2==3.1.5 # via litellm -jiter==0.7.1 +jiter==0.8.2 # via openai -json5==0.9.28 +json5==0.10.0 # via -r requirements/requirements.in jsonschema==4.23.0 # via @@ -96,7 +99,7 @@ jsonschema==4.23.0 # litellm jsonschema-specifications==2024.10.1 # via jsonschema -litellm==1.52.16 +litellm==1.60.6 # via -r requirements/requirements.in markdown-it-py==3.0.0 # via rich @@ -120,7 +123,8 @@ numpy==1.26.4 # via # -r requirements/requirements.in # scipy -openai==1.55.1 + # soundfile +openai==1.61.1 # via litellm packaging==24.2 # via @@ -134,15 +138,15 @@ pexpect==4.9.0 # via -r requirements/requirements.in pillow==10.4.0 # via -r requirements/requirements.in -posthog==3.7.3 +posthog==3.11.0 # via -r requirements/requirements.in -prompt-toolkit==3.0.48 +prompt-toolkit==3.0.50 # via -r requirements/requirements.in -propcache==0.2.0 +propcache==0.2.1 # via # aiohttp # yarl -psutil==6.1.0 +psutil==6.1.1 # via -r requirements/requirements.in ptyprocess==0.7.0 # via pexpect @@ -150,19 +154,19 @@ pycodestyle==2.12.1 # via flake8 pycparser==2.22 # via cffi -pydantic==2.10.2 +pydantic==2.10.6 # via # litellm # openai -pydantic-core==2.27.1 +pydantic-core==2.27.2 # via pydantic pydub==0.25.1 # via -r requirements/requirements.in pyflakes==3.2.0 # via flake8 -pygments==2.18.0 +pygments==2.19.1 # via rich -pypandoc==1.14 +pypandoc==1.15 # via -r requirements/requirements.in pyperclip==1.9.0 # via -r requirements/requirements.in @@ -174,7 +178,7 @@ pyyaml==6.0.2 # via # -r requirements/requirements.in # huggingface-hub -referencing==0.35.1 +referencing==0.36.2 # via # jsonschema # jsonschema-specifications @@ -183,33 +187,31 @@ regex==2024.11.6 requests==2.32.3 # via # huggingface-hub - # litellm # mixpanel # posthog # tiktoken rich==13.9.4 # via -r requirements/requirements.in -rpds-py==0.21.0 +rpds-py==0.22.3 # via # jsonschema # referencing scipy==1.13.1 # via -r requirements/requirements.in -six==1.16.0 +six==1.17.0 # via # mixpanel # posthog # python-dateutil -smmap==5.0.1 +smmap==5.0.2 # via gitdb sniffio==1.3.1 # via # anyio - # httpx # openai sounddevice==0.5.1 # via -r requirements/requirements.in -soundfile==0.12.1 +soundfile==0.13.1 # via -r requirements/requirements.in soupsieve==2.6 # via beautifulsoup4 @@ -231,17 +233,26 @@ tree-sitter-languages==1.10.2 # via grep-ast typing-extensions==4.12.2 # via + # anyio + # beautifulsoup4 # huggingface-hub # openai # pydantic # pydantic-core -urllib3==2.2.3 + # referencing +urllib3==2.3.0 # via # mixpanel # requests +watchfiles==1.0.4 + # via -r requirements/requirements.in wcwidth==0.2.13 # via prompt-toolkit -yarl==1.18.0 +yarl==1.18.3 # via aiohttp zipp==3.21.0 # via importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +pip==25.0 + # via -r requirements/requirements.in diff --git a/requirements/requirements-browser.txt b/requirements/requirements-browser.txt index 6d24b879f..00e165273 100644 --- a/requirements/requirements-browser.txt +++ b/requirements/requirements-browser.txt @@ -2,11 +2,11 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# 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 +# pip-compile --allow-unsafe --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.5.0 # via streamlit -attrs==24.2.0 +attrs==25.1.0 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -15,35 +15,35 @@ attrs==24.2.0 # referencing blinker==1.9.0 # via streamlit -cachetools==5.5.0 +cachetools==5.5.1 # via streamlit -certifi==2024.8.30 +certifi==2025.1.31 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # -c requirements/requirements-dev.txt # -c requirements/requirements-help.txt # requests -charset-normalizer==3.4.0 +charset-normalizer==3.4.1 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # -c requirements/requirements-dev.txt # -c requirements/requirements-help.txt # requests -click==8.1.7 +click==8.1.8 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # -c requirements/requirements-dev.txt # -c requirements/requirements-help.txt # streamlit -gitdb==4.0.11 +gitdb==4.0.12 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # gitpython -gitpython==3.1.43 +gitpython==3.1.44 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -55,7 +55,7 @@ idna==3.10 # -c requirements/requirements-dev.txt # -c requirements/requirements-help.txt # requests -jinja2==3.1.4 +jinja2==3.1.5 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -92,7 +92,7 @@ mdurl==0.1.2 # -c requirements.txt # -c requirements/requirements-dev.txt # markdown-it-py -narwhals==1.14.2 +narwhals==1.25.2 # via altair numpy==1.26.4 # via @@ -122,13 +122,13 @@ pillow==10.4.0 # -c requirements/requirements-dev.txt # -c requirements/requirements-help.txt # streamlit -protobuf==5.28.3 +protobuf==5.29.3 # via streamlit -pyarrow==18.1.0 +pyarrow==19.0.0 # via streamlit pydeck==0.9.1 # via streamlit -pygments==2.18.0 +pygments==2.19.1 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -140,11 +140,11 @@ python-dateutil==2.9.0.post0 # -c requirements.txt # -c requirements/requirements-dev.txt # pandas -pytz==2024.2 +pytz==2025.1 # via # -c requirements/requirements-dev.txt # pandas -referencing==0.35.1 +referencing==0.36.2 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -163,26 +163,26 @@ rich==13.9.4 # -c requirements.txt # -c requirements/requirements-dev.txt # streamlit -rpds-py==0.21.0 +rpds-py==0.22.3 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # jsonschema # referencing -six==1.16.0 +six==1.17.0 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # -c requirements/requirements-dev.txt # python-dateutil -smmap==5.0.1 +smmap==5.0.2 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # gitdb -streamlit==1.40.2 +streamlit==1.42.0 # via -r requirements/requirements-browser.in -tenacity==8.5.0 +tenacity==9.0.0 # via # -c requirements/requirements-help.txt # streamlit @@ -197,12 +197,13 @@ typing-extensions==4.12.2 # -c requirements/requirements-dev.txt # -c requirements/requirements-help.txt # altair + # referencing # streamlit -tzdata==2024.2 +tzdata==2025.1 # via # -c requirements/requirements-dev.txt # pandas -urllib3==2.2.3 +urllib3==2.3.0 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt diff --git a/requirements/requirements-dev.in b/requirements/requirements-dev.in index ccd86fcce..a9b6c2216 100644 --- a/requirements/requirements-dev.in +++ b/requirements/requirements-dev.in @@ -3,6 +3,7 @@ # pip-compile --output-file=requirements-dev.txt requirements-dev.in --upgrade # pytest +pytest-env pip-tools lox matplotlib diff --git a/requirements/requirements-dev.txt b/requirements/requirements-dev.txt index 8787a4ea5..5234c9175 100644 --- a/requirements/requirements-dev.txt +++ b/requirements/requirements-dev.txt @@ -2,33 +2,33 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile --constraint=requirements.txt --output-file=requirements/requirements-dev.txt requirements/requirements-dev.in +# pip-compile --allow-unsafe --constraint=requirements.txt --output-file=requirements/requirements-dev.txt requirements/requirements-dev.in # alabaster==1.0.0 # via sphinx -babel==2.16.0 +babel==2.17.0 # via sphinx build==1.2.2.post1 # via pip-tools -certifi==2024.8.30 +certifi==2025.1.31 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # requests cfgv==3.4.0 # via pre-commit -charset-normalizer==3.4.0 +charset-normalizer==3.4.1 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # requests -click==8.1.7 +click==8.1.8 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # pip-tools # typer -codespell==2.3.0 +codespell==2.4.1 # via -r requirements/requirements-dev.in cogapp==3.4.1 # via -r requirements/requirements-dev.in @@ -46,14 +46,14 @@ docutils==0.21.2 # via # sphinx # sphinx-rtd-theme -filelock==3.16.1 +filelock==3.17.0 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # virtualenv -fonttools==4.55.0 +fonttools==4.56.0 # via matplotlib -identify==2.6.3 +identify==2.6.6 # via pre-commit idna==3.10 # via @@ -66,12 +66,12 @@ imgcat==0.6.0 # via -r requirements/requirements-dev.in iniconfig==2.0.0 # via pytest -jinja2==3.1.4 +jinja2==3.1.5 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # sphinx -kiwisolver==1.4.7 +kiwisolver==1.4.8 # via matplotlib lox==0.12.0 # via -r requirements/requirements-dev.in @@ -85,7 +85,7 @@ markupsafe==3.0.2 # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # jinja2 -matplotlib==3.9.2 +matplotlib==3.10.0 # via -r requirements/requirements-dev.in mdurl==0.1.2 # via @@ -130,21 +130,25 @@ pox==0.3.5 # via pathos ppft==1.7.6.9 # via pathos -pre-commit==4.0.1 +pre-commit==4.1.0 # via -r requirements/requirements-dev.in -pygments==2.18.0 +pygments==2.19.1 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # rich # sphinx -pyparsing==3.2.0 +pyparsing==3.2.1 # via matplotlib pyproject-hooks==1.2.0 # via # build # pip-tools -pytest==8.3.3 +pytest==8.3.4 + # via + # -r requirements/requirements-dev.in + # pytest-env +pytest-env==1.1.5 # via -r requirements/requirements-dev.in python-dateutil==2.9.0.post0 # via @@ -152,7 +156,7 @@ python-dateutil==2.9.0.post0 # -c requirements.txt # matplotlib # pandas -pytz==2024.2 +pytz==2025.1 # via pandas pyyaml==6.0.2 # via @@ -169,11 +173,11 @@ rich==13.9.4 # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # typer -semver==3.0.2 +semver==3.0.4 # via -r requirements/requirements-dev.in shellingham==1.5.4 # via typer -six==1.16.0 +six==1.17.0 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -200,25 +204,30 @@ sphinxcontrib-qthelp==2.0.0 # via sphinx sphinxcontrib-serializinghtml==2.0.0 # via sphinx -typer==0.13.1 +typer==0.15.1 # via -r requirements/requirements-dev.in typing-extensions==4.12.2 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # typer -tzdata==2024.2 +tzdata==2025.1 # via pandas -urllib3==2.2.3 +urllib3==2.3.0 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # requests -virtualenv==20.28.0 +virtualenv==20.29.1 # via pre-commit wheel==0.45.1 # via pip-tools # The following packages are considered to be unsafe in a requirements file: -# pip -# setuptools +pip==25.0 + # via + # -c /Users/gauthier/Projects/aider/requirements.txt + # -c requirements.txt + # pip-tools +setuptools==75.8.0 + # via pip-tools diff --git a/requirements/requirements-help.txt b/requirements/requirements-help.txt index 334c3555f..f12bcf4b4 100644 --- a/requirements/requirements-help.txt +++ b/requirements/requirements-help.txt @@ -2,20 +2,20 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --output-file=requirements/requirements-help.txt requirements/requirements-help.in +# pip-compile --allow-unsafe --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --output-file=requirements/requirements-help.txt requirements/requirements-help.in # -aiohappyeyeballs==2.4.3 +aiohappyeyeballs==2.4.6 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # aiohttp -aiohttp==3.11.7 +aiohttp==3.11.12 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # huggingface-hub # llama-index-core -aiosignal==1.3.1 +aiosignal==1.3.2 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -25,17 +25,17 @@ annotated-types==0.7.0 # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # pydantic -anyio==4.6.2.post1 +anyio==4.8.0 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # httpx -attrs==24.2.0 +attrs==25.1.0 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # aiohttp -certifi==2024.8.30 +certifi==2025.1.31 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -43,13 +43,13 @@ certifi==2024.8.30 # httpcore # httpx # requests -charset-normalizer==3.4.0 +charset-normalizer==3.4.1 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # -c requirements/requirements-dev.txt # requests -click==8.1.7 +click==8.1.8 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -57,11 +57,11 @@ click==8.1.7 # nltk dataclasses-json==0.6.7 # via llama-index-core -deprecated==1.2.15 +deprecated==1.2.18 # via llama-index-core dirtyjson==1.0.8 # via llama-index-core -filelock==3.16.1 +filelock==3.17.0 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -77,7 +77,7 @@ frozenlist==1.5.0 # -c requirements.txt # aiohttp # aiosignal -fsspec==2024.10.0 +fsspec==2025.2.0 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -98,12 +98,12 @@ httpcore==1.0.7 # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # httpx -httpx==0.27.2 +httpx==0.28.1 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # llama-index-core -huggingface-hub[inference]==0.26.2 +huggingface-hub[inference]==0.28.1 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -120,7 +120,7 @@ idna==3.10 # httpx # requests # yarl -jinja2==3.1.4 +jinja2==3.1.5 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -130,11 +130,11 @@ joblib==1.4.2 # via # nltk # scikit-learn -llama-index-core==0.12.0 +llama-index-core==0.12.16.post1 # via # -r requirements/requirements-help.in # llama-index-embeddings-huggingface -llama-index-embeddings-huggingface==0.4.0 +llama-index-embeddings-huggingface==0.5.1 # via -r requirements/requirements-help.in markupsafe==3.0.2 # via @@ -142,7 +142,7 @@ markupsafe==3.0.2 # -c requirements.txt # -c requirements/requirements-dev.txt # jinja2 -marshmallow==3.23.1 +marshmallow==3.26.1 # via dataclasses-json mpmath==1.3.0 # via sympy @@ -188,18 +188,18 @@ pillow==10.4.0 # -c requirements/requirements-dev.txt # llama-index-core # sentence-transformers -propcache==0.2.0 +propcache==0.2.1 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # aiohttp # yarl -pydantic==2.10.2 +pydantic==2.10.6 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # llama-index-core -pydantic-core==2.27.1 +pydantic-core==2.27.2 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt @@ -228,9 +228,9 @@ requests==2.32.3 # llama-index-core # tiktoken # transformers -safetensors==0.4.5 +safetensors==0.5.2 # via transformers -scikit-learn==1.5.2 +scikit-learn==1.6.1 # via sentence-transformers scipy==1.13.1 # via @@ -238,21 +238,20 @@ scipy==1.13.1 # -c requirements.txt # scikit-learn # sentence-transformers -sentence-transformers==3.3.1 +sentence-transformers==3.4.1 # via llama-index-embeddings-huggingface sniffio==1.3.1 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # anyio - # httpx -sqlalchemy[asyncio]==2.0.36 +sqlalchemy[asyncio]==2.0.38 # via # llama-index-core # sqlalchemy sympy==1.13.3 # via torch -tenacity==8.5.0 +tenacity==9.0.0 # via llama-index-core threadpoolctl==3.5.0 # via scikit-learn @@ -284,6 +283,7 @@ typing-extensions==4.12.2 # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # -c requirements/requirements-dev.txt + # anyio # huggingface-hub # llama-index-core # pydantic @@ -295,17 +295,17 @@ typing-inspect==0.9.0 # via # dataclasses-json # llama-index-core -urllib3==2.2.3 +urllib3==2.3.0 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt # -c requirements/requirements-dev.txt # requests -wrapt==1.17.0 +wrapt==1.17.2 # via # deprecated # llama-index-core -yarl==1.18.0 +yarl==1.18.3 # via # -c /Users/gauthier/Projects/aider/requirements.txt # -c requirements.txt diff --git a/requirements/requirements-playwright.txt b/requirements/requirements-playwright.txt index 69fa7a74b..f84ec4f68 100644 --- a/requirements/requirements-playwright.txt +++ b/requirements/requirements-playwright.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# 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 +# pip-compile --allow-unsafe --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 diff --git a/requirements/requirements.in b/requirements/requirements.in index 6e1ba07ef..6667edbfc 100644 --- a/requirements/requirements.in +++ b/requirements/requirements.in @@ -28,6 +28,8 @@ mixpanel pexpect json5 psutil +watchfiles +pip # The proper dependency is networkx[default], but this brings # in matplotlib and a bunch of other deps diff --git a/scripts/__init__.py b/scripts/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/blame.py b/scripts/blame.py index 1cb63b4e7..2257442d9 100755 --- a/scripts/blame.py +++ b/scripts/blame.py @@ -12,6 +12,17 @@ import semver import yaml from tqdm import tqdm +website_files = [ + "aider/website/share/index.md", + "aider/website/_includes/head_custom.html", + "aider/website/docs/leaderboards/index.md", +] + +exclude_files = [ + "aider/website/install.ps1", + "aider/website/install.sh", +] + def blame(start_tag, end_tag=None): commits = get_all_commit_hashes_between_tags(start_tag, end_tag) @@ -21,15 +32,18 @@ def blame(start_tag, end_tag=None): revision = end_tag if end_tag else "HEAD" files = run(["git", "ls-tree", "-r", "--name-only", revision]).strip().split("\n") + test_files = [f for f in files if f.startswith("tests/fixtures/languages/") and "/test." in f] files = [ f for f in files if f.endswith((".js", ".py", ".scm", ".sh", "Dockerfile", "Gemfile")) or (f.startswith(".github/workflows/") and f.endswith(".yml")) - or f == "aider/website/share/index.md" - or f == "aider/website/docs/leaderboards/index.md" + or f in website_files + or f in test_files ] files = [f for f in files if not f.endswith("prompts.py")] + files = [f for f in files if not f.startswith("tests/fixtures/watch")] + files = [f for f in files if f not in exclude_files] all_file_counts = {} grand_total = defaultdict(int) @@ -203,9 +217,23 @@ def main(): def get_counts_for_file(start_tag, end_tag, authors, fname): try: if end_tag: - text = run(["git", "blame", f"{start_tag}..{end_tag}", "--", fname]) + text = run( + [ + "git", + "blame", + "-M", + "-C", + "-C", + "--abbrev=9", + f"{start_tag}..{end_tag}", + "--", + fname, + ] + ) else: - text = run(["git", "blame", f"{start_tag}..HEAD", "--", fname]) + text = run( + ["git", "blame", "-M", "-C", "-C", "--abbrev=9", f"{start_tag}..HEAD", "--", fname] + ) if not text: return None text = text.splitlines() diff --git a/scripts/history_prompts.py b/scripts/history_prompts.py new file mode 100644 index 000000000..4079d9d3e --- /dev/null +++ b/scripts/history_prompts.py @@ -0,0 +1,20 @@ +history_prompt = """ +Update the history with changes shown in the diffs. +Describe actual user-facing changes, not every single commit that was made implementing them. + +Only add new items not already listed. +Do NOT edit or update existing history entries. +Do NOT add duplicate entries for changes that have existing history entries. + +End each bullet with a period. + +If the change was made by someone other than Paul Gauthier note it at the end of the bullet point as ", by XXX." + +Be sure to attribute changes to the proper .x version. +Changes in the .x-dev version should be listed under a "### main branch" heading + +Start a new "### main branch" section at the top of the file if needed. + +Also, add this as the last bullet under the "### main branch" section: +{aider_line} +""" # noqa diff --git a/scripts/issues.py b/scripts/issues.py index 721178fa9..b474d6f42 100755 --- a/scripts/issues.py +++ b/scripts/issues.py @@ -22,7 +22,9 @@ def has_been_reopened(issue_number): # Load environment variables from .env file load_dotenv() -BOT_SUFFIX = """Note: A [bot script](https://github.com/Aider-AI/aider/blob/main/scripts/issues.py) made these updates to the issue. +BOT_SUFFIX = """ + +Note: [A bot script](https://github.com/Aider-AI/aider/blob/main/scripts/issues.py) made these updates to the issue. """ # noqa DUPLICATE_COMMENT = ( @@ -44,6 +46,20 @@ CLOSE_STALE_COMMENT = ( + BOT_SUFFIX ) +CLOSE_FIXED_ENHANCEMENT_COMMENT = ( + """I'm closing this enhancement request since it has been marked as 'fixed' for over """ + """3 weeks. The requested feature should now be available in recent versions of aider.\n\n""" + """If you find that this enhancement is still needed, please feel free to reopen this """ + """issue or create a new one.""" + BOT_SUFFIX +) + +CLOSE_FIXED_BUG_COMMENT = ( + """I'm closing this bug report since it has been marked as 'fixed' for over """ + """3 weeks. This issue should be resolved in recent versions of aider.\n\n""" + """If you find that this bug is still present, please feel free to reopen this """ + """issue or create a new one with steps to reproduce.""" + BOT_SUFFIX +) + # GitHub API configuration GITHUB_API_URL = "https://api.github.com" REPO_OWNER = "Aider-AI" @@ -304,6 +320,68 @@ def handle_stale_closing(all_issues, auto_yes): print(f" Closed issue #{issue['number']}") +def handle_fixed_issues(all_issues, auto_yes): + print("\nChecking for fixed enhancement and bug issues to close...") + + for issue in all_issues: + # Skip if not open or doesn't have fixed label + labels = [label["name"] for label in issue["labels"]] + if issue["state"] != "open" or "fixed" not in labels: + continue + + # Check if it's an enhancement or bug + is_enhancement = "enhancement" in labels + is_bug = "bug" in labels + if not (is_enhancement or is_bug): + continue + + # Find when the fixed label was added + timeline_url = ( + f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/timeline" + ) + response = requests.get(timeline_url, headers=headers) + response.raise_for_status() + events = response.json() + + # Find the most recent fixed label addition + fixed_events = [ + event + for event in events + if event.get("event") == "labeled" and event.get("label", {}).get("name") == "fixed" + ] + + if not fixed_events: + continue + + latest_fixed = datetime.strptime(fixed_events[-1]["created_at"], "%Y-%m-%dT%H:%M:%SZ") + days_fixed = (datetime.now() - latest_fixed).days + + if days_fixed >= 21: + issue_type = "enhancement" if is_enhancement else "bug" + print(f"\nFixed {issue_type} ready for closing #{issue['number']}: {issue['title']}") + print(f" Has been marked fixed for {days_fixed} days") + + if not auto_yes: + confirm = input("Close this issue? (y/n): ") + if confirm.lower() != "y": + print("Skipping this issue.") + continue + + # Add closing comment + comment_url = ( + f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/comments" + ) + comment = CLOSE_FIXED_ENHANCEMENT_COMMENT if is_enhancement else CLOSE_FIXED_BUG_COMMENT + response = requests.post(comment_url, headers=headers, json={"body": comment}) + response.raise_for_status() + + # Close the issue + url = f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}" + response = requests.patch(url, headers=headers, json={"state": "closed"}) + response.raise_for_status() + print(f" Closed issue #{issue['number']}") + + def handle_duplicate_issues(all_issues, auto_yes): open_issues = [issue for issue in all_issues if issue["state"] == "open"] grouped_open_issues = group_issues_by_subject(open_issues) @@ -361,6 +439,7 @@ def main(): handle_stale_issues(all_issues, args.yes) handle_stale_closing(all_issues, args.yes) handle_duplicate_issues(all_issues, args.yes) + handle_fixed_issues(all_issues, args.yes) if __name__ == "__main__": diff --git a/scripts/my_models.py b/scripts/my_models.py new file mode 100755 index 000000000..748c592fb --- /dev/null +++ b/scripts/my_models.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 + +import json +from collections import defaultdict, deque +from pathlib import Path + + +def collect_model_stats(n_lines=1000): + """Collect model usage statistics from the analytics file.""" + analytics_path = Path.home() / ".aider" / "analytics.jsonl" + model_stats = defaultdict(int) + + with open(analytics_path) as f: + lines = deque(f, n_lines) + for line in lines: + try: + event = json.loads(line) + if event["event"] == "message_send": + properties = event["properties"] + main_model = properties.get("main_model") + + total_tokens = properties.get("total_tokens", 0) + if main_model == "deepseek/deepseek-coder": + main_model = "deepseek/deepseek-chat" + if main_model: + model_stats[main_model] += total_tokens + except json.JSONDecodeError: + continue + + return model_stats + + +def format_text_table(model_stats): + """Format model statistics as a text table.""" + total_tokens = sum(model_stats.values()) + lines = [] + + lines.append("\nModel Token Usage Summary:") + lines.append("-" * 80) + lines.append(f"{'Model Name':<40} {'Total Tokens':>15} {'Percent':>10}") + lines.append("-" * 80) + + for model, tokens in sorted(model_stats.items(), key=lambda x: x[1], reverse=True): + percentage = (tokens / total_tokens) * 100 if total_tokens > 0 else 0 + lines.append(f"{model:<40} {tokens:>15,} {percentage:>9.1f}%") + + lines.append("-" * 80) + lines.append(f"{'TOTAL':<40} {total_tokens:>15,} {100:>9.1f}%") + + return "\n".join(lines) + + +def format_html_table(model_stats): + """Format model statistics as an HTML table.""" + total_tokens = sum(model_stats.values()) + + html = [ + "", + "", + ( + "Percent" + ), + ] + + for model, tokens in sorted(model_stats.items(), key=lambda x: x[1], reverse=True): + percentage = (tokens / total_tokens) * 100 if total_tokens > 0 else 0 + html.append( + f"" + f"" + f"" + ) + + html.append("
Model NameTotal Tokens
{model}{tokens:,}{percentage:.1f}%
") + + # Add note about redacted models if any are present + if any("REDACTED" in model for model in model_stats.keys()): + html.extend( + [ + "", + "{: .note :}", + "Some models show as REDACTED, because they are new or unpopular models.", + 'Aider\'s analytics only records the names of "well known" LLMs.', + ] + ) + + return "\n".join(html) + + +if __name__ == "__main__": + stats = collect_model_stats() + print(format_text_table(stats)) diff --git a/scripts/pip-compile.sh b/scripts/pip-compile.sh index 9d8a8ff3c..822cb819f 100755 --- a/scripts/pip-compile.sh +++ b/scripts/pip-compile.sh @@ -5,6 +5,7 @@ set -e # First compile the base requirements pip-compile \ + --allow-unsafe \ requirements/requirements.in \ --output-file=requirements.txt \ $1 @@ -15,6 +16,7 @@ CONSTRAINTS="--constraint=requirements.txt" for SUFFIX in "${SUFFIXES[@]}"; do pip-compile \ + --allow-unsafe \ requirements/requirements-${SUFFIX}.in \ --output-file=requirements/requirements-${SUFFIX}.txt \ ${CONSTRAINTS} \ diff --git a/scripts/update-blame.sh b/scripts/update-blame.sh index 4615ed2fd..d4796b355 100755 --- a/scripts/update-blame.sh +++ b/scripts/update-blame.sh @@ -3,4 +3,6 @@ # exit when any command fails set -e -./scripts/blame.py v0.1.0 --all --output aider/website/_data/blame.yml +# Use first argument as version if provided, otherwise default to v0.1.0 +VERSION=${1:-v0.1.0} +./scripts/blame.py "$VERSION" --all --output aider/website/_data/blame.yml diff --git a/scripts/update-docs.sh b/scripts/update-docs.sh index cfcf5779d..ecde8ac01 100755 --- a/scripts/update-docs.sh +++ b/scripts/update-docs.sh @@ -11,6 +11,7 @@ fi if [ "$ARG" != "--check" ]; then tail -1000 ~/.aider/analytics.jsonl > aider/website/assets/sample-analytics.jsonl + cog -r aider/website/docs/faq.md fi # README.md before index.md, because index.md uses cog to include README.md @@ -26,6 +27,8 @@ cog $ARG \ aider/website/docs/config/adv-model-settings.md \ aider/website/docs/config/model-aliases.md \ aider/website/docs/leaderboards/index.md \ + aider/website/docs/leaderboards/edit.md \ + aider/website/docs/leaderboards/refactor.md \ aider/website/docs/llms/other.md \ aider/website/docs/more/infinite-output.md \ aider/website/docs/legal/privacy.md diff --git a/scripts/update-history.py b/scripts/update-history.py index 3bc43f54c..968210a63 100755 --- a/scripts/update-history.py +++ b/scripts/update-history.py @@ -5,6 +5,8 @@ import re import subprocess import tempfile +from history_prompts import history_prompt + from aider import __version__ @@ -22,6 +24,7 @@ def run_git_log(): "git", "log", "-p", + "--pretty=full", f"v{base_ver}..HEAD", "--", "aider/", @@ -37,35 +40,79 @@ def main(): # Get the git log output diff_content = run_git_log() - # Save to temporary file - with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".diff") as tmp: - tmp.write(diff_content) - tmp_path = tmp.name + # Extract relevant portion of HISTORY.md + base_ver = get_base_version() + with open("HISTORY.md", "r") as f: + history_content = f.read() + + # Find the section for this version + version_header = f"### Aider v{base_ver}" + start_idx = history_content.find("# Release history") + if start_idx == -1: + raise ValueError("Could not find start of release history") + + # Find where this version's section ends + version_idx = history_content.find(version_header, start_idx) + if version_idx == -1: + raise ValueError(f"Could not find version header: {version_header}") + + # Find the next version header after this one + next_version_idx = history_content.find("\n### Aider v", version_idx + len(version_header)) + if next_version_idx == -1: + # No next version found, use the rest of the file + relevant_history = history_content[start_idx:] + else: + # Extract just up to the next version + relevant_history = history_content[start_idx:next_version_idx] + + # Save relevant portions to temporary files + with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".diff") as tmp_diff: + tmp_diff.write(diff_content) + diff_path = tmp_diff.name + + with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".md") as tmp_hist: + tmp_hist.write(relevant_history) + hist_path = tmp_hist.name # Run blame to get aider percentage blame_result = subprocess.run(["python3", "scripts/blame.py"], capture_output=True, text=True) aider_line = blame_result.stdout.strip().split("\n")[-1] # Get last line with percentage # Construct and run the aider command - message = f""" -Update the history with changes shown in the diffs. -Describe actual user-facing changes, not every single commit that was made implementing them. -Don't edit or duplicate changes that have existing history entries, just add any new items not already listed. -Be sure to attribute changes to the proper .x version. -Changes in the .x-dev version should be listed under a "### main branch" heading + message = history_prompt.format(aider_line=aider_line) -Also, add this as the last bullet under the "### main branch" section: -{aider_line} -""" # noqa - - cmd = ["aider", "HISTORY.md", "--read", tmp_path, "--msg", message, "--no-auto-commit"] + cmd = ["aider", hist_path, "--read", diff_path, "--msg", message, "--no-auto-commit"] subprocess.run(cmd) + # Read back the updated history + with open(hist_path, "r") as f: + updated_history = f.read() + + # Find where the next version section would start + if next_version_idx == -1: + # No next version found, use the rest of the file + full_history = history_content[:start_idx] + updated_history + else: + # Splice the updated portion back in between the unchanged parts + full_history = ( + history_content[:start_idx] + + updated_history # Keep unchanged header + + history_content[next_version_idx:] # Add updated portion # Keep older entries + ) + + # Write back the full history + with open("HISTORY.md", "w") as f: + f.write(full_history) + # Run update-docs.sh after aider subprocess.run(["scripts/update-docs.sh"]) # Cleanup - os.unlink(tmp_path) + os.unlink(diff_path) + os.unlink(hist_path) + + # Show git diff of HISTORY.md + subprocess.run(["git", "diff", "HISTORY.md"]) if __name__ == "__main__": diff --git a/scripts/versionbump.py b/scripts/versionbump.py index 018d238a1..859cab1d7 100755 --- a/scripts/versionbump.py +++ b/scripts/versionbump.py @@ -10,15 +10,6 @@ import sys from packaging import version -def check_cog_pyproject(): - result = subprocess.run(["cog", "--check", "pyproject.toml"], capture_output=True, text=True) - - if result.returncode != 0: - print("Error: cog --check pyproject.toml failed, updating.") - subprocess.run(["cog", "-r", "pyproject.toml"]) - sys.exit(1) - - def main(): parser = argparse.ArgumentParser(description="Bump version") parser.add_argument("new_version", help="New version in x.y.z format") @@ -82,7 +73,6 @@ def main(): dry_run = args.dry_run # Perform checks before proceeding - check_cog_pyproject() check_branch() check_working_directory_clean() check_main_branch_up_to_date() @@ -154,8 +144,8 @@ def main(): if not dry_run: subprocess.run(cmd, check=True) - # Remove aider/__version__.py if it exists - version_file = "aider/__version__.py" + # Remove aider/_version.py if it exists + version_file = "aider/_version.py" if os.path.exists(version_file): print(f"Removing {version_file}") if not dry_run: diff --git a/tests/basic/test_analytics.py b/tests/basic/test_analytics.py index dd25e12c8..e3178ee30 100644 --- a/tests/basic/test_analytics.py +++ b/tests/basic/test_analytics.py @@ -37,7 +37,7 @@ def test_analytics_enable_disable(temp_data_dir): analytics.asked_opt_in = True analytics.enable() - assert analytics.mp is not None + # assert analytics.mp is not None assert analytics.ph is not None analytics.disable(permanently=False) @@ -65,18 +65,18 @@ def test_analytics_event_logging(temp_analytics_file, temp_data_dir): 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) + # 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() + # 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"] + # 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): @@ -94,9 +94,6 @@ def test_need_to_ask(temp_data_dir): assert analytics.need_to_ask(True) is True assert analytics.need_to_ask(False) is False - analytics.user_id = "111" - assert analytics.need_to_ask(None) is False - analytics.user_id = "000" assert analytics.need_to_ask(None) is True @@ -108,32 +105,32 @@ def test_need_to_ask(temp_data_dir): def test_is_uuid_in_percentage(): - analytics = Analytics() + from aider.analytics import is_uuid_in_percentage # Test basic percentage thresholds - assert analytics.is_uuid_in_percentage("00000000000000000000000000000000", 1) is True - assert analytics.is_uuid_in_percentage("01999000000000000000000000000000", 1) is True - assert analytics.is_uuid_in_percentage("02000000000000000000000000000000", 1) is True - assert analytics.is_uuid_in_percentage("02910000000000000000000000000001", 1) is False - assert analytics.is_uuid_in_percentage("03000000000000000000000000000000", 1) is False - assert analytics.is_uuid_in_percentage("ff000000000000000000000000000000", 1) is False + assert is_uuid_in_percentage("00000000000000000000000000000000", 1) is True + assert is_uuid_in_percentage("01999000000000000000000000000000", 1) is True + assert is_uuid_in_percentage("02000000000000000000000000000000", 1) is True + assert is_uuid_in_percentage("02910000000000000000000000000001", 1) is False + assert is_uuid_in_percentage("03000000000000000000000000000000", 1) is False + assert is_uuid_in_percentage("ff000000000000000000000000000000", 1) is False - assert analytics.is_uuid_in_percentage("00000000000000000000000000000000", 10) is True - assert analytics.is_uuid_in_percentage("19000000000000000000000000000000", 10) is True - assert analytics.is_uuid_in_percentage("1a000000000000000000000000000000", 10) is False - assert analytics.is_uuid_in_percentage("ff000000000000000000000000000000", 10) is False + assert is_uuid_in_percentage("00000000000000000000000000000000", 10) is True + assert is_uuid_in_percentage("19000000000000000000000000000000", 10) is True + assert is_uuid_in_percentage("1a000000000000000000000000000000", 10) is False + assert is_uuid_in_percentage("ff000000000000000000000000000000", 10) is False # Test edge cases - assert analytics.is_uuid_in_percentage("00000000000000000000000000000000", 0) is False - assert analytics.is_uuid_in_percentage("00000000000000000000000000000000", 100) is True - assert analytics.is_uuid_in_percentage("ffffffffffffffffffffffffffffffff", 100) is True + assert is_uuid_in_percentage("00000000000000000000000000000000", 0) is False + assert is_uuid_in_percentage("00000000000000000000000000000000", 100) is True + assert is_uuid_in_percentage("ffffffffffffffffffffffffffffffff", 100) is True # Test invalid inputs with pytest.raises(ValueError): - analytics.is_uuid_in_percentage("00000000000000000000000000000000", -1) + is_uuid_in_percentage("00000000000000000000000000000000", -1) with pytest.raises(ValueError): - analytics.is_uuid_in_percentage("00000000000000000000000000000000", 101) + is_uuid_in_percentage("00000000000000000000000000000000", 101) # Test empty/None UUID - assert analytics.is_uuid_in_percentage("", 50) is False - assert analytics.is_uuid_in_percentage(None, 50) is False + assert is_uuid_in_percentage("", 50) is False + assert is_uuid_in_percentage(None, 50) is False diff --git a/tests/basic/test_coder.py b/tests/basic/test_coder.py index 88026cfb0..ba24e7081 100644 --- a/tests/basic/test_coder.py +++ b/tests/basic/test_coder.py @@ -7,11 +7,12 @@ from unittest.mock import MagicMock, patch import git from aider.coders import Coder -from aider.coders.base_coder import UnknownEditFormat +from aider.coders.base_coder import FinishReasonLength, UnknownEditFormat from aider.dump import dump # noqa: F401 from aider.io import InputOutput from aider.models import Model from aider.repo import GitRepo +from aider.sendchat import sanity_check_messages from aider.utils import GitTemporaryDirectory @@ -904,6 +905,25 @@ This command will print 'Hello, World!' to the console.""" self.assertIsInstance(exc.valid_formats, list) self.assertTrue(len(exc.valid_formats) > 0) + def test_system_prompt_prefix(self): + # Test that system_prompt_prefix is properly set and used + io = InputOutput(yes=True) + test_prefix = "Test prefix. " + + # Create a model with system_prompt_prefix + model = Model("gpt-3.5-turbo") + model.system_prompt_prefix = test_prefix + + coder = Coder.create(model, None, io=io) + + # Get the formatted messages + chunks = coder.format_messages() + messages = chunks.all_messages() + + # Check if the system message contains our prefix + system_message = next(msg for msg in messages if msg["role"] == "system") + self.assertTrue(system_message["content"].startswith(test_prefix)) + def test_coder_create_with_new_file_oserror(self): with GitTemporaryDirectory(): io = InputOutput(yes=True) @@ -974,6 +994,71 @@ This command will print 'Hello, World!' to the console.""" self.assertIn("Output tokens:", error_message) self.assertIn("Total tokens:", error_message) + def test_keyboard_interrupt_handling(self): + with GitTemporaryDirectory(): + io = InputOutput(yes=True) + coder = Coder.create(self.GPT35, "diff", io=io) + + # Simulate keyboard interrupt during message processing + def mock_send(*args, **kwargs): + coder.partial_response_content = "Partial response" + coder.partial_response_function_call = dict() + raise KeyboardInterrupt() + + coder.send = mock_send + + # Initial valid state + sanity_check_messages(coder.cur_messages) + + # Process message that will trigger interrupt + list(coder.send_message("Test message")) + + # Verify messages are still in valid state + sanity_check_messages(coder.cur_messages) + self.assertEqual(coder.cur_messages[-1]["role"], "assistant") + + def test_token_limit_error_handling(self): + with GitTemporaryDirectory(): + io = InputOutput(yes=True) + coder = Coder.create(self.GPT35, "diff", io=io) + + # Simulate token limit error + def mock_send(*args, **kwargs): + coder.partial_response_content = "Partial response" + coder.partial_response_function_call = dict() + raise FinishReasonLength() + + coder.send = mock_send + + # Initial valid state + sanity_check_messages(coder.cur_messages) + + # Process message that hits token limit + list(coder.send_message("Long message")) + + # Verify messages are still in valid state + sanity_check_messages(coder.cur_messages) + self.assertEqual(coder.cur_messages[-1]["role"], "assistant") + + def test_message_sanity_after_partial_response(self): + with GitTemporaryDirectory(): + io = InputOutput(yes=True) + coder = Coder.create(self.GPT35, "diff", io=io) + + # Simulate partial response then interrupt + def mock_send(*args, **kwargs): + coder.partial_response_content = "Partial response" + coder.partial_response_function_call = dict() + raise KeyboardInterrupt() + + coder.send = mock_send + + list(coder.send_message("Test")) + + # Verify message structure remains valid + sanity_check_messages(coder.cur_messages) + self.assertEqual(coder.cur_messages[-1]["role"], "assistant") + if __name__ == "__main__": unittest.main() diff --git a/tests/basic/test_commands.py b/tests/basic/test_commands.py index 0982d8bf4..a234c9b1d 100644 --- a/tests/basic/test_commands.py +++ b/tests/basic/test_commands.py @@ -236,7 +236,7 @@ class TestCommands(TestCase): self.assertIn(str(Path("test_dir/test_file2.txt").resolve()), coder.abs_fnames) self.assertIn(str(Path("test_dir/another_dir/test_file.txt").resolve()), coder.abs_fnames) - commands.cmd_drop("test_dir/another_dir") + commands.cmd_drop(str(Path("test_dir/another_dir"))) self.assertIn(str(Path("test_dir/test_file1.txt").resolve()), coder.abs_fnames) self.assertIn(str(Path("test_dir/test_file2.txt").resolve()), coder.abs_fnames) self.assertNotIn( @@ -272,6 +272,7 @@ class TestCommands(TestCase): coder = Coder.create(self.GPT35, None, io) commands = Commands(io, coder) + # Create test files in root and subdirectory subdir = Path("subdir") subdir.mkdir() (subdir / "subtest1.py").touch() @@ -279,17 +280,50 @@ class TestCommands(TestCase): Path("test1.py").touch() Path("test2.py").touch() + Path("test3.txt").touch() - # Add some files to the chat session + # Add all Python files to the chat session commands.cmd_add("*.py") + initial_count = len(coder.abs_fnames) + self.assertEqual(initial_count, 2) # Only root .py files should be added - self.assertEqual(len(coder.abs_fnames), 2) - - # Call the cmd_drop method with a glob pattern + # Test dropping with glob pattern commands.cmd_drop("*2.py") - self.assertIn(str(Path("test1.py").resolve()), coder.abs_fnames) self.assertNotIn(str(Path("test2.py").resolve()), coder.abs_fnames) + self.assertEqual(len(coder.abs_fnames), initial_count - 1) + + def test_cmd_drop_without_glob(self): + # Initialize the Commands and InputOutput objects + io = InputOutput(pretty=False, fancy_input=False, yes=True) + from aider.coders import Coder + + coder = Coder.create(self.GPT35, None, io) + commands = Commands(io, coder) + + # Create test files + test_files = ["file1.txt", "file2.txt", "file3.py"] + for fname in test_files: + Path(fname).touch() + + # Add all files to the chat session + for fname in test_files: + commands.cmd_add(fname) + + initial_count = len(coder.abs_fnames) + self.assertEqual(initial_count, 3) + + # Test dropping individual files without glob + commands.cmd_drop("file1.txt") + self.assertNotIn(str(Path("file1.txt").resolve()), coder.abs_fnames) + self.assertIn(str(Path("file2.txt").resolve()), coder.abs_fnames) + self.assertEqual(len(coder.abs_fnames), initial_count - 1) + + # Test dropping multiple files without glob + commands.cmd_drop("file2.txt file3.py") + self.assertNotIn(str(Path("file2.txt").resolve()), coder.abs_fnames) + self.assertNotIn(str(Path("file3.py").resolve()), coder.abs_fnames) + self.assertEqual(len(coder.abs_fnames), 0) def test_cmd_add_bad_encoding(self): # Initialize the Commands and InputOutput objects @@ -1397,6 +1431,76 @@ class TestCommands(TestCase): finally: os.unlink(external_file_path) + def test_cmd_drop_read_only_with_relative_path(self): + with ChdirTemporaryDirectory() as repo_dir: + test_file = Path("test_file.txt") + test_file.write_text("Test content") + + # Create a test file in a subdirectory + subdir = Path(repo_dir) / "subdir" + subdir.mkdir() + os.chdir(subdir) + + io = InputOutput(pretty=False, fancy_input=False, yes=False) + coder = Coder.create(self.GPT35, None, io) + commands = Commands(io, coder) + + # Add the file as read-only using absolute path + rel_path = str(Path("..") / "test_file.txt") + commands.cmd_read_only(rel_path) + self.assertEqual(len(coder.abs_read_only_fnames), 1) + + # Try to drop using relative path from different working directories + commands.cmd_drop("test_file.txt") + self.assertEqual(len(coder.abs_read_only_fnames), 0) + + # Add it again + commands.cmd_read_only(rel_path) + self.assertEqual(len(coder.abs_read_only_fnames), 1) + + commands.cmd_drop(rel_path) + self.assertEqual(len(coder.abs_read_only_fnames), 0) + + # Add it one more time + commands.cmd_read_only(rel_path) + self.assertEqual(len(coder.abs_read_only_fnames), 1) + + commands.cmd_drop("test_file.txt") + self.assertEqual(len(coder.abs_read_only_fnames), 0) + + def test_cmd_read_only_bulk_conversion(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 and add some test files + test_files = ["test1.txt", "test2.txt", "test3.txt"] + for fname in test_files: + Path(fname).write_text(f"Content of {fname}") + commands.cmd_add(fname) + + # Verify files are in editable mode + self.assertEqual(len(coder.abs_fnames), 3) + self.assertEqual(len(coder.abs_read_only_fnames), 0) + + # Convert all files to read-only mode + commands.cmd_read_only("") + + # Verify all files were moved to read-only + self.assertEqual(len(coder.abs_fnames), 0) + self.assertEqual(len(coder.abs_read_only_fnames), 3) + + # Check specific files + for fname in test_files: + abs_path = Path(repo_dir) / fname + self.assertTrue( + any( + os.path.samefile(str(abs_path), ro_fname) + for ro_fname in coder.abs_read_only_fnames + ) + ) + def test_cmd_read_only_with_multiple_files(self): with GitTemporaryDirectory() as repo_dir: io = InputOutput(pretty=False, fancy_input=False, yes=False) @@ -1617,3 +1721,33 @@ class TestCommands(TestCase): del coder del commands + + def test_cmd_load_with_switch_coder(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 a temporary file with commands + commands_file = Path(repo_dir) / "test_commands.txt" + commands_file.write_text("/ask Tell me about the code\n/model gpt-4\n") + + # Mock run to raise SwitchCoder for /ask and /model + def mock_run(cmd): + if cmd.startswith(("/ask", "/model")): + raise SwitchCoder() + return None + + with mock.patch.object(commands, "run", side_effect=mock_run): + # Capture tool_error output + with mock.patch.object(io, "tool_error") as mock_tool_error: + commands.cmd_load(str(commands_file)) + + # Check that appropriate error messages were shown + mock_tool_error.assert_any_call( + "Command '/ask Tell me about the code' is only supported in interactive" + " mode, skipping." + ) + mock_tool_error.assert_any_call( + "Command '/model gpt-4' is only supported in interactive mode, skipping." + ) diff --git a/tests/basic/test_editblock.py b/tests/basic/test_editblock.py index 1ac1e41b0..0a1f1bf5b 100644 --- a/tests/basic/test_editblock.py +++ b/tests/basic/test_editblock.py @@ -554,6 +554,27 @@ Hope you like it! ], ) + def test_find_original_update_blocks_quad_backticks_with_triples_in_LLM_reply(self): + # https://github.com/Aider-AI/aider/issues/2879 + edit = """ +Here's the change: + +foo.txt +```text +<<<<<<< SEARCH +======= +Tooooo +>>>>>>> REPLACE +``` + +Hope you like it! +""" + + quad_backticks = "`" * 4 + quad_backticks = (quad_backticks, quad_backticks) + edits = list(eb.find_original_update_blocks(edit, fence=quad_backticks)) + self.assertEqual(edits, [("foo.txt", "", "Tooooo\n")]) + if __name__ == "__main__": unittest.main() diff --git a/tests/basic/test_history.py b/tests/basic/test_history.py index 17b563265..c6376850d 100644 --- a/tests/basic/test_history.py +++ b/tests/basic/test_history.py @@ -10,6 +10,7 @@ class TestChatSummary(TestCase): self.mock_model.name = "gpt-3.5-turbo" self.mock_model.token_count = lambda msg: len(msg["content"].split()) self.mock_model.info = {"max_input_tokens": 4096} + self.mock_model.simple_send_with_retries = mock.Mock() self.chat_summary = ChatSummary(self.mock_model, max_tokens=100) def test_initialization(self): @@ -34,9 +35,8 @@ class TestChatSummary(TestCase): tokenized = self.chat_summary.tokenize(messages) self.assertEqual(tokenized, [(2, messages[0]), (2, messages[1])]) - @mock.patch("aider.history.simple_send_with_retries") - def test_summarize_all(self, mock_send): - mock_send.return_value = "This is a summary" + def test_summarize_all(self): + self.mock_model.simple_send_with_retries.return_value = "This is a summary" messages = [ {"role": "user", "content": "Hello world"}, {"role": "assistant", "content": "Hi there"}, @@ -69,18 +69,21 @@ class TestChatSummary(TestCase): self.assertGreater(len(result), 0) self.assertLessEqual(len(result), len(messages)) - @mock.patch("aider.history.simple_send_with_retries") - def test_fallback_to_second_model(self, mock_send): + def test_fallback_to_second_model(self): mock_model1 = mock.Mock(spec=Model) mock_model1.name = "gpt-4" + mock_model1.simple_send_with_retries = mock.Mock(side_effect=Exception("Model 1 failed")) + mock_model1.info = {"max_input_tokens": 4096} + mock_model1.token_count = lambda msg: len(msg["content"].split()) + mock_model2 = mock.Mock(spec=Model) mock_model2.name = "gpt-3.5-turbo" + mock_model2.simple_send_with_retries = mock.Mock(return_value="Summary from Model 2") + mock_model2.info = {"max_input_tokens": 4096} + mock_model2.token_count = lambda msg: len(msg["content"].split()) chat_summary = ChatSummary([mock_model1, mock_model2], max_tokens=100) - # Make the first model fail - mock_send.side_effect = [Exception("Model 1 failed"), "Summary from Model 2"] - messages = [ {"role": "user", "content": "Hello world"}, {"role": "assistant", "content": "Hi there"}, @@ -89,11 +92,8 @@ class TestChatSummary(TestCase): summary = chat_summary.summarize_all(messages) # Check that both models were tried - self.assertEqual(mock_send.call_count, 2) - - # Check that the calls were made with the correct model names - self.assertEqual(mock_send.call_args_list[0][0][0], "gpt-4") - self.assertEqual(mock_send.call_args_list[1][0][0], "gpt-3.5-turbo") + mock_model1.simple_send_with_retries.assert_called_once() + mock_model2.simple_send_with_retries.assert_called_once() # Check that we got a summary from the second model self.assertEqual( diff --git a/tests/basic/test_io.py b/tests/basic/test_io.py index 6e8f8291c..3f313219d 100644 --- a/tests/basic/test_io.py +++ b/tests/basic/test_io.py @@ -12,11 +12,35 @@ from aider.utils import ChdirTemporaryDirectory class TestInputOutput(unittest.TestCase): + def test_line_endings_validation(self): + # Test valid line endings + for ending in ["platform", "lf", "crlf"]: + io = InputOutput(line_endings=ending) + self.assertEqual( + io.newline, None if ending == "platform" else "\n" if ending == "lf" else "\r\n" + ) + + # Test invalid line endings + with self.assertRaises(ValueError) as cm: + io = InputOutput(line_endings="invalid") + self.assertIn("Invalid line_endings value: invalid", str(cm.exception)) + # Check each valid option is in the error message + self.assertIn("platform", str(cm.exception)) + self.assertIn("crlf", str(cm.exception)) + self.assertIn("lf", str(cm.exception)) + def test_no_color_environment_variable(self): with patch.dict(os.environ, {"NO_COLOR": "1"}): io = InputOutput(fancy_input=False) self.assertFalse(io.pretty) + def test_dumb_terminal(self): + with patch.dict(os.environ, {"TERM": "dumb"}): + io = InputOutput(fancy_input=True) + self.assertTrue(io.is_dumb_terminal) + self.assertFalse(io.pretty) + self.assertIsNone(io.prompt_session) + def test_autocompleter_get_command_completions(self): # Step 3: Mock the commands object commands = MagicMock() @@ -218,8 +242,37 @@ class TestInputOutput(unittest.TestCase): mock_input.assert_called_once() mock_input.reset_mock() + # Test case 4: 'skip' functions as 'no' without group + mock_input.return_value = "s" + result = io.confirm_ask("Are you sure?") + self.assertFalse(result) + mock_input.assert_called_once() + mock_input.reset_mock() + + # Test case 5: 'all' functions as 'yes' without group + mock_input.return_value = "a" + result = io.confirm_ask("Are you sure?") + self.assertTrue(result) + mock_input.assert_called_once() + mock_input.reset_mock() + + # Test case 6: Full word 'skip' functions as 'no' without group + mock_input.return_value = "skip" + result = io.confirm_ask("Are you sure?") + self.assertFalse(result) + mock_input.assert_called_once() + mock_input.reset_mock() + + # Test case 7: Full word 'all' functions as 'yes' without group + mock_input.return_value = "all" + result = io.confirm_ask("Are you sure?") + self.assertTrue(result) + mock_input.assert_called_once() + mock_input.reset_mock() + @patch("builtins.input", side_effect=["d"]) def test_confirm_ask_allow_never(self, mock_input): + """Test the 'don't ask again' functionality in confirm_ask""" io = InputOutput(pretty=False, fancy_input=False) # First call: user selects "Don't ask again" @@ -259,5 +312,87 @@ class TestInputOutput(unittest.TestCase): self.assertNotIn(("Do you want to proceed?", None), io.never_prompts) +class TestInputOutputMultilineMode(unittest.TestCase): + def setUp(self): + self.io = InputOutput(fancy_input=True) + self.io.prompt_session = MagicMock() + + def test_toggle_multiline_mode(self): + """Test that toggling multiline mode works correctly""" + # Start in single-line mode + self.io.multiline_mode = False + + # Toggle to multiline mode + self.io.toggle_multiline_mode() + self.assertTrue(self.io.multiline_mode) + + # Toggle back to single-line mode + self.io.toggle_multiline_mode() + self.assertFalse(self.io.multiline_mode) + + def test_tool_message_unicode_fallback(self): + """Test that Unicode messages are properly converted to ASCII with replacement""" + io = InputOutput(pretty=False, fancy_input=False) + + # Create a message with invalid Unicode that can't be encoded in UTF-8 + # Using a surrogate pair that's invalid in UTF-8 + invalid_unicode = "Hello \ud800World" + + # Mock console.print to capture the output + with patch.object(io.console, "print") as mock_print: + # First call will raise UnicodeEncodeError + mock_print.side_effect = [UnicodeEncodeError("utf-8", "", 0, 1, "invalid"), None] + + io._tool_message(invalid_unicode) + + # Verify that the message was converted to ASCII with replacement + self.assertEqual(mock_print.call_count, 2) + args, kwargs = mock_print.call_args + converted_message = args[0] + + # The invalid Unicode should be replaced with '?' + self.assertEqual(converted_message, "Hello ?World") + + def test_multiline_mode_restored_after_interrupt(self): + """Test that multiline mode is restored after KeyboardInterrupt""" + io = InputOutput(fancy_input=True) + io.prompt_session = MagicMock() + + # Start in multiline mode + io.multiline_mode = True + + # Mock prompt() to raise KeyboardInterrupt + io.prompt_session.prompt.side_effect = KeyboardInterrupt + + # Test confirm_ask() + with self.assertRaises(KeyboardInterrupt): + io.confirm_ask("Test question?") + self.assertTrue(io.multiline_mode) # Should be restored + + # Test prompt_ask() + with self.assertRaises(KeyboardInterrupt): + io.prompt_ask("Test prompt?") + self.assertTrue(io.multiline_mode) # Should be restored + + def test_multiline_mode_restored_after_normal_exit(self): + """Test that multiline mode is restored after normal exit""" + io = InputOutput(fancy_input=True) + io.prompt_session = MagicMock() + + # Start in multiline mode + io.multiline_mode = True + + # Mock prompt() to return normally + io.prompt_session.prompt.return_value = "y" + + # Test confirm_ask() + io.confirm_ask("Test question?") + self.assertTrue(io.multiline_mode) # Should be restored + + # Test prompt_ask() + io.prompt_ask("Test prompt?") + self.assertTrue(io.multiline_mode) # Should be restored + + if __name__ == "__main__": unittest.main() diff --git a/tests/basic/test_linter.py b/tests/basic/test_linter.py index 9310557c5..9dce56355 100644 --- a/tests/basic/test_linter.py +++ b/tests/basic/test_linter.py @@ -30,7 +30,7 @@ class TestLinter(unittest.TestCase): def test_run_cmd(self, mock_popen): mock_process = MagicMock() mock_process.returncode = 0 - mock_process.communicate.return_value = ("", None) + mock_process.stdout.read.side_effect = ("", None) mock_popen.return_value = mock_process result = self.linter.run_cmd("test_cmd", "test_file.py", "code") @@ -40,7 +40,7 @@ class TestLinter(unittest.TestCase): def test_run_cmd_with_errors(self, mock_popen): mock_process = MagicMock() mock_process.returncode = 1 - mock_process.communicate.return_value = ("Error message", None) + mock_process.stdout.read.side_effect = ("Error message", None) mock_popen.return_value = mock_process result = self.linter.run_cmd("test_cmd", "test_file.py", "code") diff --git a/tests/basic/test_main.py b/tests/basic/test_main.py index bcadd84dd..3374b1323 100644 --- a/tests/basic/test_main.py +++ b/tests/basic/test_main.py @@ -23,6 +23,7 @@ class TestMain(TestCase): self.original_env = os.environ.copy() os.environ["OPENAI_API_KEY"] = "deadbeef" os.environ["AIDER_CHECK_UPDATE"] = "false" + os.environ["AIDER_ANALYTICS"] = "false" self.original_cwd = os.getcwd() self.tempdir_obj = IgnorantTemporaryDirectory() self.tempdir = self.tempdir_obj.name @@ -139,8 +140,15 @@ class TestMain(TestCase): self.assertEqual(".aider*", gitignore.read_text().splitlines()[0]) + # Test without .env file present gitignore.write_text("one\ntwo\n") check_gitignore(cwd, io) + self.assertEqual("one\ntwo\n.aider*\n", gitignore.read_text()) + + # Test with .env file present + env_file = cwd / ".env" + env_file.touch() + check_gitignore(cwd, io) self.assertEqual("one\ntwo\n.aider*\n.env\n", gitignore.read_text()) del os.environ["GIT_CONFIG_GLOBAL"] @@ -514,6 +522,15 @@ class TestMain(TestCase): os.unlink(external_file_path) def test_model_metadata_file(self): + # Re-init so we don't have old data lying around from earlier test cases + from aider import models + + models.model_info_manager = models.ModelInfoManager() + + from aider.llm import litellm + + litellm._lazy_module = None + with GitTemporaryDirectory(): metadata_file = Path(".aider.model.metadata.json") @@ -667,6 +684,63 @@ class TestMain(TestCase): ) self.assertTrue(coder.detect_urls) + def test_pytest_env_vars(self): + # Verify that environment variables from pytest.ini are properly set + self.assertEqual(os.environ.get("AIDER_ANALYTICS"), "false") + + def test_set_env_single(self): + # Test setting a single environment variable + with GitTemporaryDirectory(): + main(["--set-env", "TEST_VAR=test_value", "--exit", "--yes"]) + self.assertEqual(os.environ.get("TEST_VAR"), "test_value") + + def test_set_env_multiple(self): + # Test setting multiple environment variables + with GitTemporaryDirectory(): + main( + [ + "--set-env", + "TEST_VAR1=value1", + "--set-env", + "TEST_VAR2=value2", + "--exit", + "--yes", + ] + ) + self.assertEqual(os.environ.get("TEST_VAR1"), "value1") + self.assertEqual(os.environ.get("TEST_VAR2"), "value2") + + def test_set_env_with_spaces(self): + # Test setting env var with spaces in value + with GitTemporaryDirectory(): + main(["--set-env", "TEST_VAR=test value with spaces", "--exit", "--yes"]) + self.assertEqual(os.environ.get("TEST_VAR"), "test value with spaces") + + def test_set_env_invalid_format(self): + # Test invalid format handling + with GitTemporaryDirectory(): + result = main(["--set-env", "INVALID_FORMAT", "--exit", "--yes"]) + self.assertEqual(result, 1) + + def test_api_key_single(self): + # Test setting a single API key + with GitTemporaryDirectory(): + main(["--api-key", "anthropic=test-key", "--exit", "--yes"]) + self.assertEqual(os.environ.get("ANTHROPIC_API_KEY"), "test-key") + + def test_api_key_multiple(self): + # Test setting multiple API keys + with GitTemporaryDirectory(): + main(["--api-key", "anthropic=key1", "--api-key", "openai=key2", "--exit", "--yes"]) + self.assertEqual(os.environ.get("ANTHROPIC_API_KEY"), "key1") + self.assertEqual(os.environ.get("OPENAI_API_KEY"), "key2") + + def test_api_key_invalid_format(self): + # Test invalid format handling + with GitTemporaryDirectory(): + result = main(["--api-key", "INVALID_FORMAT", "--exit", "--yes"]) + self.assertEqual(result, 1) + def test_invalid_edit_format(self): with GitTemporaryDirectory(): with patch("aider.io.InputOutput.offer_url") as mock_offer_url: @@ -680,6 +754,64 @@ class TestMain(TestCase): args, _ = mock_offer_url.call_args self.assertEqual(args[0], "https://aider.chat/docs/more/edit-formats.html") + def test_default_model_selection(self): + with GitTemporaryDirectory(): + # Test Anthropic API key + os.environ["ANTHROPIC_API_KEY"] = "test-key" + coder = main( + ["--exit", "--yes"], input=DummyInput(), output=DummyOutput(), return_coder=True + ) + self.assertIn("sonnet", coder.main_model.name.lower()) + del os.environ["ANTHROPIC_API_KEY"] + + # Test DeepSeek API key + os.environ["DEEPSEEK_API_KEY"] = "test-key" + coder = main( + ["--exit", "--yes"], input=DummyInput(), output=DummyOutput(), return_coder=True + ) + self.assertIn("deepseek", coder.main_model.name.lower()) + del os.environ["DEEPSEEK_API_KEY"] + + # Test OpenRouter API key + os.environ["OPENROUTER_API_KEY"] = "test-key" + coder = main( + ["--exit", "--yes"], input=DummyInput(), output=DummyOutput(), return_coder=True + ) + self.assertIn("openrouter/anthropic/claude", coder.main_model.name.lower()) + del os.environ["OPENROUTER_API_KEY"] + + # Test OpenAI API key + os.environ["OPENAI_API_KEY"] = "test-key" + coder = main( + ["--exit", "--yes"], input=DummyInput(), output=DummyOutput(), return_coder=True + ) + self.assertIn("gpt-4", coder.main_model.name.lower()) + del os.environ["OPENAI_API_KEY"] + + # Test Gemini API key + os.environ["GEMINI_API_KEY"] = "test-key" + coder = main( + ["--exit", "--yes"], input=DummyInput(), output=DummyOutput(), return_coder=True + ) + self.assertIn("flash", coder.main_model.name.lower()) + del os.environ["GEMINI_API_KEY"] + + # Test no API keys + result = main(["--exit", "--yes"], input=DummyInput(), output=DummyOutput()) + self.assertEqual(result, 1) + + def test_model_precedence(self): + with GitTemporaryDirectory(): + # Test that earlier API keys take precedence + os.environ["ANTHROPIC_API_KEY"] = "test-key" + os.environ["OPENAI_API_KEY"] = "test-key" + coder = main( + ["--exit", "--yes"], input=DummyInput(), output=DummyOutput(), return_coder=True + ) + self.assertIn("sonnet", coder.main_model.name.lower()) + del os.environ["ANTHROPIC_API_KEY"] + del os.environ["OPENAI_API_KEY"] + def test_chat_language_spanish(self): with GitTemporaryDirectory(): coder = main( @@ -701,3 +833,14 @@ class TestMain(TestCase): self.fail(f"main() raised an unexpected exception: {e}") self.assertIsNone(result, "main() should return None when called with --exit") + + def test_reasoning_effort_option(self): + coder = main( + ["--reasoning-effort", "3", "--yes", "--exit"], + input=DummyInput(), + output=DummyOutput(), + return_coder=True, + ) + self.assertEqual( + coder.main_model.extra_params.get("extra_body", {}).get("reasoning_effort"), "3" + ) diff --git a/tests/basic/test_models.py b/tests/basic/test_models.py index 6aff2be7f..aa99040a1 100644 --- a/tests/basic/test_models.py +++ b/tests/basic/test_models.py @@ -12,6 +12,19 @@ from aider.models import ( class TestModels(unittest.TestCase): + def setUp(self): + """Reset MODEL_SETTINGS before each test""" + from aider.models import MODEL_SETTINGS + + self._original_settings = MODEL_SETTINGS.copy() + + def tearDown(self): + """Restore original MODEL_SETTINGS after each test""" + from aider.models import MODEL_SETTINGS + + MODEL_SETTINGS.clear() + MODEL_SETTINGS.extend(self._original_settings) + def test_get_model_info_nonexistent(self): manager = ModelInfoManager() info = manager.get_model_info("non-existent-model") @@ -98,7 +111,7 @@ class TestModels(unittest.TestCase): self.assertEqual(model.name, "gpt-4-0613") model = Model("4o") - self.assertEqual(model.name, "gpt-4o-2024-08-06") + self.assertEqual(model.name, "gpt-4o") model = Model("35turbo") self.assertEqual(model.name, "gpt-3.5-turbo") @@ -122,6 +135,193 @@ class TestModels(unittest.TestCase): model = Model("gpt-4") self.assertEqual(model.name, "gpt-4") + def test_o1_use_temp_false(self): + # Test GitHub Copilot models + model = Model("github/o1-mini") + self.assertEqual(model.name, "github/o1-mini") + self.assertEqual(model.use_temperature, False) + + model = Model("github/o1-preview") + self.assertEqual(model.name, "github/o1-preview") + self.assertEqual(model.use_temperature, False) + + def test_get_repo_map_tokens(self): + # Test default case (no max_input_tokens in info) + model = Model("gpt-4") + model.info = {} + self.assertEqual(model.get_repo_map_tokens(), 1024) + + # Test minimum boundary (max_input_tokens < 8192) + model.info = {"max_input_tokens": 4096} + self.assertEqual(model.get_repo_map_tokens(), 1024) + + # Test middle range (max_input_tokens = 16384) + model.info = {"max_input_tokens": 16384} + self.assertEqual(model.get_repo_map_tokens(), 2048) + + # Test maximum boundary (max_input_tokens > 32768) + model.info = {"max_input_tokens": 65536} + self.assertEqual(model.get_repo_map_tokens(), 4096) + + # Test exact boundary values + model.info = {"max_input_tokens": 8192} + self.assertEqual(model.get_repo_map_tokens(), 1024) + + model.info = {"max_input_tokens": 32768} + self.assertEqual(model.get_repo_map_tokens(), 4096) + + def test_configure_model_settings(self): + # Test o3-mini case + model = Model("something/o3-mini") + self.assertEqual(model.edit_format, "diff") + self.assertTrue(model.use_repo_map) + self.assertFalse(model.use_temperature) + + # Test o1-mini case + model = Model("something/o1-mini") + self.assertTrue(model.use_repo_map) + self.assertFalse(model.use_temperature) + self.assertFalse(model.use_system_prompt) + + # Test o1-preview case + model = Model("something/o1-preview") + self.assertEqual(model.edit_format, "diff") + self.assertTrue(model.use_repo_map) + self.assertFalse(model.use_temperature) + self.assertFalse(model.use_system_prompt) + + # Test o1 case + model = Model("something/o1") + self.assertEqual(model.edit_format, "diff") + self.assertTrue(model.use_repo_map) + self.assertFalse(model.use_temperature) + self.assertFalse(model.streaming) + + # Test deepseek v3 case + model = Model("deepseek-v3") + self.assertEqual(model.edit_format, "diff") + self.assertTrue(model.use_repo_map) + self.assertEqual(model.reminder, "sys") + self.assertTrue(model.examples_as_sys_msg) + + # Test deepseek reasoner case + model = Model("deepseek-r1") + self.assertEqual(model.edit_format, "diff") + self.assertTrue(model.use_repo_map) + self.assertTrue(model.examples_as_sys_msg) + self.assertFalse(model.use_temperature) + self.assertEqual(model.remove_reasoning, "think") + + # Test provider/deepseek-r1 case + model = Model("someprovider/deepseek-r1") + self.assertEqual(model.edit_format, "diff") + self.assertTrue(model.use_repo_map) + self.assertTrue(model.examples_as_sys_msg) + self.assertFalse(model.use_temperature) + self.assertEqual(model.remove_reasoning, "think") + + # Test provider/deepseek-v3 case + model = Model("anotherprovider/deepseek-v3") + self.assertEqual(model.edit_format, "diff") + self.assertTrue(model.use_repo_map) + self.assertEqual(model.reminder, "sys") + self.assertTrue(model.examples_as_sys_msg) + + # Test llama3 70b case + model = Model("llama3-70b") + self.assertEqual(model.edit_format, "diff") + self.assertTrue(model.use_repo_map) + self.assertTrue(model.send_undo_reply) + self.assertTrue(model.examples_as_sys_msg) + + # Test gpt-4 case + model = Model("gpt-4") + self.assertEqual(model.edit_format, "diff") + self.assertTrue(model.use_repo_map) + self.assertTrue(model.send_undo_reply) + + # Test gpt-3.5 case + model = Model("gpt-3.5") + self.assertEqual(model.reminder, "sys") + + # Test 3.5-sonnet case + model = Model("claude-3.5-sonnet") + self.assertEqual(model.edit_format, "diff") + self.assertTrue(model.use_repo_map) + self.assertTrue(model.examples_as_sys_msg) + self.assertEqual(model.reminder, "user") + + # Test o1- prefix case + model = Model("o1-something") + self.assertFalse(model.use_system_prompt) + self.assertFalse(model.use_temperature) + + # Test qwen case + model = Model("qwen-coder-2.5-32b") + self.assertEqual(model.edit_format, "diff") + self.assertEqual(model.editor_edit_format, "editor-diff") + self.assertTrue(model.use_repo_map) + + def test_remove_reasoning_content(self): + # Test with no removal configured + model = Model("gpt-4") + text = "Here is some reasoning and regular text" + self.assertEqual(model.remove_reasoning_content(text), text) + + # Test with removal configured + model = Model("deepseek-r1") # This model has remove_reasoning="think" + text = """Here is some text + +This is reasoning that should be removed +Over multiple lines + +And more text here""" + expected = """Here is some text + +And more text here""" + self.assertEqual(model.remove_reasoning_content(text), expected) + + # Test with multiple reasoning blocks + text = """Start +Block 1 +Middle +Block 2 +End""" + expected = """Start + +Middle + +End""" + self.assertEqual(model.remove_reasoning_content(text), expected) + + # Test with no reasoning blocks + text = "Just regular text" + self.assertEqual(model.remove_reasoning_content(text), text) + + @patch("aider.models.litellm.completion") + def test_simple_send_with_retries_removes_reasoning(self, mock_completion): + model = Model("deepseek-r1") # This model has remove_reasoning="think" + + # Mock the completion response + mock_response = MagicMock() + mock_response.choices = [MagicMock(message=MagicMock(content="""Here is some text + +This reasoning should be removed + +And this text should remain"""))] + mock_completion.return_value = mock_response + + messages = [{"role": "user", "content": "test"}] + result = model.simple_send_with_retries(messages) + + expected = """Here is some text + +And this text should remain""" + self.assertEqual(result, expected) + + # Verify the completion was called + mock_completion.assert_called_once() + def test_aider_extra_model_settings(self): import tempfile @@ -173,6 +373,139 @@ class TestModels(unittest.TestCase): except OSError: pass + @patch("aider.models.litellm.completion") + @patch.object(Model, "token_count") + def test_ollama_num_ctx_set_when_missing(self, mock_token_count, mock_completion): + mock_token_count.return_value = 1000 + + model = Model("ollama/llama3") + messages = [{"role": "user", "content": "Hello"}] + + model.send_completion(messages, functions=None, stream=False) + + # Verify num_ctx was calculated and added to call + expected_ctx = int(1000 * 1.25) + 8192 # 9442 + mock_completion.assert_called_once_with( + model=model.name, + messages=messages, + stream=False, + temperature=0, + num_ctx=expected_ctx, + timeout=600, + ) + + @patch("aider.models.litellm.completion") + def test_ollama_uses_existing_num_ctx(self, mock_completion): + model = Model("ollama/llama3") + model.extra_params = {"num_ctx": 4096} + + messages = [{"role": "user", "content": "Hello"}] + model.send_completion(messages, functions=None, stream=False) + + # Should use provided num_ctx from extra_params + mock_completion.assert_called_once_with( + model=model.name, + messages=messages, + stream=False, + temperature=0, + num_ctx=4096, + timeout=600, + ) + + @patch("aider.models.litellm.completion") + def test_non_ollama_no_num_ctx(self, mock_completion): + model = Model("gpt-4") + messages = [{"role": "user", "content": "Hello"}] + + model.send_completion(messages, functions=None, stream=False) + + # Regular models shouldn't get num_ctx + mock_completion.assert_called_once_with( + model=model.name, + messages=messages, + stream=False, + temperature=0, + timeout=600, + ) + self.assertNotIn("num_ctx", mock_completion.call_args.kwargs) + + def test_use_temperature_settings(self): + # Test use_temperature=True (default) uses temperature=0 + model = Model("gpt-4") + self.assertTrue(model.use_temperature) + self.assertEqual(model.use_temperature, True) + + # Test use_temperature=False doesn't pass temperature + model = Model("github/o1-mini") + self.assertFalse(model.use_temperature) + + # Test use_temperature as float value + model = Model("gpt-4") + model.use_temperature = 0.7 + self.assertEqual(model.use_temperature, 0.7) + + @patch("aider.models.litellm.completion") + def test_request_timeout_default(self, mock_completion): + # Test default timeout is used when not specified in extra_params + model = Model("gpt-4") + messages = [{"role": "user", "content": "Hello"}] + model.send_completion(messages, functions=None, stream=False) + mock_completion.assert_called_with( + model=model.name, + messages=messages, + stream=False, + temperature=0, + timeout=600, # Default timeout + ) + + @patch("aider.models.litellm.completion") + def test_request_timeout_from_extra_params(self, mock_completion): + # Test timeout from extra_params overrides default + model = Model("gpt-4") + model.extra_params = {"timeout": 300} # 5 minutes + messages = [{"role": "user", "content": "Hello"}] + model.send_completion(messages, functions=None, stream=False) + mock_completion.assert_called_with( + model=model.name, + messages=messages, + stream=False, + temperature=0, + timeout=300, # From extra_params + ) + + @patch("aider.models.litellm.completion") + def test_use_temperature_in_send_completion(self, mock_completion): + # Test use_temperature=True sends temperature=0 + model = Model("gpt-4") + messages = [{"role": "user", "content": "Hello"}] + model.send_completion(messages, functions=None, stream=False) + mock_completion.assert_called_with( + model=model.name, + messages=messages, + stream=False, + temperature=0, + timeout=600, + ) + + # Test use_temperature=False doesn't send temperature + model = Model("github/o1-mini") + messages = [{"role": "user", "content": "Hello"}] + model.send_completion(messages, functions=None, stream=False) + self.assertNotIn("temperature", mock_completion.call_args.kwargs) + + # Test use_temperature as float sends that value + model = Model("gpt-4") + model.use_temperature = 0.7 + messages = [{"role": "user", "content": "Hello"}] + model.send_completion(messages, functions=None, stream=False) + mock_completion.assert_called_with( + model=model.name, + messages=messages, + stream=False, + temperature=0.7, + timeout=600, + ) + if __name__ == "__main__": unittest.main() diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py index 50cf27951..d16bee2fd 100644 --- a/tests/basic/test_repo.py +++ b/tests/basic/test_repo.py @@ -106,7 +106,7 @@ class TestRepo(unittest.TestCase): diffs = git_repo.diff_commits(False, "HEAD~1", "HEAD") self.assertIn("two", diffs) - @patch("aider.repo.simple_send_with_retries") + @patch("aider.models.Model.simple_send_with_retries") def test_get_commit_message(self, mock_send): mock_send.side_effect = ["", "a good commit message"] @@ -125,17 +125,12 @@ class TestRepo(unittest.TestCase): # Check that simple_send_with_retries was called twice self.assertEqual(mock_send.call_count, 2) - # Check that it was called with the correct model names - self.assertEqual(mock_send.call_args_list[0][0][0], model1.name) - self.assertEqual(mock_send.call_args_list[1][0][0], model2.name) + # Check that both calls were made with the same messages + first_call_messages = mock_send.call_args_list[0][0][0] # Get messages from first call + second_call_messages = mock_send.call_args_list[1][0][0] # Get messages from second call + self.assertEqual(first_call_messages, second_call_messages) - # Check that the content of the messages is the same for both calls - self.assertEqual(mock_send.call_args_list[0][0][1], mock_send.call_args_list[1][0][1]) - - # Optionally, you can still dump the call args if needed for debugging - dump(mock_send.call_args_list) - - @patch("aider.repo.simple_send_with_retries") + @patch("aider.models.Model.simple_send_with_retries") def test_get_commit_message_strip_quotes(self, mock_send): mock_send.return_value = '"a good commit message"' @@ -146,7 +141,7 @@ class TestRepo(unittest.TestCase): # Assert that the returned message is the expected one self.assertEqual(result, "a good commit message") - @patch("aider.repo.simple_send_with_retries") + @patch("aider.models.Model.simple_send_with_retries") def test_get_commit_message_no_strip_unmatched_quotes(self, mock_send): mock_send.return_value = 'a good "commit message"' @@ -157,7 +152,7 @@ class TestRepo(unittest.TestCase): # Assert that the returned message is the expected one self.assertEqual(result, 'a good "commit message"') - @patch("aider.repo.simple_send_with_retries") + @patch("aider.models.Model.simple_send_with_retries") def test_get_commit_message_with_custom_prompt(self, mock_send): mock_send.return_value = "Custom commit message" custom_prompt = "Generate a commit message in the style of Shakespeare" @@ -167,8 +162,8 @@ class TestRepo(unittest.TestCase): self.assertEqual(result, "Custom commit message") mock_send.assert_called_once() - args, _ = mock_send.call_args - self.assertEqual(args[1][0]["content"], custom_prompt) + args = mock_send.call_args[0] # Get positional args + self.assertEqual(args[0][0]["content"], custom_prompt) # Check first message content @patch("aider.repo.GitRepo.get_commit_message") def test_commit_with_custom_committer_name(self, mock_send): @@ -393,7 +388,7 @@ class TestRepo(unittest.TestCase): self.assertNotIn(str(root_file), tracked_files) self.assertNotIn(str(another_subdir_file), tracked_files) - @patch("aider.repo.simple_send_with_retries") + @patch("aider.models.Model.simple_send_with_retries") def test_noop_commit(self, mock_send): mock_send.return_value = '"a good commit message"' diff --git a/tests/basic/test_repomap.py b/tests/basic/test_repomap.py index 6f47cee09..d5770b2c1 100644 --- a/tests/basic/test_repomap.py +++ b/tests/basic/test_repomap.py @@ -290,6 +290,7 @@ class TestRepoMapAllLanguages(unittest.TestCase): "elixir": ("ex", "Greeter"), "java": ("java", "Greeting"), "javascript": ("js", "Person"), + "kotlin": ("kt", "Greeting"), "ocaml": ("ml", "Greeter"), "php": ("php", "greet"), "python": ("py", "Person"), @@ -302,6 +303,7 @@ class TestRepoMapAllLanguages(unittest.TestCase): "elisp": ("el", "greeter"), "elm": ("elm", "Person"), "go": ("go", "Greeter"), + "hcl": ("tf", "aws_vpc"), } fixtures_dir = Path(__file__).parent.parent / "fixtures" / "languages" diff --git a/tests/basic/test_sanity_check_repo.py b/tests/basic/test_sanity_check_repo.py index 860572ec5..fd17fb3b4 100644 --- a/tests/basic/test_sanity_check_repo.py +++ b/tests/basic/test_sanity_check_repo.py @@ -8,6 +8,8 @@ from git import GitError, Repo from aider import urls from aider.main import sanity_check_repo +from aider.repo import GitRepo +from aider.io import InputOutput @pytest.fixture @@ -182,3 +184,41 @@ def test_sanity_check_repo_with_no_repo(mock_io): # Assert that no errors or outputs were logged mock_io.tool_error.assert_not_called() mock_io.tool_output.assert_not_called() + + +def corrupt_git_index(repo_path): + index_path = os.path.join(repo_path, ".git", "index") + with open(index_path, "r+b") as f: + # Verify the file has the correct signature + signature = f.read(4) + if signature != b"DIRC": + raise ValueError("Invalid git index file signature.") + + # Seek to the data section and inject invalid bytes to simulate encoding error + f.seek(77) + f.write(b"\xF5" * 5) + + +def test_sanity_check_repo_with_corrupt_index(create_repo, mock_io): + repo_path, repo = create_repo + # Corrupt the Git index file + corrupt_git_index(repo_path) + + # Create GitRepo instance + git_repo = GitRepo(InputOutput(), None, repo_path) + + # Call the function + result = sanity_check_repo(git_repo, mock_io) + + # Assert that the function returns False + assert result is False + + # Assert that the appropriate error messages were logged + mock_io.tool_error.assert_called_with("Unable to read git repository, it may be corrupt?") + mock_io.tool_output.assert_called_with( + ( + "Failed to read the Git repository. This issue is likely caused by a path encoded " + "in a format different from the expected encoding \"utf-8\".\n" + "Internal error: 'utf-8' codec can't decode byte 0xf5 in position 3: invalid start byte" + ) + ) diff --git a/tests/basic/test_sendchat.py b/tests/basic/test_sendchat.py index 6b2684a40..d2fdaf88e 100644 --- a/tests/basic/test_sendchat.py +++ b/tests/basic/test_sendchat.py @@ -3,7 +3,7 @@ from unittest.mock import MagicMock, patch from aider.exceptions import LiteLLMExceptions from aider.llm import litellm -from aider.sendchat import send_completion, simple_send_with_retries +from aider.models import Model class PrintCalled(Exception): @@ -37,7 +37,7 @@ class TestSendChat(unittest.TestCase): ] # Call the simple_send_with_retries method - simple_send_with_retries("model", ["message"]) + Model(self.mock_model).simple_send_with_retries(self.mock_messages) assert mock_print.call_count == 3 @patch("litellm.completion") @@ -47,8 +47,8 @@ class TestSendChat(unittest.TestCase): mock_completion.return_value = mock_response # Test basic send_completion - hash_obj, response = send_completion( - self.mock_model, self.mock_messages, functions=None, stream=False + hash_obj, response = Model(self.mock_model).send_completion( + self.mock_messages, functions=None, stream=False ) assert response == mock_response @@ -58,8 +58,8 @@ class TestSendChat(unittest.TestCase): def test_send_completion_with_functions(self, mock_completion): mock_function = {"name": "test_function", "parameters": {"type": "object"}} - hash_obj, response = send_completion( - self.mock_model, self.mock_messages, functions=[mock_function], stream=False + hash_obj, response = Model(self.mock_model).send_completion( + self.mock_messages, functions=[mock_function], stream=False ) # Verify function was properly included in tools @@ -74,7 +74,7 @@ class TestSendChat(unittest.TestCase): mock_completion.return_value.choices = None # Should return None on AttributeError - result = simple_send_with_retries(self.mock_model, self.mock_messages) + result = Model(self.mock_model).simple_send_with_retries(self.mock_messages) assert result is None @patch("litellm.completion") @@ -88,6 +88,84 @@ class TestSendChat(unittest.TestCase): message="Invalid request", llm_provider="test_provider", model="test_model" ) - result = simple_send_with_retries(self.mock_model, self.mock_messages) + result = Model(self.mock_model).simple_send_with_retries(self.mock_messages) assert result is None + # Should only print the error message assert mock_print.call_count == 1 + + def test_ensure_alternating_roles_empty(self): + from aider.sendchat import ensure_alternating_roles + + messages = [] + result = ensure_alternating_roles(messages) + assert result == [] + + def test_ensure_alternating_roles_single_message(self): + from aider.sendchat import ensure_alternating_roles + + messages = [{"role": "user", "content": "Hello"}] + result = ensure_alternating_roles(messages) + assert result == messages + + def test_ensure_alternating_roles_already_alternating(self): + from aider.sendchat import ensure_alternating_roles + + messages = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": "Hi there"}, + {"role": "user", "content": "How are you?"}, + ] + result = ensure_alternating_roles(messages) + assert result == messages + + def test_ensure_alternating_roles_consecutive_user(self): + from aider.sendchat import ensure_alternating_roles + + messages = [ + {"role": "user", "content": "Hello"}, + {"role": "user", "content": "Are you there?"}, + ] + expected = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": ""}, + {"role": "user", "content": "Are you there?"}, + ] + result = ensure_alternating_roles(messages) + assert result == expected + + def test_ensure_alternating_roles_consecutive_assistant(self): + from aider.sendchat import ensure_alternating_roles + + messages = [ + {"role": "assistant", "content": "Hi there"}, + {"role": "assistant", "content": "How can I help?"}, + ] + expected = [ + {"role": "assistant", "content": "Hi there"}, + {"role": "user", "content": ""}, + {"role": "assistant", "content": "How can I help?"}, + ] + result = ensure_alternating_roles(messages) + assert result == expected + + def test_ensure_alternating_roles_mixed_sequence(self): + from aider.sendchat import ensure_alternating_roles + + messages = [ + {"role": "user", "content": "Hello"}, + {"role": "user", "content": "Are you there?"}, + {"role": "assistant", "content": "Yes"}, + {"role": "assistant", "content": "How can I help?"}, + {"role": "user", "content": "Write code"}, + ] + expected = [ + {"role": "user", "content": "Hello"}, + {"role": "assistant", "content": ""}, + {"role": "user", "content": "Are you there?"}, + {"role": "assistant", "content": "Yes"}, + {"role": "user", "content": ""}, + {"role": "assistant", "content": "How can I help?"}, + {"role": "user", "content": "Write code"}, + ] + result = ensure_alternating_roles(messages) + assert result == expected diff --git a/tests/basic/test_voice.py b/tests/basic/test_voice.py new file mode 100644 index 000000000..00ec1d79d --- /dev/null +++ b/tests/basic/test_voice.py @@ -0,0 +1,103 @@ +import os +import queue +from unittest.mock import MagicMock, patch + +import numpy as np +import pytest + +from aider.voice import SoundDeviceError, Voice + + +# Mock the entire sounddevice module +@pytest.fixture +def mock_sounddevice(): + mock_sd = MagicMock() + mock_sd.query_devices.return_value = [ + {"name": "test_device", "max_input_channels": 2}, + {"name": "another_device", "max_input_channels": 1}, + ] + with patch.dict("sys.modules", {"sounddevice": mock_sd}): + yield mock_sd + + +@pytest.fixture +def mock_soundfile(): + with patch("aider.voice.sf") as mock_sf: + yield mock_sf + + +def test_voice_init_default_device(mock_sounddevice): + voice = Voice() + assert voice.device_id is None + assert voice.audio_format == "wav" + assert voice.sd == mock_sounddevice + + +def test_voice_init_specific_device(mock_sounddevice): + voice = Voice(device_name="test_device") + assert voice.device_id == 0 + assert voice.sd == mock_sounddevice + + +def test_voice_init_invalid_device(mock_sounddevice): + with pytest.raises(ValueError) as exc: + Voice(device_name="nonexistent_device") + assert "Device" in str(exc.value) + assert "not found" in str(exc.value) + + +def test_voice_init_invalid_format(): + with patch("aider.voice.sf", MagicMock()): # Need to mock sf to avoid SoundDeviceError + with pytest.raises(ValueError) as exc: + Voice(audio_format="invalid") + assert "Unsupported audio format" in str(exc.value) + + +def test_callback_processing(): + with patch("aider.voice.sf", MagicMock()): # Need to mock sf to avoid SoundDeviceError + voice = Voice() + voice.q = queue.Queue() + + # Test with silence (low amplitude) + test_data = np.zeros((1000, 1)) + voice.callback(test_data, None, None, None) + assert voice.pct == 0.5 # When range is too small (<=0.001), pct is set to 0.5 + + # Test with loud signal (high amplitude) + test_data = np.ones((1000, 1)) + voice.callback(test_data, None, None, None) + assert voice.pct > 0.9 + + # Verify data is queued + assert not voice.q.empty() + + +def test_get_prompt(): + with patch("aider.voice.sf", MagicMock()): # Need to mock sf to avoid SoundDeviceError + voice = Voice() + voice.start_time = os.times().elapsed + voice.pct = 0.5 # 50% volume level + + prompt = voice.get_prompt() + assert "Recording" in prompt + assert "sec" in prompt + assert "█" in prompt # Should contain some filled blocks + assert "░" in prompt # Should contain some empty blocks + + +def test_record_and_transcribe_keyboard_interrupt(): + with patch("aider.voice.sf", MagicMock()): + voice = Voice() + with patch.object(voice, "raw_record_and_transcribe", side_effect=KeyboardInterrupt()): + result = voice.record_and_transcribe() + assert result is None + + +def test_record_and_transcribe_device_error(): + with patch("aider.voice.sf", MagicMock()): + voice = Voice() + with patch.object( + voice, "raw_record_and_transcribe", side_effect=SoundDeviceError("Test error") + ): + result = voice.record_and_transcribe() + assert result is None diff --git a/tests/basic/test_watch.py b/tests/basic/test_watch.py new file mode 100644 index 000000000..706fd1ade --- /dev/null +++ b/tests/basic/test_watch.py @@ -0,0 +1,157 @@ +from pathlib import Path + +from aider.dump import dump # noqa +from aider.io import InputOutput +from aider.watch import FileWatcher + + +class MinimalCoder: + def __init__(self, io): + self.io = io + self.root = "." + self.abs_fnames = set() + + def get_rel_fname(self, fname): + return fname + + +def test_gitignore_patterns(): + """Test that gitignore patterns are properly loaded and matched""" + from pathlib import Path + + from aider.watch import load_gitignores + + # Create a temporary gitignore file with test patterns + tmp_gitignore = Path("test.gitignore") + tmp_gitignore.write_text("custom_pattern\n*.custom") + + gitignores = [tmp_gitignore] + spec = load_gitignores(gitignores) + + # Test built-in patterns + assert spec.match_file(".aider.conf") + assert spec.match_file(".git/config") + assert spec.match_file("file~") # Emacs/vim backup + assert spec.match_file("file.bak") + assert spec.match_file("file.swp") + assert spec.match_file("file.swo") + assert spec.match_file("#temp#") # Emacs auto-save + assert spec.match_file(".#lock") # Emacs lock + assert spec.match_file("temp.tmp") + assert spec.match_file("temp.temp") + assert spec.match_file("conflict.orig") + assert spec.match_file("script.pyc") + assert spec.match_file("__pycache__/module.pyc") + assert spec.match_file(".DS_Store") + assert spec.match_file("Thumbs.db") + assert spec.match_file(".idea/workspace.xml") + assert spec.match_file(".vscode/settings.json") + assert spec.match_file("project.sublime-workspace") + assert spec.match_file(".project") + assert spec.match_file(".settings/config.json") + assert spec.match_file("workspace.code-workspace") + assert spec.match_file(".env") + assert spec.match_file(".venv/bin/python") + assert spec.match_file("node_modules/package/index.js") + assert spec.match_file("vendor/lib/module.py") + assert spec.match_file("debug.log") + assert spec.match_file(".cache/files") + assert spec.match_file(".pytest_cache/v/cache") + assert spec.match_file("coverage/lcov.info") + + # Test custom patterns from gitignore file + assert spec.match_file("custom_pattern") + assert spec.match_file("file.custom") + + # Test non-matching patterns + assert not spec.match_file("regular_file.txt") + assert not spec.match_file("src/main.py") + assert not spec.match_file("docs/index.html") + + # Cleanup + tmp_gitignore.unlink() + + +def test_get_roots_to_watch(tmp_path): + # Create a test directory structure + (tmp_path / "included").mkdir() + (tmp_path / "excluded").mkdir() + + io = InputOutput(pretty=False, fancy_input=False, yes=False) + coder = MinimalCoder(io) + + # Test with no gitignore + watcher = FileWatcher(coder, root=tmp_path) + roots = watcher.get_roots_to_watch() + assert len(roots) == 1 + assert roots[0] == str(tmp_path) + + # Test with gitignore + gitignore = tmp_path / ".gitignore" + gitignore.write_text("excluded/") + watcher = FileWatcher(coder, root=tmp_path, gitignores=[gitignore]) + roots = watcher.get_roots_to_watch() + assert len(roots) == 2 + assert Path(sorted(roots)[0]).name == ".gitignore" + assert Path(sorted(roots)[1]).name == "included" + + +def test_handle_changes(): + io = InputOutput(pretty=False, fancy_input=False, yes=False) + coder = MinimalCoder(io) + watcher = FileWatcher(coder) + + # Test no changes + assert not watcher.handle_changes([]) + assert len(watcher.changed_files) == 0 + + # Test with changes + changes = [("modified", "/path/to/file.py")] + assert watcher.handle_changes(changes) + assert len(watcher.changed_files) == 1 + assert str(Path("/path/to/file.py")) in watcher.changed_files + + +def test_ai_comment_pattern(): + # Create minimal IO and Coder instances for testing + io = InputOutput(pretty=False, fancy_input=False, yes=False) + coder = MinimalCoder(io) + watcher = FileWatcher(coder) + fixtures_dir = Path(__file__).parent.parent / "fixtures" + + # Test Python fixture + py_path = fixtures_dir / "watch.py" + py_lines, py_comments, py_has_bang = watcher.get_ai_comments(str(py_path)) + + # Count unique AI comments (excluding duplicates and variations with extra spaces) + unique_py_comments = set(comment.strip().lower() for comment in py_comments) + + py_expected = 10 + assert len(unique_py_comments) == 10, ( + f"Expected {py_expected} unique AI comments in Python fixture, found" + f" {len(unique_py_comments)}" + ) + assert py_has_bang == "!", "Expected at least one bang (!) comment in Python fixture" + + # Test JavaScript fixture + js_path = fixtures_dir / "watch.js" + js_lines, js_comments, js_has_bang = watcher.get_ai_comments(str(js_path)) + js_expected = 16 + assert ( + len(js_lines) == js_expected + ), f"Expected {js_expected} AI comments in JavaScript fixture, found {len(js_lines)}" + assert js_has_bang == "!", "Expected at least one bang (!) comment in JavaScript fixture" + + # Test watch_question.js fixture + question_js_path = fixtures_dir / "watch_question.js" + question_js_lines, question_js_comments, question_js_has_bang = watcher.get_ai_comments( + str(question_js_path) + ) + question_js_expected = 6 + assert len(question_js_lines) == question_js_expected, ( + f"Expected {question_js_expected} AI comments in watch_question.js fixture, found" + f" {len(question_js_lines)}" + ) + assert ( + question_js_has_bang == "?" + ), "Expected at least one bang (!) comment in watch_question.js fixture" diff --git a/tests/browser/test_browser.py b/tests/browser/test_browser.py index 35b1ea034..c21dfa8cb 100644 --- a/tests/browser/test_browser.py +++ b/tests/browser/test_browser.py @@ -1,3 +1,4 @@ +import os import unittest from unittest.mock import patch @@ -7,6 +8,8 @@ from aider.main import main class TestBrowser(unittest.TestCase): @patch("aider.main.launch_gui") def test_browser_flag_imports_streamlit(self, mock_launch_gui): + os.environ["AIDER_ANALYTICS"] = "false" + # Run main with --browser and --yes flags main(["--browser", "--yes"]) diff --git a/tests/fixtures/languages/hcl/test.tf b/tests/fixtures/languages/hcl/test.tf new file mode 100644 index 000000000..8b58c2311 --- /dev/null +++ b/tests/fixtures/languages/hcl/test.tf @@ -0,0 +1,52 @@ +# Variables +variable "aws_region" { + description = "AWS region for resources" + type = string + default = "us-west-2" +} + +variable "environment" { + description = "Environment name" + type = string + default = "dev" +} + +# Provider configuration +provider "aws" { + region = var.aws_region +} + +# Resource definitions +resource "aws_vpc" "main" { + cidr_block = "10.0.0.0/16" + enable_dns_hostnames = true + enable_dns_support = true + + tags = { + Name = "${var.environment}-vpc" + Environment = var.environment + } +} + +resource "aws_subnet" "public" { + vpc_id = aws_vpc.main.id + cidr_block = "10.0.1.0/24" + availability_zone = "${var.aws_region}a" + map_public_ip_on_launch = true + + tags = { + Name = "${var.environment}-public-subnet" + Environment = var.environment + } +} + +# Output values +output "vpc_id" { + description = "ID of the created VPC" + value = aws_vpc.main.id +} + +output "subnet_id" { + description = "ID of the public subnet" + value = aws_subnet.public.id +} diff --git a/tests/fixtures/languages/kotlin/test.kt b/tests/fixtures/languages/kotlin/test.kt new file mode 100644 index 000000000..c3f9772ac --- /dev/null +++ b/tests/fixtures/languages/kotlin/test.kt @@ -0,0 +1,16 @@ +interface Greeting { + fun greet(name: String): String +} + +class Test : Greeting { + private val prefix = "Hello" + + override fun greet(name: String): String { + return "$prefix, $name!" + } +} + +fun main(args: Array) { + val greeter = Test() + println(greeter.greet("World")) +} diff --git a/tests/fixtures/watch.js b/tests/fixtures/watch.js new file mode 100644 index 000000000..e0d34604c --- /dev/null +++ b/tests/fixtures/watch.js @@ -0,0 +1,38 @@ +// Regular AI comment +//ai do 1 something +//AI make 2 this better +//ai! urgent 3 change needed +//AI! another 4 urgent one +// ai with 5 space +// AI with 6 caps +// ai! with 7 bang +// this is not an ai comment +// aider is not an ai! comment + +function dummyFunction() { + // ai inside 8 function + return true; +} + +class Example { + constructor() { + // ai in 9 constructor + this.value = 42; + } + + method() { + // ai in 10 method + return this.value; + } + // ai! + //ai + //ai! + // 11-13 + + method2() { // ai 14 + return 1; + } +} +// trailing whitespace ai +// trailing whitespace ai! +// 15-16 diff --git a/tests/fixtures/watch.py b/tests/fixtures/watch.py new file mode 100644 index 000000000..1c3449fcf --- /dev/null +++ b/tests/fixtures/watch.py @@ -0,0 +1,21 @@ +# fmt: off +# flake8: noqa + +# Regular not AI comment +#ai 1 do something +# AI 2 make this better +# ai! 3 urgent change needed +#AI! 4 another urgent one +# this is not an ai comment +# aider is not an ai comment +# not an ai! comment + + +def dummy_function(): + #ai inside 5 function + # final 6 ai! + # final 7 ai + # ai + #ai + # those are 8+9 + pass # ai 10 diff --git a/tests/fixtures/watch_question.js b/tests/fixtures/watch_question.js new file mode 100644 index 000000000..fa6ce5387 --- /dev/null +++ b/tests/fixtures/watch_question.js @@ -0,0 +1,11 @@ +// Regular AI comment +//ai do 1 something +//AI make 2 this better +//ai! urgent 3 change needed +//AI! another 4 urgent one +// ai with 5 space +// with questions AI? + +// this is not an ai comment +// aider is not an ai! comment +