Merge branch 'main' into fix-flake8

This commit is contained in:
Paul Gauthier 2024-06-21 17:01:57 -07:00
commit 10ab57779a
44 changed files with 1249 additions and 188 deletions

View file

@ -1,5 +1,5 @@
repos:
- repo: https://github.com/pycqa/isort
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort

View file

@ -1,6 +1,13 @@
# Release history
### v0.39.0
- Use `--sonnet` for Claude 3.5 Sonnet, which is the top model on [aider's LLM code editing leaderboard](https://aider.chat/docs/leaderboards/#claude-35-sonnet-takes-the-top-spot).
- All `AIDER_xxx` environment variables can now be set in `.env` (by @jpshack-at-palomar).
- Use `--llm-history-file` to log raw messages sent to the LLM (by @daniel-vainsencher).
- Commit messages are no longer prefixed with "aider:". Instead the git author and committer names have "(aider)" added.
### v0.38.0
- Use `--vim` for [vim keybindings](https://aider.chat/docs/commands.html#vi) in the chat.

View file

@ -6,8 +6,8 @@
Aider lets you pair program with LLMs,
to edit code in your local git repository.
Start a new project or work with an existing git repo.
Aider works best with GPT-4o and Claude 3 Opus
and can [connect to almost any LLM](https://aider.chat/docs/llms.html).
Aider can [connect to almost any LLM](https://aider.chat/docs/llms.html).
and works best with GPT-4o, Claude 3.5 Sonnet, Claude 3 Opus and DeepSeek Coder V2.
<p align="center">
<img
@ -43,9 +43,14 @@ $ cd /to/your/git/repo
$ export OPENAI_API_KEY=your-key-goes-here
$ aider
# Or, work with Claude 3 Opus on your repo
# Or, work with Anthropic's models
$ export ANTHROPIC_API_KEY=your-key-goes-here
# Claude 3 Opus
$ aider --opus
# Claude 3.5 Sonnet
$ aider --sonnet
```
<!--[[[end]]]-->
@ -79,20 +84,13 @@ Pair program with AI.
- [Code with your voice](https://aider.chat/docs/voice.html).
## State of the art
## Top tier performance
Aider has the
[top score on SWE Bench](https://aider.chat/2024/06/02/main-swe-bench.html).
[Aider has the one of the top scores on SWE Bench](https://aider.chat/2024/06/02/main-swe-bench.html).
SWE Bench is a challenging software engineering benchmark where aider
solved *real* GitHub issues from popular open source
projects like django, scikitlearn, matplotlib, etc.
<p align="center">
<a href="https://aider.chat/2024/06/02/main-swe-bench.html">
<img src="https://aider.chat/assets/swe_bench.svg" alt="aider swe bench">
</a>
</p>
## More info
- [Documentation](https://aider.chat/)

View file

@ -1 +1 @@
__version__ = "0.38.1-dev"
__version__ = "0.39.1-dev"

4
aider/__main__.py Normal file
View file

@ -0,0 +1,4 @@
from .main import main
if __name__ == "__main__":
main()

View file

@ -7,11 +7,30 @@ import sys
import configargparse
from aider import __version__, models
from aider.args_formatter import MarkdownHelpFormatter, YamlHelpFormatter
from aider.args_formatter import (
DotEnvFormatter,
MarkdownHelpFormatter,
YamlHelpFormatter,
)
from .dump import dump # noqa: F401
def default_env_file(git_root):
return os.path.join(git_root, ".env") if git_root else ".env"
def get_preparser(git_root):
parser = configargparse.ArgumentParser(add_help=False)
parser.add_argument(
"--env-file",
metavar="ENV_FILE",
default=default_env_file(git_root),
help="Specify the .env file to load (default: .env in git root)",
)
return parser
def get_parser(default_config_files, git_root):
parser = configargparse.ArgumentParser(
description="aider is GPT powered coding in your terminal",
@ -28,10 +47,7 @@ def get_parser(default_config_files, git_root):
help="Log the conversation with the LLM to this file (for example, .aider.llm.history)",
)
group.add_argument(
"files",
metavar="FILE",
nargs="*",
help="files to edit with an LLM (optional)"
"files", metavar="FILE", nargs="*", help="files to edit with an LLM (optional)"
)
group.add_argument(
"--openai-api-key",
@ -60,7 +76,7 @@ def get_parser(default_config_files, git_root):
const=opus_model,
help=f"Use {opus_model} model for the main chat",
)
sonnet_model = "claude-3-sonnet-20240229"
sonnet_model = "claude-3-5-sonnet-20240620"
group.add_argument(
"--sonnet",
action="store_const",
@ -142,12 +158,24 @@ def get_parser(default_config_files, git_root):
env_var="OPENAI_ORGANIZATION_ID",
help="Specify the OpenAI organization ID",
)
group.add_argument(
"--model-settings-file",
metavar="MODEL_SETTINGS_FILE",
default=None,
help="Specify a file with aider model settings for unknown models",
)
group.add_argument(
"--model-metadata-file",
metavar="MODEL_FILE",
metavar="MODEL_METADATA_FILE",
default=None,
help="Specify a file with context window and costs for unknown models",
)
group.add_argument(
"--verify-ssl",
action=argparse.BooleanOptionalAction,
default=True,
help="Verify the SSL cert when connecting to models (default: True)",
)
group.add_argument(
"--edit-format",
metavar="EDIT_FORMAT",
@ -184,11 +212,12 @@ def get_parser(default_config_files, git_root):
" max_chat_history_tokens."
),
)
default_env_file = os.path.join(git_root, ".env") if git_root else ".env"
# This is a duplicate of the argument in the preparser and is a no-op by this time of
# argument parsing, but it's here so that the help is displayed as expected.
group.add_argument(
"--env-file",
metavar="ENV_FILE",
default=default_env_file,
default=default_env_file(git_root),
help="Specify the .env file to load (default: .env in git root)",
)
@ -501,11 +530,27 @@ def get_sample_yaml():
return parser.format_help()
def get_sample_dotenv():
os.environ["COLUMNS"] = "120"
sys.argv = ["aider"]
parser = get_parser([], None)
# This instantiates all the action.env_var values
parser.parse_known_args()
parser.formatter_class = DotEnvFormatter
return argparse.ArgumentParser.format_help(parser)
return parser.format_help()
def main():
arg = sys.argv[1] if len(sys.argv[1:]) else None
if arg == "md":
print(get_md_help())
elif arg == "dotenv":
print(get_sample_dotenv())
else:
print(get_sample_yaml())

View file

@ -1,8 +1,83 @@
import argparse
from aider import urls
from .dump import dump # noqa: F401
class DotEnvFormatter(argparse.HelpFormatter):
def start_section(self, heading):
res = "\n\n"
res += "#" * (len(heading) + 3)
res += f"\n# {heading}"
super().start_section(res)
def _format_usage(self, usage, actions, groups, prefix):
return ""
def _format_text(self, text):
return f"""
##########################################################
# Sample aider .env file.
# Place at the root of your git repo.
# Or use `aider --env <fname>` to specify.
##########################################################
#################
# LLM parameters:
#
# Include xxx_API_KEY parameters and other params needed for your LLMs.
# See {urls.llms} for details.
## OpenAI
#OPENAI_API_KEY=
## Anthropic
#ANTHROPIC_API_KEY=
##...
"""
def _format_action(self, action):
if not action.option_strings:
return ""
if not action.env_var:
return
parts = [""]
default = action.default
if default == argparse.SUPPRESS:
default = ""
elif isinstance(default, str):
pass
elif isinstance(default, list) and not default:
default = ""
elif action.default is not None:
default = "true" if default else "false"
else:
default = ""
if action.help:
parts.append(f"## {action.help}")
if action.env_var:
env_var = action.env_var
if default:
parts.append(f"#{env_var}={default}\n")
else:
parts.append(f"#{env_var}=\n")
return "\n".join(parts) + "\n"
def _format_action_invocation(self, action):
return ""
def _format_args(self, action, default_metavar):
return ""
class YamlHelpFormatter(argparse.HelpFormatter):
def start_section(self, heading):
res = "\n\n"

View file

@ -913,9 +913,9 @@ class Coder:
res = ["", ""]
res.append(f"Model {self.main_model.name} has hit a token limit!")
res.append("")
res.append(f"Input tokens: {input_tokens} of {max_input_tokens}{inp_err}")
res.append(f"Output tokens: {output_tokens} of {max_output_tokens}{out_err}")
res.append(f"Total tokens: {total_tokens} of {max_input_tokens}{tot_err}")
res.append(f"Input tokens: {input_tokens:,} of {max_input_tokens:,}{inp_err}")
res.append(f"Output tokens: {output_tokens:,} of {max_output_tokens:,}{out_err}")
res.append(f"Total tokens: {total_tokens:,} of {max_input_tokens:,}{tot_err}")
if output_tokens >= max_output_tokens:
res.append("")

View file

@ -414,16 +414,8 @@ def find_original_update_blocks(content, fence=DEFAULT_FENCE):
processed.append(cur) # original_marker
filename = strip_filename(processed[-2].splitlines()[-1], fence)
try:
if not filename:
filename = strip_filename(processed[-2].splitlines()[-2], fence)
if not filename:
if current_filename:
filename = current_filename
else:
raise ValueError(missing_filename_err.format(fence=fence))
except IndexError:
filename = find_filename(processed[-2].splitlines(), fence)
if not filename:
if current_filename:
filename = current_filename
else:
@ -460,6 +452,35 @@ def find_original_update_blocks(content, fence=DEFAULT_FENCE):
raise ValueError(f"{processed}\n^^^ Error parsing SEARCH/REPLACE block.")
def find_filename(lines, fence):
"""
Deepseek Coder v2 has been doing this:
```python
word_count.py
```
```python
<<<<<<< SEARCH
...
This is a more flexible search back for filenames.
"""
# Go back through the 3 preceding lines
lines.reverse()
lines = lines[:3]
for line in lines:
# If we find a filename, done
filename = strip_filename(line, fence)
if filename:
return filename
# Only continue as long as we keep seeing fences
if not line.startswith(fence[0]):
return
if __name__ == "__main__":
edit = """
Here's the change:

View file

@ -332,7 +332,7 @@ class Commands:
last_commit = self.coder.repo.repo.head.commit
if (
not last_commit.message.startswith("aider:")
not last_commit.author.name.endswith(" (aider)")
or last_commit.hexsha[:7] != self.coder.last_aider_commit_hash
):
self.io.tool_error("The last commit was not made by aider in this chat session.")

View file

@ -5,12 +5,13 @@ import sys
from pathlib import Path
import git
import httpx
from dotenv import load_dotenv
from prompt_toolkit.enums import EditingMode
from streamlit.web import cli
from aider import __version__, models, utils
from aider.args import get_parser
from aider.args import get_parser, get_preparser
from aider.coders import Coder
from aider.commands import SwitchModel
from aider.io import InputOutput
@ -124,12 +125,18 @@ def check_gitignore(git_root, io, ask=True):
def format_settings(parser, args):
show = scrub_sensitive_info(args, parser.format_values())
# clean up the headings for consistency w/ new lines
heading_env = "Environment Variables:"
heading_defaults = "Defaults:"
if heading_env in show:
show = show.replace(heading_env, "\n" + heading_env)
show = show.replace(heading_defaults, "\n" + heading_defaults)
show += "\n"
show += "Option settings:\n"
for arg, val in sorted(vars(args).items()):
if val:
val = scrub_sensitive_info(args, str(val))
show += f" - {arg}: {val}\n"
show += f" - {arg}: {val}\n" # noqa: E221
return show
@ -205,7 +212,48 @@ def parse_lint_cmds(lint_cmds, io):
return
return res
def generate_search_path_list(default_fname, git_root, command_line_file):
files = []
default_file = Path(default_fname)
files.append(Path.home() / default_file) # homedir
if git_root:
files.append(Path(git_root) / default_file) # git root
if command_line_file:
files.append(command_line_file)
files.append(default_file.resolve())
files = list(map(str, files))
files = list(dict.fromkeys(files))
return files
def register_models(git_root, model_settings_fname, io):
model_settings_files = generate_search_path_list(".aider.models.yml", git_root, model_settings_fname)
try:
files_loaded = models.register_models(model_settings_files)
if len(files_loaded) > 0:
io.tool_output(f"Loaded {len(files_loaded)} model settings file(s)")
for file_loaded in files_loaded:
io.tool_output(f" - {file_loaded}")
except Exception as e:
io.tool_error(f"Error loading aider model settings: {e}")
return 1
return None
def register_litellm_models(git_root, model_metadata_fname, io):
model_metatdata_files = generate_search_path_list(".aider.litellm.models.json", git_root, model_metadata_fname)
try:
model_metadata_files_loaded = models.register_litellm_models(model_metatdata_files)
if len(model_metadata_files_loaded) > 0:
io.tool_output(f"Loaded {len(model_metadata_files_loaded)} litellm model file(s)")
for model_metadata_file in model_metadata_files_loaded:
io.tool_output(f" - {model_metadata_file}")
except Exception as e:
io.tool_error(f"Error loading litellm models: {e}")
return 1
def main(argv=None, input=None, output=None, force_git_root=None, return_coder=False):
if argv is None:
argv = sys.argv[1:]
@ -225,9 +273,18 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
default_config_files.append(Path.home() / conf_fname) # homedir
default_config_files = list(map(str, default_config_files))
preparser = get_preparser(git_root)
pre_args, _ = preparser.parse_known_args(argv)
# Load the .env file specified in the arguments
load_dotenv(pre_args.env_file)
parser = get_parser(default_config_files, git_root)
args = parser.parse_args(argv)
if not args.verify_ssl:
litellm.client_session = httpx.Client(verify=False)
if args.gui and not return_coder:
launch_gui(argv)
return
@ -320,9 +377,6 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
cmd_line = scrub_sensitive_info(args, cmd_line)
io.tool_output(cmd_line, log_only=True)
if args.env_file:
load_dotenv(args.env_file)
if args.anthropic_api_key:
os.environ["ANTHROPIC_API_KEY"] = args.anthropic_api_key
@ -337,26 +391,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if args.openai_organization_id:
os.environ["OPENAI_ORGANIZATION"] = args.openai_organization_id
model_def_files = []
model_def_fname = Path(".aider.models.json")
model_def_files.append(Path.home() / model_def_fname) # homedir
if git_root:
model_def_files.append(Path(git_root) / model_def_fname) # git root
if args.model_metadata_file:
model_def_files.append(args.model_metadata_file)
model_def_files.append(model_def_fname.resolve())
model_def_files = list(map(str, model_def_files))
model_def_files = list(dict.fromkeys(model_def_files))
try:
model_metadata_files_loaded = models.register_models(model_def_files)
if len(model_metadata_files_loaded) > 0:
io.tool_output(f"Loaded {len(model_metadata_files_loaded)} model file(s)")
for model_metadata_file in model_metadata_files_loaded:
io.tool_output(f" - {model_metadata_file}")
except Exception as e:
io.tool_error(f"Error loading model info/cost: {e}")
return 1
register_models(git_root, args.model_settings_file, io)
register_litellm_models(git_root, args.model_metadata_file, io)
main_model = models.Model(args.model, weak_model=args.weak_model)
lint_cmds = parse_lint_cmds(args.lint_cmd, io)

View file

@ -1,5 +1,6 @@
import difflib
import json
import yaml
import math
import os
import sys
@ -178,6 +179,43 @@ MODEL_SETTINGS = [
"whole",
weak_model_name="claude-3-haiku-20240307",
),
ModelSettings(
"claude-3-5-sonnet-20240620",
"diff",
weak_model_name="claude-3-haiku-20240307",
use_repo_map=True,
),
ModelSettings(
"anthropic/claude-3-5-sonnet-20240620",
"diff",
weak_model_name="claude-3-haiku-20240307",
use_repo_map=True,
),
ModelSettings(
"openrouter/anthropic/claude-3.5-sonnet",
"diff",
weak_model_name="openrouter/anthropic/claude-3-haiku-20240307",
use_repo_map=True,
),
# Vertex AI Claude models
ModelSettings(
"vertex_ai/claude-3-5-sonnet@20240620",
"diff",
weak_model_name="vertex_ai/claude-3-haiku@20240307",
use_repo_map=True,
),
ModelSettings(
"vertex_ai/claude-3-opus@20240229",
"diff",
weak_model_name="vertex_ai/claude-3-haiku@20240307",
use_repo_map=True,
send_undo_reply=True,
),
ModelSettings(
"vertex_ai/claude-3-sonnet@20240229",
"whole",
weak_model_name="vertex_ai/claude-3-haiku@20240307",
),
# Cohere
ModelSettings(
"command-r-plus",
@ -218,7 +256,7 @@ MODEL_SETTINGS = [
send_undo_reply=True,
),
ModelSettings(
"openai/deepseek-chat",
"deepseek/deepseek-chat",
"diff",
use_repo_map=True,
send_undo_reply=True,
@ -226,7 +264,15 @@ MODEL_SETTINGS = [
reminder_as_sys_msg=True,
),
ModelSettings(
"deepseek/deepseek-chat",
"deepseek/deepseek-coder",
"diff",
use_repo_map=True,
send_undo_reply=True,
examples_as_sys_msg=True,
reminder_as_sys_msg=True,
),
ModelSettings(
"openrouter/deepseek/deepseek-coder",
"diff",
use_repo_map=True,
send_undo_reply=True,
@ -425,23 +471,47 @@ class Model:
return validate_variables(["GROQ_API_KEY"])
return res
def register_models(model_def_fnames):
model_metadata_files_loaded = []
for model_def_fname in model_def_fnames:
if not os.path.exists(model_def_fname):
def register_models(model_settings_fnames):
files_loaded = []
for model_settings_fname in model_settings_fnames:
if not os.path.exists(model_settings_fname):
continue
model_metadata_files_loaded.append(model_def_fname)
try:
with open(model_def_fname, "r") as model_def_file:
with open(model_settings_fname, "r") as model_settings_file:
model_settings_list = yaml.safe_load(model_settings_file)
for model_settings_dict in model_settings_list:
model_settings = ModelSettings(**model_settings_dict)
existing_model_settings = next((ms for ms in MODEL_SETTINGS if ms.name == model_settings.name), None)
if existing_model_settings:
MODEL_SETTINGS.remove(existing_model_settings)
MODEL_SETTINGS.append(model_settings)
except Exception as e:
raise Exception(f"Error loading model settings from {model_settings_fname}: {e}")
files_loaded.append(model_settings_fname)
return files_loaded
def register_litellm_models(model_fnames):
files_loaded = []
for model_fname in model_fnames:
if not os.path.exists(model_fname):
continue
try:
with open(model_fname, "r") as model_def_file:
model_def = json.load(model_def_file)
except json.JSONDecodeError as e:
raise Exception(f"Error loading model definition from {model_def_fname}: {e}")
litellm.register_model(model_def)
except Exception as e:
raise Exception(f"Error loading model definition from {model_fname}: {e}")
files_loaded.append(model_fname)
litellm.register_model(model_def)
return model_metadata_files_loaded
return files_loaded
def validate_variables(vars):

View file

@ -88,11 +88,15 @@ class GitRepo:
else:
cmd += ["-a"]
original_user_name = self.repo.config_reader().get_value("user", "name")
original_committer_name_env = os.environ.get("GIT_COMMITTER_NAME")
committer_name = f"{original_user_name} (aider)"
os.environ["GIT_COMMITTER_NAME"] = committer_name
if aider_edits:
user_name = self.repo.config_reader().get_value("user", "name")
committer_name = f"{user_name} (aider)"
original_committer_name = os.environ.get("GIT_COMMITTER_NAME")
os.environ["GIT_COMMITTER_NAME"] = committer_name
original_auther_name_env = os.environ.get("GIT_AUTHOR_NAME")
os.environ["GIT_AUTHOR_NAME"] = committer_name
self.repo.git.commit(cmd)
commit_hash = self.repo.head.commit.hexsha[:7]
@ -100,10 +104,15 @@ class GitRepo:
# Restore the original GIT_COMMITTER_NAME
if aider_edits:
if original_committer_name is not None:
os.environ["GIT_COMMITTER_NAME"] = original_committer_name
if original_auther_name_env is not None:
os.environ["GIT_AUTHOR_NAME"] = original_auther_name_env
else:
del os.environ["GIT_COMMITTER_NAME"]
del os.environ["GIT_AUTHOR_NAME"]
if original_committer_name_env is not None:
os.environ["GIT_COMMITTER_NAME"] = original_committer_name_env
else:
del os.environ["GIT_COMMITTER_NAME"]
return commit_hash, commit_message

View file

@ -523,16 +523,20 @@ class TestCommands(TestCase):
other_path.write_text("other content")
repo.git.add(str(other_path))
os.environ["GIT_AUTHOR_NAME"] = "Foo (aider)"
# Create and commit a file
filename = "test_file.txt"
file_path = Path(repo_dir) / filename
file_path.write_text("first content")
repo.git.add(filename)
repo.git.commit("-m", "aider: first commit")
repo.git.commit("-m", "first commit")
file_path.write_text("second content")
repo.git.add(filename)
repo.git.commit("-m", "aider: second commit")
repo.git.commit("-m", "second commit")
del os.environ["GIT_AUTHOR_NAME"]
# Store the commit hash
last_commit_hash = repo.head.commit.hexsha[:7]

View file

@ -398,6 +398,32 @@ Hope you like it!
],
)
def test_deepseek_coder_v2_filename_mangling(self):
edit = """
Here's the change:
```python
foo.txt
```
```python
<<<<<<< SEARCH
one
=======
two
>>>>>>> REPLACE
```
Hope you like it!
"""
edits = list(eb.find_original_update_blocks(edit))
self.assertEqual(
edits,
[
("foo.txt", "one\n", "two\n"),
],
)
if __name__ == "__main__":
unittest.main()

View file

@ -1,7 +1,7 @@
import os
import shutil
import subprocess
import tempfile
from io import StringIO
from pathlib import Path
from unittest import TestCase
from unittest.mock import MagicMock, patch
@ -13,24 +13,28 @@ from prompt_toolkit.output import DummyOutput
from aider.dump import dump # noqa: F401
from aider.io import InputOutput
from aider.main import check_gitignore, main, setup_git
from aider.utils import GitTemporaryDirectory, make_repo
from aider.utils import GitTemporaryDirectory, IgnorantTemporaryDirectory, make_repo
class TestMain(TestCase):
def setUp(self):
self.original_env = os.environ.copy()
os.environ["OPENAI_API_KEY"] = "deadbeef"
self.original_cwd = os.getcwd()
self.tempdir = tempfile.mkdtemp()
self.tempdir_obj = IgnorantTemporaryDirectory()
self.tempdir = self.tempdir_obj.name
os.chdir(self.tempdir)
def tearDown(self):
os.chdir(self.original_cwd)
shutil.rmtree(self.tempdir, ignore_errors=True)
self.tempdir_obj.cleanup()
os.environ.clear()
os.environ.update(self.original_env)
def test_main_with_empty_dir_no_files_on_command(self):
main(["--no-git"], input=DummyInput(), output=DummyOutput())
def test_main_with_empty_dir_new_file(self):
def test_main_with_emptqy_dir_new_file(self):
main(["foo.txt", "--yes", "--no-git"], input=DummyInput(), output=DummyOutput())
self.assertTrue(os.path.exists("foo.txt"))
@ -237,3 +241,82 @@ class TestMain(TestCase):
main(["--message", test_message])
args, kwargs = MockInputOutput.call_args
self.assertEqual(args[1], None)
def test_dark_mode_sets_code_theme(self):
# Mock Coder.create to capture the configuration
with patch("aider.coders.Coder.create") as MockCoder:
main(["--dark-mode", "--no-git"], input=DummyInput(), output=DummyOutput())
# Ensure Coder.create was called
MockCoder.assert_called_once()
# Check if the code_theme setting is for dark mode
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["code_theme"], "monokai")
def test_light_mode_sets_code_theme(self):
# Mock Coder.create to capture the configuration
with patch("aider.coders.Coder.create") as MockCoder:
main(["--light-mode", "--no-git"], input=DummyInput(), output=DummyOutput())
# Ensure Coder.create was called
MockCoder.assert_called_once()
# Check if the code_theme setting is for light mode
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["code_theme"], "default")
def create_env_file(self, file_name, content):
env_file_path = Path(self.tempdir) / file_name
env_file_path.write_text(content)
return env_file_path
def test_env_file_flag_sets_automatic_variable(self):
env_file_path = self.create_env_file(".env.test", "AIDER_DARK_MODE=True")
with patch("aider.coders.Coder.create") as MockCoder:
main(
["--env-file", str(env_file_path), "--no-git"],
input=DummyInput(),
output=DummyOutput(),
)
MockCoder.assert_called_once()
# Check if the color settings are for dark mode
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["code_theme"], "monokai")
def test_default_env_file_sets_automatic_variable(self):
self.create_env_file(".env", "AIDER_DARK_MODE=True")
with patch("aider.coders.Coder.create") as MockCoder:
main(["--no-git"], input=DummyInput(), output=DummyOutput())
# Ensure Coder.create was called
MockCoder.assert_called_once()
# Check if the color settings are for dark mode
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["code_theme"], "monokai")
def test_false_vals_in_env_file(self):
self.create_env_file(".env", "AIDER_SHOW_DIFFS=off")
with patch("aider.coders.Coder.create") as MockCoder:
main(["--no-git"], input=DummyInput(), output=DummyOutput())
MockCoder.assert_called_once()
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["show_diffs"], False)
def test_true_vals_in_env_file(self):
self.create_env_file(".env", "AIDER_SHOW_DIFFS=on")
with patch("aider.coders.Coder.create") as MockCoder:
main(["--no-git"], input=DummyInput(), output=DummyOutput())
MockCoder.assert_called_once()
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["show_diffs"], True)
def test_verbose_mode_lists_env_vars(self):
self.create_env_file(".env", "AIDER_DARK_MODE=on")
with patch("sys.stdout", new_callable=StringIO) as mock_stdout:
main(["--no-git", "--verbose"], input=DummyInput(), output=DummyOutput())
output = mock_stdout.getvalue()
relevant_output = "\n".join(
line
for line in output.splitlines()
if "AIDER_DARK_MODE" in line or "dark_mode" in line
) # this bit just helps failing assertions to be easier to read
self.assertIn("AIDER_DARK_MODE", relevant_output)
self.assertIn("dark_mode", relevant_output)
self.assertRegex(relevant_output, r"AIDER_DARK_MODE:\s+on")
self.assertRegex(relevant_output, r"dark_mode:\s+True")

View file

@ -1,4 +1,5 @@
import os
import platform
import tempfile
import unittest
from pathlib import Path
@ -141,6 +142,10 @@ class TestRepo(unittest.TestCase):
def test_commit_with_custom_committer_name(self, mock_send):
mock_send.return_value = '"a good commit message"'
# Cleanup of the git temp dir explodes on windows
if platform.system() == "Windows":
return
with GitTemporaryDirectory():
# new repo
raw_repo = git.Repo()
@ -152,7 +157,8 @@ class TestRepo(unittest.TestCase):
raw_repo.git.add(str(fname))
raw_repo.git.commit("-m", "initial commit")
git_repo = GitRepo(InputOutput(), None, None)
io = InputOutput()
git_repo = GitRepo(io, None, None)
# commit a change
fname.write_text("new content")
@ -160,11 +166,23 @@ class TestRepo(unittest.TestCase):
# check the committer name
commit = raw_repo.head.commit
self.assertEqual(commit.author.name, "Test User (aider)")
self.assertEqual(commit.committer.name, "Test User (aider)")
# commit a change without aider_edits
fname.write_text("new content again!")
git_repo.commit(fnames=[str(fname)], aider_edits=False)
# check the committer name
commit = raw_repo.head.commit
self.assertEqual(commit.author.name, "Test User")
self.assertEqual(commit.committer.name, "Test User (aider)")
# check that the original committer name is restored
original_committer_name = os.environ.get("GIT_COMMITTER_NAME")
self.assertIsNone(original_committer_name)
original_author_name = os.environ.get("GIT_AUTHOR_NAME")
self.assertIsNone(original_author_name)
def test_get_tracked_files(self):
# Create a temporary directory

View file

@ -6,3 +6,4 @@ enable_playwright = "https://aider.chat/docs/install/optional.html#enable-playwr
favicon = "https://aider.chat/assets/icons/favicon-32x32.png"
model_warnings = "https://aider.chat/docs/llms/warnings.html"
token_limits = "https://aider.chat/docs/troubleshooting/token-limits.html"
llms = "https://aider.chat/docs/llms.html"

View file

@ -17,11 +17,17 @@ class IgnorantTemporaryDirectory:
return self.temp_dir.__enter__()
def __exit__(self, exc_type, exc_val, exc_tb):
self.cleanup()
def cleanup(self):
try:
self.temp_dir.__exit__(exc_type, exc_val, exc_tb)
self.temp_dir.cleanup()
except (OSError, PermissionError):
pass # Ignore errors (Windows)
def __getattr__(self, item):
return getattr(self.temp_dir, item)
class ChdirTemporaryDirectory(IgnorantTemporaryDirectory):
def __init__(self):

View file

@ -54,7 +54,7 @@ diskcache==5.6.3
# via -r requirements.in
distro==1.9.0
# via openai
filelock==3.15.1
filelock==3.15.3
# via huggingface-hub
flake8==7.1.0
# via -r requirements.in
@ -70,14 +70,14 @@ gitpython==3.1.43
# via
# -r requirements.in
# streamlit
google-ai-generativelanguage==0.6.4
google-ai-generativelanguage==0.6.5
# via google-generativeai
google-api-core[grpc]==2.19.0
# via
# google-ai-generativelanguage
# google-api-python-client
# google-generativeai
google-api-python-client==2.133.0
google-api-python-client==2.134.0
# via google-generativeai
google-auth==2.30.0
# via
@ -88,7 +88,7 @@ google-auth==2.30.0
# google-generativeai
google-auth-httplib2==0.2.0
# via google-api-python-client
google-generativeai==0.6.0
google-generativeai==0.7.0
# via -r requirements.in
googleapis-common-protos==1.63.1
# via
@ -122,7 +122,9 @@ idna==3.7
# httpx
# requests
# yarl
importlib-metadata==7.1.0
ijson==3.3.0
# via litellm
importlib-metadata==7.2.0
# via litellm
jinja2==3.1.4
# via
@ -135,7 +137,7 @@ jsonschema==4.22.0
# altair
jsonschema-specifications==2023.12.1
# via jsonschema
litellm==1.40.15
litellm==1.40.21
# via -r requirements.in
markdown-it-py==3.0.0
# via rich
@ -151,7 +153,7 @@ multidict==6.0.5
# yarl
networkx==3.2.1
# via -r requirements.in
numpy==1.26.4
numpy==2.0.0
# via
# -r requirements.in
# altair
@ -160,7 +162,7 @@ numpy==1.26.4
# pydeck
# scipy
# streamlit
openai==1.34.0
openai==1.35.3
# via
# -r requirements.in
# litellm
@ -186,7 +188,7 @@ playwright==1.44.0
# via -r requirements.in
prompt-toolkit==3.0.47
# via -r requirements.in
proto-plus==1.23.0
proto-plus==1.24.0
# via
# google-ai-generativelanguage
# google-api-core
@ -280,9 +282,9 @@ soundfile==0.12.1
# via -r requirements.in
soupsieve==2.5
# via beautifulsoup4
streamlit==1.35.0
streamlit==1.36.0
# via -r requirements.in
tenacity==8.3.0
tenacity==8.4.1
# via streamlit
tiktoken==0.7.0
# via
@ -320,7 +322,7 @@ tzdata==2024.1
# via pandas
uritemplate==4.1.1
# via google-api-python-client
urllib3==2.2.1
urllib3==2.2.2
# via requests
watchdog==4.0.1
# via -r requirements.in

View file

@ -14,6 +14,7 @@ cog $ARG \
README.md \
website/index.md \
website/HISTORY.md \
website/docs/dotenv.md \
website/docs/commands.md \
website/docs/languages.md \
website/docs/options.md \

View file

@ -1,5 +1,6 @@
---
title: Release history
parent: More info
nav_order: 999
---
@ -11,6 +12,13 @@ cog.out(text)
# Release history
### v0.39.0
- Use `--sonnet` for Claude 3.5 Sonnet, which is the top model on [aider's LLM code editing leaderboard](https://aider.chat/docs/leaderboards/#claude-35-sonnet-takes-the-top-spot).
- All `AIDER_xxx` environment variables can now be set in `.env` (by @jpshack-at-palomar).
- Use `--llm-history-file` to log raw messages sent to the LLM (by @daniel-vainsencher).
- Commit messages are no longer prefixed with "aider:". Instead the git author and committer names have "(aider)" added.
### v0.38.0
- Use `--vim` for [vim keybindings](https://aider.chat/docs/commands.html#vi) in the chat.

View file

@ -4,6 +4,7 @@ url: "https://aider.chat"
plugins:
- jekyll-redirect-from
- jekyll-sitemap
- jekyll-feed
defaults:
- scope:
@ -19,6 +20,7 @@ exclude:
- "**/OLD/**"
- "OLD/**"
- vendor
- feed.xml
aux_links:
"GitHub":

View file

@ -44,29 +44,6 @@
seconds_per_case: 23.1
total_cost: 0.0000
- dirname: 2024-06-17-14-45-54--deepseek-coder2-whole
test_cases: 133
model: DeepSeek Coder V2
edit_format: whole
commit_hash: ca8672b
pass_rate_1: 63.9
pass_rate_2: 75.2
percent_cases_well_formed: 100.0
error_outputs: 1
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 1
lazy_comments: 0
syntax_errors: 1
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 7
command: aider --model deepseek/deepseek-coder
date: 2024-06-17
versions: 0.38.1-dev
seconds_per_case: 21.1
total_cost: 0.0537
- dirname: 2024-05-03-20-47-24--gemini-1.5-pro-diff-fenced
test_cases: 133
model: gemini-1.5-pro-latest
@ -611,4 +588,97 @@
date: 2024-06-08
versions: 0.37.1-dev
seconds_per_case: 280.6
total_cost: 0.0000
total_cost: 0.0000
- dirname: 2024-06-20-15-09-26--claude-3.5-sonnet-whole
test_cases: 133
model: claude-3.5-sonnet (whole)
edit_format: whole
commit_hash: 068609e
pass_rate_1: 61.7
pass_rate_2: 78.2
percent_cases_well_formed: 100.0
error_outputs: 4
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 2
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 0
command: aider --model openrouter/anthropic/claude-3.5-sonnet --edit-format whole
date: 2024-06-20
versions: 0.38.1-dev
seconds_per_case: 15.4
total_cost: 0.0000
- dirname: 2024-06-20-15-16-41--claude-3.5-sonnet-diff
test_cases: 133
model: claude-3.5-sonnet (diff)
edit_format: diff
commit_hash: 068609e-dirty
pass_rate_1: 57.9
pass_rate_2: 74.4
percent_cases_well_formed: 97.0
error_outputs: 48
num_malformed_responses: 11
num_with_malformed_responses: 4
user_asks: 0
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 1
command: aider --model openrouter/anthropic/claude-3.5-sonnet
date: 2024-06-20
versions: 0.38.1-dev
seconds_per_case: 21.6
total_cost: 0.0000
- dirname: 2024-06-17-14-45-54--deepseek-coder2-whole
test_cases: 133
model: DeepSeek Coder V2 (whole)
edit_format: whole
commit_hash: ca8672b
pass_rate_1: 63.9
pass_rate_2: 75.2
percent_cases_well_formed: 100.0
error_outputs: 1
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 1
lazy_comments: 0
syntax_errors: 1
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 7
command: aider --model deepseek/deepseek-coder
date: 2024-06-17
versions: 0.38.1-dev
seconds_per_case: 21.1
total_cost: 0.0537
- dirname: 2024-06-21-15-29-08--deepseek-coder2-diff-again3
test_cases: 133
model: DeepSeek Coder V2 (diff)
edit_format: diff
commit_hash: 515ab3e
pass_rate_1: 58.6
pass_rate_2: 66.2
percent_cases_well_formed: 98.5
error_outputs: 23
num_malformed_responses: 5
num_with_malformed_responses: 2
user_asks: 2
lazy_comments: 0
syntax_errors: 0
indentation_errors: 1
exhausted_context_windows: 0
test_timeouts: 2
command: aider --model deepseek/deepseek-coder
date: 2024-06-21
versions: 0.39.1-dev
seconds_per_case: 30.2
total_cost: 0.0857

View file

@ -143,4 +143,25 @@
seconds_per_case: 67.8
total_cost: 20.4889
- dirname: 2024-06-20-16-39-18--refac-claude-3.5-sonnet-diff
test_cases: 89
model: claude-3.5-sonnet (diff)
edit_format: diff
commit_hash: e5e07f9
pass_rate_1: 55.1
percent_cases_well_formed: 70.8
error_outputs: 240
num_malformed_responses: 54
num_with_malformed_responses: 26
user_asks: 10
lazy_comments: 2
syntax_errors: 0
indentation_errors: 3
exhausted_context_windows: 0
test_timeouts: 0
command: aider --model openrouter/anthropic/claude-3.5-sonnet
date: 2024-06-20
versions: 0.38.1-dev
seconds_per_case: 51.9
total_cost: 0.0000

View file

@ -10,7 +10,12 @@ $ cd /to/your/git/repo
$ export OPENAI_API_KEY=your-key-goes-here
$ aider
# Or, work with Claude 3 Opus on your repo
# Or, work with Anthropic's models
$ export ANTHROPIC_API_KEY=your-key-goes-here
# Claude 3 Opus
$ aider --opus
# Claude 3.5 Sonnet
$ aider --sonnet
```

View file

@ -5,6 +5,7 @@
<meta property="og:image" content="{{ site.url }}/assets/aider.jpg">
<meta property="twitter:image" content="{{ site.url }}/assets/aider-square.jpg">
{% endif %}
<link rel="alternate" type="application/rss+xml" title="RSS Feed" href="{{ site.url }}/feed.xml">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="preload" href="https://fonts.googleapis.com/css?family=Open+Sans:400,700&display=swap" as="style" type="text/css" crossorigin>
<meta name="viewport" content="width=device-width, initial-scale=1">

View file

@ -28,7 +28,7 @@
## Use claude-3-opus-20240229 model for the main chat
#opus: false
## Use claude-3-sonnet-20240229 model for the main chat
## Use claude-3-5-sonnet-20240620 model for the main chat
#sonnet: false
## Use gpt-4-0613 model for the main chat
@ -64,9 +64,15 @@
## Specify the OpenAI organization ID
#openai-organization-id:
## Specify a file with aider model settings for unknown models
#model-settings-file:
## Specify a file with context window and costs for unknown models
#model-metadata-file:
## Verify the SSL cert when connecting to models (default: True)
#verify-ssl: true
## Specify what edit format the LLM should use (default depends on model)
#edit-format:

232
website/assets/sample.env Normal file
View file

@ -0,0 +1,232 @@
##########################################################
# Sample aider .env file.
# Place at the root of your git repo.
# Or use `aider --env <fname>` to specify.
##########################################################
#################
# LLM parameters:
#
# Include xxx_API_KEY parameters and other params needed for your LLMs.
# See https://aider.chat/docs/llms.html for details.
## OpenAI
#OPENAI_API_KEY=
## Anthropic
#ANTHROPIC_API_KEY=
##...
#######
# Main:
## Log the conversation with the LLM to this file (for example, .aider.llm.history)
#AIDER_LLM_HISTORY_FILE=
## Specify the OpenAI API key
#OPENAI_API_KEY=
## Specify the Anthropic API key
#ANTHROPIC_API_KEY=
## Specify the model to use for the main chat (default: gpt-4o)
#AIDER_MODEL=gpt-4o
## Use claude-3-opus-20240229 model for the main chat
#AIDER_OPUS=
## Use claude-3-5-sonnet-20240620 model for the main chat
#AIDER_SONNET=
## Use gpt-4-0613 model for the main chat
#AIDER_4=
## Use gpt-4o model for the main chat
#AIDER_4O=
## Use gpt-4-1106-preview model for the main chat
#AIDER_4_TURBO=
## Use gpt-3.5-turbo model for the main chat
#AIDER_35TURBO=
#################
# Model Settings:
## List known models which match the (partial) MODEL name
#AIDER_MODELS=
## Specify the api base url
#OPENAI_API_BASE=
## Specify the api_type
#OPENAI_API_TYPE=
## Specify the api_version
#OPENAI_API_VERSION=
## Specify the deployment_id
#OPENAI_API_DEPLOYMENT_ID=
## Specify the OpenAI organization ID
#OPENAI_ORGANIZATION_ID=
## Specify a file with aider model settings for unknown models
#AIDER_MODEL_SETTINGS_FILE=
## Specify a file with context window and costs for unknown models
#AIDER_MODEL_METADATA_FILE=
## Verify the SSL cert when connecting to models (default: True)
#AIDER_VERIFY_SSL=true
## Specify what edit format the LLM should use (default depends on model)
#AIDER_EDIT_FORMAT=
## Specify the model to use for commit messages and chat history summarization (default depends on --model)
#AIDER_WEAK_MODEL=
## Only work with models that have meta-data available (default: True)
#AIDER_SHOW_MODEL_WARNINGS=true
## Max number of tokens to use for repo map, use 0 to disable (default: 1024)
#AIDER_MAP_TOKENS=true
## Maximum number of tokens to use for chat history. If not specified, uses the model's max_chat_history_tokens.
#AIDER_MAX_CHAT_HISTORY_TOKENS=
## Specify the .env file to load (default: .env in git root)
#AIDER_ENV_FILE=.env
################
# History Files:
## Specify the chat input history file (default: .aider.input.history)
#AIDER_INPUT_HISTORY_FILE=.aider.input.history
## Specify the chat history file (default: .aider.chat.history.md)
#AIDER_CHAT_HISTORY_FILE=.aider.chat.history.md
## Restore the previous chat history messages (default: False)
#AIDER_RESTORE_CHAT_HISTORY=false
##################
# Output Settings:
## Use colors suitable for a dark terminal background (default: False)
#AIDER_DARK_MODE=false
## Use colors suitable for a light terminal background (default: False)
#AIDER_LIGHT_MODE=false
## Enable/disable pretty, colorized output (default: True)
#AIDER_PRETTY=true
## Enable/disable streaming responses (default: True)
#AIDER_STREAM=true
## Set the color for user input (default: #00cc00)
#AIDER_USER_INPUT_COLOR=#00cc00
## Set the color for tool output (default: None)
#AIDER_TOOL_OUTPUT_COLOR=
## Set the color for tool error messages (default: red)
#AIDER_TOOL_ERROR_COLOR=#FF2222
## Set the color for assistant output (default: #0088ff)
#AIDER_ASSISTANT_OUTPUT_COLOR=#0088ff
## Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light)
#AIDER_CODE_THEME=default
## Show diffs when committing changes (default: False)
#AIDER_SHOW_DIFFS=false
###############
# Git Settings:
## Enable/disable looking for a git repo (default: True)
#AIDER_GIT=true
## Enable/disable adding .aider* to .gitignore (default: True)
#AIDER_GITIGNORE=true
## Specify the aider ignore file (default: .aiderignore in git root)
#AIDER_AIDERIGNORE=.aiderignore
## Enable/disable auto commit of LLM changes (default: True)
#AIDER_AUTO_COMMITS=true
## Enable/disable commits when repo is found dirty (default: True)
#AIDER_DIRTY_COMMITS=true
## Perform a dry run without modifying files (default: False)
#AIDER_DRY_RUN=false
########################
# Fixing and committing:
## Commit all pending changes with a suitable commit message, then exit
#AIDER_COMMIT=false
## Lint and fix provided files, or dirty files if none provided
#AIDER_LINT=false
## Specify lint commands to run for different languages, eg: "python: flake8 --select=..." (can be used multiple times)
#AIDER_LINT_CMD=
## Enable/disable automatic linting after changes (default: True)
#AIDER_AUTO_LINT=true
## Specify command to run tests
#AIDER_TEST_CMD=
## Enable/disable automatic testing after changes (default: False)
#AIDER_AUTO_TEST=false
## Run tests and fix problems found
#AIDER_TEST=false
#################
# Other Settings:
## Use VI editing mode in the terminal (default: False)
#AIDER_VIM=false
## Specify the language for voice using ISO 639-1 code (default: auto)
#AIDER_VOICE_LANGUAGE=en
## Check for updates and return status in the exit code
#AIDER_CHECK_UPDATE=false
## Skips checking for the update when the program runs
#AIDER_SKIP_CHECK_UPDATE=false
## Apply the changes from the given file instead of running the chat (debug)
#AIDER_APPLY=
## Always say yes to every confirmation
#AIDER_YES=
## Enable verbose output
#AIDER_VERBOSE=false
## Print the repo map and exit (debug)
#AIDER_SHOW_REPO_MAP=false
## Print the system prompts and exit (debug)
#AIDER_SHOW_PROMPTS=false
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
#AIDER_MESSAGE=
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#AIDER_MESSAGE_FILE=
## Specify the encoding for input and output (default: utf-8)
#AIDER_ENCODING=utf-8
## Run aider in your browser
#AIDER_GUI=false

View file

@ -56,7 +56,7 @@ cog.outl("```")
## Use claude-3-opus-20240229 model for the main chat
#opus: false
## Use claude-3-sonnet-20240229 model for the main chat
## Use claude-3-5-sonnet-20240620 model for the main chat
#sonnet: false
## Use gpt-4-0613 model for the main chat
@ -92,9 +92,15 @@ cog.outl("```")
## Specify the OpenAI organization ID
#openai-organization-id:
## Specify a file with aider model settings for unknown models
#model-settings-file:
## Specify a file with context window and costs for unknown models
#model-metadata-file:
## Verify the SSL cert when connecting to models (default: True)
#verify-ssl: true
## Specify what edit format the LLM should use (default depends on model)
#edit-format:

View file

@ -4,12 +4,12 @@ nav_order: 900
description: Using a .env file to store LLM API keys for aider.
---
# Storing LLM params in .env
# Config with .env
You can use a `.env` file to store API keys and other settings for the
models you use with aider.
You currently can not set general aider options
in the `.env` file, only LLM environment variables.
You can also set many general aider options
in the `.env` file.
{% include special-keys.md %}
@ -17,17 +17,253 @@ Aider will look for a `.env` file in the
root of your git repo or in the current directory.
You can give it an explicit file to load with the `--env-file <filename>` parameter.
Here is an example `.env` file:
Below is a sample `.env` file, which you
can also
[download from GitHub](https://github.com/paul-gauthier/aider/blob/main/website/assets/sample.env).
<!--[[[cog
from aider.args import get_sample_dotenv
from pathlib import Path
text=get_sample_dotenv()
Path("website/assets/sample.env").write_text(text)
cog.outl("```")
cog.out(text)
cog.outl("```")
]]]-->
```
OPENAI_API_KEY=<key>
ANTHROPIC_API_KEY=<key>
GROQ_API_KEY=<key>
OPENROUTER_API_KEY=<key>
##########################################################
# Sample aider .env file.
# Place at the root of your git repo.
# Or use `aider --env <fname>` to specify.
##########################################################
AZURE_API_KEY=<key>
AZURE_API_VERSION=2023-05-15
AZURE_API_BASE=https://example-endpoint.openai.azure.com
#################
# LLM parameters:
#
# Include xxx_API_KEY parameters and other params needed for your LLMs.
# See https://aider.chat/docs/llms.html for details.
OLLAMA_API_BASE=http://127.0.0.1:11434
## OpenAI
#OPENAI_API_KEY=
## Anthropic
#ANTHROPIC_API_KEY=
##...
#######
# Main:
## Log the conversation with the LLM to this file (for example, .aider.llm.history)
#AIDER_LLM_HISTORY_FILE=
## Specify the OpenAI API key
#OPENAI_API_KEY=
## Specify the Anthropic API key
#ANTHROPIC_API_KEY=
## Specify the model to use for the main chat (default: gpt-4o)
#AIDER_MODEL=gpt-4o
## Use claude-3-opus-20240229 model for the main chat
#AIDER_OPUS=
## Use claude-3-5-sonnet-20240620 model for the main chat
#AIDER_SONNET=
## Use gpt-4-0613 model for the main chat
#AIDER_4=
## Use gpt-4o model for the main chat
#AIDER_4O=
## Use gpt-4-1106-preview model for the main chat
#AIDER_4_TURBO=
## Use gpt-3.5-turbo model for the main chat
#AIDER_35TURBO=
#################
# Model Settings:
## List known models which match the (partial) MODEL name
#AIDER_MODELS=
## Specify the api base url
#OPENAI_API_BASE=
## Specify the api_type
#OPENAI_API_TYPE=
## Specify the api_version
#OPENAI_API_VERSION=
## Specify the deployment_id
#OPENAI_API_DEPLOYMENT_ID=
## Specify the OpenAI organization ID
#OPENAI_ORGANIZATION_ID=
## Specify a file with aider model settings for unknown models
#AIDER_MODEL_SETTINGS_FILE=
## Specify a file with context window and costs for unknown models
#AIDER_MODEL_METADATA_FILE=
## Verify the SSL cert when connecting to models (default: True)
#AIDER_VERIFY_SSL=true
## Specify what edit format the LLM should use (default depends on model)
#AIDER_EDIT_FORMAT=
## Specify the model to use for commit messages and chat history summarization (default depends on --model)
#AIDER_WEAK_MODEL=
## Only work with models that have meta-data available (default: True)
#AIDER_SHOW_MODEL_WARNINGS=true
## Max number of tokens to use for repo map, use 0 to disable (default: 1024)
#AIDER_MAP_TOKENS=true
## Maximum number of tokens to use for chat history. If not specified, uses the model's max_chat_history_tokens.
#AIDER_MAX_CHAT_HISTORY_TOKENS=
## Specify the .env file to load (default: .env in git root)
#AIDER_ENV_FILE=.env
################
# History Files:
## Specify the chat input history file (default: .aider.input.history)
#AIDER_INPUT_HISTORY_FILE=.aider.input.history
## Specify the chat history file (default: .aider.chat.history.md)
#AIDER_CHAT_HISTORY_FILE=.aider.chat.history.md
## Restore the previous chat history messages (default: False)
#AIDER_RESTORE_CHAT_HISTORY=false
##################
# Output Settings:
## Use colors suitable for a dark terminal background (default: False)
#AIDER_DARK_MODE=false
## Use colors suitable for a light terminal background (default: False)
#AIDER_LIGHT_MODE=false
## Enable/disable pretty, colorized output (default: True)
#AIDER_PRETTY=true
## Enable/disable streaming responses (default: True)
#AIDER_STREAM=true
## Set the color for user input (default: #00cc00)
#AIDER_USER_INPUT_COLOR=#00cc00
## Set the color for tool output (default: None)
#AIDER_TOOL_OUTPUT_COLOR=
## Set the color for tool error messages (default: red)
#AIDER_TOOL_ERROR_COLOR=#FF2222
## Set the color for assistant output (default: #0088ff)
#AIDER_ASSISTANT_OUTPUT_COLOR=#0088ff
## Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light)
#AIDER_CODE_THEME=default
## Show diffs when committing changes (default: False)
#AIDER_SHOW_DIFFS=false
###############
# Git Settings:
## Enable/disable looking for a git repo (default: True)
#AIDER_GIT=true
## Enable/disable adding .aider* to .gitignore (default: True)
#AIDER_GITIGNORE=true
## Specify the aider ignore file (default: .aiderignore in git root)
#AIDER_AIDERIGNORE=.aiderignore
## Enable/disable auto commit of LLM changes (default: True)
#AIDER_AUTO_COMMITS=true
## Enable/disable commits when repo is found dirty (default: True)
#AIDER_DIRTY_COMMITS=true
## Perform a dry run without modifying files (default: False)
#AIDER_DRY_RUN=false
########################
# Fixing and committing:
## Commit all pending changes with a suitable commit message, then exit
#AIDER_COMMIT=false
## Lint and fix provided files, or dirty files if none provided
#AIDER_LINT=false
## Specify lint commands to run for different languages, eg: "python: flake8 --select=..." (can be used multiple times)
#AIDER_LINT_CMD=
## Enable/disable automatic linting after changes (default: True)
#AIDER_AUTO_LINT=true
## Specify command to run tests
#AIDER_TEST_CMD=
## Enable/disable automatic testing after changes (default: False)
#AIDER_AUTO_TEST=false
## Run tests and fix problems found
#AIDER_TEST=false
#################
# Other Settings:
## Use VI editing mode in the terminal (default: False)
#AIDER_VIM=false
## Specify the language for voice using ISO 639-1 code (default: auto)
#AIDER_VOICE_LANGUAGE=en
## Check for updates and return status in the exit code
#AIDER_CHECK_UPDATE=false
## Skips checking for the update when the program runs
#AIDER_SKIP_CHECK_UPDATE=false
## Apply the changes from the given file instead of running the chat (debug)
#AIDER_APPLY=
## Always say yes to every confirmation
#AIDER_YES=
## Enable verbose output
#AIDER_VERBOSE=false
## Print the repo map and exit (debug)
#AIDER_SHOW_REPO_MAP=false
## Print the system prompts and exit (debug)
#AIDER_SHOW_PROMPTS=false
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
#AIDER_MESSAGE=
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#AIDER_MESSAGE_FILE=
## Specify the encoding for input and output (default: utf-8)
#AIDER_ENCODING=utf-8
## Run aider in your browser
#AIDER_GUI=false
```
<!--[[[end]]]-->

View file

@ -1,9 +1,9 @@
---
nav_order: 85
nav_order: 90
description: Frequently asked questions about aider.
---
# Frequently asked questions
# FAQ
{: .no_toc }
- TOC

View file

@ -1,4 +1,5 @@
---
parent: More info
nav_order: 800
description: Aider is tightly integrated with git.
---
@ -14,14 +15,21 @@ Aider is tightly integrated with git, which makes it easy to:
Aider specifically uses git in these ways:
- It asks to create a git repo if you launch it in a directory without one.
- Whenever aider edits a file, it commits those changes with a descriptive commit message. This makes it easy to undo or review aider's changes.
- Aider takes special care before editing files that already have uncommitted changes (dirty files). Aider will first commit any preexisting changes with a descriptive commit message. This keeps your edits separate from aider's edits, and makes sure you never lose your work if aider makes an inappropriate change.
- It asks to create a git repo if you launch it in a directory without one.
- Whenever aider edits a file, it commits those changes with a descriptive commit message. This makes it easy to undo or review aider's changes.
These commits will have "(aider)" appended to their git author and git committer metadata.
- Aider takes special care before editing files that already have uncommitted changes (dirty files). Aider will first commit any preexisting changes with a descriptive commit message.
This keeps your edits separate from aider's edits, and makes sure you never lose your work if aider makes an inappropriate change.
These commits will have "(aider)" appended to their git committer metadata.
## In-chat commands
Aider also allows you to use in-chat commands to `/diff` or `/undo` the last change.
To do more complex management of your git history, you cat use raw `git` commands,
either by using `/git` within the chat, or with standard git tools outside of aider.
## Disabling git integration
While it is not recommended, you can disable aider's use of git in a few ways:
- `--no-auto-commits` will stop aider from git committing each of its changes.

View file

@ -1,4 +1,5 @@
---
parent: More info
nav_order: 900
description: Aider supports pretty much all popular coding languages.
---

View file

@ -16,22 +16,19 @@ While [aider can connect to almost any LLM](/docs/llms.html),
it works best with models that score well on the benchmarks.
## DeepSeek Coder V2 beats GPT-4o, Opus
## Claude 3.5 Sonnet takes the top spot
The new
[DeepSeek Coder V2](https://aider.chat/docs/llms/deepseek.html)
model is now atop aider's code editing leaderboard!
Claude 3.5 Sonnet is now the top ranked model on aider's code editing leaderboard.
DeepSeek Coder V2 only spent 4 days in the top spot.
It's worth noting that DeepSeek Coder V2 is only capable of using aider's "whole" edit format.
This means it returns a modified full copy of each file when it makes changes.
Most other strong models are able to use aider's "diff" editing format,
which allows them to return diffs of edits -- saving time and token costs.
Models which use the "whole" edit format can only edit files
which fit within their output token limits.
These output limits are often as low as 4k tokens, even for models
with very large context windows.
The new Sonnet came in 3rd on aider's refactoring leaderboard, behind GPT-4o and Opus.
Sonnet ranked #1 when using the "whole" editing format,
but it also scored very well with
aider's "diff" editing format.
This format allows it to return code changes as diffs -- saving time and token costs,
and making it practical to work with larger source files.
As such, aider uses "diff" by default with this new Sonnet model.
## Code editing leaderboard

View file

@ -14,17 +14,21 @@ description: Aider can connect to most LLMs for AI pair programming.
## Best models
{: .no_toc }
**Aider works best with [GPT-4o](/docs/llms/openai.html) and
[Claude 3 Opus](/docs/llms/anthropic.html),**
as they are the very best models for editing code.
Aider works best with these models, which are skilled at editing code:
- [GPT-4o](/docs/llms/openai.html)
- [Claude 3.5 Sonnet](/docs/llms/anthropic.html)
- [Claude 3 Opus](/docs/llms/anthropic.html)
- [DeepSeek Coder V2](/docs/llms/deepseek.html)
## Free models
{: .no_toc }
Aider works with a number of **free** API providers:
- The [DeepSeek Coder V2](/docs/llms/deepseek.html) model gets the top score on aider's code editing benchmark. DeepSeek currently offers 5M free tokens of API usage.
- Google's [Gemini 1.5 Pro](/docs/llms/gemini.html) is the most capable free model to use with aider, with
- The [DeepSeek Coder V2](/docs/llms/deepseek.html) model gets the top score on aider's code editing benchmark. DeepSeek has been offering 5M free tokens of API usage.
- Google's [Gemini 1.5 Pro](/docs/llms/gemini.html) works with aider, with
code editing capabilities similar to GPT-3.5.
- You can use [Llama 3 70B on Groq](/docs/llms/groq.html) which is comparable to GPT-3.5 in code editing performance.
- Cohere also offers free API access to their [Command-R+ model](/docs/llms/cohere.html), which works with aider as a *very basic* coding assistant.

View file

@ -22,7 +22,7 @@ setx ANTHROPIC_API_KEY <key> # Windows
# Claude 3 Opus
aider --opus
# Claude 3 Sonnet
# Claude 3.5 Sonnet
aider --sonnet
# List models available from Anthropic

View file

@ -8,10 +8,45 @@ nav_order: 900
{% include model-warnings.md %}
## Adding settings for missing models
You can register model settings used by aider for unknown models.
Create a `.aider.models.yml` file in one of these locations:
- Your home directory.
- The root if your git repo.
- The current directory where you launch aider.
- Or specify a specific file with the `--model-settings-file <filename>` switch.
If the files above exist, they will be loaded in that order.
Files loaded last will take priority.
The yaml file should be a a list of dictionary objects for each model, as follows:
```
- name: "gpt-3.5-turbo"
edit_format: "whole"
weak_model_name: "gpt-3.5-turbo"
use_repo_map: false
send_undo_reply: false
accepts_images: false
lazy: false
reminder_as_sys_msg: true
examples_as_sys_msg: false
- name: "gpt-4-turbo-2024-04-09"
edit_format: "udiff"
weak_model_name: "gpt-3.5-turbo"
use_repo_map: true
send_undo_reply: true
accepts_images: true
lazy: true
reminder_as_sys_msg: true
examples_as_sys_msg: false
```
## Specifying context window size and token costs
You can register context window limits and costs for models that aren't known
to aider. Create a `.aider.models.json` file in one of these locations:
to aider. Create a `.aider.litellm.models.json` file in one of these locations:
- Your home directory.
- The root if your git repo.

View file

@ -0,0 +1,8 @@
---
has_children: true
nav_order: 85
---
# More info
See below for more info about aider, including some advanced topics.

View file

@ -19,8 +19,10 @@ usage: aider [-h] [--llm-history-file] [--openai-api-key]
[--4] [--4o] [--4-turbo] [--35turbo] [--models]
[--openai-api-base] [--openai-api-type]
[--openai-api-version] [--openai-api-deployment-id]
[--openai-organization-id] [--model-metadata-file]
[--edit-format] [--weak-model]
[--openai-organization-id] [--model-settings-file]
[--model-metadata-file]
[--verify-ssl | --no-verify-ssl] [--edit-format]
[--weak-model]
[--show-model-warnings | --no-show-model-warnings]
[--map-tokens] [--max-chat-history-tokens] [--env-file]
[--input-history-file] [--chat-history-file]
@ -75,7 +77,7 @@ Use claude-3-opus-20240229 model for the main chat
Environment variable: `AIDER_OPUS`
### `--sonnet`
Use claude-3-sonnet-20240229 model for the main chat
Use claude-3-5-sonnet-20240620 model for the main chat
Environment variable: `AIDER_SONNET`
### `--4`
@ -128,10 +130,22 @@ Environment variable: `OPENAI_API_DEPLOYMENT_ID`
Specify the OpenAI organization ID
Environment variable: `OPENAI_ORGANIZATION_ID`
### `--model-metadata-file MODEL_FILE`
### `--model-settings-file MODEL_SETTINGS_FILE`
Specify a file with aider model settings for unknown models
Environment variable: `AIDER_MODEL_SETTINGS_FILE`
### `--model-metadata-file MODEL_METADATA_FILE`
Specify a file with context window and costs for unknown models
Environment variable: `AIDER_MODEL_METADATA_FILE`
### `--verify-ssl`
Verify the SSL cert when connecting to models (default: True)
Default: True
Environment variable: `AIDER_VERIFY_SSL`
Aliases:
- `--verify-ssl`
- `--no-verify-ssl`
### `--edit-format EDIT_FORMAT`
Specify what edit format the LLM should use (default depends on model)
Environment variable: `AIDER_EDIT_FORMAT`

View file

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

View file

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

View file

@ -33,8 +33,8 @@ so editing errors are probably unavoidable.
## Reduce distractions
Many LLM now have very large context windows,
but filling them with irrelevant code often
cofuses the model.
but filling them with irrelevant code or conversation
can cofuse the model.
- Don't add too many files to the chat, *just* add the files you think need to be edited.
Aider also sends the LLM a [map of your entire git repo](https://aider.chat/docs/repomap.html), so other relevant code will be included automatically.

View file

@ -20,8 +20,8 @@ cog.out(text)
Aider lets you pair program with LLMs,
to edit code in your local git repository.
Start a new project or work with an existing git repo.
Aider works best with GPT-4o and Claude 3 Opus
and can [connect to almost any LLM](https://aider.chat/docs/llms.html).
Aider can [connect to almost any LLM](https://aider.chat/docs/llms.html).
and works best with GPT-4o, Claude 3.5 Sonnet, Claude 3 Opus and DeepSeek Coder V2.
<p align="center">
<img
@ -57,9 +57,14 @@ $ cd /to/your/git/repo
$ export OPENAI_API_KEY=your-key-goes-here
$ aider
# Or, work with Claude 3 Opus on your repo
# Or, work with Anthropic's models
$ export ANTHROPIC_API_KEY=your-key-goes-here
# Claude 3 Opus
$ aider --opus
# Claude 3.5 Sonnet
$ aider --sonnet
```
<!-- NOOP -->
@ -93,20 +98,13 @@ Pair program with AI.
- [Code with your voice](https://aider.chat/docs/voice.html).
## State of the art
## Top tier performance
Aider has the
[top score on SWE Bench](https://aider.chat/2024/06/02/main-swe-bench.html).
[Aider has the one of the top scores on SWE Bench](https://aider.chat/2024/06/02/main-swe-bench.html).
SWE Bench is a challenging software engineering benchmark where aider
solved *real* GitHub issues from popular open source
projects like django, scikitlearn, matplotlib, etc.
<p align="center">
<a href="https://aider.chat/2024/06/02/main-swe-bench.html">
<img src="https://aider.chat/assets/swe_bench.svg" alt="aider swe bench">
</a>
</p>
## More info
- [Documentation](https://aider.chat/)