mirror of
https://github.com/Aider-AI/aider.git
synced 2025-05-31 01:35:00 +00:00
Compare commits
93 commits
v0.83.2.de
...
main
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0bb0f169d2 | ||
![]() |
45ad3cdf47 | ||
![]() |
fc30409f74 | ||
![]() |
6d872b6dc0 | ||
![]() |
6fdc956b9e | ||
![]() |
196721d27d | ||
![]() |
e331a967a6 | ||
![]() |
48376e59c2 | ||
![]() |
52510c7da5 | ||
![]() |
c24798c44f | ||
![]() |
6085be5883 | ||
![]() |
05c56fe904 | ||
![]() |
a7afbd0708 | ||
![]() |
3f2c403cf0 | ||
![]() |
d7504bed21 | ||
![]() |
119a44debe | ||
![]() |
87dee0a5f2 | ||
![]() |
1d0e463d83 | ||
![]() |
8304029b92 | ||
![]() |
ef2986a231 | ||
![]() |
b79a777936 | ||
![]() |
9c9eedd9c5 | ||
![]() |
ebaad9d865 | ||
![]() |
d922023815 | ||
![]() |
acebc11237 | ||
![]() |
214b811ef9 | ||
![]() |
de9df51b47 | ||
![]() |
3194a35230 | ||
![]() |
a8568c3c4f | ||
![]() |
114ec42563 | ||
![]() |
f7df96d224 | ||
![]() |
79edb0e1e0 | ||
![]() |
5a0951caaf | ||
![]() |
6b2bcf651e | ||
![]() |
fea0ff189f | ||
![]() |
803a8db60c | ||
![]() |
414b4e3882 | ||
![]() |
a17599152f | ||
![]() |
7b9d8e6ba7 | ||
![]() |
9ef3211365 | ||
![]() |
d9bf69041c | ||
![]() |
e3cb907767 | ||
![]() |
ef3f8bb301 | ||
![]() |
03a489ea35 | ||
![]() |
81389b87d7 | ||
![]() |
0d8ff295d6 | ||
![]() |
6176a8dee3 | ||
![]() |
299e6ae7a2 | ||
![]() |
0b1d49d630 | ||
![]() |
037a36edba | ||
![]() |
66bc9cf292 | ||
![]() |
2b9e669930 | ||
![]() |
cb88b7e62a | ||
![]() |
4e9943f2aa | ||
![]() |
9f5018e89e | ||
![]() |
3caab85931 | ||
![]() |
756372809e | ||
![]() |
6aa05ab11c | ||
![]() |
9cf373039e | ||
![]() |
bc1272f029 | ||
![]() |
0049e78250 | ||
![]() |
56b45ce1d3 | ||
![]() |
bdd67eb229 | ||
![]() |
57020a2d5e | ||
![]() |
6b9045a2a2 | ||
![]() |
5f24a0013a | ||
![]() |
b79052501d | ||
![]() |
9e0d7d9c46 | ||
![]() |
a53ab7d937 | ||
![]() |
c055602c6f | ||
![]() |
170e8fc9a1 | ||
![]() |
ee177054b8 | ||
![]() |
f018b5fab5 | ||
![]() |
5a29ba03dc | ||
![]() |
035d99d3d3 | ||
![]() |
702eff1033 | ||
![]() |
97f3885357 | ||
![]() |
f8653613bc | ||
![]() |
b1d47c47d9 | ||
![]() |
2c4a126093 | ||
![]() |
cdd1546243 | ||
![]() |
6a3bb0f4ec | ||
![]() |
24c0fbd326 | ||
![]() |
7b9eae117f | ||
![]() |
512b4d891b | ||
![]() |
a6b0f43dce | ||
![]() |
e8d9ae9a1f | ||
![]() |
2ab0074915 | ||
![]() |
225e01717c | ||
![]() |
4d39b88110 | ||
![]() |
5052150e2e | ||
![]() |
d8fbd9cbd3 | ||
![]() |
0b112e948f |
42 changed files with 2481 additions and 1089 deletions
30
HISTORY.md
30
HISTORY.md
|
@ -1,11 +1,31 @@
|
|||
# Release history
|
||||
|
||||
### Aider v0.84.0
|
||||
|
||||
- Added support for new Claude models including the Sonnet 4 and Opus 4 series (e.g., `claude-sonnet-4-20250514`,
|
||||
`claude-opus-4-20250514`) across various providers. The default `sonnet` and `opus` aliases were updated to these newer
|
||||
versions.
|
||||
- Added support for the `vertex_ai/gemini-2.5-flash-preview-05-20` model.
|
||||
- Fixed OpenRouter token cost calculation for improved accuracy.
|
||||
- Updated default OpenRouter models during onboarding to `deepseek/deepseek-r1:free` for the free tier and
|
||||
`anthropic/claude-sonnet-4` for paid tiers.
|
||||
- Automatically refresh GitHub Copilot tokens when used as OpenAI API keys, by Lih Chen.
|
||||
- Aider wrote 79% of the code in this release.
|
||||
|
||||
### Aider v0.83.2
|
||||
|
||||
- Bumped configargparse to 1.7.1 as 1.7 was pulled.
|
||||
- Added shell tab completion for file path arguments (by saviour) and for `--edit-format`/`--editor-edit-format` options.
|
||||
- Improved OpenRouter model metadata handling by introducing a local cache, increasing reliability and performance.
|
||||
- The `/settings` command now displays detailed metadata for active main, editor, and weak models.
|
||||
- Fixed an issue where files explicitly added via the command line were not correctly ignored if listed in `.gitignore`.
|
||||
- Improved automatic commit messages by providing more context during their generation, by wangboxue.
|
||||
|
||||
### Aider v0.83.1
|
||||
|
||||
- Improved user language detection by correctly normalizing hyphenated language codes (e.g., `en-US` to `en`) and enhancing the validation of locale results.
|
||||
- Prevented Aider from instructing the LLM to reply in 'C' or 'POSIX' when these are detected as the system locale.
|
||||
- Displayed a spinner with the model name when generating commit messages.
|
||||
- Aider wrote 74% of the code in this release.
|
||||
|
||||
### Aider v0.83.0
|
||||
|
||||
|
@ -411,7 +431,7 @@
|
|||
- [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).
|
||||
- [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`.
|
||||
|
@ -579,7 +599,7 @@
|
|||
|
||||
### Aider v0.59.1
|
||||
|
||||
- Check for obsolete `yes: true` in yaml config, show helpful error.
|
||||
- Check for obsolete `yes: true` in YAML config, show helpful error.
|
||||
- Model settings for openrouter/anthropic/claude-3.5-sonnet:beta
|
||||
|
||||
### Aider v0.59.0
|
||||
|
@ -589,7 +609,7 @@
|
|||
- Still auto-completes the full paths of the repo files like `/add`.
|
||||
- Now supports globs like `src/**/*.py`
|
||||
- Renamed `--yes` to `--yes-always`.
|
||||
- Now uses `AIDER_YES_ALWAYS` env var and `yes-always:` yaml key.
|
||||
- Now uses `AIDER_YES_ALWAYS` env var and `yes-always:` YAML key.
|
||||
- Existing YAML and .env files will need to be updated.
|
||||
- Can still abbreviate to `--yes` on the command line.
|
||||
- Config file now uses standard YAML list syntax with ` - list entries`, one per line.
|
||||
|
@ -796,7 +816,7 @@
|
|||
- Use `--map-refresh <always|files|manual|auto>` to configure.
|
||||
- Improved cost estimate logic for caching.
|
||||
- Improved editing performance on Jupyter Notebook `.ipynb` files.
|
||||
- Show which config yaml file is loaded with `--verbose`.
|
||||
- Show which config YAML file is loaded with `--verbose`.
|
||||
- Bumped dependency versions.
|
||||
- Bugfix: properly load `.aider.models.metadata.json` data.
|
||||
- Bugfix: Using `--msg /ask ...` caused an exception.
|
||||
|
|
|
@ -27,13 +27,13 @@ cog.out(text)
|
|||
<a href="https://github.com/Aider-AI/aider/stargazers"><img alt="GitHub Stars" title="Total number of GitHub stars the Aider project has received"
|
||||
src="https://img.shields.io/github/stars/Aider-AI/aider?style=flat-square&logo=github&color=f1c40f&labelColor=555555"/></a>
|
||||
<a href="https://pypi.org/project/aider-chat/"><img alt="PyPI Downloads" title="Total number of installations via pip from PyPI"
|
||||
src="https://img.shields.io/badge/📦%20Installs-2.2M-2ecc71?style=flat-square&labelColor=555555"/></a>
|
||||
src="https://img.shields.io/badge/📦%20Installs-2.4M-2ecc71?style=flat-square&labelColor=555555"/></a>
|
||||
<img alt="Tokens per week" title="Number of tokens processed weekly by Aider users"
|
||||
src="https://img.shields.io/badge/📈%20Tokens%2Fweek-15B-3498db?style=flat-square&labelColor=555555"/>
|
||||
<a href="https://openrouter.ai/#options-menu"><img alt="OpenRouter Ranking" title="Aider's ranking among applications on the OpenRouter platform"
|
||||
src="https://img.shields.io/badge/🏆%20OpenRouter-Top%2020-9b59b6?style=flat-square&labelColor=555555"/></a>
|
||||
<a href="https://aider.chat/HISTORY.html"><img alt="Singularity" title="Percentage of the new code in Aider's last release written by Aider itself"
|
||||
src="https://img.shields.io/badge/🔄%20Singularity-54%25-e74c3c?style=flat-square&labelColor=555555"/></a>
|
||||
src="https://img.shields.io/badge/🔄%20Singularity-79%25-e74c3c?style=flat-square&labelColor=555555"/></a>
|
||||
<!--[[[end]]]-->
|
||||
</p>
|
||||
|
||||
|
@ -136,6 +136,7 @@ See the [installation instructions](https://aider.chat/docs/install.html) and [u
|
|||
- [LLM Leaderboards](https://aider.chat/docs/leaderboards/)
|
||||
- [GitHub Repository](https://github.com/Aider-AI/aider)
|
||||
- [Discord Community](https://discord.gg/Y7X7bhMQFV)
|
||||
- [Release notes](https://aider.chat/HISTORY.html)
|
||||
- [Blog](https://aider.chat/blog/)
|
||||
|
||||
## Kind Words From Users
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from packaging import version
|
||||
|
||||
__version__ = "0.83.2.dev"
|
||||
__version__ = "0.84.1.dev"
|
||||
safe_version = __version__
|
||||
|
||||
try:
|
||||
|
|
|
@ -40,10 +40,22 @@ def get_parser(default_config_files, git_root):
|
|||
config_file_parser_class=configargparse.YAMLConfigFileParser,
|
||||
auto_env_var_prefix="AIDER_",
|
||||
)
|
||||
# List of valid edit formats for argparse validation & shtab completion.
|
||||
# Dynamically gather them from the registered coder classes so the list
|
||||
# stays in sync if new formats are added.
|
||||
from aider import coders as _aider_coders
|
||||
|
||||
edit_format_choices = sorted(
|
||||
{
|
||||
c.edit_format
|
||||
for c in _aider_coders.__all__
|
||||
if hasattr(c, "edit_format") and c.edit_format is not None
|
||||
}
|
||||
)
|
||||
group = parser.add_argument_group("Main model")
|
||||
group.add_argument(
|
||||
"files", metavar="FILE", nargs="*", help="files to edit with an LLM (optional)"
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
group.add_argument(
|
||||
"--model",
|
||||
metavar="MODEL",
|
||||
|
@ -110,13 +122,13 @@ def get_parser(default_config_files, git_root):
|
|||
metavar="MODEL_SETTINGS_FILE",
|
||||
default=".aider.model.settings.yml",
|
||||
help="Specify a file with aider model settings for unknown models",
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
group.add_argument(
|
||||
"--model-metadata-file",
|
||||
metavar="MODEL_METADATA_FILE",
|
||||
default=".aider.model.metadata.json",
|
||||
help="Specify a file with context window and costs for unknown models",
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
group.add_argument(
|
||||
"--alias",
|
||||
action="append",
|
||||
|
@ -149,6 +161,7 @@ def get_parser(default_config_files, git_root):
|
|||
"--edit-format",
|
||||
"--chat-mode",
|
||||
metavar="EDIT_FORMAT",
|
||||
choices=edit_format_choices,
|
||||
default=None,
|
||||
help="Specify what edit format the LLM should use (default depends on model)",
|
||||
)
|
||||
|
@ -183,6 +196,7 @@ def get_parser(default_config_files, git_root):
|
|||
group.add_argument(
|
||||
"--editor-edit-format",
|
||||
metavar="EDITOR_EDIT_FORMAT",
|
||||
choices=edit_format_choices,
|
||||
default=None,
|
||||
help="Specify the edit format for the editor model (default: depends on editor model)",
|
||||
)
|
||||
|
@ -262,13 +276,13 @@ def get_parser(default_config_files, git_root):
|
|||
metavar="INPUT_HISTORY_FILE",
|
||||
default=default_input_history_file,
|
||||
help=f"Specify the chat input history file (default: {default_input_history_file})",
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
group.add_argument(
|
||||
"--chat-history-file",
|
||||
metavar="CHAT_HISTORY_FILE",
|
||||
default=default_chat_history_file,
|
||||
help=f"Specify the chat history file (default: {default_chat_history_file})",
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
group.add_argument(
|
||||
"--restore-chat-history",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
|
@ -280,7 +294,7 @@ def get_parser(default_config_files, git_root):
|
|||
metavar="LLM_HISTORY_FILE",
|
||||
default=None,
|
||||
help="Log the conversation with the LLM to this file (for example, .aider.llm.history)",
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
|
||||
##########
|
||||
group = parser.add_argument_group("Output settings")
|
||||
|
@ -406,7 +420,7 @@ def get_parser(default_config_files, git_root):
|
|||
type=lambda path_str: resolve_aiderignore_path(path_str, git_root),
|
||||
default=default_aiderignore_file,
|
||||
help="Specify the aider ignore file (default: .aiderignore in git root)",
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
group.add_argument(
|
||||
"--subtree-only",
|
||||
action="store_true",
|
||||
|
@ -552,7 +566,7 @@ def get_parser(default_config_files, git_root):
|
|||
"--analytics-log",
|
||||
metavar="ANALYTICS_LOG_FILE",
|
||||
help="Specify a file to log analytics events",
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
group.add_argument(
|
||||
"--analytics-disable",
|
||||
action="store_true",
|
||||
|
@ -619,7 +633,7 @@ def get_parser(default_config_files, git_root):
|
|||
"Specify a file containing the message to send the LLM, process reply, then exit"
|
||||
" (disables chat mode)"
|
||||
),
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
group.add_argument(
|
||||
"--gui",
|
||||
"--browser",
|
||||
|
@ -637,7 +651,7 @@ def get_parser(default_config_files, git_root):
|
|||
"--apply",
|
||||
metavar="FILE",
|
||||
help="Apply the changes from the given file instead of running the chat (debug)",
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
group.add_argument(
|
||||
"--apply-clipboard-edits",
|
||||
action="store_true",
|
||||
|
@ -698,13 +712,13 @@ def get_parser(default_config_files, git_root):
|
|||
action="append",
|
||||
metavar="FILE",
|
||||
help="specify a file to edit (can be used multiple times)",
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
group.add_argument(
|
||||
"--read",
|
||||
action="append",
|
||||
metavar="FILE",
|
||||
help="specify a read-only file (can be used multiple times)",
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
group.add_argument(
|
||||
"--vim",
|
||||
action="store_true",
|
||||
|
@ -734,7 +748,7 @@ def get_parser(default_config_files, git_root):
|
|||
"--load",
|
||||
metavar="LOAD_FILE",
|
||||
help="Load and execute /commands from a file on launch",
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
group.add_argument(
|
||||
"--encoding",
|
||||
default="utf-8",
|
||||
|
@ -755,7 +769,7 @@ def get_parser(default_config_files, git_root):
|
|||
"Specify the config file (default: search for .aider.conf.yml in git root, cwd"
|
||||
" or home directory)"
|
||||
),
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
# 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(
|
||||
|
@ -763,7 +777,7 @@ def get_parser(default_config_files, git_root):
|
|||
metavar="ENV_FILE",
|
||||
default=default_env_file(git_root),
|
||||
help="Specify the .env file to load (default: .env in git root)",
|
||||
)
|
||||
).complete = shtab.FILE
|
||||
group.add_argument(
|
||||
"--suggest-shell-commands",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
|
|
|
@ -96,7 +96,7 @@ class YamlHelpFormatter(argparse.HelpFormatter):
|
|||
# Place in your home dir, or at the root of your git repo.
|
||||
##########################################################
|
||||
|
||||
# Note: You can only put OpenAI and Anthropic API keys in the yaml
|
||||
# Note: You can only put OpenAI and Anthropic API keys in the YAML
|
||||
# config file. Keys for all APIs can be stored in a .env file
|
||||
# https://aider.chat/docs/config/dotenv.html
|
||||
|
||||
|
|
|
@ -445,6 +445,7 @@ class Coder:
|
|||
fname = Path(fname)
|
||||
if self.repo and self.repo.git_ignored_file(fname):
|
||||
self.io.tool_warning(f"Skipping {fname} that matches gitignore spec.")
|
||||
continue
|
||||
|
||||
if self.repo and self.repo.ignored_file(fname):
|
||||
self.io.tool_warning(f"Skipping {fname} that matches aiderignore spec.")
|
||||
|
|
|
@ -346,7 +346,7 @@ class Commands:
|
|||
return
|
||||
|
||||
commit_message = args.strip() if args else None
|
||||
self.coder.repo.commit(message=commit_message)
|
||||
self.coder.repo.commit(message=commit_message, coder=self.coder)
|
||||
|
||||
def cmd_lint(self, args="", fnames=None):
|
||||
"Lint and fix in-chat files or all dirty files if none in chat"
|
||||
|
@ -1392,7 +1392,30 @@ class Commands:
|
|||
"Print out the current settings"
|
||||
settings = format_settings(self.parser, self.args)
|
||||
announcements = "\n".join(self.coder.get_announcements())
|
||||
|
||||
# Build metadata for the active models (main, editor, weak)
|
||||
model_sections = []
|
||||
active_models = [
|
||||
("Main model", self.coder.main_model),
|
||||
("Editor model", getattr(self.coder.main_model, "editor_model", None)),
|
||||
("Weak model", getattr(self.coder.main_model, "weak_model", None)),
|
||||
]
|
||||
for label, model in active_models:
|
||||
if not model:
|
||||
continue
|
||||
info = getattr(model, "info", {}) or {}
|
||||
if not info:
|
||||
continue
|
||||
model_sections.append(f"{label} ({model.name}):")
|
||||
for k, v in sorted(info.items()):
|
||||
model_sections.append(f" {k}: {v}")
|
||||
model_sections.append("") # blank line between models
|
||||
|
||||
model_metadata = "\n".join(model_sections)
|
||||
|
||||
output = f"{announcements}\n{settings}"
|
||||
if model_metadata:
|
||||
output += "\n" + model_metadata
|
||||
self.io.tool_output(output)
|
||||
|
||||
def completions_raw_load(self, document, complete_event):
|
||||
|
|
|
@ -8,6 +8,7 @@ import platform
|
|||
import sys
|
||||
import time
|
||||
from dataclasses import dataclass, fields
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Optional, Union
|
||||
|
||||
|
@ -17,6 +18,7 @@ from PIL import Image
|
|||
|
||||
from aider.dump import dump # noqa: F401
|
||||
from aider.llm import litellm
|
||||
from aider.openrouter import OpenRouterModelManager
|
||||
from aider.sendchat import ensure_alternating_roles, sanity_check_messages
|
||||
from aider.utils import check_pip_install_extra
|
||||
|
||||
|
@ -69,6 +71,8 @@ claude-3-opus-20240229
|
|||
claude-3-sonnet-20240229
|
||||
claude-3-5-sonnet-20240620
|
||||
claude-3-5-sonnet-20241022
|
||||
claude-sonnet-4-20250514
|
||||
claude-opus-4-20250514
|
||||
"""
|
||||
|
||||
ANTHROPIC_MODELS = [ln.strip() for ln in ANTHROPIC_MODELS.splitlines() if ln.strip()]
|
||||
|
@ -76,9 +80,9 @@ ANTHROPIC_MODELS = [ln.strip() for ln in ANTHROPIC_MODELS.splitlines() if ln.str
|
|||
# Mapping of model aliases to their canonical names
|
||||
MODEL_ALIASES = {
|
||||
# Claude models
|
||||
"sonnet": "anthropic/claude-3-7-sonnet-20250219",
|
||||
"sonnet": "anthropic/claude-sonnet-4-20250514",
|
||||
"haiku": "claude-3-5-haiku-20241022",
|
||||
"opus": "claude-3-opus-20240229",
|
||||
"opus": "claude-opus-4-20250514",
|
||||
# GPT models
|
||||
"4": "gpt-4-0613",
|
||||
"4o": "gpt-4o",
|
||||
|
@ -149,8 +153,13 @@ class ModelInfoManager:
|
|||
self.verify_ssl = True
|
||||
self._cache_loaded = False
|
||||
|
||||
# Manager for the cached OpenRouter model database
|
||||
self.openrouter_manager = OpenRouterModelManager()
|
||||
|
||||
def set_verify_ssl(self, verify_ssl):
|
||||
self.verify_ssl = verify_ssl
|
||||
if hasattr(self, "openrouter_manager"):
|
||||
self.openrouter_manager.set_verify_ssl(verify_ssl)
|
||||
|
||||
def _load_cache(self):
|
||||
if self._cache_loaded:
|
||||
|
@ -232,6 +241,12 @@ class ModelInfoManager:
|
|||
return litellm_info
|
||||
|
||||
if not cached_info and model.startswith("openrouter/"):
|
||||
# First try using the locally cached OpenRouter model database
|
||||
openrouter_info = self.openrouter_manager.get_model_info(model)
|
||||
if openrouter_info:
|
||||
return openrouter_info
|
||||
|
||||
# Fallback to legacy web-scraping if the API cache does not contain the model
|
||||
openrouter_info = self.fetch_openrouter_model_info(model)
|
||||
if openrouter_info:
|
||||
return openrouter_info
|
||||
|
@ -861,6 +876,28 @@ class Model(ModelSettings):
|
|||
def is_ollama(self):
|
||||
return self.name.startswith("ollama/") or self.name.startswith("ollama_chat/")
|
||||
|
||||
def github_copilot_token_to_open_ai_key(self):
|
||||
# check to see if there's an openai api key
|
||||
# If so, check to see if it's expire
|
||||
openai_api_key = "OPENAI_API_KEY"
|
||||
|
||||
if openai_api_key not in os.environ or (
|
||||
int(dict(x.split("=") for x in os.environ[openai_api_key].split(";"))["exp"])
|
||||
< int(datetime.now().timestamp())
|
||||
):
|
||||
import requests
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {os.environ['GITHUB_COPILOT_TOKEN']}",
|
||||
"Editor-Version": self.extra_params["extra_headers"]["Editor-Version"],
|
||||
"Copilot-Integration-Id": self.extra_params["extra_headers"][
|
||||
"Copilot-Integration-Id"
|
||||
],
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
res = requests.get("https://api.github.com/copilot_internal/v2/token", headers=headers)
|
||||
os.environ[openai_api_key] = res.json()["token"]
|
||||
|
||||
def send_completion(self, messages, functions, stream, temperature=None):
|
||||
if os.environ.get("AIDER_SANITY_CHECK_TURNS"):
|
||||
sanity_check_messages(messages)
|
||||
|
@ -902,6 +939,10 @@ class Model(ModelSettings):
|
|||
dump(kwargs)
|
||||
kwargs["messages"] = messages
|
||||
|
||||
# Are we using github copilot?
|
||||
if "GITHUB_COPILOT_TOKEN" in os.environ:
|
||||
self.github_copilot_token_to_open_ai_key()
|
||||
|
||||
res = litellm.completion(**kwargs)
|
||||
return hash_object, res
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ def try_to_select_default_model():
|
|||
# Check if the user is on a free tier
|
||||
is_free_tier = check_openrouter_tier(openrouter_key)
|
||||
if is_free_tier:
|
||||
return "openrouter/google/gemini-2.5-pro-exp-03-25:free"
|
||||
return "openrouter/deepseek/deepseek-r1:free"
|
||||
else:
|
||||
return "openrouter/anthropic/claude-3.7-sonnet"
|
||||
return "openrouter/anthropic/claude-sonnet-4"
|
||||
|
||||
# Select model based on other available API keys
|
||||
model_key_pairs = [
|
||||
|
|
128
aider/openrouter.py
Normal file
128
aider/openrouter.py
Normal file
|
@ -0,0 +1,128 @@
|
|||
"""
|
||||
OpenRouter model metadata caching and lookup.
|
||||
|
||||
This module keeps a local cached copy of the OpenRouter model list
|
||||
(downloaded from ``https://openrouter.ai/api/v1/models``) and exposes a
|
||||
helper class that returns metadata for a given model in a format compatible
|
||||
with litellm’s ``get_model_info``.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
def _cost_per_token(val: str | None) -> float | None:
|
||||
"""Convert a price string (USD per token) to a float."""
|
||||
if val in (None, "", "0"):
|
||||
return 0.0 if val == "0" else None
|
||||
try:
|
||||
return float(val)
|
||||
except Exception: # noqa: BLE001
|
||||
return None
|
||||
|
||||
|
||||
class OpenRouterModelManager:
|
||||
MODELS_URL = "https://openrouter.ai/api/v1/models"
|
||||
CACHE_TTL = 60 * 60 * 24 # 24 h
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.cache_dir = Path.home() / ".aider" / "caches"
|
||||
self.cache_file = self.cache_dir / "openrouter_models.json"
|
||||
self.content: Dict | None = None
|
||||
self.verify_ssl: bool = True
|
||||
self._cache_loaded = False
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Public API #
|
||||
# ------------------------------------------------------------------ #
|
||||
def set_verify_ssl(self, verify_ssl: bool) -> None:
|
||||
"""Enable/disable SSL verification for API requests."""
|
||||
self.verify_ssl = verify_ssl
|
||||
|
||||
def get_model_info(self, model: str) -> Dict:
|
||||
"""
|
||||
Return metadata for *model* or an empty ``dict`` when unknown.
|
||||
|
||||
``model`` should use the aider naming convention, e.g.
|
||||
``openrouter/nousresearch/deephermes-3-mistral-24b-preview:free``.
|
||||
"""
|
||||
self._ensure_content()
|
||||
if not self.content or "data" not in self.content:
|
||||
return {}
|
||||
|
||||
route = self._strip_prefix(model)
|
||||
|
||||
# Consider both the exact id and id without any “:suffix”.
|
||||
candidates = {route}
|
||||
if ":" in route:
|
||||
candidates.add(route.split(":", 1)[0])
|
||||
|
||||
record = next((item for item in self.content["data"] if item.get("id") in candidates), None)
|
||||
if not record:
|
||||
return {}
|
||||
|
||||
context_len = (
|
||||
record.get("top_provider", {}).get("context_length")
|
||||
or record.get("context_length")
|
||||
or None
|
||||
)
|
||||
|
||||
pricing = record.get("pricing", {})
|
||||
return {
|
||||
"max_input_tokens": context_len,
|
||||
"max_tokens": context_len,
|
||||
"max_output_tokens": context_len,
|
||||
"input_cost_per_token": _cost_per_token(pricing.get("prompt")),
|
||||
"output_cost_per_token": _cost_per_token(pricing.get("completion")),
|
||||
"litellm_provider": "openrouter",
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Internal helpers #
|
||||
# ------------------------------------------------------------------ #
|
||||
def _strip_prefix(self, model: str) -> str:
|
||||
return model[len("openrouter/") :] if model.startswith("openrouter/") else model
|
||||
|
||||
def _ensure_content(self) -> None:
|
||||
self._load_cache()
|
||||
if not self.content:
|
||||
self._update_cache()
|
||||
|
||||
def _load_cache(self) -> None:
|
||||
if self._cache_loaded:
|
||||
return
|
||||
try:
|
||||
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
||||
if self.cache_file.exists():
|
||||
cache_age = time.time() - self.cache_file.stat().st_mtime
|
||||
if cache_age < self.CACHE_TTL:
|
||||
try:
|
||||
self.content = json.loads(self.cache_file.read_text())
|
||||
except json.JSONDecodeError:
|
||||
self.content = None
|
||||
except OSError:
|
||||
# Cache directory might be unwritable; ignore.
|
||||
pass
|
||||
|
||||
self._cache_loaded = True
|
||||
|
||||
def _update_cache(self) -> None:
|
||||
try:
|
||||
response = requests.get(self.MODELS_URL, timeout=10, verify=self.verify_ssl)
|
||||
if response.status_code == 200:
|
||||
self.content = response.json()
|
||||
try:
|
||||
self.cache_file.write_text(json.dumps(self.content, indent=2))
|
||||
except OSError:
|
||||
pass # Non-fatal if we can’t write the cache
|
||||
except Exception as ex: # noqa: BLE001
|
||||
print(f"Failed to fetch OpenRouter model list: {ex}")
|
||||
try:
|
||||
self.cache_file.write_text("{}")
|
||||
except OSError:
|
||||
pass
|
|
@ -49,7 +49,7 @@
|
|||
},
|
||||
"openrouter/deepseek/deepseek-chat-v3-0324": {
|
||||
"max_tokens": 8192,
|
||||
"max_input_tokens": 64000,
|
||||
"max_input_tokens": 131072,
|
||||
"max_output_tokens": 8192,
|
||||
"input_cost_per_token": 0.00000055,
|
||||
"input_cost_per_token_cache_hit": 0.00000014,
|
||||
|
|
|
@ -1435,4 +1435,333 @@
|
|||
# top_k: 20
|
||||
# min_p: 0.0
|
||||
# temperature: 0.7
|
||||
|
||||
|
||||
|
||||
- name: claude-sonnet-4-20250514
|
||||
edit_format: diff
|
||||
weak_model_name: claude-3-5-haiku-20241022
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: claude-sonnet-4-20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: anthropic/claude-sonnet-4-20250514
|
||||
edit_format: diff
|
||||
weak_model_name: anthropic/claude-3-5-haiku-20241022
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: anthropic/claude-sonnet-4-20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: bedrock/anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock/anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock/us.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: bedrock_converse/anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock_converse/anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: bedrock_converse/us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/us.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock_converse/us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: vertex_ai/claude-sonnet-4@20250514
|
||||
edit_format: diff
|
||||
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
max_tokens: 64000
|
||||
editor_model_name: vertex_ai/claude-sonnet-4@20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: vertex_ai-anthropic_models/vertex_ai/claude-sonnet-4@20250514
|
||||
edit_format: diff
|
||||
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
max_tokens: 64000
|
||||
editor_model_name: vertex_ai-anthropic_models/vertex_ai/claude-sonnet-4@20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: openrouter/anthropic/claude-sonnet-4
|
||||
edit_format: diff
|
||||
weak_model_name: openrouter/anthropic/claude-3-5-haiku
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: openrouter/anthropic/claude-sonnet-4
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: bedrock_converse/eu.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/eu.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock_converse/eu.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: eu.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: eu.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: eu.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: us.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: claude-opus-4-20250514
|
||||
edit_format: diff
|
||||
weak_model_name: claude-3-5-haiku-20241022
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: claude-sonnet-4-20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: anthropic/claude-opus-4-20250514
|
||||
edit_format: diff
|
||||
weak_model_name: anthropic/claude-3-5-haiku-20241022
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: anthropic/claude-sonnet-4-20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: anthropic.claude-opus-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: bedrock_converse/anthropic.claude-opus-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock_converse/anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: bedrock_converse/us.anthropic.claude-opus-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/us.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock_converse/us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: bedrock_converse/eu.anthropic.claude-opus-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/eu.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock_converse/eu.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: eu.anthropic.claude-opus-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: eu.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: eu.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: us.anthropic.claude-opus-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: us.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: vertex_ai/claude-opus-4@20250514
|
||||
edit_format: diff
|
||||
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
max_tokens: 32000
|
||||
editor_model_name: vertex_ai/claude-sonnet-4@20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: vertex_ai-anthropic_models/vertex_ai/claude-opus-4@20250514
|
||||
edit_format: diff
|
||||
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
max_tokens: 32000
|
||||
editor_model_name: vertex_ai-anthropic_models/vertex_ai/claude-sonnet-4@20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
- name: vertex_ai/gemini-2.5-flash-preview-05-20
|
||||
edit_format: diff
|
||||
use_repo_map: true
|
||||
accepts_settings: ["reasoning_effort", "thinking_tokens"]
|
||||
- name: openrouter/anthropic/claude-opus-4
|
||||
edit_format: diff
|
||||
weak_model_name: openrouter/anthropic/claude-3-5-haiku
|
||||
use_repo_map: true
|
||||
examples_as_sys_msg: false
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: openrouter/anthropic/claude-sonnet-4
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings: ["thinking_tokens"]
|
||||
|
||||
|
|
|
@ -24,12 +24,32 @@ cog.out(text)
|
|||
]]]-->
|
||||
|
||||
|
||||
### Aider v0.84.0
|
||||
|
||||
- Added support for new Claude models including the Sonnet 4 and Opus 4 series (e.g., `claude-sonnet-4-20250514`,
|
||||
`claude-opus-4-20250514`) across various providers. The default `sonnet` and `opus` aliases were updated to these newer
|
||||
versions.
|
||||
- Added support for the `vertex_ai/gemini-2.5-flash-preview-05-20` model.
|
||||
- Fixed OpenRouter token cost calculation for improved accuracy.
|
||||
- Updated default OpenRouter models during onboarding to `deepseek/deepseek-r1:free` for the free tier and
|
||||
`anthropic/claude-sonnet-4` for paid tiers.
|
||||
- Automatically refresh GitHub Copilot tokens when used as OpenAI API keys, by Lih Chen.
|
||||
- Aider wrote 79% of the code in this release.
|
||||
|
||||
### Aider v0.83.2
|
||||
|
||||
- Bumped configargparse to 1.7.1 as 1.7 was pulled.
|
||||
- Added shell tab completion for file path arguments (by saviour) and for `--edit-format`/`--editor-edit-format` options.
|
||||
- Improved OpenRouter model metadata handling by introducing a local cache, increasing reliability and performance.
|
||||
- The `/settings` command now displays detailed metadata for active main, editor, and weak models.
|
||||
- Fixed an issue where files explicitly added via the command line were not correctly ignored if listed in `.gitignore`.
|
||||
- Improved automatic commit messages by providing more context during their generation, by wangboxue.
|
||||
|
||||
### Aider v0.83.1
|
||||
|
||||
- Improved user language detection by correctly normalizing hyphenated language codes (e.g., `en-US` to `en`) and enhancing the validation of locale results.
|
||||
- Prevented Aider from instructing the LLM to reply in 'C' or 'POSIX' when these are detected as the system locale.
|
||||
- Displayed a spinner with the model name when generating commit messages.
|
||||
- Aider wrote 74% of the code in this release.
|
||||
|
||||
### Aider v0.83.0
|
||||
|
||||
|
@ -435,7 +455,7 @@ cog.out(text)
|
|||
- [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).
|
||||
- [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`.
|
||||
|
@ -603,7 +623,7 @@ cog.out(text)
|
|||
|
||||
### Aider v0.59.1
|
||||
|
||||
- Check for obsolete `yes: true` in yaml config, show helpful error.
|
||||
- Check for obsolete `yes: true` in YAML config, show helpful error.
|
||||
- Model settings for openrouter/anthropic/claude-3.5-sonnet:beta
|
||||
|
||||
### Aider v0.59.0
|
||||
|
@ -613,7 +633,7 @@ cog.out(text)
|
|||
- Still auto-completes the full paths of the repo files like `/add`.
|
||||
- Now supports globs like `src/**/*.py`
|
||||
- Renamed `--yes` to `--yes-always`.
|
||||
- Now uses `AIDER_YES_ALWAYS` env var and `yes-always:` yaml key.
|
||||
- Now uses `AIDER_YES_ALWAYS` env var and `yes-always:` YAML key.
|
||||
- Existing YAML and .env files will need to be updated.
|
||||
- Can still abbreviate to `--yes` on the command line.
|
||||
- Config file now uses standard YAML list syntax with ` - list entries`, one per line.
|
||||
|
@ -820,7 +840,7 @@ cog.out(text)
|
|||
- Use `--map-refresh <always|files|manual|auto>` to configure.
|
||||
- Improved cost estimate logic for caching.
|
||||
- Improved editing performance on Jupyter Notebook `.ipynb` files.
|
||||
- Show which config yaml file is loaded with `--verbose`.
|
||||
- Show which config YAML file is loaded with `--verbose`.
|
||||
- Bumped dependency versions.
|
||||
- Bugfix: properly load `.aider.models.metadata.json` data.
|
||||
- Bugfix: Using `--msg /ask ...` caused an exception.
|
||||
|
|
|
@ -4659,3 +4659,69 @@
|
|||
zjy1412: 54
|
||||
start_tag: v0.82.0
|
||||
total_lines: 2594
|
||||
- aider_percentage: 78.92
|
||||
aider_total: 655
|
||||
end_date: '2025-05-30'
|
||||
end_tag: v0.84.0
|
||||
file_counts:
|
||||
aider/__init__.py:
|
||||
Paul Gauthier: 1
|
||||
aider/args.py:
|
||||
Paul Gauthier (aider): 27
|
||||
saviour: 2
|
||||
aider/args_formatter.py:
|
||||
Paul Gauthier: 1
|
||||
aider/coders/base_coder.py:
|
||||
Paul Gauthier: 4
|
||||
Paul Gauthier (aider): 10
|
||||
aider/commands.py:
|
||||
Paul Gauthier (aider): 23
|
||||
wangboxue: 1
|
||||
aider/models.py:
|
||||
Lih Chen: 15
|
||||
Paul Gauthier: 16
|
||||
Paul Gauthier (aider): 12
|
||||
aider/onboarding.py:
|
||||
Paul Gauthier: 2
|
||||
aider/openrouter.py:
|
||||
Paul Gauthier (aider): 120
|
||||
aider/repo.py:
|
||||
Paul Gauthier: 1
|
||||
Paul Gauthier (aider): 10
|
||||
aider/repomap.py:
|
||||
Paul Gauthier (aider): 1
|
||||
aider/resources/model-settings.yml:
|
||||
Paul Gauthier: 71
|
||||
Paul Gauthier (aider): 193
|
||||
Trung Dinh: 11
|
||||
aider/utils.py:
|
||||
Paul Gauthier (aider): 1
|
||||
aider/waiting.py:
|
||||
Paul Gauthier: 2
|
||||
Paul Gauthier (aider): 6
|
||||
aider/website/docs/leaderboards/index.md:
|
||||
Paul Gauthier: 1
|
||||
aider/website/index.html:
|
||||
Paul Gauthier: 43
|
||||
scripts/update-history.py:
|
||||
Paul Gauthier: 2
|
||||
tests/basic/test_coder.py:
|
||||
Paul Gauthier: 2
|
||||
Paul Gauthier (aider): 144
|
||||
tests/basic/test_main.py:
|
||||
Paul Gauthier (aider): 28
|
||||
tests/basic/test_models.py:
|
||||
Paul Gauthier (aider): 2
|
||||
tests/basic/test_onboarding.py:
|
||||
Paul Gauthier (aider): 5
|
||||
tests/basic/test_openrouter.py:
|
||||
Paul Gauthier (aider): 73
|
||||
grand_total:
|
||||
Lih Chen: 15
|
||||
Paul Gauthier: 146
|
||||
Paul Gauthier (aider): 655
|
||||
Trung Dinh: 11
|
||||
saviour: 2
|
||||
wangboxue: 1
|
||||
start_tag: v0.83.0
|
||||
total_lines: 830
|
||||
|
|
|
@ -1306,4 +1306,175 @@
|
|||
versions: 0.82.4.dev
|
||||
seconds_per_case: 45.4
|
||||
total_cost: 0.0000
|
||||
|
||||
|
||||
- dirname: 2025-05-24-21-17-54--sonnet4-diff-exuser
|
||||
test_cases: 225
|
||||
model: claude-sonnet-4-20250514 (no thinking)
|
||||
edit_format: diff
|
||||
commit_hash: ef3f8bb-dirty
|
||||
pass_rate_1: 20.4
|
||||
pass_rate_2: 56.4
|
||||
pass_num_1: 46
|
||||
pass_num_2: 127
|
||||
percent_cases_well_formed: 98.2
|
||||
error_outputs: 6
|
||||
num_malformed_responses: 4
|
||||
num_with_malformed_responses: 4
|
||||
user_asks: 129
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 1
|
||||
prompt_tokens: 3460663
|
||||
completion_tokens: 433373
|
||||
test_timeouts: 7
|
||||
total_tests: 225
|
||||
command: aider --model claude-sonnet-4-20250514
|
||||
date: 2025-05-24
|
||||
versions: 0.83.3.dev
|
||||
seconds_per_case: 29.8
|
||||
total_cost: 15.8155
|
||||
|
||||
- dirname: 2025-05-24-22-10-36--sonnet4-diff-exuser-think32k
|
||||
test_cases: 225
|
||||
model: claude-sonnet-4-20250514 (32k thinking)
|
||||
edit_format: diff
|
||||
commit_hash: e3cb907
|
||||
thinking_tokens: 32000
|
||||
pass_rate_1: 25.8
|
||||
pass_rate_2: 61.3
|
||||
pass_num_1: 58
|
||||
pass_num_2: 138
|
||||
percent_cases_well_formed: 97.3
|
||||
error_outputs: 10
|
||||
num_malformed_responses: 10
|
||||
num_with_malformed_responses: 6
|
||||
user_asks: 111
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
prompt_tokens: 2863068
|
||||
completion_tokens: 1271074
|
||||
test_timeouts: 6
|
||||
total_tests: 225
|
||||
command: aider --model claude-sonnet-4-20250514
|
||||
date: 2025-05-24
|
||||
versions: 0.83.3.dev
|
||||
seconds_per_case: 79.9
|
||||
total_cost: 26.5755
|
||||
|
||||
- dirname: 2025-05-25-19-57-20--opus4-diff-exuser
|
||||
test_cases: 225
|
||||
model: claude-opus-4-20250514 (no think)
|
||||
edit_format: diff
|
||||
commit_hash: 9ef3211
|
||||
pass_rate_1: 32.9
|
||||
pass_rate_2: 70.7
|
||||
pass_num_1: 74
|
||||
pass_num_2: 159
|
||||
percent_cases_well_formed: 98.7
|
||||
error_outputs: 3
|
||||
num_malformed_responses: 3
|
||||
num_with_malformed_responses: 3
|
||||
user_asks: 105
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
prompt_tokens: 2671437
|
||||
completion_tokens: 380717
|
||||
test_timeouts: 3
|
||||
total_tests: 225
|
||||
command: aider --model claude-opus-4-20250514
|
||||
date: 2025-05-25
|
||||
versions: 0.83.3.dev
|
||||
seconds_per_case: 42.5
|
||||
total_cost: 68.6253
|
||||
|
||||
- dirname: 2025-05-25-20-40-51--opus4-diff-exuser
|
||||
test_cases: 225
|
||||
model: claude-opus-4-20250514 (32k thinking)
|
||||
edit_format: diff
|
||||
commit_hash: 9ef3211
|
||||
thinking_tokens: 32000
|
||||
pass_rate_1: 37.3
|
||||
pass_rate_2: 72.0
|
||||
pass_num_1: 84
|
||||
pass_num_2: 162
|
||||
percent_cases_well_formed: 97.3
|
||||
error_outputs: 10
|
||||
num_malformed_responses: 6
|
||||
num_with_malformed_responses: 6
|
||||
user_asks: 97
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
prompt_tokens: 2567514
|
||||
completion_tokens: 363142
|
||||
test_timeouts: 4
|
||||
total_tests: 225
|
||||
command: aider --model claude-opus-4-20250514
|
||||
date: 2025-05-25
|
||||
versions: 0.83.3.dev
|
||||
seconds_per_case: 44.1
|
||||
total_cost: 65.7484
|
||||
|
||||
- dirname: 2025-05-26-15-56-31--flash25-05-20-24k-think # dirname is misleading
|
||||
test_cases: 225
|
||||
model: gemini-2.5-flash-preview-05-20 (no think)
|
||||
edit_format: diff
|
||||
commit_hash: 214b811-dirty
|
||||
thinking_tokens: 0 # <-- no thinking
|
||||
pass_rate_1: 20.9
|
||||
pass_rate_2: 44.0
|
||||
pass_num_1: 47
|
||||
pass_num_2: 99
|
||||
percent_cases_well_formed: 93.8
|
||||
error_outputs: 16
|
||||
num_malformed_responses: 16
|
||||
num_with_malformed_responses: 14
|
||||
user_asks: 79
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
prompt_tokens: 5512458
|
||||
completion_tokens: 514145
|
||||
test_timeouts: 4
|
||||
total_tests: 225
|
||||
command: aider --model gemini/gemini-2.5-flash-preview-05-20
|
||||
date: 2025-05-26
|
||||
versions: 0.83.3.dev
|
||||
seconds_per_case: 12.2
|
||||
total_cost: 1.1354
|
||||
|
||||
- dirname: 2025-05-25-22-58-44--flash25-05-20-24k-think
|
||||
test_cases: 225
|
||||
model: gemini-2.5-flash-preview-05-20 (24k think)
|
||||
edit_format: diff
|
||||
commit_hash: a8568c3-dirty
|
||||
thinking_tokens: 24576
|
||||
pass_rate_1: 26.2
|
||||
pass_rate_2: 55.1
|
||||
pass_num_1: 59
|
||||
pass_num_2: 124
|
||||
percent_cases_well_formed: 95.6
|
||||
error_outputs: 15
|
||||
num_malformed_responses: 15
|
||||
num_with_malformed_responses: 10
|
||||
user_asks: 101
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
prompt_tokens: 3666792
|
||||
completion_tokens: 2703162
|
||||
test_timeouts: 4
|
||||
total_tests: 225
|
||||
command: aider --model gemini/gemini-2.5-flash-preview-05-20
|
||||
date: 2025-05-25
|
||||
versions: 0.83.3.dev
|
||||
seconds_per_case: 53.9
|
||||
total_cost: 8.5625
|
|
@ -15,12 +15,12 @@ nav_exclude: true
|
|||
I recently wanted to draw a graph showing how LLM code editing skill has been
|
||||
changing over time as new models have been released by OpenAI, Anthropic and others.
|
||||
I have all the
|
||||
[data in a yaml file](https://github.com/Aider-AI/aider/blob/main/website/_data/edit_leaderboard.yml) that is used to render
|
||||
[data in a YAML file](https://github.com/Aider-AI/aider/blob/main/website/_data/edit_leaderboard.yml) that is used to render
|
||||
[aider's LLM leaderboards](https://aider.chat/docs/leaderboards/).
|
||||
|
||||
Below is the aider chat transcript, which shows:
|
||||
|
||||
- I launch aider with the yaml file, a file with other plots I've done recently (so GPT can crib the style) and an empty file called `over_time.py`.
|
||||
- I launch aider with the YAML file, a file with other plots I've done recently (so GPT can crib the style) and an empty file called `over_time.py`.
|
||||
- Then I ask GPT to draw the scatterplot I want.
|
||||
- I run the resulting script and share the error output with GPT so it can fix a small bug.
|
||||
- I ask it to color the points for GPT-4 and GPT-3.5 family models differently, to better see trends within those model families.
|
||||
|
@ -28,7 +28,7 @@ Below is the aider chat transcript, which shows:
|
|||
- I work through a series of other small style changes, like changing fonts and the graph border.
|
||||
|
||||
In the end I have the graph, but I also have the python code in my repo.
|
||||
So I can update this graph easily whenever I add new entries to the yaml data file.
|
||||
So I can update this graph easily whenever I add new entries to the YAML data file.
|
||||
|
||||
|
||||
## Aider chat transcript
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,7 +4,7 @@
|
|||
# Place in your home dir, or at the root of your git repo.
|
||||
##########################################################
|
||||
|
||||
# Note: You can only put OpenAI and Anthropic API keys in the yaml
|
||||
# Note: You can only put OpenAI and Anthropic API keys in the YAML
|
||||
# config file. Keys for all APIs can be stored in a .env file
|
||||
# https://aider.chat/docs/config/dotenv.html
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ You can override or add settings for any model by creating a `.aider.model.setti
|
|||
If the files above exist, they will be loaded in that order.
|
||||
Files loaded last will take priority.
|
||||
|
||||
The yaml file should be a list of dictionary objects for each model.
|
||||
The YAML file should be a list of dictionary objects for each model.
|
||||
|
||||
|
||||
### Passing extra params to litellm.completion
|
||||
|
@ -158,6 +158,34 @@ cog.out("```\n")
|
|||
system_prompt_prefix: null
|
||||
accepts_settings: null
|
||||
|
||||
- name: anthropic.claude-opus-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: 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,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: 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,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: anthropic/claude-3-5-haiku-20241022
|
||||
edit_format: diff
|
||||
weak_model_name: anthropic/claude-3-5-haiku-20241022
|
||||
|
@ -246,6 +274,34 @@ cog.out("```\n")
|
|||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25
|
||||
cache_control: true
|
||||
|
||||
- name: anthropic/claude-opus-4-20250514
|
||||
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,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: anthropic/claude-sonnet-4-20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: anthropic/claude-sonnet-4-20250514
|
||||
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,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: anthropic/claude-sonnet-4-20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: azure/gpt-4.1
|
||||
edit_format: diff
|
||||
weak_model_name: azure/gpt-4.1-mini
|
||||
|
@ -407,6 +463,20 @@ cog.out("```\n")
|
|||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: bedrock/anthropic.claude-sonnet-4-20250514-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,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock/anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock/us.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
|
@ -423,6 +493,20 @@ cog.out("```\n")
|
|||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock/us.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,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: bedrock_converse/anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
|
@ -439,6 +523,62 @@ cog.out("```\n")
|
|||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: bedrock_converse/anthropic.claude-opus-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/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,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock_converse/anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: bedrock_converse/anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/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,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock_converse/anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: bedrock_converse/eu.anthropic.claude-opus-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/eu.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,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock_converse/eu.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: bedrock_converse/eu.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/eu.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,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock_converse/eu.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: bedrock_converse/us.anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/us.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
|
@ -455,6 +595,34 @@ cog.out("```\n")
|
|||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: bedrock_converse/us.anthropic.claude-opus-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/us.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,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock_converse/us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: bedrock_converse/us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: bedrock_converse/us.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,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: bedrock_converse/us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: claude-3-5-haiku-20241022
|
||||
edit_format: diff
|
||||
weak_model_name: claude-3-5-haiku-20241022
|
||||
|
@ -538,6 +706,34 @@ cog.out("```\n")
|
|||
- name: claude-3-sonnet-20240229
|
||||
weak_model_name: claude-3-5-haiku-20241022
|
||||
|
||||
- name: claude-opus-4-20250514
|
||||
edit_format: diff
|
||||
weak_model_name: claude-3-5-haiku-20241022
|
||||
use_repo_map: true
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: claude-sonnet-4-20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: claude-sonnet-4-20250514
|
||||
edit_format: diff
|
||||
weak_model_name: claude-3-5-haiku-20241022
|
||||
use_repo_map: true
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: claude-sonnet-4-20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: cohere_chat/command-a-03-2025
|
||||
examples_as_sys_msg: true
|
||||
|
||||
|
@ -600,6 +796,34 @@ cog.out("```\n")
|
|||
editor_model_name: deepseek/deepseek-chat
|
||||
editor_edit_format: editor-diff
|
||||
|
||||
- name: eu.anthropic.claude-opus-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: eu.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,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: eu.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: eu.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: eu.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,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: eu.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: fireworks_ai/accounts/fireworks/models/deepseek-r1
|
||||
edit_format: diff
|
||||
weak_model_name: fireworks_ai/accounts/fireworks/models/deepseek-v3
|
||||
|
@ -1145,6 +1369,34 @@ cog.out("```\n")
|
|||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: openrouter/anthropic/claude-opus-4
|
||||
edit_format: diff
|
||||
weak_model_name: openrouter/anthropic/claude-3-5-haiku
|
||||
use_repo_map: true
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: openrouter/anthropic/claude-sonnet-4
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: openrouter/anthropic/claude-sonnet-4
|
||||
edit_format: diff
|
||||
weak_model_name: openrouter/anthropic/claude-3-5-haiku
|
||||
use_repo_map: true
|
||||
extra_params:
|
||||
extra_headers:
|
||||
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: openrouter/anthropic/claude-sonnet-4
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: openrouter/cohere/command-a-03-2025
|
||||
examples_as_sys_msg: true
|
||||
|
||||
|
@ -1434,6 +1686,34 @@ cog.out("```\n")
|
|||
accepts_settings:
|
||||
- reasoning_effort
|
||||
|
||||
- name: us.anthropic.claude-opus-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: us.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,output-128k-2025-02-19
|
||||
max_tokens: 32000
|
||||
cache_control: true
|
||||
editor_model_name: us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
edit_format: diff
|
||||
weak_model_name: us.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,output-128k-2025-02-19
|
||||
max_tokens: 64000
|
||||
cache_control: true
|
||||
editor_model_name: us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: vertex_ai-anthropic_models/vertex_ai/claude-3-7-sonnet@20250219
|
||||
edit_format: diff
|
||||
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
|
||||
|
@ -1447,6 +1727,28 @@ cog.out("```\n")
|
|||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: vertex_ai-anthropic_models/vertex_ai/claude-opus-4@20250514
|
||||
edit_format: diff
|
||||
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
|
||||
use_repo_map: true
|
||||
extra_params:
|
||||
max_tokens: 32000
|
||||
editor_model_name: vertex_ai-anthropic_models/vertex_ai/claude-sonnet-4@20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: vertex_ai-anthropic_models/vertex_ai/claude-sonnet-4@20250514
|
||||
edit_format: diff
|
||||
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
|
||||
use_repo_map: true
|
||||
extra_params:
|
||||
max_tokens: 64000
|
||||
editor_model_name: vertex_ai-anthropic_models/vertex_ai/claude-sonnet-4@20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
|
||||
edit_format: diff
|
||||
use_repo_map: true
|
||||
|
@ -1502,6 +1804,35 @@ cog.out("```\n")
|
|||
- name: vertex_ai/claude-3-sonnet@20240229
|
||||
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
|
||||
|
||||
- name: vertex_ai/claude-opus-4@20250514
|
||||
edit_format: diff
|
||||
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
|
||||
use_repo_map: true
|
||||
extra_params:
|
||||
max_tokens: 32000
|
||||
editor_model_name: vertex_ai/claude-sonnet-4@20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: vertex_ai/claude-sonnet-4@20250514
|
||||
edit_format: diff
|
||||
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
|
||||
use_repo_map: true
|
||||
extra_params:
|
||||
max_tokens: 64000
|
||||
editor_model_name: vertex_ai/claude-sonnet-4@20250514
|
||||
editor_edit_format: editor-diff
|
||||
accepts_settings:
|
||||
- thinking_tokens
|
||||
|
||||
- name: vertex_ai/gemini-2.5-flash-preview-05-20
|
||||
edit_format: diff
|
||||
use_repo_map: true
|
||||
accepts_settings:
|
||||
- reasoning_effort
|
||||
- thinking_tokens
|
||||
|
||||
- name: vertex_ai/gemini-2.5-pro-exp-03-25
|
||||
edit_format: diff-fenced
|
||||
weak_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
parent: Configuration
|
||||
nav_order: 15
|
||||
description: How to configure aider with a yaml config file.
|
||||
description: How to configure aider with a YAML config file.
|
||||
---
|
||||
|
||||
# YAML config file
|
||||
|
@ -58,7 +58,7 @@ cog.outl("```")
|
|||
# Place in your home dir, or at the root of your git repo.
|
||||
##########################################################
|
||||
|
||||
# Note: You can only put OpenAI and Anthropic API keys in the yaml
|
||||
# Note: You can only put OpenAI and Anthropic API keys in the YAML
|
||||
# config file. Keys for all APIs can be stored in a .env file
|
||||
# https://aider.chat/docs/config/dotenv.html
|
||||
|
||||
|
|
|
@ -40,9 +40,9 @@ OPENAI_API_KEY=<key>
|
|||
ANTHROPIC_API_KEY=<key>
|
||||
```
|
||||
|
||||
#### Yaml config file
|
||||
#### 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 config file](/docs/config/aider_conf.html), like this:
|
||||
|
||||
```yaml
|
||||
openai-api-key: <key>
|
||||
|
@ -74,7 +74,7 @@ OPENROUTER_API_KEY=bar
|
|||
DEEPSEEK_API_KEY=baz
|
||||
```
|
||||
|
||||
#### Yaml config file
|
||||
#### YAML config file
|
||||
|
||||
|
||||
You can also set API keys in the
|
||||
|
|
|
@ -12,7 +12,7 @@ Aider allows you to configure your preferred text editor for use with the `/edit
|
|||
|
||||
You can specify the text editor with the `--editor` switch or using
|
||||
`editor:` in aider's
|
||||
[yaml config file](https://aider.chat/docs/config/aider_conf.html).
|
||||
[YAML config file](https://aider.chat/docs/config/aider_conf.html).
|
||||
|
||||
## Environment variables
|
||||
|
||||
|
|
|
@ -86,10 +86,10 @@ for alias, model in sorted(MODEL_ALIASES.items()):
|
|||
- `grok3`: xai/grok-3-beta
|
||||
- `haiku`: claude-3-5-haiku-20241022
|
||||
- `optimus`: openrouter/openrouter/optimus-alpha
|
||||
- `opus`: claude-3-opus-20240229
|
||||
- `opus`: claude-opus-4-20250514
|
||||
- `quasar`: openrouter/openrouter/quasar-alpha
|
||||
- `r1`: deepseek/deepseek-reasoner
|
||||
- `sonnet`: anthropic/claude-3-7-sonnet-20250219
|
||||
- `sonnet`: anthropic/claude-sonnet-4-20250514
|
||||
<!--[[[end]]]-->
|
||||
|
||||
## Priority
|
||||
|
|
|
@ -264,9 +264,12 @@ tr:hover { background-color: #f5f5f5; }
|
|||
</style>
|
||||
<table>
|
||||
<tr><th>Model Name</th><th class='right'>Total Tokens</th><th class='right'>Percent</th></tr>
|
||||
<tr><td>gemini/gemini-2.5-pro-exp-03-25</td><td class='right'>1,253,243</td><td class='right'>90.6%</td></tr>
|
||||
<tr><td>o3</td><td class='right'>121,023</td><td class='right'>8.8%</td></tr>
|
||||
<tr><td>openrouter/REDACTED</td><td class='right'>8,745</td><td class='right'>0.6%</td></tr>
|
||||
<tr><td>o3</td><td class='right'>542,669</td><td class='right'>45.1%</td></tr>
|
||||
<tr><td>gemini/gemini-2.5-pro-exp-03-25</td><td class='right'>479,518</td><td class='right'>39.9%</td></tr>
|
||||
<tr><td>anthropic/claude-sonnet-4-20250514</td><td class='right'>131,972</td><td class='right'>11.0%</td></tr>
|
||||
<tr><td>gemini/gemini-2.5-pro-preview-05-06</td><td class='right'>40,256</td><td class='right'>3.3%</td></tr>
|
||||
<tr><td>gemini/gemini-2.5-flash-preview-05-20</td><td class='right'>7,638</td><td class='right'>0.6%</td></tr>
|
||||
<tr><td>gemini/REDACTED</td><td class='right'>643</td><td class='right'>0.1%</td></tr>
|
||||
</table>
|
||||
|
||||
{: .note :}
|
||||
|
|
|
@ -28,12 +28,6 @@ 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:
|
||||
|
@ -48,6 +42,12 @@ If your system doesn't have curl, you can use wget:
|
|||
wget -qO- https://aider.chat/install.sh | sh
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy ByPass -c "irm https://aider.chat/install.ps1 | iex"
|
||||
```
|
||||
|
||||
|
||||
## Install with uv
|
||||
|
||||
|
@ -55,7 +55,7 @@ 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
|
||||
uv tool install --force --python python3.12 --with pip aider-chat@latest
|
||||
```
|
||||
|
||||
This will install uv using your existing python version 3.8-3.13,
|
||||
|
|
|
@ -285,6 +285,6 @@ mod_dates = [get_last_modified_date(file) for file in files]
|
|||
latest_mod_date = max(mod_dates)
|
||||
cog.out(f"{latest_mod_date.strftime('%B %d, %Y.')}")
|
||||
]]]-->
|
||||
May 09, 2025.
|
||||
May 26, 2025.
|
||||
<!--[[[end]]]-->
|
||||
</p>
|
||||
|
|
105
aider/website/docs/llms/github.md
Normal file
105
aider/website/docs/llms/github.md
Normal file
|
@ -0,0 +1,105 @@
|
|||
---
|
||||
parent: Connecting to LLMs
|
||||
nav_order: 510
|
||||
---
|
||||
|
||||
# GitHub Copilot
|
||||
|
||||
Aider can connect to GitHub Copilot’s LLMs because Copilot exposes a standard **OpenAI-style**
|
||||
endpoint at:
|
||||
|
||||
```
|
||||
https://api.githubcopilot.com
|
||||
```
|
||||
|
||||
First, install aider:
|
||||
|
||||
{% include install.md %}
|
||||
|
||||
---
|
||||
|
||||
## Configure your environment
|
||||
|
||||
```bash
|
||||
# macOS/Linux
|
||||
export OPENAI_API_BASE=https://api.githubcopilot.com
|
||||
export OPENAI_API_KEY=<oauth_token>
|
||||
|
||||
# Windows (PowerShell)
|
||||
setx OPENAI_API_BASE https://api.githubcopilot.com
|
||||
setx OPENAI_API_KEY <oauth_token>
|
||||
# …restart the shell after setx commands
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Where do I get the token?
|
||||
The easiest path is to sign in to Copilot from any JetBrains IDE (PyCharm, GoLand, etc).
|
||||
After you authenticate a file appears:
|
||||
|
||||
```
|
||||
~/.config/github-copilot/apps.json
|
||||
```
|
||||
|
||||
Copy the `oauth_token` value – that string is your `OPENAI_API_KEY`.
|
||||
|
||||
*Note:* tokens created by the Neovim **copilot.lua** plugin (old `hosts.json`) sometimes lack the
|
||||
needed scopes. If you see “access to this endpoint is forbidden”, regenerate the token with a
|
||||
JetBrains IDE or the VS Code Copilot extension.
|
||||
|
||||
---
|
||||
|
||||
## Discover available models
|
||||
|
||||
Copilot hosts many models (OpenAI, Anthropic, Google, etc).
|
||||
List the models your subscription allows with:
|
||||
|
||||
```bash
|
||||
curl -s https://api.githubcopilot.com/models \
|
||||
-H "Authorization: Bearer $OPENAI_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Copilot-Integration-Id: vscode-chat" | jq -r '.data[].id'
|
||||
```
|
||||
|
||||
Each returned ID can be used with aider by **prefixing it with `openai/`**:
|
||||
|
||||
```bash
|
||||
aider --model openai/gpt-4o
|
||||
# or
|
||||
aider --model openai/claude-3.7-sonnet-thought
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
# change into your project
|
||||
cd /to/your/project
|
||||
|
||||
# talk to Copilot
|
||||
aider --model openai/gpt-4o
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Optional config file (`~/.aider.conf.yml`)
|
||||
|
||||
```yaml
|
||||
openai-api-base: https://api.githubcopilot.com
|
||||
openai-api-key: "<oauth_token>"
|
||||
model: openai/gpt-4o
|
||||
weak-model: openai/gpt-4o-mini
|
||||
show-model-warnings: false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## FAQ
|
||||
|
||||
* Calls made through aider are billed through your Copilot subscription
|
||||
(aider will still print *estimated* costs).
|
||||
* The Copilot docs explicitly allow third-party “agents” that hit this API – aider is playing by
|
||||
the rules.
|
||||
* Aider talks directly to the REST endpoint—no web-UI scraping or browser automation.
|
||||
|
|
@ -40,7 +40,7 @@ cd /to/your/project
|
|||
aider --model vertex_ai/claude-3-5-sonnet@20240620
|
||||
```
|
||||
|
||||
Or you can use the [yaml config](/docs/config/aider_conf.html) to set the model to any of the
|
||||
Or you can use the [YAML config](/docs/config/aider_conf.html) to set the model to any of the
|
||||
models supported by Vertex AI.
|
||||
|
||||
Example `.aider.conf.yml` file:
|
||||
|
|
|
@ -58,6 +58,9 @@ cog.out(model_list)
|
|||
- anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
- anthropic.claude-3-5-sonnet-20241022-v2:0
|
||||
- anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||
- anthropic.claude-opus-4-20250514-v1:0
|
||||
- anthropic.claude-sonnet-4-20250514-v1:0
|
||||
- azure_ai/mistral-medium-2505
|
||||
- claude-3-5-haiku-20241022
|
||||
- claude-3-5-haiku-latest
|
||||
- claude-3-5-sonnet-20240620
|
||||
|
@ -69,6 +72,8 @@ cog.out(model_list)
|
|||
- claude-3-opus-20240229
|
||||
- claude-3-opus-latest
|
||||
- claude-3-sonnet-20240229
|
||||
- claude-opus-4-20250514
|
||||
- claude-sonnet-4-20250514
|
||||
- codestral/codestral-2405
|
||||
- codestral/codestral-latest
|
||||
- databricks/databricks-claude-3-7-sonnet
|
||||
|
@ -77,15 +82,20 @@ cog.out(model_list)
|
|||
- deepseek/deepseek-reasoner
|
||||
- eu.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
- eu.anthropic.claude-3-5-sonnet-20241022-v2:0
|
||||
- eu.anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||
- eu.anthropic.claude-opus-4-20250514-v1:0
|
||||
- eu.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
- mistral/codestral-2405
|
||||
- mistral/codestral-latest
|
||||
- mistral/codestral-mamba-latest
|
||||
- mistral/devstral-small-2505
|
||||
- mistral/mistral-large-2402
|
||||
- mistral/mistral-large-2407
|
||||
- mistral/mistral-large-2411
|
||||
- mistral/mistral-large-latest
|
||||
- mistral/mistral-medium
|
||||
- mistral/mistral-medium-2312
|
||||
- mistral/mistral-medium-2505
|
||||
- mistral/mistral-medium-latest
|
||||
- mistral/mistral-small
|
||||
- mistral/mistral-small-latest
|
||||
|
@ -105,6 +115,8 @@ cog.out(model_list)
|
|||
- us.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||
- us.anthropic.claude-3-5-sonnet-20241022-v2:0
|
||||
- us.anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||
- us.anthropic.claude-opus-4-20250514-v1:0
|
||||
- us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||
- vertex_ai/claude-3-5-haiku
|
||||
- vertex_ai/claude-3-5-haiku@20241022
|
||||
- vertex_ai/claude-3-5-sonnet
|
||||
|
@ -118,6 +130,8 @@ cog.out(model_list)
|
|||
- vertex_ai/claude-3-opus@20240229
|
||||
- vertex_ai/claude-3-sonnet
|
||||
- vertex_ai/claude-3-sonnet@20240229
|
||||
- vertex_ai/claude-opus-4@20250514
|
||||
- vertex_ai/claude-sonnet-4@20250514
|
||||
<!--[[[end]]]-->
|
||||
|
||||
|
||||
|
|
|
@ -69,11 +69,11 @@ cog.out(text)
|
|||
]]]-->
|
||||
<a href="https://github.com/Aider-AI/aider" class="github-badge badge-stars" title="Total number of GitHub stars the Aider project has received">
|
||||
<span class="badge-label">⭐ GitHub Stars</span>
|
||||
<span class="badge-value">33K</span>
|
||||
<span class="badge-value">34K</span>
|
||||
</a>
|
||||
<a href="https://pypi.org/project/aider-chat/" class="github-badge badge-installs" title="Total number of installations via pip from PyPI">
|
||||
<span class="badge-label">📦 Installs</span>
|
||||
<span class="badge-value">2.2M</span>
|
||||
<span class="badge-value">2.4M</span>
|
||||
</a>
|
||||
<div class="github-badge badge-tokens" title="Number of tokens processed weekly by Aider users">
|
||||
<span class="badge-label">📈 Tokens/week</span>
|
||||
|
@ -85,7 +85,7 @@ cog.out(text)
|
|||
</a>
|
||||
<a href="/HISTORY.html" class="github-badge badge-coded" title="Percentage of the new code in Aider's last release written by Aider itself">
|
||||
<span class="badge-label">🔄 Singularity</span>
|
||||
<span class="badge-value">54%</span>
|
||||
<span class="badge-value">79%</span>
|
||||
</a>
|
||||
<!--[[[end]]]-->
|
||||
</div>
|
||||
|
@ -642,6 +642,7 @@ const testimonials = [
|
|||
<li><a href="/docs/leaderboards/">LLM Leaderboards</a></li>
|
||||
<li><a href="https://github.com/Aider-AI/aider">GitHub Repository</a></li>
|
||||
<li><a href="https://discord.gg/Y7X7bhMQFV">Discord Community</a></li>
|
||||
<li><a href="https://aider.chat/HISTORY.html">Release notes</a></li>
|
||||
<li><a href="/blog/">Blog</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -425,7 +425,7 @@ function Invoke-Installer($artifacts, $platforms) {
|
|||
|
||||
Write-Information ""
|
||||
Write-Information "Installing aider-chat..."
|
||||
& "$dest_dir\uv.exe" tool install --force --python python3.12 aider-chat@latest
|
||||
& "$dest_dir\uv.exe" tool install --force --python python3.12 --with pip aider-chat@latest
|
||||
|
||||
if (-not $NoModifyPath) {
|
||||
Add-Ci-Path $dest_dir
|
||||
|
|
|
@ -1178,7 +1178,7 @@ install() {
|
|||
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
|
||||
ensure "${_install_dir}/uv" tool install --force --python python3.12 --with pip aider-chat@latest
|
||||
|
||||
# Avoid modifying the users PATH if they are managing their PATH manually
|
||||
case :$PATH:
|
||||
|
|
|
@ -60,7 +60,7 @@ click==8.1.8
|
|||
# via
|
||||
# -c requirements/common-constraints.txt
|
||||
# litellm
|
||||
configargparse==1.7
|
||||
configargparse==1.7.1
|
||||
# via
|
||||
# -c requirements/common-constraints.txt
|
||||
# -r requirements/requirements.in
|
||||
|
|
|
@ -65,7 +65,7 @@ cogapp==3.4.1
|
|||
# via -r requirements/requirements-dev.in
|
||||
colorama==0.4.6
|
||||
# via griffe
|
||||
configargparse==1.7
|
||||
configargparse==1.7.1
|
||||
# via -r requirements/requirements.in
|
||||
contourpy==1.3.2
|
||||
# via matplotlib
|
||||
|
|
|
@ -46,3 +46,6 @@ scipy
|
|||
# https://github.com/pypa/twine/blob/6fbf880ee60915cf1666348c4bdd78a10415f2ac/twine/__init__.py#L40
|
||||
# Uses importlib-metadata
|
||||
importlib-metadata<8.0.0
|
||||
|
||||
# configargparse was 1.7 pulled
|
||||
configargparse>1.7
|
||||
|
|
|
@ -5,7 +5,7 @@ FROM bretfisher/jekyll-serve
|
|||
WORKDIR /site
|
||||
|
||||
# Copy the current directory contents into the container at /srv/jekyll
|
||||
COPY website /site
|
||||
COPY aider/website /site
|
||||
|
||||
RUN apt-get update && apt-get install libcurl4
|
||||
|
||||
|
|
|
@ -112,6 +112,8 @@ def main():
|
|||
|
||||
cmd = [
|
||||
"aider",
|
||||
"--model",
|
||||
"sonnet",
|
||||
hist_path,
|
||||
"--read",
|
||||
log_path,
|
||||
|
|
|
@ -834,6 +834,36 @@ two
|
|||
self.assertNotIn(fname2, str(coder.abs_fnames))
|
||||
self.assertNotIn(fname3, str(coder.abs_fnames))
|
||||
|
||||
def test_skip_gitignored_files_on_init(self):
|
||||
with GitTemporaryDirectory() as _:
|
||||
repo_path = Path(".")
|
||||
repo = git.Repo.init(repo_path)
|
||||
|
||||
ignored_file = repo_path / "ignored_by_git.txt"
|
||||
ignored_file.write_text("This file should be ignored by git.")
|
||||
|
||||
regular_file = repo_path / "regular_file.txt"
|
||||
regular_file.write_text("This is a regular file.")
|
||||
|
||||
gitignore_content = "ignored_by_git.txt\n"
|
||||
(repo_path / ".gitignore").write_text(gitignore_content)
|
||||
|
||||
repo.index.add([str(regular_file), ".gitignore"])
|
||||
repo.index.commit("Initial commit with gitignore and regular file")
|
||||
|
||||
mock_io = MagicMock()
|
||||
mock_io.tool_warning = MagicMock()
|
||||
|
||||
fnames_to_add = [str(ignored_file), str(regular_file)]
|
||||
|
||||
coder = Coder.create(self.GPT35, None, mock_io, fnames=fnames_to_add)
|
||||
|
||||
self.assertNotIn(str(ignored_file.resolve()), coder.abs_fnames)
|
||||
self.assertIn(str(regular_file.resolve()), coder.abs_fnames)
|
||||
mock_io.tool_warning.assert_any_call(
|
||||
f"Skipping {ignored_file.name} that matches gitignore spec."
|
||||
)
|
||||
|
||||
def test_check_for_urls(self):
|
||||
io = InputOutput(yes=True)
|
||||
coder = Coder.create(self.GPT35, None, io=io)
|
||||
|
|
|
@ -949,16 +949,19 @@ class TestMain(TestCase):
|
|||
|
||||
def test_invalid_edit_format(self):
|
||||
with GitTemporaryDirectory():
|
||||
with patch("aider.io.InputOutput.offer_url") as mock_offer_url:
|
||||
result = main(
|
||||
["--edit-format", "not-a-real-format", "--exit", "--yes"],
|
||||
input=DummyInput(),
|
||||
output=DummyOutput(),
|
||||
)
|
||||
self.assertEqual(result, 1) # main() should return 1 on error
|
||||
mock_offer_url.assert_called_once()
|
||||
args, _ = mock_offer_url.call_args
|
||||
self.assertEqual(args[0], "https://aider.chat/docs/more/edit-formats.html")
|
||||
# Suppress stderr for this test as argparse prints an error message
|
||||
with patch("sys.stderr", new_callable=StringIO) as mock_stderr:
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
_ = main(
|
||||
["--edit-format", "not-a-real-format", "--exit", "--yes"],
|
||||
input=DummyInput(),
|
||||
output=DummyOutput(),
|
||||
)
|
||||
# argparse.ArgumentParser.exit() is called with status 2 for invalid choice
|
||||
self.assertEqual(cm.exception.code, 2)
|
||||
stderr_output = mock_stderr.getvalue()
|
||||
self.assertIn("invalid choice", stderr_output)
|
||||
self.assertIn("not-a-real-format", stderr_output)
|
||||
|
||||
def test_default_model_selection(self):
|
||||
with GitTemporaryDirectory():
|
||||
|
@ -1275,6 +1278,21 @@ class TestMain(TestCase):
|
|||
for call in mock_io_instance.tool_warning.call_args_list:
|
||||
self.assertNotIn("Cost estimates may be inaccurate", call[0][0])
|
||||
|
||||
def test_argv_file_respects_git(self):
|
||||
with GitTemporaryDirectory():
|
||||
fname = Path("not_in_git.txt")
|
||||
fname.touch()
|
||||
with open(".gitignore", "w+") as f:
|
||||
f.write("not_in_git.txt")
|
||||
coder = main(
|
||||
argv=["--file", "not_in_git.txt"],
|
||||
input=DummyInput(),
|
||||
output=DummyOutput(),
|
||||
return_coder=True,
|
||||
)
|
||||
self.assertNotIn("not_in_git.txt", str(coder.abs_fnames))
|
||||
self.assertFalse(coder.allowed_to_edit("not_in_git.txt"))
|
||||
|
||||
def test_load_dotenv_files_override(self):
|
||||
with GitTemporaryDirectory() as git_dir:
|
||||
git_dir = Path(git_dir)
|
||||
|
|
|
@ -138,13 +138,13 @@ class TestModels(unittest.TestCase):
|
|||
self.assertEqual(model.name, "gpt-3.5-turbo")
|
||||
|
||||
model = Model("sonnet")
|
||||
self.assertEqual(model.name, "anthropic/claude-3-7-sonnet-20250219")
|
||||
self.assertEqual(model.name, "anthropic/claude-sonnet-4-20250514")
|
||||
|
||||
model = Model("haiku")
|
||||
self.assertEqual(model.name, "claude-3-5-haiku-20241022")
|
||||
|
||||
model = Model("opus")
|
||||
self.assertEqual(model.name, "claude-3-opus-20240229")
|
||||
self.assertEqual(model.name, "claude-opus-4-20250514")
|
||||
|
||||
# Test non-alias passes through unchanged
|
||||
model = Model("gpt-4")
|
||||
|
|
|
@ -93,16 +93,14 @@ class TestOnboarding(unittest.TestCase):
|
|||
@patch.dict(os.environ, {"OPENROUTER_API_KEY": "or_key"}, clear=True)
|
||||
def test_try_select_default_model_openrouter_free(self, mock_check_tier):
|
||||
"""Test OpenRouter free model selection."""
|
||||
self.assertEqual(
|
||||
try_to_select_default_model(), "openrouter/google/gemini-2.5-pro-exp-03-25:free"
|
||||
)
|
||||
self.assertEqual(try_to_select_default_model(), "openrouter/deepseek/deepseek-r1:free")
|
||||
mock_check_tier.assert_called_once_with("or_key")
|
||||
|
||||
@patch("aider.onboarding.check_openrouter_tier", return_value=False) # Assume paid tier
|
||||
@patch.dict(os.environ, {"OPENROUTER_API_KEY": "or_key"}, clear=True)
|
||||
def test_try_select_default_model_openrouter_paid(self, mock_check_tier):
|
||||
"""Test OpenRouter paid model selection."""
|
||||
self.assertEqual(try_to_select_default_model(), "openrouter/anthropic/claude-3.7-sonnet")
|
||||
self.assertEqual(try_to_select_default_model(), "openrouter/anthropic/claude-sonnet-4")
|
||||
mock_check_tier.assert_called_once_with("or_key")
|
||||
|
||||
@patch("aider.onboarding.check_openrouter_tier")
|
||||
|
@ -146,7 +144,7 @@ class TestOnboarding(unittest.TestCase):
|
|||
)
|
||||
def test_try_select_default_model_priority_openrouter(self, mock_check_tier):
|
||||
"""Test OpenRouter key takes priority."""
|
||||
self.assertEqual(try_to_select_default_model(), "openrouter/anthropic/claude-3.7-sonnet")
|
||||
self.assertEqual(try_to_select_default_model(), "openrouter/anthropic/claude-sonnet-4")
|
||||
mock_check_tier.assert_called_once_with("or_key")
|
||||
|
||||
@patch("aider.onboarding.check_openrouter_tier")
|
||||
|
@ -346,7 +344,7 @@ class TestOnboarding(unittest.TestCase):
|
|||
|
||||
@patch(
|
||||
"aider.onboarding.try_to_select_default_model",
|
||||
side_effect=[None, "openrouter/google/gemini-2.5-pro-exp-03-25:free"],
|
||||
side_effect=[None, "openrouter/deepseek/deepseek-r1:free"],
|
||||
) # Fails first, succeeds after oauth
|
||||
@patch(
|
||||
"aider.onboarding.offer_openrouter_oauth", return_value=True
|
||||
|
@ -360,7 +358,7 @@ class TestOnboarding(unittest.TestCase):
|
|||
|
||||
selected_model = select_default_model(args, io_mock, analytics_mock)
|
||||
|
||||
self.assertEqual(selected_model, "openrouter/google/gemini-2.5-pro-exp-03-25:free")
|
||||
self.assertEqual(selected_model, "openrouter/deepseek/deepseek-r1:free")
|
||||
self.assertEqual(mock_try_select.call_count, 2) # Called before and after oauth
|
||||
mock_offer_oauth.assert_called_once_with(io_mock, analytics_mock)
|
||||
# Only one warning is expected: "No LLM model..."
|
||||
|
|
73
tests/basic/test_openrouter.py
Normal file
73
tests/basic/test_openrouter.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
from pathlib import Path
|
||||
|
||||
from aider.models import ModelInfoManager
|
||||
from aider.openrouter import OpenRouterModelManager
|
||||
|
||||
|
||||
class DummyResponse:
|
||||
"""Minimal stand-in for requests.Response used in tests."""
|
||||
|
||||
def __init__(self, json_data):
|
||||
self.status_code = 200
|
||||
self._json_data = json_data
|
||||
|
||||
def json(self):
|
||||
return self._json_data
|
||||
|
||||
|
||||
def test_openrouter_get_model_info_from_cache(monkeypatch, tmp_path):
|
||||
"""
|
||||
OpenRouterModelManager should return correct metadata taken from the
|
||||
downloaded (and locally cached) models JSON payload.
|
||||
"""
|
||||
payload = {
|
||||
"data": [
|
||||
{
|
||||
"id": "mistralai/mistral-medium-3",
|
||||
"context_length": 32768,
|
||||
"pricing": {"prompt": "100", "completion": "200"},
|
||||
"top_provider": {"context_length": 32768},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Fake out the network call and the HOME directory used for the cache file
|
||||
monkeypatch.setattr("requests.get", lambda *a, **k: DummyResponse(payload))
|
||||
monkeypatch.setattr(Path, "home", staticmethod(lambda: tmp_path))
|
||||
|
||||
manager = OpenRouterModelManager()
|
||||
info = manager.get_model_info("openrouter/mistralai/mistral-medium-3")
|
||||
|
||||
assert info["max_input_tokens"] == 32768
|
||||
assert info["input_cost_per_token"] == 100.0
|
||||
assert info["output_cost_per_token"] == 200.0
|
||||
assert info["litellm_provider"] == "openrouter"
|
||||
|
||||
|
||||
def test_model_info_manager_uses_openrouter_manager(monkeypatch):
|
||||
"""
|
||||
ModelInfoManager should delegate to OpenRouterModelManager when litellm
|
||||
provides no data for an OpenRouter-prefixed model.
|
||||
"""
|
||||
# Ensure litellm path returns no info so that fallback logic triggers
|
||||
monkeypatch.setattr("aider.models.litellm.get_model_info", lambda *a, **k: {})
|
||||
|
||||
stub_info = {
|
||||
"max_input_tokens": 512,
|
||||
"max_tokens": 512,
|
||||
"max_output_tokens": 512,
|
||||
"input_cost_per_token": 100.0,
|
||||
"output_cost_per_token": 200.0,
|
||||
"litellm_provider": "openrouter",
|
||||
}
|
||||
|
||||
# Force OpenRouterModelManager to return our stub info
|
||||
monkeypatch.setattr(
|
||||
"aider.models.OpenRouterModelManager.get_model_info",
|
||||
lambda self, model: stub_info,
|
||||
)
|
||||
|
||||
mim = ModelInfoManager()
|
||||
info = mim.get_model_info("openrouter/fake/model")
|
||||
|
||||
assert info == stub_info
|
Loading…
Add table
Add a link
Reference in a new issue