mirror of
https://github.com/Aider-AI/aider
synced 2026-04-26 01:25:17 +02:00
Compare commits
282 Commits
v0.67.1.de
...
v0.69.2.de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c848d59b2 | ||
|
|
b1c04dece9 | ||
|
|
b87c7987bb | ||
|
|
0bef52ae7d | ||
|
|
9ae04cf1ec | ||
|
|
0f7c4a8d4f | ||
|
|
07353207c0 | ||
|
|
d89be83414 | ||
|
|
01382527f5 | ||
|
|
dece2193fc | ||
|
|
d298f864fa | ||
|
|
ff37d8c691 | ||
|
|
f7f305a564 | ||
|
|
86f38e11cd | ||
|
|
0b60c48253 | ||
|
|
024b9840f0 | ||
|
|
2f4f59d82f | ||
|
|
830d5ee763 | ||
|
|
5bc63f7a33 | ||
|
|
b54f970e12 | ||
|
|
0cc8c54152 | ||
|
|
241e1e27d0 | ||
|
|
0145e86202 | ||
|
|
4d50e1e373 | ||
|
|
4b6ae34800 | ||
|
|
2feb85e831 | ||
|
|
a67ac81265 | ||
|
|
dab536c9e8 | ||
|
|
64cf298521 | ||
|
|
10b5aaa6a5 | ||
|
|
8c79e5ccfb | ||
|
|
2ef536a342 | ||
|
|
85b1303460 | ||
|
|
60aca3a241 | ||
|
|
db98381a86 | ||
|
|
f62ef34715 | ||
|
|
f95a6c1a5a | ||
|
|
65555b5dd0 | ||
|
|
9f6331a35e | ||
|
|
8c10cb6230 | ||
|
|
c8894bcead | ||
|
|
edc602c33a | ||
|
|
abfb2ca810 | ||
|
|
9967efe45a | ||
|
|
e77d80bda5 | ||
|
|
a691d1750a | ||
|
|
834e2f9304 | ||
|
|
66e5e9c1ce | ||
|
|
2d5f613984 | ||
|
|
868e7a278f | ||
|
|
f953d17889 | ||
|
|
3473969aae | ||
|
|
ec11ae7c40 | ||
|
|
8217ee1bbb | ||
|
|
1ad3ee0aec | ||
|
|
b3e9a2fede | ||
|
|
2f5d6bf909 | ||
|
|
cd79f479e9 | ||
|
|
12c0f675ce | ||
|
|
29471b8019 | ||
|
|
cad661f0c8 | ||
|
|
261d770482 | ||
|
|
a75c9c74fd | ||
|
|
8b5bdf9a16 | ||
|
|
e35eba2d51 | ||
|
|
df8c88cef4 | ||
|
|
844e12769c | ||
|
|
b982626ac4 | ||
|
|
517b2b42a6 | ||
|
|
6778c33628 | ||
|
|
bc0b11e1ef | ||
|
|
6b0d4b9c93 | ||
|
|
7d4e4f029e | ||
|
|
1fbdb629ff | ||
|
|
a437237947 | ||
|
|
910637c549 | ||
|
|
e8974a3e69 | ||
|
|
6c98310f7f | ||
|
|
72aed0d26d | ||
|
|
e10ef8b9e0 | ||
|
|
39fa8ba831 | ||
|
|
8ee8279044 | ||
|
|
c3f85c3bb2 | ||
|
|
ad59c4cbf3 | ||
|
|
26bc981981 | ||
|
|
514c34b242 | ||
|
|
6f266c0090 | ||
|
|
baa7352ca6 | ||
|
|
fdb1c8d99a | ||
|
|
79f5dba094 | ||
|
|
2134965f16 | ||
|
|
77b7a59a27 | ||
|
|
365e7126d0 | ||
|
|
d3daf9d159 | ||
|
|
8d59a519a6 | ||
|
|
239262f360 | ||
|
|
9eb938fd6f | ||
|
|
3fcbf1a43f | ||
|
|
2b7ee271df | ||
|
|
11512c6281 | ||
|
|
b16ba547ab | ||
|
|
e5b8899b4c | ||
|
|
fee3e9e63b | ||
|
|
57a24d30b5 | ||
|
|
5a83610fb1 | ||
|
|
96086f12c6 | ||
|
|
a6ee3ce07f | ||
|
|
5f36ddd425 | ||
|
|
bec67074e0 | ||
|
|
895c92cdae | ||
|
|
7406a5bc26 | ||
|
|
ef97714404 | ||
|
|
6d6daee511 | ||
|
|
32cd1c2a65 | ||
|
|
abad920a8a | ||
|
|
e1ab49e100 | ||
|
|
df300e89a2 | ||
|
|
9a278bed21 | ||
|
|
4a7fc084ce | ||
|
|
2649e736fb | ||
|
|
42ac891e28 | ||
|
|
4dc3b9072e | ||
|
|
ae3235b099 | ||
|
|
7cc5e0d577 | ||
|
|
f6b956dc8e | ||
|
|
fcb2bacd1e | ||
|
|
a9401e921e | ||
|
|
02e7e315b2 | ||
|
|
def72a64e0 | ||
|
|
46e7672197 | ||
|
|
2f8a5ce935 | ||
|
|
730e5bd831 | ||
|
|
b7984a05af | ||
|
|
5d4af67186 | ||
|
|
370e08cf4d | ||
|
|
aaf7e3f943 | ||
|
|
fbde0936e7 | ||
|
|
af48f7bab4 | ||
|
|
61def89878 | ||
|
|
88e86cee77 | ||
|
|
acc1625406 | ||
|
|
502f448053 | ||
|
|
55b081884c | ||
|
|
fd67171908 | ||
|
|
16a53aa641 | ||
|
|
4aec676950 | ||
|
|
d8fff0e90a | ||
|
|
57ad6cc3ea | ||
|
|
2b46a8b9c9 | ||
|
|
4d1a2e8c53 | ||
|
|
58b1409bd2 | ||
|
|
a2525dbf56 | ||
|
|
36eb2a31b5 | ||
|
|
0483bfc9cb | ||
|
|
3f63a64254 | ||
|
|
16332b285f | ||
|
|
f7371f6faf | ||
|
|
92d29805f1 | ||
|
|
4a37d07acb | ||
|
|
bb4c61e9cc | ||
|
|
f4e5515c82 | ||
|
|
141a2df19c | ||
|
|
e2385b4922 | ||
|
|
9974fb50f7 | ||
|
|
c5d51d62c4 | ||
|
|
4fcbf28f91 | ||
|
|
f678b664ff | ||
|
|
4206920a7d | ||
|
|
ad2e5ead54 | ||
|
|
eb72719117 | ||
|
|
20b46afbf2 | ||
|
|
1925e4a7f4 | ||
|
|
1a12322354 | ||
|
|
73f3f4ec7e | ||
|
|
a8c42f453a | ||
|
|
79dd0c5ba6 | ||
|
|
89bc3b6b16 | ||
|
|
a997dd6c49 | ||
|
|
6aa80d2a4c | ||
|
|
f009e8fb14 | ||
|
|
a8dde17155 | ||
|
|
cbcbff341b | ||
|
|
e50992bb93 | ||
|
|
fa6c3068c0 | ||
|
|
dd9bdca572 | ||
|
|
3f7dffe47d | ||
|
|
c7fde14458 | ||
|
|
57f4186cad | ||
|
|
fa5a6021b1 | ||
|
|
42ae279b91 | ||
|
|
a74cdbfc28 | ||
|
|
a56fa567dd | ||
|
|
c9c2d5ab6f | ||
|
|
ccf460c1f7 | ||
|
|
2325f542b8 | ||
|
|
63fdf3f3f6 | ||
|
|
efa83bdf34 | ||
|
|
5705bda818 | ||
|
|
20042334ff | ||
|
|
7ae9569816 | ||
|
|
cacba526b3 | ||
|
|
50f203cc8a | ||
|
|
3efcd154f3 | ||
|
|
bdb08d7c78 | ||
|
|
f3874dd40a | ||
|
|
935c39e341 | ||
|
|
7ddcc30e8d | ||
|
|
13ff038e58 | ||
|
|
1d4918dfbf | ||
|
|
ba14ab96da | ||
|
|
054e0820b7 | ||
|
|
af3d8dd6a7 | ||
|
|
e10d06cb47 | ||
|
|
87a1469c1e | ||
|
|
2492f1635c | ||
|
|
b3305e6e19 | ||
|
|
491d3e6606 | ||
|
|
e41bf67f73 | ||
|
|
66b99c4fa0 | ||
|
|
f2f2645fe6 | ||
|
|
4c77d0509a | ||
|
|
33d77f4355 | ||
|
|
ecf8617246 | ||
|
|
bec216d72a | ||
|
|
374e8c3307 | ||
|
|
b5eff8a9dd | ||
|
|
d53002a494 | ||
|
|
04662f0875 | ||
|
|
aec92c7c17 | ||
|
|
f7a7976923 | ||
|
|
1b50d4507f | ||
|
|
045cf887df | ||
|
|
277d7c0e04 | ||
|
|
0e2c703e77 | ||
|
|
62b3f38f00 | ||
|
|
422658293d | ||
|
|
74cfd05642 | ||
|
|
80586f1de3 | ||
|
|
a933177ac0 | ||
|
|
ade2db696b | ||
|
|
cf266037ff | ||
|
|
5f14277fbf | ||
|
|
b677349ec9 | ||
|
|
7f72d2a703 | ||
|
|
779983cb85 | ||
|
|
f2d2ab51b1 | ||
|
|
0a54f8c4a7 | ||
|
|
881527ddd0 | ||
|
|
cca4f894a8 | ||
|
|
20dae33be5 | ||
|
|
fd301c519d | ||
|
|
a96d87814b | ||
|
|
2a3eefc5be | ||
|
|
c5dc10e3cd | ||
|
|
c251a93609 | ||
|
|
2df509effd | ||
|
|
53e0d670b3 | ||
|
|
ccd19d2c96 | ||
|
|
b69f084db9 | ||
|
|
9639395937 | ||
|
|
117b7afd81 | ||
|
|
009c4dc8db | ||
|
|
0fdf3fc851 | ||
|
|
ffc2d91cef | ||
|
|
6efdf8a7f4 | ||
|
|
623770e24b | ||
|
|
402940a215 | ||
|
|
7fea85cdcd | ||
|
|
93b3b7a184 | ||
|
|
8f2a84629a | ||
|
|
7a1c1982f0 | ||
|
|
75d8982b23 | ||
|
|
87dbb56d7e | ||
|
|
aa217a3a43 | ||
|
|
22fc961dc0 | ||
|
|
8f57186945 | ||
|
|
f8277c55a8 | ||
|
|
6163713e34 | ||
|
|
d2d5887936 | ||
|
|
2a1065efc1 | ||
|
|
6f36a97c4a | ||
|
|
eeed79009a |
2
.github/workflows/pages.yml
vendored
2
.github/workflows/pages.yml
vendored
@@ -84,4 +84,4 @@ jobs:
|
||||
|
||||
- name: Run linkchecker
|
||||
run: |
|
||||
linkchecker https://aider.chat
|
||||
linkchecker --ignore-url='.+\.(mp4|mov|avi)' https://aider.chat
|
||||
|
||||
39
HISTORY.md
39
HISTORY.md
@@ -1,5 +1,42 @@
|
||||
# Release history
|
||||
|
||||
### Aider v0.69.0
|
||||
|
||||
- [Watch files](https://aider.chat/docs/usage/watch.html) improvements:
|
||||
- Use `# ... AI?` comments to trigger aider and ask questions about your code.
|
||||
- Now watches *all* files, not just certain source files.
|
||||
- Use `# AI comments`, `// AI comments`, or `-- AI comments` to give aider instructions in any text file.
|
||||
- Full support for Gemini Flash 2.0 Exp:
|
||||
- `aider --model flash` or `aider --model gemini/gemini-2.0-flash-exp`
|
||||
- [New `--multiline` flag and `/multiline-mode` command](https://aider.chat/docs/usage/commands.html#entering-multi-line-chat-messages) makes ENTER a soft newline and META-ENTER send the message, by @miradnanali.
|
||||
- `/copy-context <instructions>` now takes optional "instructions" when [copying code context to the clipboard](https://aider.chat/docs/usage/copypaste.html#copy-aiders-code-context-to-your-clipboard-paste-into-the-web-ui).
|
||||
- Improved clipboard error handling with helpful requirements install info.
|
||||
- Ask 5% of users if they want to opt-in to analytics.
|
||||
- `/voice` now lets you edit the transcribed text before sending.
|
||||
- Disabled auto-complete in Y/N prompts.
|
||||
- Aider wrote 68% of the code in this release.
|
||||
|
||||
### Aider v0.68.0
|
||||
|
||||
- [Aider works with LLM web chat UIs](https://aider.chat/docs/usage/copypaste.html).
|
||||
- New `--copy-paste` mode.
|
||||
- New `/copy-context` command.
|
||||
- [Set API keys and other environment variables for all providers from command line or yaml conf file](https://aider.chat/docs/config/aider_conf.html#storing-llm-keys).
|
||||
- New `--api-key provider=key` setting.
|
||||
- New `--set-env VAR=value` setting.
|
||||
- Added bash and zsh support to `--watch-files`.
|
||||
- Better error messages when missing dependencies for Gemini and Bedrock models.
|
||||
- Control-D now properly exits the program.
|
||||
- Don't count token costs when API provider returns a hard error.
|
||||
- Bugfix so watch files works with files that don't have tree-sitter support.
|
||||
- Bugfix so o1 models can be used as weak model.
|
||||
- Updated shell command prompt.
|
||||
- Added docstrings for all Coders.
|
||||
- Reorganized command line arguments with improved help messages and grouping.
|
||||
- Use the exact `sys.python` for self-upgrades.
|
||||
- Added experimental Gemini models.
|
||||
- Aider wrote 71% of the code in this release.
|
||||
|
||||
### Aider v0.67.0
|
||||
|
||||
- [Use aider in your IDE or editor](https://aider.chat/docs/usage/watch.html).
|
||||
@@ -13,7 +50,7 @@
|
||||
- Spinner now falls back to ASCII art if fancy symbols throw unicode errors.
|
||||
- `--read` now expands `~` home dirs.
|
||||
- Enabled exception capture in analytics.
|
||||
- Aider wrote 61% of the code in this release.
|
||||
- [Aider wrote 61% of the code in this release.](https://aider.chat/HISTORY.html)
|
||||
|
||||
### Aider v0.66.0
|
||||
|
||||
|
||||
14
MANIFEST.in
Normal file
14
MANIFEST.in
Normal file
@@ -0,0 +1,14 @@
|
||||
# This needs to sync with aider/help_pats.py
|
||||
|
||||
global-exclude .DS_Store
|
||||
recursive-exclude aider/website/examples *
|
||||
recursive-exclude aider/website/_posts *
|
||||
exclude aider/website/HISTORY.md
|
||||
exclude aider/website/docs/benchmarks*.md
|
||||
exclude aider/website/docs/ctags.md
|
||||
exclude aider/website/docs/unified-diffs.md
|
||||
exclude aider/website/docs/leaderboards/index.md
|
||||
recursive-exclude aider/website/assets *
|
||||
recursive-exclude aider/website *.js
|
||||
recursive-exclude aider/website *.html
|
||||
recursive-exclude aider/website *.yml
|
||||
19
README.md
19
README.md
@@ -43,28 +43,27 @@ VIDEO END -->
|
||||
cog.out(open("aider/website/_includes/get-started.md").read())
|
||||
]]]-->
|
||||
|
||||
You can get started quickly like this:
|
||||
You can get started quickly like this, with python 3.8-3.13:
|
||||
|
||||
```
|
||||
python -m pip install -U aider-chat
|
||||
```bash
|
||||
python -m pip install aider-install
|
||||
aider-install
|
||||
|
||||
# Change directory into a git repo
|
||||
# Change directory into your code base
|
||||
cd /to/your/git/repo
|
||||
|
||||
# Work with Claude 3.5 Sonnet on your repo
|
||||
export ANTHROPIC_API_KEY=your-key-goes-here
|
||||
aider
|
||||
aider --model sonnet --anthropic-api-key your-key-goes-here
|
||||
|
||||
# Work with GPT-4o on your repo
|
||||
export OPENAI_API_KEY=your-key-goes-here
|
||||
aider
|
||||
aider --model gpt-4o --openai-api-key your-key-goes-here
|
||||
```
|
||||
<!--[[[end]]]-->
|
||||
|
||||
See the
|
||||
[installation instructions](https://aider.chat/docs/install.html)
|
||||
and other
|
||||
[documentation](https://aider.chat/docs/usage.html)
|
||||
and
|
||||
[usage documentation](https://aider.chat/docs/usage.html)
|
||||
for more details.
|
||||
|
||||
## Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from packaging import version
|
||||
|
||||
__version__ = "0.67.1.dev"
|
||||
__version__ = "0.69.2.dev"
|
||||
safe_version = __version__
|
||||
|
||||
try:
|
||||
|
||||
@@ -56,6 +56,7 @@ class Analytics:
|
||||
host=posthog_host,
|
||||
on_error=self.posthog_error,
|
||||
enable_exception_autocapture=True,
|
||||
super_properties=self.get_system_info(), # Add system info to all events
|
||||
)
|
||||
|
||||
def disable(self, permanently):
|
||||
@@ -83,7 +84,7 @@ class Analytics:
|
||||
if not self.user_id:
|
||||
return False
|
||||
|
||||
PERCENT = 2.5
|
||||
PERCENT = 5
|
||||
return self.is_uuid_in_percentage(self.user_id, PERCENT)
|
||||
|
||||
def is_uuid_in_percentage(self, uuid_str, percent):
|
||||
@@ -164,6 +165,7 @@ class Analytics:
|
||||
"os_platform": platform.system(),
|
||||
"os_release": platform.release(),
|
||||
"machine": platform.machine(),
|
||||
"aider_version": __version__,
|
||||
}
|
||||
|
||||
def _redact_model_name(self, model):
|
||||
@@ -179,6 +181,7 @@ class Analytics:
|
||||
|
||||
def posthog_error(self):
|
||||
"""disable posthog if we get an error"""
|
||||
print("X" * 100)
|
||||
# https://github.com/PostHog/posthog-python/blob/9e1bb8c58afaa229da24c4fb576c08bb88a75752/posthog/consumer.py#L86
|
||||
# https://github.com/Aider-AI/aider/issues/2532
|
||||
self.ph = None
|
||||
@@ -195,7 +198,6 @@ class Analytics:
|
||||
properties["editor_model"] = self._redact_model_name(main_model.editor_model)
|
||||
|
||||
properties.update(kwargs)
|
||||
properties.update(self.get_system_info()) # Add system info to all events
|
||||
|
||||
# Handle numeric values
|
||||
for key, value in properties.items():
|
||||
@@ -204,8 +206,6 @@ class Analytics:
|
||||
else:
|
||||
properties[key] = str(value)
|
||||
|
||||
properties["aider_version"] = __version__
|
||||
|
||||
if self.mp:
|
||||
try:
|
||||
self.mp.track(self.user_id, event_name, dict(properties))
|
||||
|
||||
331
aider/args.py
331
aider/args.py
@@ -28,22 +28,10 @@ def get_parser(default_config_files, git_root):
|
||||
config_file_parser_class=configargparse.YAMLConfigFileParser,
|
||||
auto_env_var_prefix="AIDER_",
|
||||
)
|
||||
group = parser.add_argument_group("Main")
|
||||
group = parser.add_argument_group("Main model")
|
||||
group.add_argument(
|
||||
"files", metavar="FILE", nargs="*", help="files to edit with an LLM (optional)"
|
||||
)
|
||||
group.add_argument(
|
||||
"--openai-api-key",
|
||||
metavar="OPENAI_API_KEY",
|
||||
env_var="OPENAI_API_KEY",
|
||||
help="Specify the OpenAI API key",
|
||||
)
|
||||
group.add_argument(
|
||||
"--anthropic-api-key",
|
||||
metavar="ANTHROPIC_API_KEY",
|
||||
env_var="ANTHROPIC_API_KEY",
|
||||
help="Specify the Anthropic API key",
|
||||
)
|
||||
group.add_argument(
|
||||
"--model",
|
||||
metavar="MODEL",
|
||||
@@ -144,43 +132,59 @@ def get_parser(default_config_files, git_root):
|
||||
)
|
||||
|
||||
##########
|
||||
group = parser.add_argument_group("Model Settings")
|
||||
group = parser.add_argument_group("API Keys and settings")
|
||||
group.add_argument(
|
||||
"--openai-api-key",
|
||||
help="Specify the OpenAI API key",
|
||||
)
|
||||
group.add_argument(
|
||||
"--anthropic-api-key",
|
||||
help="Specify the Anthropic API key",
|
||||
)
|
||||
group.add_argument(
|
||||
"--openai-api-base",
|
||||
help="Specify the api base url",
|
||||
)
|
||||
group.add_argument(
|
||||
"--openai-api-type",
|
||||
help="(deprecated, use --set-env OPENAI_API_TYPE=<value>)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--openai-api-version",
|
||||
help="(deprecated, use --set-env OPENAI_API_VERSION=<value>)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--openai-api-deployment-id",
|
||||
help="(deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=<value>)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--openai-organization-id",
|
||||
help="(deprecated, use --set-env OPENAI_ORGANIZATION=<value>)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--set-env",
|
||||
action="append",
|
||||
metavar="ENV_VAR_NAME=value",
|
||||
help="Set an environment variable (to control API settings, can be used multiple times)",
|
||||
default=[],
|
||||
)
|
||||
group.add_argument(
|
||||
"--api-key",
|
||||
action="append",
|
||||
metavar="PROVIDER=KEY",
|
||||
help=(
|
||||
"Set an API key for a provider (eg: --api-key provider=<key> sets"
|
||||
" PROVIDER_API_KEY=<key>)"
|
||||
),
|
||||
default=[],
|
||||
)
|
||||
group = parser.add_argument_group("Model settings")
|
||||
group.add_argument(
|
||||
"--list-models",
|
||||
"--models",
|
||||
metavar="MODEL",
|
||||
help="List known models which match the (partial) MODEL name",
|
||||
)
|
||||
group.add_argument(
|
||||
"--openai-api-base",
|
||||
metavar="OPENAI_API_BASE",
|
||||
env_var="OPENAI_API_BASE",
|
||||
help="Specify the api base url",
|
||||
)
|
||||
group.add_argument(
|
||||
"--openai-api-type",
|
||||
metavar="OPENAI_API_TYPE",
|
||||
env_var="OPENAI_API_TYPE",
|
||||
help="Specify the api_type",
|
||||
)
|
||||
group.add_argument(
|
||||
"--openai-api-version",
|
||||
metavar="OPENAI_API_VERSION",
|
||||
env_var="OPENAI_API_VERSION",
|
||||
help="Specify the api_version",
|
||||
)
|
||||
group.add_argument(
|
||||
"--openai-api-deployment-id",
|
||||
metavar="OPENAI_API_DEPLOYMENT_ID",
|
||||
env_var="OPENAI_API_DEPLOYMENT_ID",
|
||||
help="Specify the deployment_id",
|
||||
)
|
||||
group.add_argument(
|
||||
"--openai-organization-id",
|
||||
metavar="OPENAI_ORGANIZATION_ID",
|
||||
env_var="OPENAI_ORGANIZATION_ID",
|
||||
help="Specify the OpenAI organization ID",
|
||||
)
|
||||
group.add_argument(
|
||||
"--model-settings-file",
|
||||
metavar="MODEL_SETTINGS_FILE",
|
||||
@@ -261,17 +265,9 @@ def get_parser(default_config_files, git_root):
|
||||
" If unspecified, defaults to the model's max_chat_history_tokens."
|
||||
),
|
||||
)
|
||||
# This is a duplicate of the argument in the preparser and is a no-op by this time of
|
||||
# argument parsing, but it's here so that the help is displayed as expected.
|
||||
group.add_argument(
|
||||
"--env-file",
|
||||
metavar="ENV_FILE",
|
||||
default=default_env_file(git_root),
|
||||
help="Specify the .env file to load (default: .env in git root)",
|
||||
)
|
||||
|
||||
##########
|
||||
group = parser.add_argument_group("Cache Settings")
|
||||
group = parser.add_argument_group("Cache settings")
|
||||
group.add_argument(
|
||||
"--cache-prompts",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
@@ -286,7 +282,7 @@ def get_parser(default_config_files, git_root):
|
||||
)
|
||||
|
||||
##########
|
||||
group = parser.add_argument_group("Repomap Settings")
|
||||
group = parser.add_argument_group("Repomap settings")
|
||||
group.add_argument(
|
||||
"--map-tokens",
|
||||
type=int,
|
||||
@@ -343,7 +339,7 @@ def get_parser(default_config_files, git_root):
|
||||
)
|
||||
|
||||
##########
|
||||
group = parser.add_argument_group("Output Settings")
|
||||
group = parser.add_argument_group("Output settings")
|
||||
group.add_argument(
|
||||
"--dark-mode",
|
||||
action="store_true",
|
||||
@@ -442,7 +438,7 @@ def get_parser(default_config_files, git_root):
|
||||
)
|
||||
|
||||
##########
|
||||
group = parser.add_argument_group("Git Settings")
|
||||
group = parser.add_argument_group("Git settings")
|
||||
group.add_argument(
|
||||
"--git",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
@@ -595,37 +591,8 @@ def get_parser(default_config_files, git_root):
|
||||
default=False,
|
||||
)
|
||||
|
||||
group = parser.add_argument_group("Other Settings")
|
||||
group.add_argument(
|
||||
"--file",
|
||||
action="append",
|
||||
metavar="FILE",
|
||||
help="specify a file to edit (can be used multiple times)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--read",
|
||||
action="append",
|
||||
metavar="FILE",
|
||||
help="specify a read-only file (can be used multiple times)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--vim",
|
||||
action="store_true",
|
||||
help="Use VI editing mode in the terminal (default: False)",
|
||||
default=False,
|
||||
)
|
||||
group.add_argument(
|
||||
"--chat-language",
|
||||
metavar="CHAT_LANGUAGE",
|
||||
default=None,
|
||||
help="Specify the language to use in the chat (default: None, uses system settings)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--version",
|
||||
action="version",
|
||||
version=f"%(prog)s {__version__}",
|
||||
help="Show the version number and exit",
|
||||
)
|
||||
#########
|
||||
group = parser.add_argument_group("Upgrading")
|
||||
group.add_argument(
|
||||
"--just-check-update",
|
||||
action="store_true",
|
||||
@@ -658,47 +625,14 @@ def get_parser(default_config_files, git_root):
|
||||
default=False,
|
||||
)
|
||||
group.add_argument(
|
||||
"--apply",
|
||||
metavar="FILE",
|
||||
help="Apply the changes from the given file instead of running the chat (debug)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--apply-clipboard-edits",
|
||||
action="store_true",
|
||||
help="Apply clipboard contents as edits using the main model's editor format",
|
||||
default=False,
|
||||
)
|
||||
group.add_argument(
|
||||
"--yes-always",
|
||||
action="store_true",
|
||||
help="Always say yes to every confirmation",
|
||||
default=None,
|
||||
)
|
||||
group.add_argument(
|
||||
"-v",
|
||||
"--verbose",
|
||||
action="store_true",
|
||||
help="Enable verbose output",
|
||||
default=False,
|
||||
)
|
||||
group.add_argument(
|
||||
"--show-repo-map",
|
||||
action="store_true",
|
||||
help="Print the repo map and exit (debug)",
|
||||
default=False,
|
||||
)
|
||||
group.add_argument(
|
||||
"--show-prompts",
|
||||
action="store_true",
|
||||
help="Print the system prompts and exit (debug)",
|
||||
default=False,
|
||||
)
|
||||
group.add_argument(
|
||||
"--exit",
|
||||
action="store_true",
|
||||
help="Do all startup activities then exit before accepting user input (debug)",
|
||||
default=False,
|
||||
"--version",
|
||||
action="version",
|
||||
version=f"%(prog)s {__version__}",
|
||||
help="Show the version number and exit",
|
||||
)
|
||||
|
||||
##########
|
||||
group = parser.add_argument_group("Modes")
|
||||
group.add_argument(
|
||||
"--message",
|
||||
"--msg",
|
||||
@@ -717,6 +651,110 @@ def get_parser(default_config_files, git_root):
|
||||
" (disables chat mode)"
|
||||
),
|
||||
)
|
||||
group.add_argument(
|
||||
"--gui",
|
||||
"--browser",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
help="Run aider in your browser (default: False)",
|
||||
default=False,
|
||||
)
|
||||
group.add_argument(
|
||||
"--copy-paste",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
default=False,
|
||||
help="Enable automatic copy/paste of chat between aider and web UI (default: False)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--apply",
|
||||
metavar="FILE",
|
||||
help="Apply the changes from the given file instead of running the chat (debug)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--apply-clipboard-edits",
|
||||
action="store_true",
|
||||
help="Apply clipboard contents as edits using the main model's editor format",
|
||||
default=False,
|
||||
)
|
||||
group.add_argument(
|
||||
"--exit",
|
||||
action="store_true",
|
||||
help="Do all startup activities then exit before accepting user input (debug)",
|
||||
default=False,
|
||||
)
|
||||
group.add_argument(
|
||||
"--show-repo-map",
|
||||
action="store_true",
|
||||
help="Print the repo map and exit (debug)",
|
||||
default=False,
|
||||
)
|
||||
group.add_argument(
|
||||
"--show-prompts",
|
||||
action="store_true",
|
||||
help="Print the system prompts and exit (debug)",
|
||||
default=False,
|
||||
)
|
||||
|
||||
##########
|
||||
group = parser.add_argument_group("Voice settings")
|
||||
group.add_argument(
|
||||
"--voice-format",
|
||||
metavar="VOICE_FORMAT",
|
||||
default="wav",
|
||||
choices=["wav", "mp3", "webm"],
|
||||
help="Audio format for voice recording (default: wav). webm and mp3 require ffmpeg",
|
||||
)
|
||||
group.add_argument(
|
||||
"--voice-language",
|
||||
metavar="VOICE_LANGUAGE",
|
||||
default="en",
|
||||
help="Specify the language for voice using ISO 639-1 code (default: auto)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--voice-input-device",
|
||||
metavar="VOICE_INPUT_DEVICE",
|
||||
default=None,
|
||||
help="Specify the input device name for voice recording",
|
||||
)
|
||||
|
||||
######
|
||||
group = parser.add_argument_group("Other settings")
|
||||
group.add_argument(
|
||||
"--file",
|
||||
action="append",
|
||||
metavar="FILE",
|
||||
help="specify a file to edit (can be used multiple times)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--read",
|
||||
action="append",
|
||||
metavar="FILE",
|
||||
help="specify a read-only file (can be used multiple times)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--vim",
|
||||
action="store_true",
|
||||
help="Use VI editing mode in the terminal (default: False)",
|
||||
default=False,
|
||||
)
|
||||
group.add_argument(
|
||||
"--chat-language",
|
||||
metavar="CHAT_LANGUAGE",
|
||||
default=None,
|
||||
help="Specify the language to use in the chat (default: None, uses system settings)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--yes-always",
|
||||
action="store_true",
|
||||
help="Always say yes to every confirmation",
|
||||
default=None,
|
||||
)
|
||||
group.add_argument(
|
||||
"-v",
|
||||
"--verbose",
|
||||
action="store_true",
|
||||
help="Enable verbose output",
|
||||
default=False,
|
||||
)
|
||||
group.add_argument(
|
||||
"--load",
|
||||
metavar="LOAD_FILE",
|
||||
@@ -737,12 +775,13 @@ def get_parser(default_config_files, git_root):
|
||||
" or home directory)"
|
||||
),
|
||||
)
|
||||
# This is a duplicate of the argument in the preparser and is a no-op by this time of
|
||||
# argument parsing, but it's here so that the help is displayed as expected.
|
||||
group.add_argument(
|
||||
"--gui",
|
||||
"--browser",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
help="Run aider in your browser (default: False)",
|
||||
default=False,
|
||||
"--env-file",
|
||||
metavar="ENV_FILE",
|
||||
default=default_env_file(git_root),
|
||||
help="Specify the .env file to load (default: .env in git root)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--suggest-shell-commands",
|
||||
@@ -756,6 +795,12 @@ def get_parser(default_config_files, git_root):
|
||||
default=True,
|
||||
help="Enable/disable fancy input with history and completion (default: True)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--multiline",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
default=False,
|
||||
help="Enable/disable multi-line input mode with Meta-Enter to submit (default: False)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--detect-urls",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
@@ -767,28 +812,6 @@ def get_parser(default_config_files, git_root):
|
||||
help="Specify which editor to use for the /editor command",
|
||||
)
|
||||
|
||||
##########
|
||||
group = parser.add_argument_group("Voice Settings")
|
||||
group.add_argument(
|
||||
"--voice-format",
|
||||
metavar="VOICE_FORMAT",
|
||||
default="wav",
|
||||
choices=["wav", "mp3", "webm"],
|
||||
help="Audio format for voice recording (default: wav). webm and mp3 require ffmpeg",
|
||||
)
|
||||
group.add_argument(
|
||||
"--voice-language",
|
||||
metavar="VOICE_LANGUAGE",
|
||||
default="en",
|
||||
help="Specify the language for voice using ISO 639-1 code (default: auto)",
|
||||
)
|
||||
group.add_argument(
|
||||
"--voice-input-device",
|
||||
metavar="VOICE_INPUT_DEVICE",
|
||||
default=None,
|
||||
help="Specify the input device name for voice recording",
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
|
||||
@@ -248,6 +248,9 @@ class Coder:
|
||||
if self.done_messages:
|
||||
lines.append("Restored previous conversation history.")
|
||||
|
||||
if self.io.multiline_mode:
|
||||
lines.append("Multiline mode: Enabled. Enter inserts newline, Alt-Enter submits text")
|
||||
|
||||
return lines
|
||||
|
||||
def __init__(
|
||||
@@ -286,6 +289,7 @@ class Coder:
|
||||
detect_urls=True,
|
||||
ignore_mentions=None,
|
||||
file_watcher=None,
|
||||
auto_copy_context=False,
|
||||
):
|
||||
# Fill in a dummy Analytics if needed, but it is never .enable()'d
|
||||
self.analytics = analytics if analytics is not None else Analytics()
|
||||
@@ -297,6 +301,8 @@ class Coder:
|
||||
self.rejected_urls = set()
|
||||
self.abs_root_path_cache = {}
|
||||
|
||||
self.auto_copy_context = auto_copy_context
|
||||
|
||||
self.ignore_mentions = ignore_mentions
|
||||
if not self.ignore_mentions:
|
||||
self.ignore_mentions = set()
|
||||
@@ -792,9 +798,10 @@ class Coder:
|
||||
self.io.user_input(with_message)
|
||||
self.run_one(with_message, preproc)
|
||||
return self.partial_response_content
|
||||
|
||||
while True:
|
||||
try:
|
||||
if not self.io.placeholder:
|
||||
self.copy_context()
|
||||
user_message = self.get_input()
|
||||
self.run_one(user_message, preproc)
|
||||
self.show_undo_hint()
|
||||
@@ -803,6 +810,10 @@ class Coder:
|
||||
except EOFError:
|
||||
return
|
||||
|
||||
def copy_context(self):
|
||||
if self.auto_copy_context:
|
||||
self.commands.cmd_copy_context()
|
||||
|
||||
def get_input(self):
|
||||
inchat_files = self.get_inchat_relative_files()
|
||||
read_only_files = [self.get_rel_fname(fname) for fname in self.abs_read_only_fnames]
|
||||
@@ -1114,7 +1125,10 @@ class Coder:
|
||||
# add the reminder anyway
|
||||
total_tokens = 0
|
||||
|
||||
final = chunks.cur[-1]
|
||||
if chunks.cur:
|
||||
final = chunks.cur[-1]
|
||||
else:
|
||||
final = None
|
||||
|
||||
max_input_tokens = self.main_model.info.get("max_input_tokens") or 0
|
||||
# Add the reminder prompt if we still have room to include it.
|
||||
@@ -1125,7 +1139,7 @@ class Coder:
|
||||
):
|
||||
if self.main_model.reminder == "sys":
|
||||
chunks.reminder = reminder_message
|
||||
elif self.main_model.reminder == "user" and final["role"] == "user":
|
||||
elif self.main_model.reminder == "user" and final and final["role"] == "user":
|
||||
# stuff it into the user message
|
||||
new_content = (
|
||||
final["content"]
|
||||
@@ -1460,7 +1474,7 @@ class Coder:
|
||||
words = set(word for word in content.split())
|
||||
|
||||
# drop sentence punctuation from the end
|
||||
words = set(word.rstrip(",.!;:") for word in words)
|
||||
words = set(word.rstrip(",.!;:?") for word in words)
|
||||
|
||||
# strip away all kinds of quotes
|
||||
quotes = "".join(['"', "'", "`"])
|
||||
@@ -1549,6 +1563,16 @@ class Coder:
|
||||
yield from self.show_send_output_stream(completion)
|
||||
else:
|
||||
self.show_send_output(completion)
|
||||
|
||||
# Calculate costs for successful responses
|
||||
self.calculate_and_show_tokens_and_cost(messages, completion)
|
||||
|
||||
except LiteLLMExceptions().exceptions_tuple() as err:
|
||||
ex_info = LiteLLMExceptions().get_ex_info(err)
|
||||
if ex_info.name == "ContextWindowExceededError":
|
||||
# Still calculate costs for context window errors
|
||||
self.calculate_and_show_tokens_and_cost(messages, completion)
|
||||
raise
|
||||
except KeyboardInterrupt as kbi:
|
||||
self.keyboard_interrupt()
|
||||
raise kbi
|
||||
@@ -1566,8 +1590,6 @@ class Coder:
|
||||
if args:
|
||||
self.io.ai_output(json.dumps(args, indent=4))
|
||||
|
||||
self.calculate_and_show_tokens_and_cost(messages, completion)
|
||||
|
||||
def show_send_output(self, completion):
|
||||
if self.verbose:
|
||||
print(completion)
|
||||
|
||||
@@ -35,7 +35,9 @@ ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
|
||||
|
||||
Just suggest shell commands this way, not example code.
|
||||
Only suggest complete shell commands that are ready to execute, without placeholders.
|
||||
Only suggest at most a few shell commands at a time, not more than 1-3.
|
||||
Only suggest at most a few shell commands at a time, not more than 1-3, one per line.
|
||||
Do not suggest multi-line shell commands.
|
||||
All shell commands will run from the root directory of the user's project.
|
||||
|
||||
Use the appropriate shell based on the user's system info:
|
||||
{platform}
|
||||
|
||||
@@ -3,5 +3,6 @@ from .editor_editblock_prompts import EditorEditBlockPrompts
|
||||
|
||||
|
||||
class EditorEditBlockCoder(EditBlockCoder):
|
||||
"A coder that uses search/replace blocks, focused purely on editing files."
|
||||
edit_format = "editor-diff"
|
||||
gpt_prompts = EditorEditBlockPrompts()
|
||||
|
||||
@@ -3,5 +3,6 @@ from .wholefile_coder import WholeFileCoder
|
||||
|
||||
|
||||
class EditorWholeFileCoder(WholeFileCoder):
|
||||
"A coder that operates on entire files, focused purely on editing files."
|
||||
edit_format = "editor-whole"
|
||||
gpt_prompts = EditorWholeFilePrompts()
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import git
|
||||
try:
|
||||
import git
|
||||
except ImportError:
|
||||
git = None
|
||||
|
||||
from diff_match_patch import diff_match_patch
|
||||
from tqdm import tqdm
|
||||
|
||||
|
||||
@@ -103,6 +103,13 @@ class Commands:
|
||||
("help", "Get help about using aider (usage, config, troubleshoot)."),
|
||||
("ask", "Ask questions about your code without making any changes."),
|
||||
("code", "Ask for changes to your code (using the best edit format)."),
|
||||
(
|
||||
"architect",
|
||||
(
|
||||
"Work with an architect model to design code changes, and an editor to make"
|
||||
" them."
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -1118,36 +1125,14 @@ class Commands:
|
||||
)
|
||||
return
|
||||
|
||||
history_iter = self.io.get_input_history()
|
||||
|
||||
history = []
|
||||
size = 0
|
||||
for line in history_iter:
|
||||
if line.startswith("/"):
|
||||
continue
|
||||
if line in history:
|
||||
continue
|
||||
if size + len(line) > 1024:
|
||||
break
|
||||
size += len(line)
|
||||
history.append(line)
|
||||
|
||||
history.reverse()
|
||||
history = "\n".join(history)
|
||||
|
||||
try:
|
||||
text = self.voice.record_and_transcribe(history, language=self.voice_language)
|
||||
text = self.voice.record_and_transcribe(None, language=self.voice_language)
|
||||
except litellm.OpenAIError as err:
|
||||
self.io.tool_error(f"Unable to use OpenAI whisper model: {err}")
|
||||
return
|
||||
|
||||
if text:
|
||||
self.io.add_to_input_history(text)
|
||||
self.io.print()
|
||||
self.io.user_input(text, log_only=False)
|
||||
self.io.print()
|
||||
|
||||
return text
|
||||
self.io.placeholder = text
|
||||
|
||||
def cmd_paste(self, args):
|
||||
"""Paste image/text from the clipboard into the chat.\
|
||||
@@ -1200,9 +1185,14 @@ class Commands:
|
||||
self.io.tool_error(f"Error processing clipboard content: {e}")
|
||||
|
||||
def cmd_read_only(self, args):
|
||||
"Add files to the chat that are for reference, not to be edited"
|
||||
"Add files to the chat that are for reference only, or turn added files to read-only"
|
||||
if not args.strip():
|
||||
self.io.tool_error("Please provide filenames or directories to read.")
|
||||
# Convert all files in chat to read-only
|
||||
for fname in list(self.coder.abs_fnames):
|
||||
self.coder.abs_fnames.remove(fname)
|
||||
self.coder.abs_read_only_fnames.add(fname)
|
||||
rel_fname = self.coder.get_rel_fname(fname)
|
||||
self.io.tool_output(f"Converted {rel_fname} to read-only")
|
||||
return
|
||||
|
||||
filenames = parse_quoted_filenames(args)
|
||||
@@ -1351,6 +1341,10 @@ class Commands:
|
||||
except Exception as e:
|
||||
self.io.tool_error(f"Error saving commands to file: {e}")
|
||||
|
||||
def cmd_multiline_mode(self, args):
|
||||
"Toggle multiline mode (swaps behavior of Enter and Meta+Enter)"
|
||||
self.io.toggle_multiline_mode()
|
||||
|
||||
def cmd_copy(self, args):
|
||||
"Copy the last assistant message to the clipboard"
|
||||
all_messages = self.coder.done_messages + self.coder.cur_messages
|
||||
@@ -1399,6 +1393,50 @@ class Commands:
|
||||
if user_input.strip():
|
||||
self.io.set_placeholder(user_input.rstrip())
|
||||
|
||||
def cmd_copy_context(self, args=None):
|
||||
"""Copy the current chat context as markdown, suitable to paste into a web UI"""
|
||||
|
||||
chunks = self.coder.format_chat_chunks()
|
||||
|
||||
markdown = ""
|
||||
|
||||
# Only include specified chunks in order
|
||||
for messages in [chunks.repo, chunks.readonly_files, chunks.chat_files]:
|
||||
for msg in messages:
|
||||
# Only include user messages
|
||||
if msg["role"] != "user":
|
||||
continue
|
||||
|
||||
content = msg["content"]
|
||||
|
||||
# Handle image/multipart content
|
||||
if isinstance(content, list):
|
||||
for part in content:
|
||||
if part.get("type") == "text":
|
||||
markdown += part["text"] + "\n\n"
|
||||
else:
|
||||
markdown += content + "\n\n"
|
||||
|
||||
args = args or ""
|
||||
markdown += f"""
|
||||
Just tell me how to edit the files to make the changes.
|
||||
Don't give me back entire files.
|
||||
Just show me the edits I need to make.
|
||||
|
||||
{args}
|
||||
"""
|
||||
|
||||
try:
|
||||
pyperclip.copy(markdown)
|
||||
self.io.tool_output("Copied code context to clipboard.")
|
||||
except pyperclip.PyperclipException as e:
|
||||
self.io.tool_error(f"Failed to copy to clipboard: {str(e)}")
|
||||
self.io.tool_output(
|
||||
"You may need to install xclip or xsel on Linux, or pbcopy on macOS."
|
||||
)
|
||||
except Exception as e:
|
||||
self.io.tool_error(f"An unexpected error occurred while copying to clipboard: {str(e)}")
|
||||
|
||||
|
||||
def expand_subdir(file_path):
|
||||
if file_path.is_file():
|
||||
|
||||
72
aider/copypaste.py
Normal file
72
aider/copypaste.py
Normal file
@@ -0,0 +1,72 @@
|
||||
import threading
|
||||
import time
|
||||
|
||||
import pyperclip
|
||||
|
||||
|
||||
class ClipboardWatcher:
|
||||
"""Watches clipboard for changes and updates IO placeholder"""
|
||||
|
||||
def __init__(self, io, verbose=False):
|
||||
self.io = io
|
||||
self.verbose = verbose
|
||||
self.stop_event = None
|
||||
self.watcher_thread = None
|
||||
self.last_clipboard = None
|
||||
self.io.clipboard_watcher = self
|
||||
|
||||
def start(self):
|
||||
"""Start watching clipboard for changes"""
|
||||
self.stop_event = threading.Event()
|
||||
self.last_clipboard = pyperclip.paste()
|
||||
|
||||
def watch_clipboard():
|
||||
while not self.stop_event.is_set():
|
||||
try:
|
||||
current = pyperclip.paste()
|
||||
if current != self.last_clipboard:
|
||||
self.last_clipboard = current
|
||||
self.io.interrupt_input()
|
||||
self.io.placeholder = current
|
||||
if len(current.splitlines()) > 1:
|
||||
self.io.placeholder = "\n" + self.io.placeholder + "\n"
|
||||
|
||||
time.sleep(0.5)
|
||||
except Exception as e:
|
||||
if self.verbose:
|
||||
from aider.dump import dump
|
||||
|
||||
dump(f"Clipboard watcher error: {e}")
|
||||
continue
|
||||
|
||||
self.watcher_thread = threading.Thread(target=watch_clipboard, daemon=True)
|
||||
self.watcher_thread.start()
|
||||
|
||||
def stop(self):
|
||||
"""Stop watching clipboard for changes"""
|
||||
if self.stop_event:
|
||||
self.stop_event.set()
|
||||
if self.watcher_thread:
|
||||
self.watcher_thread.join()
|
||||
self.watcher_thread = None
|
||||
self.stop_event = None
|
||||
|
||||
|
||||
def main():
|
||||
"""Example usage of the clipboard watcher"""
|
||||
from aider.io import InputOutput
|
||||
|
||||
io = InputOutput()
|
||||
watcher = ClipboardWatcher(io, verbose=True)
|
||||
|
||||
try:
|
||||
watcher.start()
|
||||
while True:
|
||||
time.sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
print("\nStopped watching clipboard")
|
||||
watcher.stop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -78,4 +78,13 @@ class LiteLLMExceptions:
|
||||
|
||||
def get_ex_info(self, ex):
|
||||
"""Return the ExInfo for a given exception instance"""
|
||||
import litellm
|
||||
|
||||
if ex.__class__ is litellm.APIConnectionError:
|
||||
if "google.auth" in str(ex):
|
||||
return ExInfo(
|
||||
"APIConnectionError", False, "You need to: pip install google-generativeai"
|
||||
)
|
||||
if "boto3" in str(ex):
|
||||
return ExInfo("APIConnectionError", False, "You need to: pip install boto3")
|
||||
return self.exceptions.get(ex.__class__, ExInfo(None, None, None))
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# This needs to sync with MANIFEST.in
|
||||
|
||||
exclude_website_pats = [
|
||||
"**/.DS_Store",
|
||||
"examples/**",
|
||||
"_posts/**",
|
||||
"HISTORY.md",
|
||||
@@ -7,5 +10,4 @@ exclude_website_pats = [
|
||||
"docs/unified-diffs.md",
|
||||
"docs/leaderboards/index.md",
|
||||
"assets/**",
|
||||
"**/.DS_Store",
|
||||
]
|
||||
|
||||
@@ -108,9 +108,7 @@ class ChatSummary:
|
||||
|
||||
for model in self.models:
|
||||
try:
|
||||
summary = simple_send_with_retries(
|
||||
model.name, summarize_messages, extra_params=model.extra_params
|
||||
)
|
||||
summary = simple_send_with_retries(model, summarize_messages)
|
||||
if summary is not None:
|
||||
summary = prompts.summary_prefix + summary
|
||||
return [dict(role="user", content=summary)]
|
||||
|
||||
69
aider/io.py
69
aider/io.py
@@ -12,7 +12,7 @@ from pathlib import Path
|
||||
from prompt_toolkit.completion import Completer, Completion, ThreadedCompleter
|
||||
from prompt_toolkit.cursor_shapes import ModalCursorShapeConfig
|
||||
from prompt_toolkit.enums import EditingMode
|
||||
from prompt_toolkit.filters import Condition
|
||||
from prompt_toolkit.filters import Condition, is_searching
|
||||
from prompt_toolkit.history import FileHistory
|
||||
from prompt_toolkit.key_binding import KeyBindings
|
||||
from prompt_toolkit.keys import Keys
|
||||
@@ -176,6 +176,7 @@ class AutoCompleter(Completer):
|
||||
class InputOutput:
|
||||
num_error_outputs = 0
|
||||
num_user_asks = 0
|
||||
clipboard_watcher = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -201,11 +202,13 @@ class InputOutput:
|
||||
editingmode=EditingMode.EMACS,
|
||||
fancy_input=True,
|
||||
file_watcher=None,
|
||||
multiline_mode=False,
|
||||
):
|
||||
self.placeholder = None
|
||||
self.interrupted = False
|
||||
self.never_prompts = set()
|
||||
self.editingmode = editingmode
|
||||
self.multiline_mode = multiline_mode
|
||||
no_color = os.environ.get("NO_COLOR")
|
||||
if no_color is not None and no_color != "":
|
||||
pretty = False
|
||||
@@ -411,6 +414,8 @@ class InputOutput:
|
||||
show = self.format_files_for_input(rel_fnames, rel_read_only_fnames)
|
||||
if edit_format:
|
||||
show += edit_format
|
||||
if self.multiline_mode:
|
||||
show += (" " if edit_format else "") + "multi"
|
||||
show += "> "
|
||||
|
||||
inp = ""
|
||||
@@ -455,9 +460,25 @@ class InputOutput:
|
||||
"Navigate forward through history"
|
||||
event.current_buffer.history_forward()
|
||||
|
||||
@kb.add("escape", "c-m", eager=True)
|
||||
@kb.add("enter", eager=True, filter=~is_searching)
|
||||
def _(event):
|
||||
event.current_buffer.insert_text("\n")
|
||||
"Handle Enter key press"
|
||||
if self.multiline_mode:
|
||||
# In multiline mode, Enter adds a newline
|
||||
event.current_buffer.insert_text("\n")
|
||||
else:
|
||||
# In normal mode, Enter submits
|
||||
event.current_buffer.validate_and_handle()
|
||||
|
||||
@kb.add("escape", "enter", eager=True, filter=~is_searching) # This is Alt+Enter
|
||||
def _(event):
|
||||
"Handle Alt+Enter key press"
|
||||
if self.multiline_mode:
|
||||
# In multiline mode, Alt+Enter submits
|
||||
event.current_buffer.validate_and_handle()
|
||||
else:
|
||||
# In normal mode, Alt+Enter adds a newline
|
||||
event.current_buffer.insert_text("\n")
|
||||
|
||||
while True:
|
||||
if multiline_input:
|
||||
@@ -470,8 +491,11 @@ class InputOutput:
|
||||
self.placeholder = None
|
||||
|
||||
self.interrupted = False
|
||||
if not multiline_input and self.file_watcher:
|
||||
self.file_watcher.start()
|
||||
if not multiline_input:
|
||||
if self.file_watcher:
|
||||
self.file_watcher.start()
|
||||
if self.clipboard_watcher:
|
||||
self.clipboard_watcher.start()
|
||||
|
||||
line = self.prompt_session.prompt(
|
||||
show,
|
||||
@@ -487,11 +511,13 @@ class InputOutput:
|
||||
|
||||
# Check if we were interrupted by a file change
|
||||
if self.interrupted:
|
||||
cmd = self.file_watcher.process_changes()
|
||||
return cmd
|
||||
line = line or ""
|
||||
if self.file_watcher:
|
||||
cmd = self.file_watcher.process_changes()
|
||||
return cmd
|
||||
|
||||
except EOFError:
|
||||
return ""
|
||||
raise
|
||||
except Exception as err:
|
||||
import traceback
|
||||
|
||||
@@ -504,6 +530,8 @@ class InputOutput:
|
||||
finally:
|
||||
if self.file_watcher:
|
||||
self.file_watcher.stop()
|
||||
if self.clipboard_watcher:
|
||||
self.clipboard_watcher.stop()
|
||||
|
||||
if line.strip("\r\n") and not multiline_input:
|
||||
stripped = line.strip("\r\n")
|
||||
@@ -621,6 +649,9 @@ class InputOutput:
|
||||
group=None,
|
||||
allow_never=False,
|
||||
):
|
||||
# Temporarily disable multiline mode for yes/no prompts
|
||||
orig_multiline = self.multiline_mode
|
||||
self.multiline_mode = False
|
||||
self.num_user_asks += 1
|
||||
|
||||
question_id = (question, subject)
|
||||
@@ -678,6 +709,7 @@ class InputOutput:
|
||||
res = self.prompt_session.prompt(
|
||||
question,
|
||||
style=style,
|
||||
complete_while_typing=False,
|
||||
)
|
||||
else:
|
||||
res = input(question)
|
||||
@@ -718,9 +750,15 @@ class InputOutput:
|
||||
hist = f"{question.strip()} {res}"
|
||||
self.append_chat_history(hist, linebreak=True, blockquote=True)
|
||||
|
||||
# Restore original multiline mode
|
||||
self.multiline_mode = orig_multiline
|
||||
|
||||
return is_yes
|
||||
|
||||
def prompt_ask(self, question, default="", subject=None):
|
||||
# Temporarily disable multiline mode for prompts
|
||||
orig_multiline = self.multiline_mode
|
||||
self.multiline_mode = False
|
||||
self.num_user_asks += 1
|
||||
|
||||
if subject:
|
||||
@@ -744,6 +782,9 @@ class InputOutput:
|
||||
if self.yes in (True, False):
|
||||
self.tool_output(hist)
|
||||
|
||||
# Restore original multiline mode
|
||||
self.multiline_mode = orig_multiline
|
||||
|
||||
return res
|
||||
|
||||
def _tool_message(self, message="", strip=True, color=None):
|
||||
@@ -813,6 +854,18 @@ class InputOutput:
|
||||
def print(self, message=""):
|
||||
print(message)
|
||||
|
||||
def toggle_multiline_mode(self):
|
||||
"""Toggle between normal and multiline input modes"""
|
||||
self.multiline_mode = not self.multiline_mode
|
||||
if self.multiline_mode:
|
||||
self.tool_output(
|
||||
"Multiline mode: Enabled. Enter inserts newline, Alt-Enter submits text"
|
||||
)
|
||||
else:
|
||||
self.tool_output(
|
||||
"Multiline mode: Disabled. Alt-Enter inserts newline, Enter submits text"
|
||||
)
|
||||
|
||||
def append_chat_history(self, text, linebreak=False, blockquote=False, strip=True):
|
||||
if blockquote:
|
||||
if strip:
|
||||
|
||||
@@ -9,7 +9,11 @@ import webbrowser
|
||||
from dataclasses import fields
|
||||
from pathlib import Path
|
||||
|
||||
import git
|
||||
try:
|
||||
import git
|
||||
except ImportError:
|
||||
git = None
|
||||
|
||||
import importlib_resources
|
||||
from dotenv import load_dotenv
|
||||
from prompt_toolkit.enums import EditingMode
|
||||
@@ -20,6 +24,7 @@ from aider.args import get_parser
|
||||
from aider.coders import Coder
|
||||
from aider.coders.base_coder import UnknownEditFormat
|
||||
from aider.commands import Commands, SwitchCoder
|
||||
from aider.copypaste import ClipboardWatcher
|
||||
from aider.format_settings import format_settings, scrub_sensitive_info
|
||||
from aider.history import ChatSummary
|
||||
from aider.io import InputOutput
|
||||
@@ -92,6 +97,9 @@ def make_new_repo(git_root, io):
|
||||
|
||||
|
||||
def setup_git(git_root, io):
|
||||
if git is None:
|
||||
return
|
||||
|
||||
try:
|
||||
cwd = Path.cwd()
|
||||
except OSError:
|
||||
@@ -409,7 +417,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
||||
if argv is None:
|
||||
argv = sys.argv[1:]
|
||||
|
||||
if force_git_root:
|
||||
if git is None:
|
||||
git_root = None
|
||||
elif force_git_root:
|
||||
git_root = force_git_root
|
||||
else:
|
||||
git_root = get_git_root()
|
||||
@@ -456,6 +466,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
||||
# Parse again to include any arguments that might have been defined in .env
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
if git is None:
|
||||
args.git = False
|
||||
|
||||
if args.analytics_disable:
|
||||
analytics = Analytics(permanently_disable=True)
|
||||
print("Analytics have been permanently disabled.")
|
||||
@@ -514,6 +527,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
||||
llm_history_file=args.llm_history_file,
|
||||
editingmode=editing_mode,
|
||||
fancy_input=args.fancy_input,
|
||||
multiline_mode=args.multiline,
|
||||
)
|
||||
|
||||
io = get_io(args.pretty)
|
||||
@@ -525,6 +539,50 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
||||
io = get_io(False)
|
||||
io.tool_warning("Terminal does not support pretty output (UnicodeDecodeError)")
|
||||
|
||||
# Process any environment variables set via --set-env
|
||||
if args.set_env:
|
||||
for env_setting in args.set_env:
|
||||
try:
|
||||
name, value = env_setting.split("=", 1)
|
||||
os.environ[name.strip()] = value.strip()
|
||||
except ValueError:
|
||||
io.tool_error(f"Invalid --set-env format: {env_setting}")
|
||||
io.tool_output("Format should be: ENV_VAR_NAME=value")
|
||||
return 1
|
||||
|
||||
# Process any API keys set via --api-key
|
||||
if args.api_key:
|
||||
for api_setting in args.api_key:
|
||||
try:
|
||||
provider, key = api_setting.split("=", 1)
|
||||
env_var = f"{provider.strip().upper()}_API_KEY"
|
||||
os.environ[env_var] = key.strip()
|
||||
except ValueError:
|
||||
io.tool_error(f"Invalid --api-key format: {api_setting}")
|
||||
io.tool_output("Format should be: provider=key")
|
||||
return 1
|
||||
|
||||
if args.anthropic_api_key:
|
||||
os.environ["ANTHROPIC_API_KEY"] = args.anthropic_api_key
|
||||
|
||||
if args.openai_api_key:
|
||||
os.environ["OPENAI_API_KEY"] = args.openai_api_key
|
||||
if args.openai_api_base:
|
||||
os.environ["OPENAI_API_BASE"] = args.openai_api_base
|
||||
if args.openai_api_version:
|
||||
io.tool_warning(
|
||||
"--openai-api-version is deprecated, use --set-env OPENAI_API_VERSION=<value>"
|
||||
)
|
||||
os.environ["OPENAI_API_VERSION"] = args.openai_api_version
|
||||
if args.openai_api_type:
|
||||
io.tool_warning("--openai-api-type is deprecated, use --set-env OPENAI_API_TYPE=<value>")
|
||||
os.environ["OPENAI_API_TYPE"] = args.openai_api_type
|
||||
if args.openai_organization_id:
|
||||
io.tool_warning(
|
||||
"--openai-organization-id is deprecated, use --set-env OPENAI_ORGANIZATION=<value>"
|
||||
)
|
||||
os.environ["OPENAI_ORGANIZATION"] = args.openai_organization_id
|
||||
|
||||
analytics = Analytics(logfile=args.analytics_log, permanently_disable=args.analytics_disable)
|
||||
if args.analytics is not False:
|
||||
if analytics.need_to_ask(args.analytics):
|
||||
@@ -600,7 +658,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
||||
# We can't know the git repo for sure until after parsing the args.
|
||||
# If we guessed wrong, reparse because that changes things like
|
||||
# the location of the config.yml and history files.
|
||||
if args.git and not force_git_root:
|
||||
if args.git and not force_git_root and git is not None:
|
||||
right_repo_root = guessed_wrong_repo(io, git_root, fnames, git_dname)
|
||||
if right_repo_root:
|
||||
analytics.event("exit", reason="Recursing with correct repo")
|
||||
@@ -645,20 +703,6 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
||||
is_first_run = is_first_run_of_new_version(io, verbose=args.verbose)
|
||||
check_and_load_imports(io, is_first_run, verbose=args.verbose)
|
||||
|
||||
if args.anthropic_api_key:
|
||||
os.environ["ANTHROPIC_API_KEY"] = args.anthropic_api_key
|
||||
|
||||
if args.openai_api_key:
|
||||
os.environ["OPENAI_API_KEY"] = args.openai_api_key
|
||||
if args.openai_api_base:
|
||||
os.environ["OPENAI_API_BASE"] = args.openai_api_base
|
||||
if args.openai_api_version:
|
||||
os.environ["OPENAI_API_VERSION"] = args.openai_api_version
|
||||
if args.openai_api_type:
|
||||
os.environ["OPENAI_API_TYPE"] = args.openai_api_type
|
||||
if args.openai_organization_id:
|
||||
os.environ["OPENAI_ORGANIZATION"] = args.openai_organization_id
|
||||
|
||||
register_models(git_root, args.model_settings_file, io, verbose=args.verbose)
|
||||
register_litellm_models(git_root, args.model_metadata_file, io, verbose=args.verbose)
|
||||
|
||||
@@ -687,6 +731,10 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
||||
editor_edit_format=args.editor_edit_format,
|
||||
)
|
||||
|
||||
if args.copy_paste and args.edit_format is None:
|
||||
if main_model.edit_format in ("diff", "whole"):
|
||||
main_model.edit_format = "editor-" + main_model.edit_format
|
||||
|
||||
if args.verbose:
|
||||
io.tool_output("Model metadata:")
|
||||
io.tool_output(json.dumps(main_model.info, indent=4))
|
||||
@@ -800,6 +848,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
||||
suggest_shell_commands=args.suggest_shell_commands,
|
||||
chat_language=args.chat_language,
|
||||
detect_urls=args.detect_urls,
|
||||
auto_copy_context=args.copy_paste,
|
||||
)
|
||||
except UnknownEditFormat as err:
|
||||
io.tool_error(str(err))
|
||||
@@ -822,9 +871,15 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
||||
ignores.append(args.aiderignore)
|
||||
|
||||
if args.watch_files:
|
||||
file_watcher = FileWatcher(coder, gitignores=ignores, verbose=args.verbose)
|
||||
file_watcher = FileWatcher(
|
||||
coder, gitignores=ignores, verbose=args.verbose, analytics=analytics
|
||||
)
|
||||
coder.file_watcher = file_watcher
|
||||
|
||||
if args.copy_paste:
|
||||
analytics.event("copy-paste mode")
|
||||
ClipboardWatcher(coder.io, verbose=args.verbose)
|
||||
|
||||
coder.show_announcements()
|
||||
|
||||
if args.show_prompts:
|
||||
@@ -844,9 +899,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
||||
io.tool_error("No --test-cmd provided.")
|
||||
analytics.event("exit", reason="No test command provided")
|
||||
return 1
|
||||
test_errors = coder.commands.cmd_test(args.test_cmd)
|
||||
if test_errors:
|
||||
coder.run(test_errors)
|
||||
coder.commands.cmd_test(args.test_cmd)
|
||||
if io.placeholder:
|
||||
coder.run(io.placeholder)
|
||||
|
||||
if args.commit:
|
||||
if args.dry_run:
|
||||
|
||||
@@ -76,6 +76,7 @@ MODEL_ALIASES = {
|
||||
"3": "gpt-3.5-turbo",
|
||||
# Other models
|
||||
"deepseek": "deepseek/deepseek-coder",
|
||||
"flash": "gemini/gemini-2.0-flash-exp",
|
||||
}
|
||||
|
||||
|
||||
@@ -583,6 +584,21 @@ MODEL_SETTINGS = [
|
||||
"diff-fenced",
|
||||
use_repo_map=True,
|
||||
),
|
||||
ModelSettings(
|
||||
"gemini/gemini-exp-1206",
|
||||
"diff",
|
||||
use_repo_map=True,
|
||||
),
|
||||
ModelSettings(
|
||||
"gemini/gemini-exp-1114",
|
||||
"diff",
|
||||
use_repo_map=True,
|
||||
),
|
||||
ModelSettings(
|
||||
"gemini/gemini-exp-1121",
|
||||
"diff",
|
||||
use_repo_map=True,
|
||||
),
|
||||
ModelSettings(
|
||||
"vertex_ai/gemini-pro-experimental",
|
||||
"diff-fenced",
|
||||
@@ -594,6 +610,12 @@ MODEL_SETTINGS = [
|
||||
use_repo_map=False,
|
||||
send_undo_reply=False,
|
||||
),
|
||||
ModelSettings(
|
||||
"gemini/gemini-2.0-flash-exp",
|
||||
"diff",
|
||||
use_repo_map=True,
|
||||
send_undo_reply=False,
|
||||
),
|
||||
ModelSettings(
|
||||
"deepseek/deepseek-chat",
|
||||
"diff",
|
||||
@@ -1210,10 +1232,10 @@ def sanity_check_model(io, model):
|
||||
status = "Set" if value else "Not set"
|
||||
io.tool_output(f"- {key}: {status}")
|
||||
|
||||
if platform.system() == "Windows" or True:
|
||||
if platform.system() == "Windows":
|
||||
io.tool_output(
|
||||
"If you just set these environment variables using `setx` you may need to restart"
|
||||
" your terminal or command prompt for the changes to take effect."
|
||||
"Note: You may need to restart your terminal or command prompt for `setx` to take"
|
||||
" effect."
|
||||
)
|
||||
|
||||
elif not model.keys_in_environment:
|
||||
|
||||
@@ -2,7 +2,17 @@ import os
|
||||
import time
|
||||
from pathlib import Path, PurePosixPath
|
||||
|
||||
import git
|
||||
try:
|
||||
import git
|
||||
|
||||
ANY_GIT_ERROR = [
|
||||
git.exc.ODBError,
|
||||
git.exc.GitError,
|
||||
]
|
||||
except ImportError:
|
||||
git = None
|
||||
ANY_GIT_ERROR = []
|
||||
|
||||
import pathspec
|
||||
|
||||
from aider import prompts, utils
|
||||
@@ -10,15 +20,14 @@ from aider.sendchat import simple_send_with_retries
|
||||
|
||||
from .dump import dump # noqa: F401
|
||||
|
||||
ANY_GIT_ERROR = (
|
||||
git.exc.ODBError,
|
||||
git.exc.GitError,
|
||||
ANY_GIT_ERROR += [
|
||||
OSError,
|
||||
IndexError,
|
||||
BufferError,
|
||||
TypeError,
|
||||
ValueError,
|
||||
)
|
||||
]
|
||||
ANY_GIT_ERROR = tuple(ANY_GIT_ERROR)
|
||||
|
||||
|
||||
class GitRepo:
|
||||
@@ -192,9 +201,7 @@ class GitRepo:
|
||||
max_tokens = model.info.get("max_input_tokens") or 0
|
||||
if max_tokens and num_tokens > max_tokens:
|
||||
continue
|
||||
commit_message = simple_send_with_retries(
|
||||
model.name, messages, extra_params=model.extra_params
|
||||
)
|
||||
commit_message = simple_send_with_retries(model, messages)
|
||||
if commit_message:
|
||||
break
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"vertex_ai-language-models/gemini-2.0-flash-exp": {
|
||||
"max_tokens": 8192,
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 8192,
|
||||
"max_images_per_prompt": 3000,
|
||||
"max_videos_per_prompt": 10,
|
||||
"max_video_length": 1,
|
||||
"max_audio_length_hours": 8.4,
|
||||
"max_audio_per_prompt": 1,
|
||||
"max_pdf_size_mb": 30,
|
||||
"litellm_provider": "vertex_ai-language-models",
|
||||
"mode": "chat",
|
||||
"supports_system_messages": true,
|
||||
"supports_function_calling": true,
|
||||
"supports_vision": true,
|
||||
"supports_response_schema": true,
|
||||
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/gemini-v2"
|
||||
},
|
||||
"gemini/gemini-2.0-flash-exp": {
|
||||
"max_tokens": 8192,
|
||||
"max_input_tokens": 1048576,
|
||||
"max_output_tokens": 8192,
|
||||
"max_images_per_prompt": 3000,
|
||||
"max_videos_per_prompt": 10,
|
||||
"max_video_length": 1,
|
||||
"max_audio_length_hours": 8.4,
|
||||
"max_audio_per_prompt": 1,
|
||||
"max_pdf_size_mb": 30,
|
||||
"litellm_provider": "gemini",
|
||||
"mode": "chat",
|
||||
"supports_system_messages": true,
|
||||
"supports_function_calling": true,
|
||||
"supports_vision": true,
|
||||
"supports_response_schema": true,
|
||||
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/gemini-v2"
|
||||
},
|
||||
}
|
||||
|
||||
@@ -56,18 +56,19 @@ def send_completion(
|
||||
return hash_object, res
|
||||
|
||||
|
||||
def simple_send_with_retries(model_name, messages, extra_params=None):
|
||||
def simple_send_with_retries(model, messages):
|
||||
litellm_ex = LiteLLMExceptions()
|
||||
|
||||
retry_delay = 0.125
|
||||
while True:
|
||||
try:
|
||||
kwargs = {
|
||||
"model_name": model_name,
|
||||
"model_name": model.name,
|
||||
"messages": messages,
|
||||
"functions": None,
|
||||
"stream": False,
|
||||
"extra_params": extra_params,
|
||||
"temperature": None if not model.use_temperature else 0,
|
||||
"extra_params": model.extra_params,
|
||||
}
|
||||
|
||||
_hash, response = send_completion(**kwargs)
|
||||
|
||||
@@ -2,15 +2,12 @@ import itertools
|
||||
import os
|
||||
import platform
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import git
|
||||
|
||||
from aider.dump import dump # noqa: F401
|
||||
|
||||
IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".webp", ".pdf"}
|
||||
@@ -74,6 +71,8 @@ class GitTemporaryDirectory(ChdirTemporaryDirectory):
|
||||
|
||||
|
||||
def make_repo(path=None):
|
||||
import git
|
||||
|
||||
if not path:
|
||||
path = "."
|
||||
repo = git.Repo.init(path)
|
||||
@@ -194,25 +193,9 @@ def split_chat_history_markdown(text, include_tool=False):
|
||||
return messages
|
||||
|
||||
|
||||
# Copied from pip, MIT license
|
||||
# https://github.com/pypa/pip/blob/b989e6ef04810bbd4033a3683020bd4ddcbdb627/src/pip/_internal/utils/entrypoints.py#L73
|
||||
def get_best_invocation_for_this_python() -> str:
|
||||
"""Try to figure out the best way to invoke the current Python."""
|
||||
exe = sys.executable
|
||||
exe_name = os.path.basename(exe)
|
||||
|
||||
# Try to use the basename, if it's the first executable.
|
||||
found_executable = shutil.which(exe_name)
|
||||
if found_executable and os.path.samefile(found_executable, exe):
|
||||
return exe_name
|
||||
|
||||
# Use the full executable name, because we couldn't find something simpler.
|
||||
return exe
|
||||
|
||||
|
||||
def get_pip_install(args):
|
||||
cmd = [
|
||||
get_best_invocation_for_this_python(),
|
||||
sys.executable,
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
|
||||
@@ -14,6 +14,8 @@ from .dump import dump # noqa: F401
|
||||
warnings.filterwarnings(
|
||||
"ignore", message="Couldn't find ffmpeg or avconv - defaulting to ffmpeg, but may not work"
|
||||
)
|
||||
warnings.filterwarnings("ignore", category=SyntaxWarning)
|
||||
|
||||
|
||||
from pydub import AudioSegment # noqa
|
||||
|
||||
@@ -43,7 +45,6 @@ class Voice:
|
||||
|
||||
self.sd = sd
|
||||
|
||||
|
||||
devices = sd.query_devices()
|
||||
|
||||
if device_name:
|
||||
@@ -55,7 +56,10 @@ class Voice:
|
||||
break
|
||||
if device_id is None:
|
||||
available_inputs = [d["name"] for d in devices if d["max_input_channels"] > 0]
|
||||
raise ValueError(f"Device '{device_name}' not found. Available input devices: {available_inputs}")
|
||||
raise ValueError(
|
||||
f"Device '{device_name}' not found. Available input devices:"
|
||||
f" {available_inputs}"
|
||||
)
|
||||
|
||||
print(f"Using input device: {device_name} (ID: {device_id})")
|
||||
|
||||
@@ -125,7 +129,9 @@ class Voice:
|
||||
self.start_time = time.time()
|
||||
|
||||
try:
|
||||
with self.sd.InputStream(samplerate=sample_rate, channels=1, callback=self.callback, device=self.device_id):
|
||||
with self.sd.InputStream(
|
||||
samplerate=sample_rate, channels=1, callback=self.callback, device=self.device_id
|
||||
):
|
||||
prompt(self.get_prompt, refresh_interval=0.1)
|
||||
except self.sd.PortAudioError as err:
|
||||
raise SoundDeviceError(f"Error accessing audio input device: {err}")
|
||||
|
||||
170
aider/watch.py
170
aider/watch.py
@@ -9,49 +9,7 @@ from pathspec.patterns import GitWildMatchPattern
|
||||
from watchfiles import watch
|
||||
|
||||
from aider.dump import dump # noqa
|
||||
|
||||
|
||||
def is_source_file(path: Path) -> bool:
|
||||
"""
|
||||
Check if a file is a source file that uses # or // style comments.
|
||||
This includes Python, JavaScript, TypeScript, C, C++, etc.
|
||||
"""
|
||||
COMMENT_STYLE_EXTENSIONS = {
|
||||
# # style comments
|
||||
".py",
|
||||
".r",
|
||||
".rb",
|
||||
".pl",
|
||||
".pm",
|
||||
".sh",
|
||||
".bash",
|
||||
".yaml",
|
||||
".yml",
|
||||
# // style comments
|
||||
".js",
|
||||
".ts",
|
||||
".jsx",
|
||||
".tsx",
|
||||
".cpp",
|
||||
".c",
|
||||
".h",
|
||||
".hpp",
|
||||
".java",
|
||||
".swift",
|
||||
".kt",
|
||||
".cs",
|
||||
".go",
|
||||
".rs",
|
||||
".php",
|
||||
# -- style comments
|
||||
".sql",
|
||||
".hs", # Haskell
|
||||
".lua",
|
||||
".elm",
|
||||
".vhd", # VHDL
|
||||
".vhdl",
|
||||
}
|
||||
return path.suffix.lower() in COMMENT_STYLE_EXTENSIONS
|
||||
from aider.watch_prompts import watch_ask_prompt, watch_code_prompt
|
||||
|
||||
|
||||
def load_gitignores(gitignore_paths: list[Path]) -> Optional[PathSpec]:
|
||||
@@ -59,7 +17,41 @@ def load_gitignores(gitignore_paths: list[Path]) -> Optional[PathSpec]:
|
||||
if not gitignore_paths:
|
||||
return None
|
||||
|
||||
patterns = [".aider*", ".git"] # Always ignore
|
||||
patterns = [
|
||||
".aider*",
|
||||
".git",
|
||||
# Common editor backup/temp files
|
||||
"*~", # Emacs/vim backup
|
||||
"*.bak", # Generic backup
|
||||
"*.swp", # Vim swap
|
||||
"*.swo", # Vim swap
|
||||
"\\#*\\#", # Emacs auto-save
|
||||
".#*", # Emacs lock files
|
||||
"*.tmp", # Generic temp files
|
||||
"*.temp", # Generic temp files
|
||||
"*.orig", # Merge conflict originals
|
||||
"*.pyc", # Python bytecode
|
||||
"__pycache__/", # Python cache dir
|
||||
".DS_Store", # macOS metadata
|
||||
"Thumbs.db", # Windows thumbnail cache
|
||||
# IDE files
|
||||
".idea/", # JetBrains IDEs
|
||||
".vscode/", # VS Code
|
||||
"*.sublime-*", # Sublime Text
|
||||
".project", # Eclipse
|
||||
".settings/", # Eclipse
|
||||
"*.code-workspace", # VS Code workspace
|
||||
# Environment files
|
||||
".env", # Environment variables
|
||||
".venv/", # Python virtual environments
|
||||
"node_modules/", # Node.js dependencies
|
||||
"vendor/", # Various dependencies
|
||||
# Logs and caches
|
||||
"*.log", # Log files
|
||||
".cache/", # Cache directories
|
||||
".pytest_cache/", # Python test cache
|
||||
"coverage/", # Code coverage reports
|
||||
] # Always ignore
|
||||
for path in gitignore_paths:
|
||||
if path.exists():
|
||||
with open(path) as f:
|
||||
@@ -72,13 +64,14 @@ class FileWatcher:
|
||||
"""Watches source files for changes and AI comments"""
|
||||
|
||||
# Compiled regex pattern for AI comments
|
||||
ai_comment_pattern = re.compile(r"(?:#|//|--) *(ai\b.*|ai\b.*|.*\bai!?)$", re.IGNORECASE)
|
||||
ai_comment_pattern = re.compile(r"(?:#|//|--) *(ai\b.*|ai\b.*|.*\bai[?!]?) *$", re.IGNORECASE)
|
||||
|
||||
def __init__(self, coder, gitignores=None, verbose=False):
|
||||
def __init__(self, coder, gitignores=None, verbose=False, analytics=None):
|
||||
self.coder = coder
|
||||
self.io = coder.io
|
||||
self.root = Path(coder.root)
|
||||
self.verbose = verbose
|
||||
self.analytics = analytics
|
||||
self.stop_event = None
|
||||
self.watcher_thread = None
|
||||
self.changed_files = set()
|
||||
@@ -105,9 +98,6 @@ class FileWatcher:
|
||||
if self.gitignore_spec and self.gitignore_spec.match_file(str(rel_path)):
|
||||
return False
|
||||
|
||||
if not is_source_file(path_obj):
|
||||
return False
|
||||
|
||||
if self.verbose:
|
||||
dump("ok", rel_path)
|
||||
|
||||
@@ -154,33 +144,43 @@ class FileWatcher:
|
||||
def process_changes(self):
|
||||
"""Get any detected file changes"""
|
||||
|
||||
has_bangs = False
|
||||
has_action = None
|
||||
added = False
|
||||
for fname in self.changed_files:
|
||||
_, _, has_bang = self.get_ai_comments(fname)
|
||||
has_bangs |= has_bang
|
||||
_, _, action = self.get_ai_comments(fname)
|
||||
if action in ("!", "?"):
|
||||
has_action = action
|
||||
|
||||
if fname in self.coder.abs_fnames:
|
||||
continue
|
||||
if self.analytics:
|
||||
self.analytics.event("ai-comments file-add")
|
||||
self.coder.abs_fnames.add(fname)
|
||||
rel_fname = self.coder.get_rel_fname(fname)
|
||||
if not added:
|
||||
self.io.tool_output()
|
||||
added = True
|
||||
self.io.tool_output(f"Added {rel_fname} to the chat")
|
||||
self.io.tool_output()
|
||||
|
||||
if not has_bangs:
|
||||
if not has_action:
|
||||
if added:
|
||||
self.io.tool_output(
|
||||
"End your comment with AI! to request changes or AI? to ask questions"
|
||||
)
|
||||
return ""
|
||||
|
||||
if self.analytics:
|
||||
self.analytics.event("ai-comments execute")
|
||||
self.io.tool_output("Processing your request...")
|
||||
|
||||
res = """The "AI" comments below can be found in the code files I've shared with you.
|
||||
They contain your instructions.
|
||||
Make the requested changes.
|
||||
Be sure to remove all these "AI" comments from the code!
|
||||
|
||||
"""
|
||||
if has_action == "!":
|
||||
res = watch_code_prompt
|
||||
elif has_action == "?":
|
||||
res = watch_ask_prompt
|
||||
|
||||
# Refresh all AI comments from tracked files
|
||||
for fname in self.coder.abs_fnames:
|
||||
line_nums, comments, _has_bang = self.get_ai_comments(fname)
|
||||
line_nums, comments, _action = self.get_ai_comments(fname)
|
||||
if not line_nums:
|
||||
continue
|
||||
|
||||
@@ -194,30 +194,34 @@ Be sure to remove all these "AI" comments from the code!
|
||||
# Convert comment line numbers to line indices (0-based)
|
||||
lois = [ln - 1 for ln, _ in zip(line_nums, comments) if ln > 0]
|
||||
|
||||
context = TreeContext(
|
||||
rel_fname,
|
||||
code,
|
||||
color=False,
|
||||
line_number=False,
|
||||
child_context=False,
|
||||
last_line=False,
|
||||
margin=0,
|
||||
mark_lois=False,
|
||||
loi_pad=3,
|
||||
show_top_of_file_parent_scope=False,
|
||||
)
|
||||
context.lines_of_interest = set()
|
||||
context.add_lines_of_interest(lois)
|
||||
context.add_context()
|
||||
res += context.format()
|
||||
try:
|
||||
context = TreeContext(
|
||||
rel_fname,
|
||||
code,
|
||||
color=False,
|
||||
line_number=False,
|
||||
child_context=False,
|
||||
last_line=False,
|
||||
margin=0,
|
||||
mark_lois=True,
|
||||
loi_pad=3,
|
||||
show_top_of_file_parent_scope=False,
|
||||
)
|
||||
context.lines_of_interest = set()
|
||||
context.add_lines_of_interest(lois)
|
||||
context.add_context()
|
||||
res += context.format()
|
||||
except ValueError:
|
||||
for ln, comment in zip(line_nums, comments):
|
||||
res += f" Line {ln}: {comment}\n"
|
||||
|
||||
return res
|
||||
|
||||
def get_ai_comments(self, filepath):
|
||||
"""Extract AI comment line numbers, comments and bang status from a file"""
|
||||
"""Extract AI comment line numbers, comments and action status from a file"""
|
||||
line_nums = []
|
||||
comments = []
|
||||
has_bang = False
|
||||
has_action = None # None, "!" or "?"
|
||||
content = self.io.read_text(filepath, silent=True)
|
||||
for i, line in enumerate(content.splitlines(), 1):
|
||||
if match := self.ai_comment_pattern.search(line):
|
||||
@@ -229,10 +233,12 @@ Be sure to remove all these "AI" comments from the code!
|
||||
comment = comment.lstrip("/#-")
|
||||
comment = comment.strip()
|
||||
if comment.startswith("ai!") or comment.endswith("ai!"):
|
||||
has_bang = True
|
||||
has_action = "!"
|
||||
elif comment.startswith("ai?") or comment.endswith("ai?"):
|
||||
has_action = "?"
|
||||
if not line_nums:
|
||||
return None, None, False
|
||||
return line_nums, comments, has_bang
|
||||
return None, None, None
|
||||
return line_nums, comments, has_action
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
11
aider/watch_prompts.py
Normal file
11
aider/watch_prompts.py
Normal file
@@ -0,0 +1,11 @@
|
||||
watch_code_prompt = """
|
||||
Find the "AI" comments below (marked with █) in the code files I've shared with you.
|
||||
They contain your instructions.
|
||||
Make the requested changes.
|
||||
Be sure to remove all these "AI" comments from the code!
|
||||
"""
|
||||
|
||||
watch_ask_prompt = """/ask
|
||||
Find the "AI" comments below (marked with █) in the code files I've shared with you.
|
||||
They contain your questions you need to answer and other instructions.
|
||||
"""
|
||||
@@ -1,7 +1,6 @@
|
||||
---
|
||||
title: Release history
|
||||
parent: More info
|
||||
nav_order: 900
|
||||
nav_order: 925
|
||||
highlight_image: /assets/blame.jpg
|
||||
description: Release notes and stats on aider writing its own code.
|
||||
---
|
||||
@@ -24,6 +23,43 @@ cog.out(text)
|
||||
]]]-->
|
||||
|
||||
|
||||
### Aider v0.69.0
|
||||
|
||||
- [Watch files](https://aider.chat/docs/usage/watch.html) improvements:
|
||||
- Use `# ... AI?` comments to trigger aider and ask questions about your code.
|
||||
- Now watches *all* files, not just certain source files.
|
||||
- Use `# AI comments`, `// AI comments`, or `-- AI comments` to give aider instructions in any text file.
|
||||
- Full support for Gemini Flash 2.0 Exp:
|
||||
- `aider --model flash` or `aider --model gemini/gemini-2.0-flash-exp`
|
||||
- [New `--multiline` flag and `/multiline-mode` command](https://aider.chat/docs/usage/commands.html#entering-multi-line-chat-messages) makes ENTER a soft newline and META-ENTER send the message, by @miradnanali.
|
||||
- `/copy-context <instructions>` now takes optional "instructions" when [copying code context to the clipboard](https://aider.chat/docs/usage/copypaste.html#copy-aiders-code-context-to-your-clipboard-paste-into-the-web-ui).
|
||||
- Improved clipboard error handling with helpful requirements install info.
|
||||
- Ask 5% of users if they want to opt-in to analytics.
|
||||
- `/voice` now lets you edit the transcribed text before sending.
|
||||
- Disabled auto-complete in Y/N prompts.
|
||||
- Aider wrote 68% of the code in this release.
|
||||
|
||||
### Aider v0.68.0
|
||||
|
||||
- [Aider works with LLM web chat UIs](https://aider.chat/docs/usage/copypaste.html).
|
||||
- New `--copy-paste` mode.
|
||||
- New `/copy-context` command.
|
||||
- [Set API keys and other environment variables for all providers from command line or yaml conf file](https://aider.chat/docs/config/aider_conf.html#storing-llm-keys).
|
||||
- New `--api-key provider=key` setting.
|
||||
- New `--set-env VAR=value` setting.
|
||||
- Added bash and zsh support to `--watch-files`.
|
||||
- Better error messages when missing dependencies for Gemini and Bedrock models.
|
||||
- Control-D now properly exits the program.
|
||||
- Don't count token costs when API provider returns a hard error.
|
||||
- Bugfix so watch files works with files that don't have tree-sitter support.
|
||||
- Bugfix so o1 models can be used as weak model.
|
||||
- Updated shell command prompt.
|
||||
- Added docstrings for all Coders.
|
||||
- Reorganized command line arguments with improved help messages and grouping.
|
||||
- Use the exact `sys.python` for self-upgrades.
|
||||
- Added experimental Gemini models.
|
||||
- Aider wrote 71% of the code in this release.
|
||||
|
||||
### Aider v0.67.0
|
||||
|
||||
- [Use aider in your IDE or editor](https://aider.chat/docs/usage/watch.html).
|
||||
@@ -37,7 +73,7 @@ cog.out(text)
|
||||
- Spinner now falls back to ASCII art if fancy symbols throw unicode errors.
|
||||
- `--read` now expands `~` home dirs.
|
||||
- Enabled exception capture in analytics.
|
||||
- Aider wrote 61% of the code in this release.
|
||||
- [Aider wrote 61% of the code in this release.](https://aider.chat/HISTORY.html)
|
||||
|
||||
### Aider v0.66.0
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -644,7 +644,7 @@
|
||||
|
||||
- dirname: 2024-07-19-08-57-13--openrouter-deepseek-chat-v2-0628
|
||||
test_cases: 133
|
||||
model: DeepSeek Chat V2 0628 (deprecated)
|
||||
model: DeepSeek Chat V2 0628
|
||||
edit_format: diff
|
||||
commit_hash: 96ff06e-dirty
|
||||
pass_rate_1: 60.9
|
||||
@@ -716,7 +716,7 @@
|
||||
|
||||
- dirname: 2024-07-24-07-10-58--deepseek-coder2-0724-diff-direct
|
||||
test_cases: 133
|
||||
model: DeepSeek Coder V2 0724 (deprecated)
|
||||
model: DeepSeek Coder V2 0724
|
||||
edit_format: diff
|
||||
commit_hash: 89965bf
|
||||
pass_rate_1: 57.9
|
||||
@@ -1232,7 +1232,7 @@
|
||||
|
||||
- dirname: 2024-09-24-16-33-23--gemini-1.5-flash-002-whole
|
||||
test_cases: 133
|
||||
model: gemini-1.5-flash-002
|
||||
model: gemini-1.5-flash-002 (0924)
|
||||
edit_format: whole
|
||||
commit_hash: 3edcd71
|
||||
pass_rate_1: 37.6
|
||||
@@ -2042,4 +2042,142 @@
|
||||
date: 2024-12-04
|
||||
versions: 0.66.1.dev
|
||||
seconds_per_case: 8.7
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-12-06-18-27-47--llama33-diff
|
||||
test_cases: 133
|
||||
model: llama-3.3-70b-instruct
|
||||
edit_format: diff
|
||||
commit_hash: 53e0d67
|
||||
pass_rate_1: 42.1
|
||||
pass_rate_2: 59.4
|
||||
percent_cases_well_formed: 88.7
|
||||
error_outputs: 33
|
||||
num_malformed_responses: 33
|
||||
num_with_malformed_responses: 15
|
||||
user_asks: 3
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 3
|
||||
command: aider --model openrouter/meta-llama/llama-3.3-70b-instruct
|
||||
date: 2024-12-06
|
||||
versions: 0.67.1.dev
|
||||
seconds_per_case: 20.2
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-12-06-21-35-50--gemini-exp-1206-diff
|
||||
test_cases: 133
|
||||
model: gemini-exp-1206 (diff)
|
||||
edit_format: diff
|
||||
commit_hash: f2d2ab5
|
||||
pass_rate_1: 55.6
|
||||
pass_rate_2: 69.2
|
||||
percent_cases_well_formed: 84.2
|
||||
error_outputs: 68
|
||||
num_malformed_responses: 68
|
||||
num_with_malformed_responses: 21
|
||||
user_asks: 5
|
||||
lazy_comments: 0
|
||||
syntax_errors: 2
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 0
|
||||
command: aider --model gemini/gemini-exp-1206
|
||||
date: 2024-12-06
|
||||
versions: 0.67.1.dev
|
||||
seconds_per_case: 32.1
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-12-08-21-39-06--gemini-exp-1206-whole
|
||||
test_cases: 133
|
||||
model: gemini-exp-1206 (whole)
|
||||
edit_format: whole
|
||||
commit_hash: f2d2ab5
|
||||
pass_rate_1: 60.9
|
||||
pass_rate_2: 80.5
|
||||
percent_cases_well_formed: 100.0
|
||||
error_outputs: 0
|
||||
num_malformed_responses: 0
|
||||
num_with_malformed_responses: 0
|
||||
user_asks: 1
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 3
|
||||
command: aider --model gemini/gemini-exp-1206
|
||||
date: 2024-12-08
|
||||
versions: 0.67.1.dev
|
||||
seconds_per_case: 64.2
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-12-10-14-45-21--deepseek-1210-diff
|
||||
test_cases: 133
|
||||
model: DeepSeek-V2.5-1210
|
||||
edit_format: diff
|
||||
commit_hash: 16332b2
|
||||
pass_rate_1: 58.6
|
||||
pass_rate_2: 72.2
|
||||
percent_cases_well_formed: 99.2
|
||||
error_outputs: 1
|
||||
num_malformed_responses: 1
|
||||
num_with_malformed_responses: 1
|
||||
user_asks: 2
|
||||
lazy_comments: 0
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 2
|
||||
command: aider --model deepseek/deepseek-chat
|
||||
date: 2024-12-10
|
||||
versions: 0.67.1.dev
|
||||
seconds_per_case: 32.7
|
||||
total_cost: 0.1106
|
||||
|
||||
- dirname: 2024-12-11-00-37-08--yi-test
|
||||
test_cases: 133
|
||||
model: yi-lightning
|
||||
edit_format: whole
|
||||
commit_hash: e909a3d-dirty
|
||||
pass_rate_1: 49.6
|
||||
pass_rate_2: 65.4
|
||||
percent_cases_well_formed: 97.0
|
||||
error_outputs: 304
|
||||
num_malformed_responses: 5
|
||||
num_with_malformed_responses: 4
|
||||
user_asks: 34
|
||||
lazy_comments: 2
|
||||
syntax_errors: 0
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 0
|
||||
test_timeouts: 2
|
||||
command: aider --model openai/yi-lightning
|
||||
date: 2024-12-11
|
||||
versions: 0.67.1.dev
|
||||
seconds_per_case: 57.8
|
||||
total_cost: 0.0000
|
||||
|
||||
- dirname: 2024-12-11-21-07-00--gemini-2-flash-diff
|
||||
test_cases: 133
|
||||
model: gemini-2.0-flash-exp
|
||||
edit_format: diff
|
||||
commit_hash: fcb2bac-dirty, 02e7e31-dirty
|
||||
pass_rate_1: 56.4
|
||||
pass_rate_2: 69.9
|
||||
percent_cases_well_formed: 97.0
|
||||
error_outputs: 10
|
||||
num_malformed_responses: 6
|
||||
num_with_malformed_responses: 4
|
||||
user_asks: 8
|
||||
lazy_comments: 0
|
||||
syntax_errors: 1
|
||||
indentation_errors: 0
|
||||
exhausted_context_windows: 2
|
||||
test_timeouts: 1
|
||||
command: aider --model gemini/gemini-2.0-flash-exp
|
||||
date: 2024-12-11
|
||||
versions: 0.68.1.dev
|
||||
seconds_per_case: 7.3
|
||||
total_cost: 0.0000
|
||||
@@ -1,13 +1,21 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var ctx = document.getElementById('editChart').getContext('2d');
|
||||
const HIGHTLIGHT_MODEL = 'no no no no';
|
||||
const blueDiagonalPattern = pattern.draw('diagonal', 'rgba(54, 162, 235, 0.2)');
|
||||
const redDiagonalPattern = pattern.draw('diagonal', 'rgba(255, 99, 132, 0.2)');
|
||||
let displayedData = [];
|
||||
|
||||
const HIGHTLIGHT_MODEL = 'no no no';
|
||||
var leaderboardData = {
|
||||
labels: [],
|
||||
datasets: [{
|
||||
label: 'Percent completed correctly',
|
||||
data: [],
|
||||
backgroundColor: function(context) {
|
||||
const label = context.chart.data.labels[context.dataIndex] || '';
|
||||
const row = allData[context.dataIndex];
|
||||
if (row && row.edit_format === 'whole') {
|
||||
return diagonalPattern;
|
||||
}
|
||||
const label = leaderboardData.labels[context.dataIndex] || '';
|
||||
return (label && label.includes(HIGHTLIGHT_MODEL)) ? 'rgba(255, 99, 132, 0.2)' : 'rgba(54, 162, 235, 0.2)';
|
||||
},
|
||||
borderColor: function(context) {
|
||||
@@ -23,7 +31,8 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
allData.push({
|
||||
model: '{{ row.model }}',
|
||||
pass_rate_2: {{ row.pass_rate_2 }},
|
||||
percent_cases_well_formed: {{ row.percent_cases_well_formed }}
|
||||
percent_cases_well_formed: {{ row.percent_cases_well_formed }},
|
||||
edit_format: '{{ row.edit_format }}'
|
||||
});
|
||||
{% endfor %}
|
||||
|
||||
@@ -31,6 +40,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
var selectedRows = document.querySelectorAll('tr.selected');
|
||||
var showAll = selectedRows.length === 0;
|
||||
|
||||
displayedData = [];
|
||||
leaderboardData.labels = [];
|
||||
leaderboardData.datasets[0].data = [];
|
||||
|
||||
@@ -40,14 +50,30 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
rowElement.classList.remove('selected');
|
||||
}
|
||||
if (showAll || rowElement.classList.contains('selected')) {
|
||||
displayedData.push(row);
|
||||
leaderboardData.labels.push(row.model);
|
||||
leaderboardData.datasets[0].data.push(row.pass_rate_2);
|
||||
}
|
||||
});
|
||||
|
||||
leaderboardChart.update();
|
||||
leaderboardChart.render();
|
||||
}
|
||||
|
||||
// Use displayedData in the backgroundColor callback instead of allData
|
||||
leaderboardData.datasets[0].backgroundColor = function(context) {
|
||||
const row = displayedData[context.dataIndex];
|
||||
const label = leaderboardData.labels[context.dataIndex] || '';
|
||||
if (label && label.includes(HIGHTLIGHT_MODEL)) {
|
||||
if (row && row.edit_format === 'whole') return redDiagonalPattern;
|
||||
else return 'rgba(255, 99, 132, 0.2)';
|
||||
} else if (row && row.edit_format === 'whole') {
|
||||
return blueDiagonalPattern;
|
||||
} else {
|
||||
return 'rgba(54, 162, 235, 0.2)';
|
||||
}
|
||||
};
|
||||
|
||||
var tableBody = document.querySelector('table tbody');
|
||||
allData.forEach(function(row, index) {
|
||||
var tr = tableBody.children[index];
|
||||
@@ -63,9 +89,69 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
type: 'bar',
|
||||
data: leaderboardData,
|
||||
options: {
|
||||
plugins: {
|
||||
legend: {
|
||||
display: true,
|
||||
labels: {
|
||||
generateLabels: function(chart) {
|
||||
return [
|
||||
{
|
||||
text: 'Diff-like format',
|
||||
fillStyle: 'rgba(54, 162, 235, 0.2)',
|
||||
strokeStyle: 'rgba(54, 162, 235, 1)',
|
||||
lineWidth: 1
|
||||
},
|
||||
{
|
||||
text: 'Whole format',
|
||||
fillStyle: blueDiagonalPattern,
|
||||
strokeStyle: 'rgba(54, 162, 235, 1)',
|
||||
lineWidth: 1
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true
|
||||
beginAtZero: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Percent completed correctly'
|
||||
}
|
||||
},
|
||||
x: {
|
||||
ticks: {
|
||||
callback: function(value, index) {
|
||||
const label = this.getLabelForValue(value);
|
||||
if (label.length <= "claude-3-5-sonnet".length) {
|
||||
return label;
|
||||
}
|
||||
|
||||
// Find all possible split positions
|
||||
const splitPositions = [];
|
||||
for (let i = 0; i < label.length; i++) {
|
||||
if (label[i] === '-' || label[i] === ' ') {
|
||||
splitPositions.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (splitPositions.length === 0) {
|
||||
return label;
|
||||
}
|
||||
|
||||
// Find split position closest to middle
|
||||
const middle = label.length / 2;
|
||||
const splitIndex = splitPositions.reduce((closest, current) => {
|
||||
return Math.abs(current - middle) < Math.abs(closest - middle) ? current : closest;
|
||||
});
|
||||
|
||||
return [
|
||||
label.slice(0, splitIndex),
|
||||
label.slice(splitIndex + 1)
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,6 +165,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
var tableBody = document.querySelector('table:first-of-type tbody');
|
||||
var rows = tableBody.getElementsByTagName('tr');
|
||||
|
||||
displayedData = [];
|
||||
leaderboardData.labels = [];
|
||||
leaderboardData.datasets[0].data = [];
|
||||
|
||||
@@ -86,6 +173,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
var rowText = rows[i].textContent;
|
||||
if (searchWords.every(word => rowText.toLowerCase().includes(word))) {
|
||||
rows[i].style.display = '';
|
||||
displayedData.push(allData[i]);
|
||||
leaderboardData.labels.push(allData[i].model);
|
||||
leaderboardData.datasets[0].data.push(allData[i].pass_rate_2);
|
||||
} else {
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{: .tip }
|
||||
All API keys can be stored in a
|
||||
[.env file](/docs/config/dotenv.html).
|
||||
Only OpenAI and Anthropic keys can be stored in the
|
||||
[YAML config file](/docs/config/aider_conf.html).
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
|
||||
You can get started quickly like this:
|
||||
You can get started quickly like this, with python 3.8-3.13:
|
||||
|
||||
```
|
||||
python -m pip install -U aider-chat
|
||||
```bash
|
||||
python -m pip install aider-install
|
||||
aider-install
|
||||
|
||||
# Change directory into a git repo
|
||||
# Change directory into your code base
|
||||
cd /to/your/git/repo
|
||||
|
||||
# Work with Claude 3.5 Sonnet on your repo
|
||||
export ANTHROPIC_API_KEY=your-key-goes-here
|
||||
aider
|
||||
aider --model sonnet --anthropic-api-key your-key-goes-here
|
||||
|
||||
# Work with GPT-4o on your repo
|
||||
export OPENAI_API_KEY=your-key-goes-here
|
||||
aider
|
||||
aider --model gpt-4o --openai-api-key your-key-goes-here
|
||||
```
|
||||
|
||||
@@ -18,3 +18,63 @@
|
||||
<link rel="mask-icon" href="{{ '/assets/icons/safari-pinned-tab.svg' | relative_url }}" color="#5bbad5">
|
||||
<meta name="msapplication-TileColor" content="#da532c">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<!-- Cookie Consent -->
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.css" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.js" data-cfasync="false"></script>
|
||||
<script>
|
||||
window.addEventListener('load', function(){
|
||||
window.cookieconsent.initialise({
|
||||
palette: {
|
||||
popup: {
|
||||
background: "#333333",
|
||||
text: "#ffffff"
|
||||
},
|
||||
button: {
|
||||
background: "#ffffff",
|
||||
text: "#333333"
|
||||
}
|
||||
},
|
||||
type: "opt-in",
|
||||
position: "bottom-left",
|
||||
showLink: false,
|
||||
dismissOnScroll: true,
|
||||
cookie: {
|
||||
name: 'cookieconsent_status',
|
||||
path: '/',
|
||||
domain: 'aider.chat',
|
||||
expiryDays: 365
|
||||
},
|
||||
content: {
|
||||
message: "This website uses analytics cookies to help us understand how you use the site.",
|
||||
dismiss: "Decline",
|
||||
allow: "Accept",
|
||||
link: "Learn more",
|
||||
href: "https://aider.chat/docs/legal/privacy.html"
|
||||
},
|
||||
onInitialise: function(status) {
|
||||
var type = this.options.type;
|
||||
var didConsent = this.hasConsented();
|
||||
if (didConsent) {
|
||||
initPostHog();
|
||||
}
|
||||
},
|
||||
onStatusChange: function(status, chosenBefore) {
|
||||
var type = this.options.type;
|
||||
var didConsent = this.hasConsented();
|
||||
if (didConsent) {
|
||||
initPostHog();
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// PostHog initialization function
|
||||
function initPostHog() {
|
||||
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey getNextSurveyStep identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty createPersonProfile opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing clear_opt_in_out_capturing debug".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
|
||||
posthog.init('phc_99T7muzafUMMZX15H8XePbMSreEUzahHbtWjy3l5Qbv', {
|
||||
api_host:'https://us.i.posthog.com',
|
||||
person_profiles: 'identified_only'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
4
aider/website/_includes/keys.md
Normal file
4
aider/website/_includes/keys.md
Normal file
@@ -0,0 +1,4 @@
|
||||
{: .tip :}
|
||||
See the
|
||||
[API key configuration docs](/docs/config/api-keys.html)
|
||||
for information on how to configure and store your API keys.
|
||||
@@ -5,7 +5,10 @@ You can send long, multi-line messages in the chat in a few ways:
|
||||
- Use Meta-ENTER to start a new line without sending the message (Esc+ENTER in some environments).
|
||||
- Use `/paste` to paste text from the clipboard into the chat.
|
||||
- Use the `/editor` command to open your editor to create the next chat message. See [editor configuration docs](/docs/config/editor.html) for more info.
|
||||
|
||||
- Use multiline-mode, which swaps the function of Meta-Enter and Enter, so that Enter inserts a newline, and Meta-Enter submits your command. To enable multiline mode:
|
||||
- Use the `/multiline-mode` command to toggle it during a session.
|
||||
- Use the `--multiline` switch.
|
||||
|
||||
Example with a tag:
|
||||
```
|
||||
{python
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
To use aider with pipx on replit, you can run these commands in the replit shell:
|
||||
|
||||
```
|
||||
```bash
|
||||
pip install pipx
|
||||
pipx run aider-chat ...normal aider args...
|
||||
```
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
Aider has special support for providing
|
||||
OpenAI and Anthropic API keys
|
||||
via
|
||||
[command line switches](/docs/config/options.html)
|
||||
and
|
||||
[yaml config file](/docs/config/aider_conf.html).
|
||||
*All other LLM providers* must
|
||||
have their keys and settings
|
||||
specified in environment variables.
|
||||
This can be done in your shell,
|
||||
or by using a
|
||||
[.env file](/docs/config/dotenv.html).
|
||||
@@ -1,7 +0,0 @@
|
||||
{: .tip }
|
||||
Using a Python
|
||||
[virtual environment](https://docs.python.org/3/library/venv.html){:target="_blank"}
|
||||
is recommended.
|
||||
Or, you could
|
||||
[use pipx to install aider](/docs/install/pipx.html)
|
||||
once for your whole system.
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Aider has written 7% of its own code
|
||||
excerpt: Aider has written 7% of its own code, via 600+ commits that inserted 4.8K and deleted 1.5K lines of code.
|
||||
title: Aider has written 7% of its own code (outdated, now 70%)
|
||||
excerpt: This article is quite out dated. Aider is currently writing about 70% of the new code in each release.
|
||||
highlight_image: /assets/self-assembly.jpg
|
||||
nav_exclude: true
|
||||
---
|
||||
@@ -8,13 +8,16 @@ nav_exclude: true
|
||||
<p class="post-date">{{ page.date | date: "%B %d, %Y" }}</p>
|
||||
{% endif %}
|
||||
|
||||
# Aider has written 7% of its own code
|
||||
# Aider has written 7% of its own code (outdated, now 70%)
|
||||
|
||||
[](https://aider.chat/assets/self-assembly.jpg)
|
||||
|
||||
{: .note }
|
||||
This article is quite out dated. For current statistics, see
|
||||
[aider's release history](/HISTORY.html).
|
||||
This article is quite old and outdated.
|
||||
Aider is currently writing about 70% of the new code
|
||||
in each release.
|
||||
See
|
||||
[aider's release history](/HISTORY.html) for the latest statistics.
|
||||
|
||||
The
|
||||
[aider git repo](https://github.com/Aider-AI/aider)
|
||||
|
||||
BIN
aider/website/assets/copypaste.jpg
Normal file
BIN
aider/website/assets/copypaste.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 314 KiB |
BIN
aider/website/assets/copypaste.mp4
Normal file
BIN
aider/website/assets/copypaste.mp4
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -14,14 +14,8 @@
|
||||
## show this help message and exit
|
||||
#help: xxx
|
||||
|
||||
#######
|
||||
# Main:
|
||||
|
||||
## Specify the OpenAI API key
|
||||
#openai-api-key: xxx
|
||||
|
||||
## Specify the Anthropic API key
|
||||
#anthropic-api-key: xxx
|
||||
#############
|
||||
# Main model:
|
||||
|
||||
## Specify the model to use for the main chat
|
||||
#model: xxx
|
||||
@@ -59,27 +53,52 @@
|
||||
## Use o1-preview model for the main chat
|
||||
#o1-preview: false
|
||||
|
||||
#################
|
||||
# Model Settings:
|
||||
########################
|
||||
# API Keys and settings:
|
||||
|
||||
## List known models which match the (partial) MODEL name
|
||||
#list-models: xxx
|
||||
## Specify the OpenAI API key
|
||||
#openai-api-key: xxx
|
||||
|
||||
## Specify the Anthropic API key
|
||||
#anthropic-api-key: xxx
|
||||
|
||||
## Specify the api base url
|
||||
#openai-api-base: xxx
|
||||
|
||||
## Specify the api_type
|
||||
## (deprecated, use --set-env OPENAI_API_TYPE=<value>)
|
||||
#openai-api-type: xxx
|
||||
|
||||
## Specify the api_version
|
||||
## (deprecated, use --set-env OPENAI_API_VERSION=<value>)
|
||||
#openai-api-version: xxx
|
||||
|
||||
## Specify the deployment_id
|
||||
## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=<value>)
|
||||
#openai-api-deployment-id: xxx
|
||||
|
||||
## Specify the OpenAI organization ID
|
||||
## (deprecated, use --set-env OPENAI_ORGANIZATION=<value>)
|
||||
#openai-organization-id: xxx
|
||||
|
||||
## Set an environment variable (to control API settings, can be used multiple times)
|
||||
#set-env: xxx
|
||||
## Specify multiple values like this:
|
||||
#set-env:
|
||||
# - xxx
|
||||
# - yyy
|
||||
# - zzz
|
||||
|
||||
## Set an API key for a provider (eg: --api-key provider=<key> sets PROVIDER_API_KEY=<key>)
|
||||
#api-key: xxx
|
||||
## Specify multiple values like this:
|
||||
#api-key:
|
||||
# - xxx
|
||||
# - yyy
|
||||
# - zzz
|
||||
|
||||
#################
|
||||
# Model settings:
|
||||
|
||||
## List known models which match the (partial) MODEL name
|
||||
#list-models: xxx
|
||||
|
||||
## Specify a file with aider model settings for unknown models
|
||||
#model-settings-file: .aider.model.settings.yml
|
||||
|
||||
@@ -121,11 +140,8 @@
|
||||
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
|
||||
#max-chat-history-tokens: xxx
|
||||
|
||||
## Specify the .env file to load (default: .env in git root)
|
||||
#env-file: .env
|
||||
|
||||
#################
|
||||
# Cache Settings:
|
||||
# Cache settings:
|
||||
|
||||
## Enable caching of prompts (default: False)
|
||||
#cache-prompts: false
|
||||
@@ -134,7 +150,7 @@
|
||||
#cache-keepalive-pings: false
|
||||
|
||||
###################
|
||||
# Repomap Settings:
|
||||
# Repomap settings:
|
||||
|
||||
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
|
||||
#map-tokens: xxx
|
||||
@@ -161,7 +177,7 @@
|
||||
#llm-history-file: xxx
|
||||
|
||||
##################
|
||||
# Output Settings:
|
||||
# Output settings:
|
||||
|
||||
## Use colors suitable for a dark terminal background (default: False)
|
||||
#dark-mode: false
|
||||
@@ -209,7 +225,7 @@
|
||||
#show-diffs: false
|
||||
|
||||
###############
|
||||
# Git Settings:
|
||||
# Git settings:
|
||||
|
||||
## Enable/disable looking for a git repo (default: True)
|
||||
#git: true
|
||||
@@ -294,8 +310,71 @@
|
||||
## Permanently disable analytics
|
||||
#analytics-disable: false
|
||||
|
||||
############
|
||||
# Upgrading:
|
||||
|
||||
## Check for updates and return status in the exit code
|
||||
#just-check-update: false
|
||||
|
||||
## Check for new aider versions on launch
|
||||
#check-update: true
|
||||
|
||||
## Show release notes on first run of new version (default: None, ask user)
|
||||
#show-release-notes: xxx
|
||||
|
||||
## Install the latest version from the main branch
|
||||
#install-main-branch: false
|
||||
|
||||
## Upgrade aider to the latest version from PyPI
|
||||
#upgrade: false
|
||||
|
||||
## Show the version number and exit
|
||||
#version: xxx
|
||||
|
||||
########
|
||||
# Modes:
|
||||
|
||||
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
|
||||
#message: xxx
|
||||
|
||||
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
|
||||
#message-file: xxx
|
||||
|
||||
## Run aider in your browser (default: False)
|
||||
#gui: false
|
||||
|
||||
## Enable automatic copy/paste of chat between aider and web UI (default: False)
|
||||
#copy-paste: false
|
||||
|
||||
## Apply the changes from the given file instead of running the chat (debug)
|
||||
#apply: xxx
|
||||
|
||||
## Apply clipboard contents as edits using the main model's editor format
|
||||
#apply-clipboard-edits: false
|
||||
|
||||
## Do all startup activities then exit before accepting user input (debug)
|
||||
#exit: false
|
||||
|
||||
## Print the repo map and exit (debug)
|
||||
#show-repo-map: false
|
||||
|
||||
## Print the system prompts and exit (debug)
|
||||
#show-prompts: false
|
||||
|
||||
#################
|
||||
# Other Settings:
|
||||
# Voice settings:
|
||||
|
||||
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
|
||||
#voice-format: wav
|
||||
|
||||
## Specify the language for voice using ISO 639-1 code (default: auto)
|
||||
#voice-language: en
|
||||
|
||||
## Specify the input device name for voice recording
|
||||
#voice-input-device: xxx
|
||||
|
||||
#################
|
||||
# Other settings:
|
||||
|
||||
## specify a file to edit (can be used multiple times)
|
||||
#file: xxx
|
||||
@@ -319,51 +398,12 @@
|
||||
## Specify the language to use in the chat (default: None, uses system settings)
|
||||
#chat-language: xxx
|
||||
|
||||
## Show the version number and exit
|
||||
#version: xxx
|
||||
|
||||
## Check for updates and return status in the exit code
|
||||
#just-check-update: false
|
||||
|
||||
## Check for new aider versions on launch
|
||||
#check-update: true
|
||||
|
||||
## Show release notes on first run of new version (default: None, ask user)
|
||||
#show-release-notes: xxx
|
||||
|
||||
## Install the latest version from the main branch
|
||||
#install-main-branch: false
|
||||
|
||||
## Upgrade aider to the latest version from PyPI
|
||||
#upgrade: false
|
||||
|
||||
## Apply the changes from the given file instead of running the chat (debug)
|
||||
#apply: xxx
|
||||
|
||||
## Apply clipboard contents as edits using the main model's editor format
|
||||
#apply-clipboard-edits: false
|
||||
|
||||
## Always say yes to every confirmation
|
||||
#yes-always: false
|
||||
|
||||
## Enable verbose output
|
||||
#verbose: false
|
||||
|
||||
## Print the repo map and exit (debug)
|
||||
#show-repo-map: false
|
||||
|
||||
## Print the system prompts and exit (debug)
|
||||
#show-prompts: false
|
||||
|
||||
## Do all startup activities then exit before accepting user input (debug)
|
||||
#exit: false
|
||||
|
||||
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
|
||||
#message: xxx
|
||||
|
||||
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
|
||||
#message-file: xxx
|
||||
|
||||
## Load and execute /commands from a file on launch
|
||||
#load: xxx
|
||||
|
||||
@@ -373,8 +413,8 @@
|
||||
## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
|
||||
#config: xxx
|
||||
|
||||
## Run aider in your browser (default: False)
|
||||
#gui: false
|
||||
## Specify the .env file to load (default: .env in git root)
|
||||
#env-file: .env
|
||||
|
||||
## Enable/disable suggesting shell commands (default: True)
|
||||
#suggest-shell-commands: true
|
||||
@@ -382,20 +422,11 @@
|
||||
## Enable/disable fancy input with history and completion (default: True)
|
||||
#fancy-input: true
|
||||
|
||||
## Enable/disable multi-line input mode with Meta-Enter to submit (default: False)
|
||||
#multiline: false
|
||||
|
||||
## Enable/disable detection and offering to add URLs to chat (default: True)
|
||||
#detect-urls: true
|
||||
|
||||
## Specify which editor to use for the /editor command
|
||||
#editor: xxx
|
||||
|
||||
#################
|
||||
# Voice Settings:
|
||||
|
||||
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
|
||||
#voice-format: wav
|
||||
|
||||
## Specify the language for voice using ISO 639-1 code (default: auto)
|
||||
#voice-language: en
|
||||
|
||||
## Specify the input device name for voice recording
|
||||
#voice-input-device: xxx
|
||||
|
||||
@@ -18,14 +18,8 @@
|
||||
|
||||
##...
|
||||
|
||||
#######
|
||||
# Main:
|
||||
|
||||
## Specify the OpenAI API key
|
||||
#OPENAI_API_KEY=
|
||||
|
||||
## Specify the Anthropic API key
|
||||
#ANTHROPIC_API_KEY=
|
||||
#############
|
||||
# Main model:
|
||||
|
||||
## Specify the model to use for the main chat
|
||||
#AIDER_MODEL=
|
||||
@@ -63,27 +57,42 @@
|
||||
## Use o1-preview model for the main chat
|
||||
#AIDER_O1_PREVIEW=
|
||||
|
||||
########################
|
||||
# API Keys and settings:
|
||||
|
||||
## Specify the OpenAI API key
|
||||
#AIDER_OPENAI_API_KEY=
|
||||
|
||||
## Specify the Anthropic API key
|
||||
#AIDER_ANTHROPIC_API_KEY=
|
||||
|
||||
## Specify the api base url
|
||||
#AIDER_OPENAI_API_BASE=
|
||||
|
||||
## (deprecated, use --set-env OPENAI_API_TYPE=<value>)
|
||||
#AIDER_OPENAI_API_TYPE=
|
||||
|
||||
## (deprecated, use --set-env OPENAI_API_VERSION=<value>)
|
||||
#AIDER_OPENAI_API_VERSION=
|
||||
|
||||
## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=<value>)
|
||||
#AIDER_OPENAI_API_DEPLOYMENT_ID=
|
||||
|
||||
## (deprecated, use --set-env OPENAI_ORGANIZATION=<value>)
|
||||
#AIDER_OPENAI_ORGANIZATION_ID=
|
||||
|
||||
## Set an environment variable (to control API settings, can be used multiple times)
|
||||
#AIDER_SET_ENV=
|
||||
|
||||
## Set an API key for a provider (eg: --api-key provider=<key> sets PROVIDER_API_KEY=<key>)
|
||||
#AIDER_API_KEY=
|
||||
|
||||
#################
|
||||
# Model Settings:
|
||||
# Model settings:
|
||||
|
||||
## List known models which match the (partial) MODEL name
|
||||
#AIDER_LIST_MODELS=
|
||||
|
||||
## Specify the api base url
|
||||
#OPENAI_API_BASE=
|
||||
|
||||
## Specify the api_type
|
||||
#OPENAI_API_TYPE=
|
||||
|
||||
## Specify the api_version
|
||||
#OPENAI_API_VERSION=
|
||||
|
||||
## Specify the deployment_id
|
||||
#OPENAI_API_DEPLOYMENT_ID=
|
||||
|
||||
## Specify the OpenAI organization ID
|
||||
#OPENAI_ORGANIZATION_ID=
|
||||
|
||||
## Specify a file with aider model settings for unknown models
|
||||
#AIDER_MODEL_SETTINGS_FILE=.aider.model.settings.yml
|
||||
|
||||
@@ -120,11 +129,8 @@
|
||||
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
|
||||
#AIDER_MAX_CHAT_HISTORY_TOKENS=
|
||||
|
||||
## Specify the .env file to load (default: .env in git root)
|
||||
#AIDER_ENV_FILE=.env
|
||||
|
||||
#################
|
||||
# Cache Settings:
|
||||
# Cache settings:
|
||||
|
||||
## Enable caching of prompts (default: False)
|
||||
#AIDER_CACHE_PROMPTS=false
|
||||
@@ -133,7 +139,7 @@
|
||||
#AIDER_CACHE_KEEPALIVE_PINGS=false
|
||||
|
||||
###################
|
||||
# Repomap Settings:
|
||||
# Repomap settings:
|
||||
|
||||
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
|
||||
#AIDER_MAP_TOKENS=
|
||||
@@ -160,7 +166,7 @@
|
||||
#AIDER_LLM_HISTORY_FILE=
|
||||
|
||||
##################
|
||||
# Output Settings:
|
||||
# Output settings:
|
||||
|
||||
## Use colors suitable for a dark terminal background (default: False)
|
||||
#AIDER_DARK_MODE=false
|
||||
@@ -208,7 +214,7 @@
|
||||
#AIDER_SHOW_DIFFS=false
|
||||
|
||||
###############
|
||||
# Git Settings:
|
||||
# Git settings:
|
||||
|
||||
## Enable/disable looking for a git repo (default: True)
|
||||
#AIDER_GIT=true
|
||||
@@ -288,20 +294,8 @@
|
||||
## Permanently disable analytics
|
||||
#AIDER_ANALYTICS_DISABLE=false
|
||||
|
||||
#################
|
||||
# Other Settings:
|
||||
|
||||
## specify a file to edit (can be used multiple times)
|
||||
#AIDER_FILE=
|
||||
|
||||
## specify a read-only file (can be used multiple times)
|
||||
#AIDER_READ=
|
||||
|
||||
## Use VI editing mode in the terminal (default: False)
|
||||
#AIDER_VIM=false
|
||||
|
||||
## Specify the language to use in the chat (default: None, uses system settings)
|
||||
#AIDER_CHAT_LANGUAGE=
|
||||
############
|
||||
# Upgrading:
|
||||
|
||||
## Check for updates and return status in the exit code
|
||||
#AIDER_JUST_CHECK_UPDATE=false
|
||||
@@ -318,26 +312,8 @@
|
||||
## Upgrade aider to the latest version from PyPI
|
||||
#AIDER_UPGRADE=false
|
||||
|
||||
## Apply the changes from the given file instead of running the chat (debug)
|
||||
#AIDER_APPLY=
|
||||
|
||||
## Apply clipboard contents as edits using the main model's editor format
|
||||
#AIDER_APPLY_CLIPBOARD_EDITS=false
|
||||
|
||||
## Always say yes to every confirmation
|
||||
#AIDER_YES_ALWAYS=
|
||||
|
||||
## Enable verbose output
|
||||
#AIDER_VERBOSE=false
|
||||
|
||||
## Print the repo map and exit (debug)
|
||||
#AIDER_SHOW_REPO_MAP=false
|
||||
|
||||
## Print the system prompts and exit (debug)
|
||||
#AIDER_SHOW_PROMPTS=false
|
||||
|
||||
## Do all startup activities then exit before accepting user input (debug)
|
||||
#AIDER_EXIT=false
|
||||
########
|
||||
# Modes:
|
||||
|
||||
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
|
||||
#AIDER_MESSAGE=
|
||||
@@ -345,29 +321,29 @@
|
||||
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
|
||||
#AIDER_MESSAGE_FILE=
|
||||
|
||||
## Load and execute /commands from a file on launch
|
||||
#AIDER_LOAD=
|
||||
|
||||
## Specify the encoding for input and output (default: utf-8)
|
||||
#AIDER_ENCODING=utf-8
|
||||
|
||||
## Run aider in your browser (default: False)
|
||||
#AIDER_GUI=false
|
||||
|
||||
## Enable/disable suggesting shell commands (default: True)
|
||||
#AIDER_SUGGEST_SHELL_COMMANDS=true
|
||||
## Enable automatic copy/paste of chat between aider and web UI (default: False)
|
||||
#AIDER_COPY_PASTE=false
|
||||
|
||||
## Enable/disable fancy input with history and completion (default: True)
|
||||
#AIDER_FANCY_INPUT=true
|
||||
## Apply the changes from the given file instead of running the chat (debug)
|
||||
#AIDER_APPLY=
|
||||
|
||||
## Enable/disable detection and offering to add URLs to chat (default: True)
|
||||
#AIDER_DETECT_URLS=true
|
||||
## Apply clipboard contents as edits using the main model's editor format
|
||||
#AIDER_APPLY_CLIPBOARD_EDITS=false
|
||||
|
||||
## Specify which editor to use for the /editor command
|
||||
#AIDER_EDITOR=
|
||||
## Do all startup activities then exit before accepting user input (debug)
|
||||
#AIDER_EXIT=false
|
||||
|
||||
## Print the repo map and exit (debug)
|
||||
#AIDER_SHOW_REPO_MAP=false
|
||||
|
||||
## Print the system prompts and exit (debug)
|
||||
#AIDER_SHOW_PROMPTS=false
|
||||
|
||||
#################
|
||||
# Voice Settings:
|
||||
# Voice settings:
|
||||
|
||||
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
|
||||
#AIDER_VOICE_FORMAT=wav
|
||||
@@ -377,3 +353,48 @@
|
||||
|
||||
## Specify the input device name for voice recording
|
||||
#AIDER_VOICE_INPUT_DEVICE=
|
||||
|
||||
#################
|
||||
# Other settings:
|
||||
|
||||
## specify a file to edit (can be used multiple times)
|
||||
#AIDER_FILE=
|
||||
|
||||
## specify a read-only file (can be used multiple times)
|
||||
#AIDER_READ=
|
||||
|
||||
## Use VI editing mode in the terminal (default: False)
|
||||
#AIDER_VIM=false
|
||||
|
||||
## Specify the language to use in the chat (default: None, uses system settings)
|
||||
#AIDER_CHAT_LANGUAGE=
|
||||
|
||||
## Always say yes to every confirmation
|
||||
#AIDER_YES_ALWAYS=
|
||||
|
||||
## Enable verbose output
|
||||
#AIDER_VERBOSE=false
|
||||
|
||||
## Load and execute /commands from a file on launch
|
||||
#AIDER_LOAD=
|
||||
|
||||
## Specify the encoding for input and output (default: utf-8)
|
||||
#AIDER_ENCODING=utf-8
|
||||
|
||||
## Specify the .env file to load (default: .env in git root)
|
||||
#AIDER_ENV_FILE=.env
|
||||
|
||||
## Enable/disable suggesting shell commands (default: True)
|
||||
#AIDER_SUGGEST_SHELL_COMMANDS=true
|
||||
|
||||
## Enable/disable fancy input with history and completion (default: True)
|
||||
#AIDER_FANCY_INPUT=true
|
||||
|
||||
## Enable/disable multi-line input mode with Meta-Enter to submit (default: False)
|
||||
#AIDER_MULTILINE=false
|
||||
|
||||
## Enable/disable detection and offering to add URLs to chat (default: True)
|
||||
#AIDER_DETECT_URLS=true
|
||||
|
||||
## Specify which editor to use for the /editor command
|
||||
#AIDER_EDITOR=
|
||||
|
||||
@@ -40,5 +40,5 @@ Using an `.env` file:
|
||||
AIDER_DARK_MODE=true
|
||||
```
|
||||
|
||||
{% include env-keys-tip.md %}
|
||||
{% include keys.md %}
|
||||
|
||||
|
||||
@@ -46,14 +46,19 @@ The json file should be a dictionary with an entry for each model, as follows:
|
||||
}
|
||||
```
|
||||
|
||||
See
|
||||
[litellm's model_prices_and_context_window.json file](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) for more examples.
|
||||
Consider submitting a PR to that file to add missing models.
|
||||
|
||||
{: .tip }
|
||||
Use a fully qualified model name with a `provider/` at the front
|
||||
in the `.aider.model.metadata.json` file.
|
||||
For example, use `deepseek/deepseek-chat`, not just `deepseek-chat`.
|
||||
That prefix should match the `litellm_provider` field.
|
||||
|
||||
### Contribute model metadata
|
||||
|
||||
Aider relies on
|
||||
[litellm's model_prices_and_context_window.json file](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json)
|
||||
for model metadata.
|
||||
|
||||
Consider submitting a PR to that file to add missing models.
|
||||
|
||||
## Model settings
|
||||
|
||||
@@ -978,6 +983,54 @@ cog.out("```\n")
|
||||
use_system_prompt: true
|
||||
use_temperature: true
|
||||
weak_model_name: null
|
||||
- cache_control: false
|
||||
caches_by_default: false
|
||||
edit_format: diff
|
||||
editor_edit_format: null
|
||||
editor_model_name: null
|
||||
examples_as_sys_msg: false
|
||||
extra_params: null
|
||||
lazy: false
|
||||
name: gemini/gemini-exp-1206
|
||||
reminder: user
|
||||
send_undo_reply: false
|
||||
streaming: true
|
||||
use_repo_map: true
|
||||
use_system_prompt: true
|
||||
use_temperature: true
|
||||
weak_model_name: null
|
||||
- cache_control: false
|
||||
caches_by_default: false
|
||||
edit_format: diff
|
||||
editor_edit_format: null
|
||||
editor_model_name: null
|
||||
examples_as_sys_msg: false
|
||||
extra_params: null
|
||||
lazy: false
|
||||
name: gemini/gemini-exp-1114
|
||||
reminder: user
|
||||
send_undo_reply: false
|
||||
streaming: true
|
||||
use_repo_map: true
|
||||
use_system_prompt: true
|
||||
use_temperature: true
|
||||
weak_model_name: null
|
||||
- cache_control: false
|
||||
caches_by_default: false
|
||||
edit_format: diff
|
||||
editor_edit_format: null
|
||||
editor_model_name: null
|
||||
examples_as_sys_msg: false
|
||||
extra_params: null
|
||||
lazy: false
|
||||
name: gemini/gemini-exp-1121
|
||||
reminder: user
|
||||
send_undo_reply: false
|
||||
streaming: true
|
||||
use_repo_map: true
|
||||
use_system_prompt: true
|
||||
use_temperature: true
|
||||
weak_model_name: null
|
||||
- cache_control: false
|
||||
caches_by_default: false
|
||||
edit_format: diff-fenced
|
||||
@@ -1010,6 +1063,22 @@ cog.out("```\n")
|
||||
use_system_prompt: true
|
||||
use_temperature: true
|
||||
weak_model_name: null
|
||||
- cache_control: false
|
||||
caches_by_default: false
|
||||
edit_format: diff
|
||||
editor_edit_format: null
|
||||
editor_model_name: null
|
||||
examples_as_sys_msg: false
|
||||
extra_params: null
|
||||
lazy: false
|
||||
name: gemini/gemini-2.0-flash-exp
|
||||
reminder: user
|
||||
send_undo_reply: false
|
||||
streaming: true
|
||||
use_repo_map: true
|
||||
use_system_prompt: true
|
||||
use_temperature: true
|
||||
weak_model_name: null
|
||||
- cache_control: false
|
||||
caches_by_default: false
|
||||
edit_format: diff
|
||||
|
||||
@@ -15,11 +15,7 @@ load whichever is found first.
|
||||
- The root of your git repo.
|
||||
- Your home directory.
|
||||
|
||||
## Storing LLM keys
|
||||
|
||||
{% include special-keys.md %}
|
||||
|
||||
{% include env-keys-tip.md %}
|
||||
{% include keys.md %}
|
||||
|
||||
## A note on lists
|
||||
|
||||
@@ -70,14 +66,8 @@ cog.outl("```")
|
||||
## show this help message and exit
|
||||
#help: xxx
|
||||
|
||||
#######
|
||||
# Main:
|
||||
|
||||
## Specify the OpenAI API key
|
||||
#openai-api-key: xxx
|
||||
|
||||
## Specify the Anthropic API key
|
||||
#anthropic-api-key: xxx
|
||||
#############
|
||||
# Main model:
|
||||
|
||||
## Specify the model to use for the main chat
|
||||
#model: xxx
|
||||
@@ -115,27 +105,52 @@ cog.outl("```")
|
||||
## Use o1-preview model for the main chat
|
||||
#o1-preview: false
|
||||
|
||||
#################
|
||||
# Model Settings:
|
||||
########################
|
||||
# API Keys and settings:
|
||||
|
||||
## List known models which match the (partial) MODEL name
|
||||
#list-models: xxx
|
||||
## Specify the OpenAI API key
|
||||
#openai-api-key: xxx
|
||||
|
||||
## Specify the Anthropic API key
|
||||
#anthropic-api-key: xxx
|
||||
|
||||
## Specify the api base url
|
||||
#openai-api-base: xxx
|
||||
|
||||
## Specify the api_type
|
||||
## (deprecated, use --set-env OPENAI_API_TYPE=<value>)
|
||||
#openai-api-type: xxx
|
||||
|
||||
## Specify the api_version
|
||||
## (deprecated, use --set-env OPENAI_API_VERSION=<value>)
|
||||
#openai-api-version: xxx
|
||||
|
||||
## Specify the deployment_id
|
||||
## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=<value>)
|
||||
#openai-api-deployment-id: xxx
|
||||
|
||||
## Specify the OpenAI organization ID
|
||||
## (deprecated, use --set-env OPENAI_ORGANIZATION=<value>)
|
||||
#openai-organization-id: xxx
|
||||
|
||||
## Set an environment variable (to control API settings, can be used multiple times)
|
||||
#set-env: xxx
|
||||
## Specify multiple values like this:
|
||||
#set-env:
|
||||
# - xxx
|
||||
# - yyy
|
||||
# - zzz
|
||||
|
||||
## Set an API key for a provider (eg: --api-key provider=<key> sets PROVIDER_API_KEY=<key>)
|
||||
#api-key: xxx
|
||||
## Specify multiple values like this:
|
||||
#api-key:
|
||||
# - xxx
|
||||
# - yyy
|
||||
# - zzz
|
||||
|
||||
#################
|
||||
# Model settings:
|
||||
|
||||
## List known models which match the (partial) MODEL name
|
||||
#list-models: xxx
|
||||
|
||||
## Specify a file with aider model settings for unknown models
|
||||
#model-settings-file: .aider.model.settings.yml
|
||||
|
||||
@@ -177,11 +192,8 @@ cog.outl("```")
|
||||
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
|
||||
#max-chat-history-tokens: xxx
|
||||
|
||||
## Specify the .env file to load (default: .env in git root)
|
||||
#env-file: .env
|
||||
|
||||
#################
|
||||
# Cache Settings:
|
||||
# Cache settings:
|
||||
|
||||
## Enable caching of prompts (default: False)
|
||||
#cache-prompts: false
|
||||
@@ -190,7 +202,7 @@ cog.outl("```")
|
||||
#cache-keepalive-pings: false
|
||||
|
||||
###################
|
||||
# Repomap Settings:
|
||||
# Repomap settings:
|
||||
|
||||
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
|
||||
#map-tokens: xxx
|
||||
@@ -217,7 +229,7 @@ cog.outl("```")
|
||||
#llm-history-file: xxx
|
||||
|
||||
##################
|
||||
# Output Settings:
|
||||
# Output settings:
|
||||
|
||||
## Use colors suitable for a dark terminal background (default: False)
|
||||
#dark-mode: false
|
||||
@@ -265,7 +277,7 @@ cog.outl("```")
|
||||
#show-diffs: false
|
||||
|
||||
###############
|
||||
# Git Settings:
|
||||
# Git settings:
|
||||
|
||||
## Enable/disable looking for a git repo (default: True)
|
||||
#git: true
|
||||
@@ -350,8 +362,71 @@ cog.outl("```")
|
||||
## Permanently disable analytics
|
||||
#analytics-disable: false
|
||||
|
||||
############
|
||||
# Upgrading:
|
||||
|
||||
## Check for updates and return status in the exit code
|
||||
#just-check-update: false
|
||||
|
||||
## Check for new aider versions on launch
|
||||
#check-update: true
|
||||
|
||||
## Show release notes on first run of new version (default: None, ask user)
|
||||
#show-release-notes: xxx
|
||||
|
||||
## Install the latest version from the main branch
|
||||
#install-main-branch: false
|
||||
|
||||
## Upgrade aider to the latest version from PyPI
|
||||
#upgrade: false
|
||||
|
||||
## Show the version number and exit
|
||||
#version: xxx
|
||||
|
||||
########
|
||||
# Modes:
|
||||
|
||||
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
|
||||
#message: xxx
|
||||
|
||||
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
|
||||
#message-file: xxx
|
||||
|
||||
## Run aider in your browser (default: False)
|
||||
#gui: false
|
||||
|
||||
## Enable automatic copy/paste of chat between aider and web UI (default: False)
|
||||
#copy-paste: false
|
||||
|
||||
## Apply the changes from the given file instead of running the chat (debug)
|
||||
#apply: xxx
|
||||
|
||||
## Apply clipboard contents as edits using the main model's editor format
|
||||
#apply-clipboard-edits: false
|
||||
|
||||
## Do all startup activities then exit before accepting user input (debug)
|
||||
#exit: false
|
||||
|
||||
## Print the repo map and exit (debug)
|
||||
#show-repo-map: false
|
||||
|
||||
## Print the system prompts and exit (debug)
|
||||
#show-prompts: false
|
||||
|
||||
#################
|
||||
# Other Settings:
|
||||
# Voice settings:
|
||||
|
||||
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
|
||||
#voice-format: wav
|
||||
|
||||
## Specify the language for voice using ISO 639-1 code (default: auto)
|
||||
#voice-language: en
|
||||
|
||||
## Specify the input device name for voice recording
|
||||
#voice-input-device: xxx
|
||||
|
||||
#################
|
||||
# Other settings:
|
||||
|
||||
## specify a file to edit (can be used multiple times)
|
||||
#file: xxx
|
||||
@@ -375,51 +450,12 @@ cog.outl("```")
|
||||
## Specify the language to use in the chat (default: None, uses system settings)
|
||||
#chat-language: xxx
|
||||
|
||||
## Show the version number and exit
|
||||
#version: xxx
|
||||
|
||||
## Check for updates and return status in the exit code
|
||||
#just-check-update: false
|
||||
|
||||
## Check for new aider versions on launch
|
||||
#check-update: true
|
||||
|
||||
## Show release notes on first run of new version (default: None, ask user)
|
||||
#show-release-notes: xxx
|
||||
|
||||
## Install the latest version from the main branch
|
||||
#install-main-branch: false
|
||||
|
||||
## Upgrade aider to the latest version from PyPI
|
||||
#upgrade: false
|
||||
|
||||
## Apply the changes from the given file instead of running the chat (debug)
|
||||
#apply: xxx
|
||||
|
||||
## Apply clipboard contents as edits using the main model's editor format
|
||||
#apply-clipboard-edits: false
|
||||
|
||||
## Always say yes to every confirmation
|
||||
#yes-always: false
|
||||
|
||||
## Enable verbose output
|
||||
#verbose: false
|
||||
|
||||
## Print the repo map and exit (debug)
|
||||
#show-repo-map: false
|
||||
|
||||
## Print the system prompts and exit (debug)
|
||||
#show-prompts: false
|
||||
|
||||
## Do all startup activities then exit before accepting user input (debug)
|
||||
#exit: false
|
||||
|
||||
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
|
||||
#message: xxx
|
||||
|
||||
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
|
||||
#message-file: xxx
|
||||
|
||||
## Load and execute /commands from a file on launch
|
||||
#load: xxx
|
||||
|
||||
@@ -429,8 +465,8 @@ cog.outl("```")
|
||||
## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
|
||||
#config: xxx
|
||||
|
||||
## Run aider in your browser (default: False)
|
||||
#gui: false
|
||||
## Specify the .env file to load (default: .env in git root)
|
||||
#env-file: .env
|
||||
|
||||
## Enable/disable suggesting shell commands (default: True)
|
||||
#suggest-shell-commands: true
|
||||
@@ -438,22 +474,13 @@ cog.outl("```")
|
||||
## Enable/disable fancy input with history and completion (default: True)
|
||||
#fancy-input: true
|
||||
|
||||
## Enable/disable multi-line input mode with Meta-Enter to submit (default: False)
|
||||
#multiline: false
|
||||
|
||||
## Enable/disable detection and offering to add URLs to chat (default: True)
|
||||
#detect-urls: true
|
||||
|
||||
## Specify which editor to use for the /editor command
|
||||
#editor: xxx
|
||||
|
||||
#################
|
||||
# Voice Settings:
|
||||
|
||||
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
|
||||
#voice-format: wav
|
||||
|
||||
## Specify the language for voice using ISO 639-1 code (default: auto)
|
||||
#voice-language: en
|
||||
|
||||
## Specify the input device name for voice recording
|
||||
#voice-input-device: xxx
|
||||
```
|
||||
<!--[[[end]]]-->
|
||||
|
||||
68
aider/website/docs/config/api-keys.md
Normal file
68
aider/website/docs/config/api-keys.md
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
parent: Configuration
|
||||
nav_order: 5
|
||||
description: Setting API keys for API providers.
|
||||
---
|
||||
|
||||
# API Keys
|
||||
|
||||
### OpenAI and Anthropic
|
||||
|
||||
Aider has special support for providing
|
||||
OpenAI and Anthropic API keys
|
||||
via dedicated switches and configuration options.
|
||||
Settings keys for other providers works a bit differently, see below.
|
||||
|
||||
You can set OpenAI and Anthropic API keys via
|
||||
[command line switches](/docs/config/options.html#api-keys-and-settings)
|
||||
`--openai-api-key` and `--anthropic-api-key`.
|
||||
|
||||
You can also set those API keys via special entries in the
|
||||
[yaml config file](/docs/config/aider_conf.html), like this:
|
||||
|
||||
```yaml
|
||||
openai-api-key: <key>
|
||||
anthropic-api-key: <key>
|
||||
```
|
||||
|
||||
You can also store them in environment variables or a
|
||||
[.env file](/docs/config/dotenv.html), which also works
|
||||
for every API provider:
|
||||
|
||||
```
|
||||
OPENAI_API_KEY=<key>
|
||||
ANTHROPIC_API_KEY=<key>
|
||||
```
|
||||
|
||||
All other LLM providers can use one of these other methods to set their API keys.
|
||||
|
||||
### API keys on the command line
|
||||
{: .no_toc }
|
||||
|
||||
Use `--api-key provider=<key>` which has the effect of setting the environment variable `PROVIDER_API_KEY=<key>`. So `--api-key gemini=xxx` would set `GEMINI_API_KEY=xxx`.
|
||||
|
||||
### API keys in .aider.conf.yml
|
||||
{: .no_toc }
|
||||
|
||||
You can also set API keys in the
|
||||
[`.aider.conf.yml` file](/docs/config/aider_conf.html)
|
||||
via the `api-key` entry:
|
||||
|
||||
```
|
||||
api-key:
|
||||
- gemini=foo # Sets env var GEMINI_API_KEY=foo
|
||||
- openrouter=bar # Sets env var OPENROUTER_API_KEY=bar
|
||||
- deepseek=baz # Sets env var DEEPSEEK_API_KEY=baz
|
||||
```
|
||||
|
||||
### API keys in a .env file
|
||||
{: .no_toc }
|
||||
|
||||
The [.env file](/docs/config/dotenv.html)
|
||||
is a great place to set API keys and other provider API environment variables:
|
||||
|
||||
```bash
|
||||
GEMINI_API_KEY=foo
|
||||
OPENROUTER_API_KEY=bar
|
||||
DEEPSEEK_API_KEY=baz
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
parent: Configuration
|
||||
nav_order: 900
|
||||
nav_order: 20
|
||||
description: Using a .env file to store LLM API keys for aider.
|
||||
---
|
||||
|
||||
@@ -20,9 +20,7 @@ Aider will look for a `.env` file in these locations:
|
||||
|
||||
If the files above exist, they will be loaded in that order. Files loaded last will take priority.
|
||||
|
||||
## Storing LLM keys
|
||||
|
||||
{% include special-keys.md %}
|
||||
{% include keys.md %}
|
||||
|
||||
## Sample .env file
|
||||
|
||||
@@ -60,14 +58,8 @@ cog.outl("```")
|
||||
|
||||
##...
|
||||
|
||||
#######
|
||||
# Main:
|
||||
|
||||
## Specify the OpenAI API key
|
||||
#OPENAI_API_KEY=
|
||||
|
||||
## Specify the Anthropic API key
|
||||
#ANTHROPIC_API_KEY=
|
||||
#############
|
||||
# Main model:
|
||||
|
||||
## Specify the model to use for the main chat
|
||||
#AIDER_MODEL=
|
||||
@@ -105,27 +97,42 @@ cog.outl("```")
|
||||
## Use o1-preview model for the main chat
|
||||
#AIDER_O1_PREVIEW=
|
||||
|
||||
########################
|
||||
# API Keys and settings:
|
||||
|
||||
## Specify the OpenAI API key
|
||||
#AIDER_OPENAI_API_KEY=
|
||||
|
||||
## Specify the Anthropic API key
|
||||
#AIDER_ANTHROPIC_API_KEY=
|
||||
|
||||
## Specify the api base url
|
||||
#AIDER_OPENAI_API_BASE=
|
||||
|
||||
## (deprecated, use --set-env OPENAI_API_TYPE=<value>)
|
||||
#AIDER_OPENAI_API_TYPE=
|
||||
|
||||
## (deprecated, use --set-env OPENAI_API_VERSION=<value>)
|
||||
#AIDER_OPENAI_API_VERSION=
|
||||
|
||||
## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=<value>)
|
||||
#AIDER_OPENAI_API_DEPLOYMENT_ID=
|
||||
|
||||
## (deprecated, use --set-env OPENAI_ORGANIZATION=<value>)
|
||||
#AIDER_OPENAI_ORGANIZATION_ID=
|
||||
|
||||
## Set an environment variable (to control API settings, can be used multiple times)
|
||||
#AIDER_SET_ENV=
|
||||
|
||||
## Set an API key for a provider (eg: --api-key provider=<key> sets PROVIDER_API_KEY=<key>)
|
||||
#AIDER_API_KEY=
|
||||
|
||||
#################
|
||||
# Model Settings:
|
||||
# Model settings:
|
||||
|
||||
## List known models which match the (partial) MODEL name
|
||||
#AIDER_LIST_MODELS=
|
||||
|
||||
## Specify the api base url
|
||||
#OPENAI_API_BASE=
|
||||
|
||||
## Specify the api_type
|
||||
#OPENAI_API_TYPE=
|
||||
|
||||
## Specify the api_version
|
||||
#OPENAI_API_VERSION=
|
||||
|
||||
## Specify the deployment_id
|
||||
#OPENAI_API_DEPLOYMENT_ID=
|
||||
|
||||
## Specify the OpenAI organization ID
|
||||
#OPENAI_ORGANIZATION_ID=
|
||||
|
||||
## Specify a file with aider model settings for unknown models
|
||||
#AIDER_MODEL_SETTINGS_FILE=.aider.model.settings.yml
|
||||
|
||||
@@ -162,11 +169,8 @@ cog.outl("```")
|
||||
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
|
||||
#AIDER_MAX_CHAT_HISTORY_TOKENS=
|
||||
|
||||
## Specify the .env file to load (default: .env in git root)
|
||||
#AIDER_ENV_FILE=.env
|
||||
|
||||
#################
|
||||
# Cache Settings:
|
||||
# Cache settings:
|
||||
|
||||
## Enable caching of prompts (default: False)
|
||||
#AIDER_CACHE_PROMPTS=false
|
||||
@@ -175,7 +179,7 @@ cog.outl("```")
|
||||
#AIDER_CACHE_KEEPALIVE_PINGS=false
|
||||
|
||||
###################
|
||||
# Repomap Settings:
|
||||
# Repomap settings:
|
||||
|
||||
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
|
||||
#AIDER_MAP_TOKENS=
|
||||
@@ -202,7 +206,7 @@ cog.outl("```")
|
||||
#AIDER_LLM_HISTORY_FILE=
|
||||
|
||||
##################
|
||||
# Output Settings:
|
||||
# Output settings:
|
||||
|
||||
## Use colors suitable for a dark terminal background (default: False)
|
||||
#AIDER_DARK_MODE=false
|
||||
@@ -250,7 +254,7 @@ cog.outl("```")
|
||||
#AIDER_SHOW_DIFFS=false
|
||||
|
||||
###############
|
||||
# Git Settings:
|
||||
# Git settings:
|
||||
|
||||
## Enable/disable looking for a git repo (default: True)
|
||||
#AIDER_GIT=true
|
||||
@@ -330,20 +334,8 @@ cog.outl("```")
|
||||
## Permanently disable analytics
|
||||
#AIDER_ANALYTICS_DISABLE=false
|
||||
|
||||
#################
|
||||
# Other Settings:
|
||||
|
||||
## specify a file to edit (can be used multiple times)
|
||||
#AIDER_FILE=
|
||||
|
||||
## specify a read-only file (can be used multiple times)
|
||||
#AIDER_READ=
|
||||
|
||||
## Use VI editing mode in the terminal (default: False)
|
||||
#AIDER_VIM=false
|
||||
|
||||
## Specify the language to use in the chat (default: None, uses system settings)
|
||||
#AIDER_CHAT_LANGUAGE=
|
||||
############
|
||||
# Upgrading:
|
||||
|
||||
## Check for updates and return status in the exit code
|
||||
#AIDER_JUST_CHECK_UPDATE=false
|
||||
@@ -360,26 +352,8 @@ cog.outl("```")
|
||||
## Upgrade aider to the latest version from PyPI
|
||||
#AIDER_UPGRADE=false
|
||||
|
||||
## Apply the changes from the given file instead of running the chat (debug)
|
||||
#AIDER_APPLY=
|
||||
|
||||
## Apply clipboard contents as edits using the main model's editor format
|
||||
#AIDER_APPLY_CLIPBOARD_EDITS=false
|
||||
|
||||
## Always say yes to every confirmation
|
||||
#AIDER_YES_ALWAYS=
|
||||
|
||||
## Enable verbose output
|
||||
#AIDER_VERBOSE=false
|
||||
|
||||
## Print the repo map and exit (debug)
|
||||
#AIDER_SHOW_REPO_MAP=false
|
||||
|
||||
## Print the system prompts and exit (debug)
|
||||
#AIDER_SHOW_PROMPTS=false
|
||||
|
||||
## Do all startup activities then exit before accepting user input (debug)
|
||||
#AIDER_EXIT=false
|
||||
########
|
||||
# Modes:
|
||||
|
||||
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
|
||||
#AIDER_MESSAGE=
|
||||
@@ -387,29 +361,29 @@ cog.outl("```")
|
||||
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
|
||||
#AIDER_MESSAGE_FILE=
|
||||
|
||||
## Load and execute /commands from a file on launch
|
||||
#AIDER_LOAD=
|
||||
|
||||
## Specify the encoding for input and output (default: utf-8)
|
||||
#AIDER_ENCODING=utf-8
|
||||
|
||||
## Run aider in your browser (default: False)
|
||||
#AIDER_GUI=false
|
||||
|
||||
## Enable/disable suggesting shell commands (default: True)
|
||||
#AIDER_SUGGEST_SHELL_COMMANDS=true
|
||||
## Enable automatic copy/paste of chat between aider and web UI (default: False)
|
||||
#AIDER_COPY_PASTE=false
|
||||
|
||||
## Enable/disable fancy input with history and completion (default: True)
|
||||
#AIDER_FANCY_INPUT=true
|
||||
## Apply the changes from the given file instead of running the chat (debug)
|
||||
#AIDER_APPLY=
|
||||
|
||||
## Enable/disable detection and offering to add URLs to chat (default: True)
|
||||
#AIDER_DETECT_URLS=true
|
||||
## Apply clipboard contents as edits using the main model's editor format
|
||||
#AIDER_APPLY_CLIPBOARD_EDITS=false
|
||||
|
||||
## Specify which editor to use for the /editor command
|
||||
#AIDER_EDITOR=
|
||||
## Do all startup activities then exit before accepting user input (debug)
|
||||
#AIDER_EXIT=false
|
||||
|
||||
## Print the repo map and exit (debug)
|
||||
#AIDER_SHOW_REPO_MAP=false
|
||||
|
||||
## Print the system prompts and exit (debug)
|
||||
#AIDER_SHOW_PROMPTS=false
|
||||
|
||||
#################
|
||||
# Voice Settings:
|
||||
# Voice settings:
|
||||
|
||||
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
|
||||
#AIDER_VOICE_FORMAT=wav
|
||||
@@ -419,5 +393,50 @@ cog.outl("```")
|
||||
|
||||
## Specify the input device name for voice recording
|
||||
#AIDER_VOICE_INPUT_DEVICE=
|
||||
|
||||
#################
|
||||
# Other settings:
|
||||
|
||||
## specify a file to edit (can be used multiple times)
|
||||
#AIDER_FILE=
|
||||
|
||||
## specify a read-only file (can be used multiple times)
|
||||
#AIDER_READ=
|
||||
|
||||
## Use VI editing mode in the terminal (default: False)
|
||||
#AIDER_VIM=false
|
||||
|
||||
## Specify the language to use in the chat (default: None, uses system settings)
|
||||
#AIDER_CHAT_LANGUAGE=
|
||||
|
||||
## Always say yes to every confirmation
|
||||
#AIDER_YES_ALWAYS=
|
||||
|
||||
## Enable verbose output
|
||||
#AIDER_VERBOSE=false
|
||||
|
||||
## Load and execute /commands from a file on launch
|
||||
#AIDER_LOAD=
|
||||
|
||||
## Specify the encoding for input and output (default: utf-8)
|
||||
#AIDER_ENCODING=utf-8
|
||||
|
||||
## Specify the .env file to load (default: .env in git root)
|
||||
#AIDER_ENV_FILE=.env
|
||||
|
||||
## Enable/disable suggesting shell commands (default: True)
|
||||
#AIDER_SUGGEST_SHELL_COMMANDS=true
|
||||
|
||||
## Enable/disable fancy input with history and completion (default: True)
|
||||
#AIDER_FANCY_INPUT=true
|
||||
|
||||
## Enable/disable multi-line input mode with Meta-Enter to submit (default: False)
|
||||
#AIDER_MULTILINE=false
|
||||
|
||||
## Enable/disable detection and offering to add URLs to chat (default: True)
|
||||
#AIDER_DETECT_URLS=true
|
||||
|
||||
## Specify which editor to use for the /editor command
|
||||
#AIDER_EDITOR=
|
||||
```
|
||||
<!--[[[end]]]-->
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
parent: Configuration
|
||||
nav_order: 15
|
||||
nav_order: 100
|
||||
description: How to configure a custom editor for aider's /editor command
|
||||
---
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ for alias, model in sorted(MODEL_ALIASES.items()):
|
||||
- `4-turbo`: gpt-4-1106-preview
|
||||
- `4o`: gpt-4o
|
||||
- `deepseek`: deepseek/deepseek-coder
|
||||
- `flash`: gemini/gemini-2.0-flash-exp
|
||||
- `haiku`: claude-3-5-haiku-20241022
|
||||
- `opus`: claude-3-opus-20240229
|
||||
- `sonnet`: claude-3-5-sonnet-20241022
|
||||
|
||||
@@ -13,10 +13,7 @@ or review them below.
|
||||
- TOC
|
||||
{:toc}
|
||||
|
||||
## LLM keys
|
||||
{: .no_toc }
|
||||
|
||||
{% include special-keys.md %}
|
||||
{% include keys.md %}
|
||||
|
||||
## Usage summary
|
||||
|
||||
@@ -25,18 +22,19 @@ from aider.args import get_md_help
|
||||
cog.out(get_md_help())
|
||||
]]]-->
|
||||
```
|
||||
usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model]
|
||||
[--opus] [--sonnet] [--haiku] [--4] [--4o] [--mini]
|
||||
[--4-turbo] [--35turbo] [--deepseek] [--o1-mini]
|
||||
[--o1-preview] [--list-models] [--openai-api-base]
|
||||
usage: aider [-h] [--model] [--opus] [--sonnet] [--haiku] [--4]
|
||||
[--4o] [--mini] [--4-turbo] [--35turbo] [--deepseek]
|
||||
[--o1-mini] [--o1-preview] [--openai-api-key]
|
||||
[--anthropic-api-key] [--openai-api-base]
|
||||
[--openai-api-type] [--openai-api-version]
|
||||
[--openai-api-deployment-id] [--openai-organization-id]
|
||||
[--set-env] [--api-key] [--list-models]
|
||||
[--model-settings-file] [--model-metadata-file]
|
||||
[--alias] [--verify-ssl | --no-verify-ssl] [--timeout]
|
||||
[--edit-format] [--architect] [--weak-model]
|
||||
[--editor-model] [--editor-edit-format]
|
||||
[--show-model-warnings | --no-show-model-warnings]
|
||||
[--max-chat-history-tokens] [--env-file]
|
||||
[--max-chat-history-tokens]
|
||||
[--cache-prompts | --no-cache-prompts]
|
||||
[--cache-keepalive-pings] [--map-tokens]
|
||||
[--map-refresh] [--map-multiplier-no-files]
|
||||
@@ -64,20 +62,22 @@ usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model]
|
||||
[--lint-cmd] [--auto-lint | --no-auto-lint]
|
||||
[--test-cmd] [--auto-test | --no-auto-test] [--test]
|
||||
[--analytics | --no-analytics] [--analytics-log]
|
||||
[--analytics-disable] [--file] [--read] [--vim]
|
||||
[--chat-language] [--version] [--just-check-update]
|
||||
[--analytics-disable] [--just-check-update]
|
||||
[--check-update | --no-check-update]
|
||||
[--show-release-notes | --no-show-release-notes]
|
||||
[--install-main-branch] [--upgrade] [--apply]
|
||||
[--apply-clipboard-edits] [--yes-always] [-v]
|
||||
[--show-repo-map] [--show-prompts] [--exit] [--message]
|
||||
[--message-file] [--load] [--encoding] [-c]
|
||||
[--install-main-branch] [--upgrade] [--version]
|
||||
[--message] [--message-file]
|
||||
[--gui | --no-gui | --browser | --no-browser]
|
||||
[--copy-paste | --no-copy-paste] [--apply]
|
||||
[--apply-clipboard-edits] [--exit] [--show-repo-map]
|
||||
[--show-prompts] [--voice-format] [--voice-language]
|
||||
[--voice-input-device] [--file] [--read] [--vim]
|
||||
[--chat-language] [--yes-always] [-v] [--load]
|
||||
[--encoding] [-c] [--env-file]
|
||||
[--suggest-shell-commands | --no-suggest-shell-commands]
|
||||
[--fancy-input | --no-fancy-input]
|
||||
[--multiline | --no-multiline]
|
||||
[--detect-urls | --no-detect-urls] [--editor]
|
||||
[--voice-format] [--voice-language]
|
||||
[--voice-input-device]
|
||||
|
||||
```
|
||||
|
||||
@@ -89,15 +89,7 @@ Aliases:
|
||||
- `-h`
|
||||
- `--help`
|
||||
|
||||
## Main:
|
||||
|
||||
### `--openai-api-key OPENAI_API_KEY`
|
||||
Specify the OpenAI API key
|
||||
Environment variable: `OPENAI_API_KEY`
|
||||
|
||||
### `--anthropic-api-key ANTHROPIC_API_KEY`
|
||||
Specify the Anthropic API key
|
||||
Environment variable: `ANTHROPIC_API_KEY`
|
||||
## Main model:
|
||||
|
||||
### `--model MODEL`
|
||||
Specify the model to use for the main chat
|
||||
@@ -155,7 +147,47 @@ Environment variable: `AIDER_O1_MINI`
|
||||
Use o1-preview model for the main chat
|
||||
Environment variable: `AIDER_O1_PREVIEW`
|
||||
|
||||
## Model Settings:
|
||||
## API Keys and settings:
|
||||
|
||||
### `--openai-api-key VALUE`
|
||||
Specify the OpenAI API key
|
||||
Environment variable: `AIDER_OPENAI_API_KEY`
|
||||
|
||||
### `--anthropic-api-key VALUE`
|
||||
Specify the Anthropic API key
|
||||
Environment variable: `AIDER_ANTHROPIC_API_KEY`
|
||||
|
||||
### `--openai-api-base VALUE`
|
||||
Specify the api base url
|
||||
Environment variable: `AIDER_OPENAI_API_BASE`
|
||||
|
||||
### `--openai-api-type VALUE`
|
||||
(deprecated, use --set-env OPENAI_API_TYPE=<value>)
|
||||
Environment variable: `AIDER_OPENAI_API_TYPE`
|
||||
|
||||
### `--openai-api-version VALUE`
|
||||
(deprecated, use --set-env OPENAI_API_VERSION=<value>)
|
||||
Environment variable: `AIDER_OPENAI_API_VERSION`
|
||||
|
||||
### `--openai-api-deployment-id VALUE`
|
||||
(deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=<value>)
|
||||
Environment variable: `AIDER_OPENAI_API_DEPLOYMENT_ID`
|
||||
|
||||
### `--openai-organization-id VALUE`
|
||||
(deprecated, use --set-env OPENAI_ORGANIZATION=<value>)
|
||||
Environment variable: `AIDER_OPENAI_ORGANIZATION_ID`
|
||||
|
||||
### `--set-env ENV_VAR_NAME=value`
|
||||
Set an environment variable (to control API settings, can be used multiple times)
|
||||
Default: []
|
||||
Environment variable: `AIDER_SET_ENV`
|
||||
|
||||
### `--api-key PROVIDER=KEY`
|
||||
Set an API key for a provider (eg: --api-key provider=<key> sets PROVIDER_API_KEY=<key>)
|
||||
Default: []
|
||||
Environment variable: `AIDER_API_KEY`
|
||||
|
||||
## Model settings:
|
||||
|
||||
### `--list-models MODEL`
|
||||
List known models which match the (partial) MODEL name
|
||||
@@ -164,26 +196,6 @@ Aliases:
|
||||
- `--list-models MODEL`
|
||||
- `--models MODEL`
|
||||
|
||||
### `--openai-api-base OPENAI_API_BASE`
|
||||
Specify the api base url
|
||||
Environment variable: `OPENAI_API_BASE`
|
||||
|
||||
### `--openai-api-type OPENAI_API_TYPE`
|
||||
Specify the api_type
|
||||
Environment variable: `OPENAI_API_TYPE`
|
||||
|
||||
### `--openai-api-version OPENAI_API_VERSION`
|
||||
Specify the api_version
|
||||
Environment variable: `OPENAI_API_VERSION`
|
||||
|
||||
### `--openai-api-deployment-id OPENAI_API_DEPLOYMENT_ID`
|
||||
Specify the deployment_id
|
||||
Environment variable: `OPENAI_API_DEPLOYMENT_ID`
|
||||
|
||||
### `--openai-organization-id OPENAI_ORGANIZATION_ID`
|
||||
Specify the OpenAI organization ID
|
||||
Environment variable: `OPENAI_ORGANIZATION_ID`
|
||||
|
||||
### `--model-settings-file MODEL_SETTINGS_FILE`
|
||||
Specify a file with aider model settings for unknown models
|
||||
Default: .aider.model.settings.yml
|
||||
@@ -245,12 +257,7 @@ Aliases:
|
||||
Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
|
||||
Environment variable: `AIDER_MAX_CHAT_HISTORY_TOKENS`
|
||||
|
||||
### `--env-file ENV_FILE`
|
||||
Specify the .env file to load (default: .env in git root)
|
||||
Default: .env
|
||||
Environment variable: `AIDER_ENV_FILE`
|
||||
|
||||
## Cache Settings:
|
||||
## Cache settings:
|
||||
|
||||
### `--cache-prompts`
|
||||
Enable caching of prompts (default: False)
|
||||
@@ -265,7 +272,7 @@ Number of times to ping at 5min intervals to keep prompt cache warm (default: 0)
|
||||
Default: 0
|
||||
Environment variable: `AIDER_CACHE_KEEPALIVE_PINGS`
|
||||
|
||||
## Repomap Settings:
|
||||
## Repomap settings:
|
||||
|
||||
### `--map-tokens VALUE`
|
||||
Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
|
||||
@@ -305,7 +312,7 @@ Aliases:
|
||||
Log the conversation with the LLM to this file (for example, .aider.llm.history)
|
||||
Environment variable: `AIDER_LLM_HISTORY_FILE`
|
||||
|
||||
## Output Settings:
|
||||
## Output settings:
|
||||
|
||||
### `--dark-mode`
|
||||
Use colors suitable for a dark terminal background (default: False)
|
||||
@@ -383,7 +390,7 @@ Show diffs when committing changes (default: False)
|
||||
Default: False
|
||||
Environment variable: `AIDER_SHOW_DIFFS`
|
||||
|
||||
## Git Settings:
|
||||
## Git settings:
|
||||
|
||||
### `--git`
|
||||
Enable/disable looking for a git repo (default: True)
|
||||
@@ -545,27 +552,7 @@ Permanently disable analytics
|
||||
Default: False
|
||||
Environment variable: `AIDER_ANALYTICS_DISABLE`
|
||||
|
||||
## Other Settings:
|
||||
|
||||
### `--file FILE`
|
||||
specify a file to edit (can be used multiple times)
|
||||
Environment variable: `AIDER_FILE`
|
||||
|
||||
### `--read FILE`
|
||||
specify a read-only file (can be used multiple times)
|
||||
Environment variable: `AIDER_READ`
|
||||
|
||||
### `--vim`
|
||||
Use VI editing mode in the terminal (default: False)
|
||||
Default: False
|
||||
Environment variable: `AIDER_VIM`
|
||||
|
||||
### `--chat-language CHAT_LANGUAGE`
|
||||
Specify the language to use in the chat (default: None, uses system settings)
|
||||
Environment variable: `AIDER_CHAT_LANGUAGE`
|
||||
|
||||
### `--version`
|
||||
Show the version number and exit
|
||||
## Upgrading:
|
||||
|
||||
### `--just-check-update`
|
||||
Check for updates and return status in the exit code
|
||||
@@ -600,41 +587,10 @@ Aliases:
|
||||
- `--upgrade`
|
||||
- `--update`
|
||||
|
||||
### `--apply FILE`
|
||||
Apply the changes from the given file instead of running the chat (debug)
|
||||
Environment variable: `AIDER_APPLY`
|
||||
### `--version`
|
||||
Show the version number and exit
|
||||
|
||||
### `--apply-clipboard-edits`
|
||||
Apply clipboard contents as edits using the main model's editor format
|
||||
Default: False
|
||||
Environment variable: `AIDER_APPLY_CLIPBOARD_EDITS`
|
||||
|
||||
### `--yes-always`
|
||||
Always say yes to every confirmation
|
||||
Environment variable: `AIDER_YES_ALWAYS`
|
||||
|
||||
### `--verbose`
|
||||
Enable verbose output
|
||||
Default: False
|
||||
Environment variable: `AIDER_VERBOSE`
|
||||
Aliases:
|
||||
- `-v`
|
||||
- `--verbose`
|
||||
|
||||
### `--show-repo-map`
|
||||
Print the repo map and exit (debug)
|
||||
Default: False
|
||||
Environment variable: `AIDER_SHOW_REPO_MAP`
|
||||
|
||||
### `--show-prompts`
|
||||
Print the system prompts and exit (debug)
|
||||
Default: False
|
||||
Environment variable: `AIDER_SHOW_PROMPTS`
|
||||
|
||||
### `--exit`
|
||||
Do all startup activities then exit before accepting user input (debug)
|
||||
Default: False
|
||||
Environment variable: `AIDER_EXIT`
|
||||
## Modes:
|
||||
|
||||
### `--message COMMAND`
|
||||
Specify a single message to send the LLM, process reply then exit (disables chat mode)
|
||||
@@ -651,6 +607,95 @@ Aliases:
|
||||
- `--message-file MESSAGE_FILE`
|
||||
- `-f MESSAGE_FILE`
|
||||
|
||||
### `--gui`
|
||||
Run aider in your browser (default: False)
|
||||
Default: False
|
||||
Environment variable: `AIDER_GUI`
|
||||
Aliases:
|
||||
- `--gui`
|
||||
- `--no-gui`
|
||||
- `--browser`
|
||||
- `--no-browser`
|
||||
|
||||
### `--copy-paste`
|
||||
Enable automatic copy/paste of chat between aider and web UI (default: False)
|
||||
Default: False
|
||||
Environment variable: `AIDER_COPY_PASTE`
|
||||
Aliases:
|
||||
- `--copy-paste`
|
||||
- `--no-copy-paste`
|
||||
|
||||
### `--apply FILE`
|
||||
Apply the changes from the given file instead of running the chat (debug)
|
||||
Environment variable: `AIDER_APPLY`
|
||||
|
||||
### `--apply-clipboard-edits`
|
||||
Apply clipboard contents as edits using the main model's editor format
|
||||
Default: False
|
||||
Environment variable: `AIDER_APPLY_CLIPBOARD_EDITS`
|
||||
|
||||
### `--exit`
|
||||
Do all startup activities then exit before accepting user input (debug)
|
||||
Default: False
|
||||
Environment variable: `AIDER_EXIT`
|
||||
|
||||
### `--show-repo-map`
|
||||
Print the repo map and exit (debug)
|
||||
Default: False
|
||||
Environment variable: `AIDER_SHOW_REPO_MAP`
|
||||
|
||||
### `--show-prompts`
|
||||
Print the system prompts and exit (debug)
|
||||
Default: False
|
||||
Environment variable: `AIDER_SHOW_PROMPTS`
|
||||
|
||||
## Voice settings:
|
||||
|
||||
### `--voice-format VOICE_FORMAT`
|
||||
Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
|
||||
Default: wav
|
||||
Environment variable: `AIDER_VOICE_FORMAT`
|
||||
|
||||
### `--voice-language VOICE_LANGUAGE`
|
||||
Specify the language for voice using ISO 639-1 code (default: auto)
|
||||
Default: en
|
||||
Environment variable: `AIDER_VOICE_LANGUAGE`
|
||||
|
||||
### `--voice-input-device VOICE_INPUT_DEVICE`
|
||||
Specify the input device name for voice recording
|
||||
Environment variable: `AIDER_VOICE_INPUT_DEVICE`
|
||||
|
||||
## Other settings:
|
||||
|
||||
### `--file FILE`
|
||||
specify a file to edit (can be used multiple times)
|
||||
Environment variable: `AIDER_FILE`
|
||||
|
||||
### `--read FILE`
|
||||
specify a read-only file (can be used multiple times)
|
||||
Environment variable: `AIDER_READ`
|
||||
|
||||
### `--vim`
|
||||
Use VI editing mode in the terminal (default: False)
|
||||
Default: False
|
||||
Environment variable: `AIDER_VIM`
|
||||
|
||||
### `--chat-language CHAT_LANGUAGE`
|
||||
Specify the language to use in the chat (default: None, uses system settings)
|
||||
Environment variable: `AIDER_CHAT_LANGUAGE`
|
||||
|
||||
### `--yes-always`
|
||||
Always say yes to every confirmation
|
||||
Environment variable: `AIDER_YES_ALWAYS`
|
||||
|
||||
### `--verbose`
|
||||
Enable verbose output
|
||||
Default: False
|
||||
Environment variable: `AIDER_VERBOSE`
|
||||
Aliases:
|
||||
- `-v`
|
||||
- `--verbose`
|
||||
|
||||
### `--load LOAD_FILE`
|
||||
Load and execute /commands from a file on launch
|
||||
Environment variable: `AIDER_LOAD`
|
||||
@@ -666,15 +711,10 @@ Aliases:
|
||||
- `-c CONFIG_FILE`
|
||||
- `--config CONFIG_FILE`
|
||||
|
||||
### `--gui`
|
||||
Run aider in your browser (default: False)
|
||||
Default: False
|
||||
Environment variable: `AIDER_GUI`
|
||||
Aliases:
|
||||
- `--gui`
|
||||
- `--no-gui`
|
||||
- `--browser`
|
||||
- `--no-browser`
|
||||
### `--env-file ENV_FILE`
|
||||
Specify the .env file to load (default: .env in git root)
|
||||
Default: .env
|
||||
Environment variable: `AIDER_ENV_FILE`
|
||||
|
||||
### `--suggest-shell-commands`
|
||||
Enable/disable suggesting shell commands (default: True)
|
||||
@@ -692,6 +732,14 @@ Aliases:
|
||||
- `--fancy-input`
|
||||
- `--no-fancy-input`
|
||||
|
||||
### `--multiline`
|
||||
Enable/disable multi-line input mode with Meta-Enter to submit (default: False)
|
||||
Default: False
|
||||
Environment variable: `AIDER_MULTILINE`
|
||||
Aliases:
|
||||
- `--multiline`
|
||||
- `--no-multiline`
|
||||
|
||||
### `--detect-urls`
|
||||
Enable/disable detection and offering to add URLs to chat (default: True)
|
||||
Default: True
|
||||
@@ -703,20 +751,4 @@ Aliases:
|
||||
### `--editor VALUE`
|
||||
Specify which editor to use for the /editor command
|
||||
Environment variable: `AIDER_EDITOR`
|
||||
|
||||
## Voice Settings:
|
||||
|
||||
### `--voice-format VOICE_FORMAT`
|
||||
Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
|
||||
Default: wav
|
||||
Environment variable: `AIDER_VOICE_FORMAT`
|
||||
|
||||
### `--voice-language VOICE_LANGUAGE`
|
||||
Specify the language for voice using ISO 639-1 code (default: auto)
|
||||
Default: en
|
||||
Environment variable: `AIDER_VOICE_LANGUAGE`
|
||||
|
||||
### `--voice-input-device VOICE_INPUT_DEVICE`
|
||||
Specify the input device name for voice recording
|
||||
Environment variable: `AIDER_VOICE_INPUT_DEVICE`
|
||||
<!--[[[end]]]-->
|
||||
|
||||
@@ -209,6 +209,47 @@ all the raw information being sent to/from the LLM in the conversation.
|
||||
You can also refer to the
|
||||
[instructions for installing a development version of aider](https://aider.chat/docs/install/optional.html#install-the-development-version-of-aider).
|
||||
|
||||
## What LLMs do you use to build aider?
|
||||
|
||||
Aider writes a lot of its own code, usually about 70% of the new code in each
|
||||
release.
|
||||
People often ask which LLMs I use with aider, when writing aider.
|
||||
Below is a table showing the models I have used recently,
|
||||
extracted from the
|
||||
[public log](https://github.com/aider-ai/aider/blob/main/aider/website/assets/sample-analytics.jsonl)
|
||||
of my
|
||||
[aider analytics](https://aider.chat/docs/more/analytics.html).
|
||||
|
||||
<!--[[[cog
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
import scripts.my_models as my_models
|
||||
stats = my_models.collect_model_stats()
|
||||
html = my_models.format_html_table(stats)
|
||||
cog.out(html)
|
||||
]]]-->
|
||||
<style>
|
||||
table { border-collapse: collapse; width: 100%; }
|
||||
th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }
|
||||
th { background-color: #f2f2f2; }
|
||||
tr:hover { background-color: #f5f5f5; }
|
||||
.right { text-align: right; }
|
||||
</style>
|
||||
<table>
|
||||
<tr><th>Model Name</th><th class='right'>Total Tokens</th><th class='right'>Percent</th></tr>
|
||||
<tr><td>claude-3-5-sonnet-20241022</td><td class='right'>1,630,102</td><td class='right'>88.9%</td></tr>
|
||||
<tr><td>o1-preview</td><td class='right'>83,782</td><td class='right'>4.6%</td></tr>
|
||||
<tr><td>gemini/REDACTED</td><td class='right'>82,572</td><td class='right'>4.5%</td></tr>
|
||||
<tr><td>deepseek/deepseek-coder</td><td class='right'>24,628</td><td class='right'>1.3%</td></tr>
|
||||
<tr><td>gpt-4o</td><td class='right'>9,243</td><td class='right'>0.5%</td></tr>
|
||||
<tr><td>gpt-4o-mini</td><td class='right'>3,420</td><td class='right'>0.2%</td></tr>
|
||||
<tr><td>mistral/REDACTED</td><td class='right'>620</td><td class='right'>0.0%</td></tr>
|
||||
</table>
|
||||
|
||||
{: .note :}
|
||||
Some models show as REDACTED, because they are new or unpopular models.
|
||||
Aider's analytics only records the names of "well known" LLMs.
|
||||
<!--[[[end]]]-->
|
||||
|
||||
## How are the "aider wrote xx% of code" stats computed?
|
||||
|
||||
|
||||
@@ -5,41 +5,84 @@ nav_order: 20
|
||||
description: How to install and get started pair programming with aider.
|
||||
---
|
||||
|
||||
# Quick start
|
||||
# Installation
|
||||
{: .no_toc }
|
||||
|
||||
|
||||
## Get started quickly with aider-install
|
||||
|
||||
{% include get-started.md %}
|
||||
|
||||
Or see the
|
||||
[full installation instructions](/docs/install/install.html)
|
||||
for more details,
|
||||
or the
|
||||
[usage instructions](https://aider.chat/docs/usage.html) to start coding with aider.
|
||||
If needed,
|
||||
aider-install will automatically install a separate version of python3.12 to use with aider.
|
||||
|
||||
There are some [optional install steps](/docs/install/optional.html) you could consider.
|
||||
See the [usage instructions](https://aider.chat/docs/usage.html) to start coding with aider.
|
||||
|
||||
## Install with uv
|
||||
|
||||
A recommended way to install aider is with uv:
|
||||
|
||||
```bash
|
||||
python -m pip install uv # If you need to install uv
|
||||
uv tool install --python python3.12 aider-chat
|
||||
```
|
||||
|
||||
You can use uv to install aider with your existing python versions 3.8-3.13.
|
||||
If needed,
|
||||
uv will automatically install a separate version of python3.12 to use with aider.
|
||||
|
||||
Also see the
|
||||
[docs on other methods for installing uv itself](https://docs.astral.sh/uv/getting-started/installation/).
|
||||
|
||||
## Install with pipx
|
||||
|
||||
A recommended way to install aider is with pipx:
|
||||
|
||||
```bash
|
||||
python -m pip install pipx # If you need to install pipx
|
||||
pipx install aider-chat
|
||||
```
|
||||
|
||||
You can use pipx to install aider with python versions 3.9-3.12.
|
||||
|
||||
Also see the
|
||||
[docs on other methods for installing pipx itself](https://pipx.pypa.io/stable/installation/).
|
||||
|
||||
|
||||
## Install with pip
|
||||
|
||||
You can directly install aider with pip, but one of the above
|
||||
methods is usually safer.
|
||||
If you do install with pip, you should consider
|
||||
using a
|
||||
[virtual environment](https://docs.python.org/3/library/venv.html)
|
||||
to keep aider's dependencies separated.
|
||||
|
||||
|
||||
You can use pip to install aider with python versions 3.9-3.12.
|
||||
|
||||
```bash
|
||||
# Install aider
|
||||
python -m pip install -U --upgrade-strategy only-if-needed aider-chat
|
||||
|
||||
# To work with GPT-4o:
|
||||
aider --4o --openai-api-key sk-xxx...
|
||||
|
||||
# To work with Claude 3.5 Sonnet:
|
||||
aider --sonnet --anthropic-api-key sk-xxx...
|
||||
```
|
||||
|
||||
{% include python-m-aider.md %}
|
||||
|
||||
<div class="video-container">
|
||||
<video controls poster="/assets/install.jpg">
|
||||
<source src="/assets/install.mp4" type="video/mp4">
|
||||
<a href="/assets/install.mp4">Installing aider</a>
|
||||
</video>
|
||||
</div>
|
||||
## Installing with package managers
|
||||
|
||||
<style>
|
||||
.video-container {
|
||||
position: relative;
|
||||
padding-bottom: 76.2711864407%;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.video-container video {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
It's best to install aider using aider-install, uv or pipx as described above.
|
||||
While aider is available in a number of system package managers,
|
||||
they often install aider with incorrect dependencies.
|
||||
|
||||
## Next steps...
|
||||
|
||||
There are some [optional install steps](/docs/install/optional.html) you could consider.
|
||||
See the [usage instructions](https://aider.chat/docs/usage.html) to start coding with aider.
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ nav_order: 900
|
||||
|
||||
You can use aider in GitHub Codespaces via the built-in Terminal pane.
|
||||
See below for an example,
|
||||
but you can see the
|
||||
but you can just follow the
|
||||
[main install instructions](/docs/install.html)
|
||||
for all the details.
|
||||
inside your codespace terminal.
|
||||
|
||||
|
||||
<div class="video-container">
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
---
|
||||
parent: Installation
|
||||
nav_order: 10
|
||||
---
|
||||
|
||||
# Installing aider
|
||||
{: .no_toc }
|
||||
|
||||
- TOC
|
||||
{:toc}
|
||||
|
||||
## Python version
|
||||
|
||||
Aider currently works with python 3.9-3.12.
|
||||
|
||||
## Install git
|
||||
|
||||
Make sure you have git installed.
|
||||
Here are
|
||||
[instructions for installing git in various environments](https://github.com/git-guides/install-git).
|
||||
|
||||
## Get your API key
|
||||
|
||||
To work with OpenAI's models like GPT-4o or GPT-3.5 you need a paid
|
||||
[OpenAI API key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-secret-api-key).
|
||||
Note that this is different than being a "ChatGPT Plus" subscriber.
|
||||
|
||||
To work with Anthropic's models like Claude 3.5 Sonnet you need a paid
|
||||
[Anthropic API key](https://docs.anthropic.com/claude/reference/getting-started-with-the-api).
|
||||
|
||||
|
||||
{% include venv-pipx.md %}
|
||||
|
||||
## Mac/Linux install
|
||||
|
||||
```
|
||||
# Install aider
|
||||
python -m pip install -U --upgrade-strategy only-if-needed aider-chat
|
||||
|
||||
# To work with GPT-4o:
|
||||
$ aider --4o --openai-api-key sk-xxx...
|
||||
|
||||
# To work with Claude 3.5 Sonnet:
|
||||
$ aider --sonnet --anthropic-api-key sk-xxx...
|
||||
```
|
||||
|
||||
## Windows install
|
||||
|
||||
```
|
||||
# Install aider
|
||||
python -m pip install -U --upgrade-strategy only-if-needed aider-chat
|
||||
|
||||
# To work with GPT-4o:
|
||||
$ aider --4o --openai-api-key sk-xxx...
|
||||
|
||||
# To work with Claude 3.5 Sonnet:
|
||||
$ aider --sonnet --anthropic-api-key sk-xxx...
|
||||
```
|
||||
|
||||
{% include python-m-aider.md %}
|
||||
|
||||
## Working with other LLMs
|
||||
|
||||
{% include works-best.md %}
|
||||
|
||||
## You are done!
|
||||
|
||||
There are some [optional install steps](/docs/install/optional.html) you could consider.
|
||||
See the [usage instructions](https://aider.chat/docs/usage.html) to start coding with aider.
|
||||
|
||||
@@ -11,10 +11,29 @@ The steps below are completely optional.
|
||||
- TOC
|
||||
{:toc}
|
||||
|
||||
## Install git
|
||||
|
||||
## Store your api keys
|
||||
Aider works best if you have git installed.
|
||||
Here are
|
||||
[instructions for installing git in various environments](https://github.com/git-guides/install-git).
|
||||
|
||||
You can [store your api keys in a .env file](/docs/config/dotenv.html)
|
||||
## Get your API key
|
||||
|
||||
To work with OpenAI's models like GPT-4o or o1-preview you need a paid
|
||||
[OpenAI API key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-secret-api-key).
|
||||
Note that this is different than being a "ChatGPT Plus" subscriber.
|
||||
|
||||
To work with Anthropic's models like Claude 3.5 Sonnet you need a paid
|
||||
[Anthropic API key](https://docs.anthropic.com/claude/reference/getting-started-with-the-api).
|
||||
|
||||
|
||||
### Working with other LLMs
|
||||
|
||||
{% include works-best.md %}
|
||||
|
||||
### Store your api keys
|
||||
|
||||
You can [store your api keys in configuration or env files](/docs/config/api-keys.html)
|
||||
and they will be loaded automatically whenever you run aider.
|
||||
|
||||
## Enable Playwright
|
||||
@@ -55,13 +74,17 @@ Installing PortAudio is completely optional, but can usually be accomplished lik
|
||||
- For Linux, do `sudo apt-get install libportaudio2`
|
||||
- Some linux environments may also need `sudo apt install libasound2-plugins`
|
||||
|
||||
## Add aider to your editor
|
||||
## Add aider to your IDE/editor
|
||||
|
||||
Other projects have integrated aider into some IDE/editors.
|
||||
You can use
|
||||
[aider's `--watch-files` mode](https://aider.chat/docs/usage/watch.html)
|
||||
to integrate with any IDE or editor.
|
||||
|
||||
Other projects have made plugins for various IDE/editors.
|
||||
It's not clear if they are tracking the latest
|
||||
versions of aider,
|
||||
so it may be best to just run the latest
|
||||
aider in a terminal alongside your editor.
|
||||
aider in a terminal alongside your editor and use `--watch-files`.
|
||||
|
||||
### NeoVim
|
||||
|
||||
@@ -71,9 +94,9 @@ aider in a terminal alongside your editor.
|
||||
|
||||
### VS Code
|
||||
|
||||
joshuavial also confirmed that aider works inside a VS Code terminal window.
|
||||
Aider detects if it is running inside VSCode and turns off pretty/color output,
|
||||
since the VSCode terminal doesn't seem to support it well.
|
||||
You can run aider inside a VS Code terminal window.
|
||||
There are a number of 3rd party
|
||||
[aider plugins for VSCode](https://marketplace.visualstudio.com/search?term=aider%20-kodu&target=VSCode&category=All%20categories&sortBy=Relevance).
|
||||
|
||||
### Other editors
|
||||
|
||||
@@ -85,15 +108,8 @@ please let me know by opening a
|
||||
## Install the development version of aider
|
||||
|
||||
If you want the very latest development version of aider
|
||||
you can install directly from GitHub:
|
||||
you can install it like this:
|
||||
|
||||
```
|
||||
python -m pip install --upgrade git+https://github.com/Aider-AI/aider.git
|
||||
aider --install-main-branch
|
||||
```
|
||||
|
||||
If you've git cloned the aider repository already, you can install "live" from your local copy. This is mostly useful if you are developing aider and want your current modifications to take effect immediately.
|
||||
|
||||
```
|
||||
python -m pip install -e .
|
||||
```
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
parent: Installation
|
||||
nav_order: 100
|
||||
---
|
||||
|
||||
# Install with pipx
|
||||
|
||||
If you are using aider to work on a python project, sometimes your project will require
|
||||
specific versions of python packages which conflict with the versions that aider
|
||||
requires.
|
||||
If this happens, the `python -m pip install` command may return errors like these:
|
||||
|
||||
```
|
||||
aider-chat 0.23.0 requires somepackage==X.Y.Z, but you have somepackage U.W.V which is incompatible.
|
||||
```
|
||||
|
||||
You can avoid this problem by installing aider using `pipx`,
|
||||
which will install it globally on your system
|
||||
within its own python environment.
|
||||
This way you can use aider to work on any python project,
|
||||
even if that project has conflicting dependencies.
|
||||
|
||||
Install [pipx](https://pipx.pypa.io/stable/) then just do:
|
||||
|
||||
```
|
||||
pipx install aider-chat
|
||||
```
|
||||
|
||||
|
||||
## pipx on replit
|
||||
|
||||
{% include replit-pipx.md %}
|
||||
|
||||
8
aider/website/docs/install/replit.md
Normal file
8
aider/website/docs/install/replit.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
parent: Installation
|
||||
nav_order: 900
|
||||
---
|
||||
|
||||
### Replit
|
||||
|
||||
{% include replit-pipx.md %}
|
||||
@@ -58,6 +58,7 @@ The model also has to successfully apply all its changes to the source file with
|
||||
</table>
|
||||
|
||||
<canvas id="editChart" width="800" height="450" style="margin-top: 20px"></canvas>
|
||||
<script src="https://unpkg.com/patternomaly/dist/patternomaly.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script>
|
||||
{% include edit-leaderboard.js %}
|
||||
@@ -113,6 +114,7 @@ Therefore, results are available for fewer models.
|
||||
</table>
|
||||
|
||||
<canvas id="refacChart" width="800" height="450" style="margin-top: 20px"></canvas>
|
||||
<script src="https://unpkg.com/patternomaly/dist/patternomaly.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script>
|
||||
{% include refactor-leaderboard.js %}
|
||||
@@ -181,6 +183,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.')}")
|
||||
]]]-->
|
||||
December 04, 2024.
|
||||
December 11, 2024.
|
||||
<!--[[[end]]]-->
|
||||
</p>
|
||||
|
||||
@@ -69,7 +69,7 @@ We make reasonable efforts to protect your information by using physical and ele
|
||||
|
||||
### Children’s Privacy
|
||||
|
||||
We do not knowingly collect, maintain, or use personal information from children under 18 years of age, and no part of our Service(s) is directed to children. If you learn that a child has provided us with personal information in violation of this Privacy Policy, then you may alert us at [INSERT EMAIL ADDRESS].
|
||||
We do not knowingly collect, maintain, or use personal information from children under 18 years of age, and no part of our Service(s) is directed to children. If you learn that a child has provided us with personal information in violation of this Privacy Policy, then you may alert us at privacy@aider.chat.
|
||||
|
||||
### International Visitors
|
||||
|
||||
@@ -98,7 +98,7 @@ if result.returncode == 0:
|
||||
date = datetime.datetime.fromtimestamp(timestamp)
|
||||
cog.out(f"{date.strftime('%B %d, %Y.')}")
|
||||
]]]-->
|
||||
October 31, 2024.
|
||||
December 06, 2024.
|
||||
<!--[[[end]]]-->
|
||||
|
||||
</p>
|
||||
|
||||
@@ -50,7 +50,7 @@ pip install boto3
|
||||
To use aider installed via `pipx` with AWS Bedrock, you must add the `boto3` dependency to aider's virtual environment by running
|
||||
|
||||
```bash
|
||||
pipx inject aider boto3
|
||||
pipx inject aider-chat boto3
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -5,15 +5,17 @@ nav_order: 300
|
||||
|
||||
# Gemini
|
||||
|
||||
Google currently offers
|
||||
[*free* API access to the Gemini 1.5 Pro model](https://ai.google.dev/pricing).
|
||||
This is the most capable free model to use with aider,
|
||||
with code editing capability that's comparable to GPT-3.5.
|
||||
You'll need a [Gemini API key](https://aistudio.google.com/app/u/2/apikey).
|
||||
|
||||
```
|
||||
python -m pip install -U aider-chat
|
||||
|
||||
# You may need to install google-generativeai
|
||||
pip install -U google-generativeai
|
||||
|
||||
# Or with pipx...
|
||||
pipx inject aider-chat google-generativeai
|
||||
|
||||
export GEMINI_API_KEY=<key> # Mac/Linux
|
||||
setx GEMINI_API_KEY <key> # Windows, restart shell after setx
|
||||
|
||||
|
||||
@@ -14,12 +14,11 @@ You may see an error message like this:
|
||||
|
||||
> aider: The term 'aider' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
|
||||
|
||||
Below is the most fail safe way to install and run aider in these situations:
|
||||
Below is the most fail safe way to run aider in these situations:
|
||||
|
||||
```
|
||||
python -m pip install -U aider-chat
|
||||
python -m aider
|
||||
```
|
||||
|
||||
|
||||
{% include venv-pipx.md %}
|
||||
You should also consider
|
||||
[installing aider using aider-install, uv or pipx](/docs/install.html).
|
||||
|
||||
@@ -5,7 +5,7 @@ nav_order: 28
|
||||
|
||||
# Dependency versions
|
||||
|
||||
Aider expects to be installed via `pip` or `pipx`, which will install
|
||||
Aider expects to be installed with the
|
||||
correct versions of all of its required dependencies.
|
||||
|
||||
If you've been linked to this doc from a GitHub issue,
|
||||
@@ -13,43 +13,38 @@ or if aider is reporting `ImportErrors`
|
||||
it is likely that your
|
||||
aider install is using incorrect dependencies.
|
||||
|
||||
## Install with pipx
|
||||
|
||||
## Avoid package conflicts
|
||||
|
||||
If you are using aider to work on a python project, sometimes your project will require
|
||||
specific versions of python packages which conflict with the versions that aider
|
||||
requires.
|
||||
If this happens, you may see errors like these when running pip installs:
|
||||
|
||||
```
|
||||
aider-chat 0.23.0 requires somepackage==X.Y.Z, but you have somepackage U.W.V which is incompatible.
|
||||
```
|
||||
|
||||
## Install with aider-install, uv or pipx
|
||||
|
||||
If you are having dependency problems you should consider
|
||||
[installing aider using pipx](/docs/install/pipx.html).
|
||||
[installing aider using aider-install, uv or pipx](/docs/install.html).
|
||||
This will ensure that aider is installed in its own python environment,
|
||||
with the correct set of dependencies.
|
||||
|
||||
Try re-installing cleanly:
|
||||
|
||||
```
|
||||
pipx uninstall aider-chat
|
||||
pipx install aider-chat
|
||||
```
|
||||
|
||||
## Package managers like Homebrew, AUR, ports
|
||||
|
||||
Package managers often install aider with the wrong dependencies, leading
|
||||
to import errors and other problems.
|
||||
|
||||
The recommended way to
|
||||
install aider is with
|
||||
[pip](/docs/install/install.html).
|
||||
Be sure to use the `--upgrade-strategy only-if-needed` switch so that the correct
|
||||
versions of dependencies will be installed.
|
||||
It is recommended to
|
||||
[install aider using aider-install, uv or pipx](/docs/install.html).
|
||||
|
||||
```
|
||||
python -m pip install -U --upgrade-strategy only-if-needed aider-chat
|
||||
```
|
||||
|
||||
A very safe way is to
|
||||
[install aider using pipx](/docs/install/pipx.html),
|
||||
which will ensure it is installed in a stand alone virtual environment.
|
||||
|
||||
## Dependency versions matter
|
||||
|
||||
Aider pins its dependencies and is tested to work with those specific versions.
|
||||
If you are installing aider with pip (rather than pipx),
|
||||
If you are installing aider directly with pip
|
||||
you should be careful about upgrading or downgrading the python packages that
|
||||
aider uses.
|
||||
|
||||
@@ -64,9 +59,4 @@ and sometimes introduces bugs or backwards incompatible changes.
|
||||
|
||||
## Replit
|
||||
|
||||
You can `pip install -U aider-chat` on replit.
|
||||
|
||||
Or you can install aider with
|
||||
pipx as follows:
|
||||
|
||||
{% include replit-pipx.md %}
|
||||
|
||||
@@ -29,6 +29,7 @@ cog.out(get_help_md())
|
||||
| **/code** | Ask for changes to your code |
|
||||
| **/commit** | Commit edits to the repo made outside the chat (commit message optional) |
|
||||
| **/copy** | Copy the last assistant message to the clipboard |
|
||||
| **/copy-context** | Copy the current chat context as markdown, suitable to paste into a web UI |
|
||||
| **/diff** | Display the diff of changes since the last message |
|
||||
| **/drop** | Remove files from the chat session to free up context space |
|
||||
| **/editor** | Open an editor to write a prompt |
|
||||
@@ -42,9 +43,10 @@ cog.out(get_help_md())
|
||||
| **/map-refresh** | Force a refresh of the repository map |
|
||||
| **/model** | Switch to a new LLM |
|
||||
| **/models** | Search the list of available models |
|
||||
| **/multiline-mode** | Toggle multiline mode (swaps behavior of Enter and Meta+Enter) |
|
||||
| **/paste** | Paste image/text from the clipboard into the chat. Optionally provide a name for the image. |
|
||||
| **/quit** | Exit the application |
|
||||
| **/read-only** | Add files to the chat that are for reference, not to be edited |
|
||||
| **/read-only** | Add files to the chat that are for reference only, or turn added files to read-only |
|
||||
| **/report** | Report a problem by opening a GitHub Issue |
|
||||
| **/reset** | Drop all files and clear the chat history |
|
||||
| **/run** | Run a shell command and optionally add the output to the chat (alias: !) |
|
||||
|
||||
@@ -28,6 +28,11 @@ or `aider --read CONVENTIONS.md`.
|
||||
This way it is marked as read-only, and cached if prompt caching
|
||||
is enabled.
|
||||
|
||||
## Community contributed conventions
|
||||
|
||||
You can check the [aider conventions repository](https://github.com/Aider-AI/conventions)
|
||||
to find or contribute conventions files.
|
||||
|
||||
## Always load conventions
|
||||
|
||||
You can also configure aider to always load your conventions file
|
||||
|
||||
121
aider/website/docs/usage/copypaste.md
Normal file
121
aider/website/docs/usage/copypaste.md
Normal file
@@ -0,0 +1,121 @@
|
||||
---
|
||||
title: Copy/paste with web chat
|
||||
#highlight_image: /assets/browser.jpg
|
||||
parent: Usage
|
||||
nav_order: 850
|
||||
description: Aider works with LLM web chat UIs
|
||||
---
|
||||
|
||||
# Copy/paste with web chat
|
||||
|
||||
<div class="video-container">
|
||||
<video controls loop poster="/assets/copypaste.jpg">
|
||||
<source src="/assets/copypaste.mp4" type="video/mp4">
|
||||
<a href="/assets/copypaste.mp4">Aider browser UI demo video</a>
|
||||
</video>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.video-container {
|
||||
position: relative;
|
||||
padding-bottom: 66.34%; /* 2160 / 3256 = 0.6634 */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.video-container video {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
## Working with an LLM web chat
|
||||
|
||||
[Aider can connect to most LLMs via API](https://aider.chat/docs/llms.html) and works best that way.
|
||||
But there are times when you may want to work with an LLM via its web chat interface:
|
||||
|
||||
- Workplace policies may limit your LLM usage to a proprietary web chat system.
|
||||
- The web chat LLM may have access to unique context or may have been specially fine tuned for your task.
|
||||
- It may be cost prohibitive to use some models via API.
|
||||
- There may not be an API available.
|
||||
|
||||
Aider has features for working with an LLM via its web chat interface.
|
||||
This allows you to use the web chat LLM as the "big brain code architect"
|
||||
while running aider with a smaller, cheaper LLM to actually make changes
|
||||
to your local files.
|
||||
|
||||
For this "file editor" part of the process
|
||||
you can run aider with many open source, free or very inexpensive LLMs.
|
||||
For example, the demo video above shows aider using DeepSeek to apply the changes
|
||||
that o1-preview is suggesting in the web chat.
|
||||
|
||||
### Copy aider's code context to your clipboard, paste into the web UI
|
||||
|
||||
The `/copy-context <instructions>` command can be used in chat to copy aider's code context to your clipboard.
|
||||
It will include:
|
||||
|
||||
- All the files which have been added to the chat via `/add`.
|
||||
- Any read only files which have been added via `/read`.
|
||||
- Aider's [repository map](https://aider.chat/docs/repomap.html) that brings in code context related to the above files from elsewhere in your git repo.
|
||||
- Some instructions to the LLM that ask it to output change instructions concisely.
|
||||
- If you include `<instructions>`, they will be copied too.
|
||||
|
||||
You can paste the context into your browser, and start interacting with the LLM web chat to
|
||||
ask for code changes.
|
||||
|
||||
### Paste the LLM's reply back into aider to edit your files
|
||||
|
||||
Once the LLM has replied, you can use the "copy response" button in the web UI to copy
|
||||
the LLM's response.
|
||||
Back in aider, you can run `/paste` and aider will edit your files
|
||||
to implement the changes suggested by the LLM.
|
||||
|
||||
You can use a cheap, efficient model like GPT-4o Mini, DeepSeek or Qwen to do these edits.
|
||||
This works best if you run aider with `--edit-format editor-diff` or `--edit-format editor-whole`.
|
||||
|
||||
### Copy/paste mode
|
||||
|
||||
Aider has a `--copy-paste` mode that streamlines this entire process:
|
||||
|
||||
- Whenever you `/add` or `/read` files, aider will automatically copy the entire, updated
|
||||
code context to your clipboard.
|
||||
You'll see "Copied code context to clipboard" whenever this happens.
|
||||
- When you copy the LLM reply to your clipboard outside aider, aider will automatically notice
|
||||
and load it into the aider chat.
|
||||
Just press ENTER to send the message
|
||||
and aider will apply the LLMs changes to your local files.
|
||||
- Aider will automatically select the best edit format for this copy/paste functionality.
|
||||
Depending on the LLM you have aider use, it will be either `editor-whole` or `editor-diff`.
|
||||
|
||||
## Terms of service
|
||||
|
||||
Be sure to review the Terms Of Service of any LLM web chat service you use with
|
||||
these features.
|
||||
These features are not intended to be used in violation of any service's Terms Of Service (TOS).
|
||||
|
||||
Aider's web chat features have been designed to be compliant with the
|
||||
terms of service of most LLM web chats.
|
||||
|
||||
There are 4 copy/paste steps involved when coding with an LLM web chat:
|
||||
|
||||
1. Copy code and context from aider.
|
||||
2. Paste the code and context into the LLM web chat.
|
||||
3. Copy the reply from the LLM web chat.
|
||||
4. Paste the LLM reply into aider.
|
||||
|
||||
Most LLM web chat TOS prohibit automating steps (2) and (3) where code
|
||||
is copied from and pasted into the web chat.
|
||||
Aider's `--copy-paste` mode leaves those as 100% manual steps for the user to complete.
|
||||
It simply streamlines steps (1) and (4) that are interactions with aider,
|
||||
and which should not be under the scope of an LLM web chat TOS.
|
||||
|
||||
If you are concerned that
|
||||
the automatic interactions with aider in steps (1) and (4) may be problematic with respect to
|
||||
your LLM web chat provider's TOS, you can forego `--copy-paste` mode.
|
||||
Instead, manually use the `/copy-context` and `/paste` commands if that
|
||||
will keep you in compliance.
|
||||
|
||||
Again, do not use these features in violation of any service's Terms Of Service.
|
||||
@@ -18,7 +18,7 @@ description: Aider can run in your browser, not just on the command line.
|
||||
<style>
|
||||
.video-container {
|
||||
position: relative;
|
||||
padding-bottom: 101.89%; /* 1080 / 1060 = 1.0189 */
|
||||
padding-bottom: 102.7%; /1.027 */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -37,21 +37,29 @@ description: Aider can run in your browser, not just on the command line.
|
||||
If you run aider with `--watch-files`, it will watch all files in your repo
|
||||
and look for any AI coding instructions you add using your favorite IDE or text editor.
|
||||
|
||||
Specifically, aider looks for one-liner comments (# ... or // ...) that either start or end with `AI` or `AI!`, like these:
|
||||
Specifically, aider looks for one-liner comments (# ... or // ...) that either start or end with `AI`, `AI!` or `AI?` like these:
|
||||
|
||||
```python
|
||||
# Implement a snake game. AI!
|
||||
# Make a snake game. AI!
|
||||
# What is the purpose of this method AI?
|
||||
```
|
||||
|
||||
Or in `//` comment languages...
|
||||
|
||||
```js
|
||||
// Write a self-learning protein folding prediction engine. AI!
|
||||
// Write a protein folding prediction engine. AI!
|
||||
```
|
||||
|
||||
Aider will take note of all the comments that start or end with `AI`, but
|
||||
a comment that includes `AI!` with an exclamation point is special.
|
||||
That triggers aider to take action to collect *all* the AI comments and use them as instructions to make code changes.
|
||||
Aider will take note of all the comments that start or end with `AI`.
|
||||
Comments that include `AI!` with an exclamation point or `AI?` with a question
|
||||
mark are special.
|
||||
They triggers aider to take action to collect *all* the AI comments and use them
|
||||
as your instructions.
|
||||
|
||||
- `AI!` triggers aider to make changes to your code.
|
||||
- `AI?` triggers aider to answer your question.
|
||||
|
||||
See the demo video above that shows aider working with AI comments in VSCode.
|
||||
|
||||
|
||||
## Example
|
||||
@@ -74,8 +82,19 @@ function factorial(n) {
|
||||
}
|
||||
```
|
||||
|
||||
## Comment styles
|
||||
|
||||
Also see the demo video above that shows aider working with AI comments in VSCode.
|
||||
Aider only watches for these types of **one-liner** comments:
|
||||
|
||||
```
|
||||
# Python and bash style
|
||||
// Javascript style
|
||||
-- SQL style
|
||||
```
|
||||
|
||||
Aider will look for those comment types in all files.
|
||||
You can use them into any code file you're editing, even if they aren't the
|
||||
correct comment syntax for that language.
|
||||
|
||||
## Multiple uses
|
||||
|
||||
@@ -99,7 +118,7 @@ app.get('/sqrt/:n', (req, res) => {
|
||||
|
||||
### Multiple comments
|
||||
|
||||
You can drop multiple `AI` comments without the `!`,
|
||||
You can add multiple `AI` comments without the `!`,
|
||||
before triggering aider with a final `AI!`.
|
||||
Also keep in mind that you can spread the AI comments across
|
||||
multiple files, if you want to coordinate changes in multiple places.
|
||||
@@ -146,12 +165,33 @@ simply put an `#AI` comment in it and save the file.
|
||||
You can undo/remove the comment immediately if you like, the file
|
||||
will still be added to the aider chat.
|
||||
|
||||
## Also use aider chat in the terminal
|
||||
|
||||
### You can be lazy
|
||||
It can be really helpful to get a change started with AI comments.
|
||||
But sometimes you want to build on or refine those changes.
|
||||
You can of course continue to do that with AI comments,
|
||||
but it can sometimes be effective to switch over to the aider terminal chat.
|
||||
The chat has the history of the AI comments you just made,
|
||||
so you can continue on naturally from there.
|
||||
|
||||
The comments in the examples above all show AI
|
||||
You can also use the normal aider chat in your terminal to work with
|
||||
many of aider's more advanced features:
|
||||
|
||||
- Use `/undo` to revert changes you don't like. Although you may also be able to use your IDE's undo function to step back in the file history.
|
||||
- Use [chat modes](https://aider.chat/docs/usage/modes.html) to ask questions or get help.
|
||||
- Manage the chat context with `/tokens`, `/clear`, `/drop`, `/reset`.
|
||||
Adding an AI comment will add the file to the chat.
|
||||
Periodically, you may want remove extra context that is no longer needed.
|
||||
- [Fix lint and test errors](https://aider.chat/docs/usage/lint-test.html).
|
||||
- Run shell commands.
|
||||
- Etc.
|
||||
|
||||
|
||||
## You can be lazy
|
||||
|
||||
The examples above all show AI
|
||||
comments with full sentences, proper capitalization, punctuation, etc.
|
||||
This was done for clarity, but is not needed in practice.
|
||||
This was done to help explain how AI comments work, but is not needed in practice.
|
||||
|
||||
Most LLMs are perfectly capable of dealing with ambiguity and
|
||||
inferring implied intent.
|
||||
@@ -211,3 +251,45 @@ def factorial(n):
|
||||
|
||||
As you use aider with your chosen LLM, you can develop a sense for how
|
||||
explicit you need to make your AI comments.
|
||||
|
||||
## Behind the scenes
|
||||
|
||||
Aider sends your AI comments to the LLM with the
|
||||
[repo map](https://aider.chat/docs/repomap.html)
|
||||
and all the other code context you've added to the chat.
|
||||
|
||||
It also pulls out and highlights the AI comments with specific context, showing the LLM
|
||||
exactly how they fit into the code base.
|
||||
|
||||
```
|
||||
The "AI" comments below marked with █ can be found in the code files I've shared with you.
|
||||
They contain your instructions.
|
||||
Make the requested changes.
|
||||
Be sure to remove all these "AI" comments from the code!
|
||||
|
||||
todo_app.py:
|
||||
⋮...
|
||||
│class TodoList:
|
||||
⋮...
|
||||
│ def __init__(self):
|
||||
│ """Initialize an empty todo list"""
|
||||
⋮...
|
||||
│
|
||||
│ def list_tasks(self):
|
||||
│ """Display all tasks"""
|
||||
█ # Implement this. AI!
|
||||
│
|
||||
│def main():
|
||||
│ todo = TodoList()
|
||||
│
|
||||
⋮...
|
||||
```
|
||||
|
||||
--------
|
||||
|
||||
#### Credits
|
||||
|
||||
*This feature was inspired by
|
||||
the way [Override](https://github.com/oi-overide) watches for file changes
|
||||
to find prompts embedded within `//> a specific set of delimiters <//`.*
|
||||
|
||||
|
||||
@@ -70,28 +70,27 @@ Aider works best with GPT-4o & Claude 3.5 Sonnet and can
|
||||
cog.out(open("aider/website/_includes/get-started.md").read())
|
||||
-->
|
||||
|
||||
You can get started quickly like this:
|
||||
You can get started quickly like this, with python 3.8-3.13:
|
||||
|
||||
```
|
||||
python -m pip install -U aider-chat
|
||||
```bash
|
||||
python -m pip install aider-install
|
||||
aider-install
|
||||
|
||||
# Change directory into a git repo
|
||||
# Change directory into your code base
|
||||
cd /to/your/git/repo
|
||||
|
||||
# Work with Claude 3.5 Sonnet on your repo
|
||||
export ANTHROPIC_API_KEY=your-key-goes-here
|
||||
aider
|
||||
aider --model sonnet --anthropic-api-key your-key-goes-here
|
||||
|
||||
# Work with GPT-4o on your repo
|
||||
export OPENAI_API_KEY=your-key-goes-here
|
||||
aider
|
||||
aider --model gpt-4o --openai-api-key your-key-goes-here
|
||||
```
|
||||
<!-- NOOP -->
|
||||
|
||||
See the
|
||||
[installation instructions](https://aider.chat/docs/install.html)
|
||||
and other
|
||||
[documentation](https://aider.chat/docs/usage.html)
|
||||
and
|
||||
[usage documentation](https://aider.chat/docs/usage.html)
|
||||
for more details.
|
||||
|
||||
## Features
|
||||
|
||||
@@ -24,8 +24,8 @@ from dotenv import load_dotenv
|
||||
from plots import plot_refactoring
|
||||
from rich.console import Console
|
||||
|
||||
from aider import models
|
||||
from aider.coders import Coder
|
||||
from aider import models, sendchat
|
||||
from aider.coders import Coder, base_coder
|
||||
from aider.dump import dump # noqa: F401
|
||||
from aider.io import InputOutput
|
||||
|
||||
@@ -158,6 +158,9 @@ def main(
|
||||
dirnames: Optional[List[str]] = typer.Argument(None, help="Directory names"),
|
||||
graphs: bool = typer.Option(False, "--graphs", help="Generate graphs"),
|
||||
model: str = typer.Option("gpt-3.5-turbo", "--model", "-m", help="Model name"),
|
||||
sleep: float = typer.Option(
|
||||
0, "--sleep", help="Sleep seconds between tests when single threaded"
|
||||
),
|
||||
edit_format: str = typer.Option(None, "--edit-format", "-e", help="Edit format"),
|
||||
editor_model: str = typer.Option(None, "--editor-model", help="Editor model name"),
|
||||
editor_edit_format: str = typer.Option(None, "--editor-edit-format", help="Editor edit format"),
|
||||
@@ -267,6 +270,11 @@ def main(
|
||||
if num_tests > 0:
|
||||
test_dnames = test_dnames[:num_tests]
|
||||
|
||||
# Don't give up when benchmarking
|
||||
LONG_TIMEOUT = 24 * 60 * 60
|
||||
sendchat.RETRY_TIMEOUT = LONG_TIMEOUT
|
||||
base_coder.RETRY_TIMEOUT = LONG_TIMEOUT
|
||||
|
||||
if threads == 1:
|
||||
all_results = []
|
||||
for testname in test_dnames:
|
||||
@@ -285,10 +293,13 @@ def main(
|
||||
editor_model,
|
||||
editor_edit_format,
|
||||
num_ctx,
|
||||
sleep,
|
||||
)
|
||||
|
||||
all_results.append(results)
|
||||
summarize_results(dirname)
|
||||
if sleep:
|
||||
time.sleep(sleep)
|
||||
else:
|
||||
run_test_threaded = lox.thread(threads)(run_test)
|
||||
for testname in test_dnames:
|
||||
@@ -565,6 +576,7 @@ def run_test_real(
|
||||
editor_model,
|
||||
editor_edit_format,
|
||||
num_ctx=None,
|
||||
sleep=0,
|
||||
):
|
||||
if not os.path.isdir(testdir):
|
||||
print("Not a dir:", testdir)
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
# [[[cog
|
||||
# from aider.help_pats import exclude_website_pats
|
||||
# ]]]
|
||||
# [[[end]]]
|
||||
|
||||
[project]
|
||||
name = "aider-chat"
|
||||
@@ -38,29 +34,11 @@ help = { file = "requirements/requirements-help.txt" }
|
||||
browser = { file = "requirements/requirements-browser.txt" }
|
||||
playwright = { file = "requirements/requirements-playwright.txt" }
|
||||
|
||||
[tool.setuptools]
|
||||
include-package-data = true
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
include = ["aider*", "aider.website"]
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
"aider" = ["queries/*.scm"]
|
||||
"aider.website" = ["**/*.md"]
|
||||
|
||||
[tool.setuptools.exclude-package-data]
|
||||
"aider.website" = [
|
||||
# [[[cog
|
||||
# cog.out("\n".join(f' "{pat}",' for pat in exclude_website_pats))
|
||||
# ]]]
|
||||
"examples/**",
|
||||
"_posts/**",
|
||||
"HISTORY.md",
|
||||
"docs/benchmarks*md",
|
||||
"docs/ctags.md",
|
||||
"docs/unified-diffs.md",
|
||||
"docs/leaderboards/index.md",
|
||||
"assets/**",
|
||||
"**/.DS_Store",
|
||||
# [[[end]]]
|
||||
]
|
||||
include = ["aider"]
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools>=68", "setuptools_scm[toml]>=8"]
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
# This file is autogenerated by pip-compile with Python 3.12
|
||||
# by the following command:
|
||||
#
|
||||
# pip-compile --output-file=requirements.txt requirements/requirements.in
|
||||
# pip-compile --allow-unsafe --output-file=requirements.txt requirements/requirements.in
|
||||
#
|
||||
aiohappyeyeballs==2.4.4
|
||||
# via aiohttp
|
||||
aiohttp==3.11.9
|
||||
aiohttp==3.11.10
|
||||
# via litellm
|
||||
aiosignal==1.3.1
|
||||
# via aiohttp
|
||||
annotated-types==0.7.0
|
||||
# via pydantic
|
||||
anyio==4.6.2.post1
|
||||
anyio==4.7.0
|
||||
# via
|
||||
# httpx
|
||||
# openai
|
||||
@@ -73,7 +73,7 @@ httpx==0.27.2
|
||||
# via
|
||||
# litellm
|
||||
# openai
|
||||
huggingface-hub==0.26.3
|
||||
huggingface-hub==0.26.5
|
||||
# via tokenizers
|
||||
idna==3.10
|
||||
# via
|
||||
@@ -99,7 +99,7 @@ jsonschema==4.23.0
|
||||
# litellm
|
||||
jsonschema-specifications==2024.10.1
|
||||
# via jsonschema
|
||||
litellm==1.53.5
|
||||
litellm==1.53.9
|
||||
# via -r requirements/requirements.in
|
||||
markdown-it-py==3.0.0
|
||||
# via rich
|
||||
@@ -123,7 +123,7 @@ numpy==1.26.4
|
||||
# via
|
||||
# -r requirements/requirements.in
|
||||
# scipy
|
||||
openai==1.56.2
|
||||
openai==1.57.0
|
||||
# via litellm
|
||||
packaging==24.2
|
||||
# via
|
||||
@@ -234,6 +234,7 @@ tree-sitter-languages==1.10.2
|
||||
# via grep-ast
|
||||
typing-extensions==4.12.2
|
||||
# via
|
||||
# anyio
|
||||
# huggingface-hub
|
||||
# openai
|
||||
# pydantic
|
||||
@@ -250,3 +251,7 @@ yarl==1.18.3
|
||||
# via aiohttp
|
||||
zipp==3.21.0
|
||||
# via importlib-metadata
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
pip==24.3.1
|
||||
# via -r requirements/requirements.in
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# This file is autogenerated by pip-compile with Python 3.12
|
||||
# by the following command:
|
||||
#
|
||||
# pip-compile --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --constraint=requirements/requirements-help.txt --output-file=requirements/requirements-browser.txt requirements/requirements-browser.in
|
||||
# pip-compile --allow-unsafe --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --constraint=requirements/requirements-help.txt --output-file=requirements/requirements-browser.txt requirements/requirements-browser.in
|
||||
#
|
||||
altair==5.5.0
|
||||
# via streamlit
|
||||
@@ -92,7 +92,7 @@ mdurl==0.1.2
|
||||
# -c requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# markdown-it-py
|
||||
narwhals==1.15.2
|
||||
narwhals==1.16.0
|
||||
# via altair
|
||||
numpy==1.26.4
|
||||
# via
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# This file is autogenerated by pip-compile with Python 3.12
|
||||
# by the following command:
|
||||
#
|
||||
# pip-compile --constraint=requirements.txt --output-file=requirements/requirements-dev.txt requirements/requirements-dev.in
|
||||
# pip-compile --allow-unsafe --constraint=requirements.txt --output-file=requirements/requirements-dev.txt requirements/requirements-dev.in
|
||||
#
|
||||
alabaster==1.0.0
|
||||
# via sphinx
|
||||
@@ -51,7 +51,7 @@ filelock==3.16.1
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# virtualenv
|
||||
fonttools==4.55.1
|
||||
fonttools==4.55.2
|
||||
# via matplotlib
|
||||
identify==2.6.3
|
||||
# via pre-commit
|
||||
@@ -224,5 +224,10 @@ wheel==0.45.1
|
||||
# via pip-tools
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
# pip
|
||||
# setuptools
|
||||
pip==24.3.1
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# pip-tools
|
||||
setuptools==75.6.0
|
||||
# via pip-tools
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
# This file is autogenerated by pip-compile with Python 3.12
|
||||
# by the following command:
|
||||
#
|
||||
# pip-compile --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --output-file=requirements/requirements-help.txt requirements/requirements-help.in
|
||||
# pip-compile --allow-unsafe --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --output-file=requirements/requirements-help.txt requirements/requirements-help.in
|
||||
#
|
||||
aiohappyeyeballs==2.4.4
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# aiohttp
|
||||
aiohttp==3.11.9
|
||||
aiohttp==3.11.10
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
@@ -25,7 +25,7 @@ annotated-types==0.7.0
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# pydantic
|
||||
anyio==4.6.2.post1
|
||||
anyio==4.7.0
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
@@ -103,7 +103,7 @@ httpx==0.27.2
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# llama-index-core
|
||||
huggingface-hub[inference]==0.26.3
|
||||
huggingface-hub[inference]==0.26.5
|
||||
# via
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
@@ -284,6 +284,7 @@ typing-extensions==4.12.2
|
||||
# -c /Users/gauthier/Projects/aider/requirements.txt
|
||||
# -c requirements.txt
|
||||
# -c requirements/requirements-dev.txt
|
||||
# anyio
|
||||
# huggingface-hub
|
||||
# llama-index-core
|
||||
# pydantic
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# This file is autogenerated by pip-compile with Python 3.12
|
||||
# by the following command:
|
||||
#
|
||||
# pip-compile --constraint=requirements.txt --constraint=requirements/requirements-browser.txt --constraint=requirements/requirements-dev.txt --constraint=requirements/requirements-help.txt --output-file=requirements/requirements-playwright.txt requirements/requirements-playwright.in
|
||||
# pip-compile --allow-unsafe --constraint=requirements.txt --constraint=requirements/requirements-browser.txt --constraint=requirements/requirements-dev.txt --constraint=requirements/requirements-help.txt --output-file=requirements/requirements-playwright.txt requirements/requirements-playwright.in
|
||||
#
|
||||
greenlet==3.0.3
|
||||
# via
|
||||
|
||||
@@ -29,6 +29,7 @@ pexpect
|
||||
json5
|
||||
psutil
|
||||
watchfiles
|
||||
pip
|
||||
|
||||
# The proper dependency is networkx[default], but this brings
|
||||
# in matplotlib and a bunch of other deps
|
||||
|
||||
0
scripts/__init__.py
Normal file
0
scripts/__init__.py
Normal file
@@ -12,6 +12,12 @@ import semver
|
||||
import yaml
|
||||
from tqdm import tqdm
|
||||
|
||||
website_files = [
|
||||
"aider/website/share/index.md",
|
||||
"aider/website/_includes/head_custom.html",
|
||||
"aider/website/docs/leaderboards/index.md",
|
||||
]
|
||||
|
||||
|
||||
def blame(start_tag, end_tag=None):
|
||||
commits = get_all_commit_hashes_between_tags(start_tag, end_tag)
|
||||
@@ -26,10 +32,10 @@ def blame(start_tag, end_tag=None):
|
||||
for f in files
|
||||
if f.endswith((".js", ".py", ".scm", ".sh", "Dockerfile", "Gemfile"))
|
||||
or (f.startswith(".github/workflows/") and f.endswith(".yml"))
|
||||
or f == "aider/website/share/index.md"
|
||||
or f == "aider/website/docs/leaderboards/index.md"
|
||||
or f in website_files
|
||||
]
|
||||
files = [f for f in files if not f.endswith("prompts.py")]
|
||||
files = [f for f in files if not f.startswith("tests/fixtures/watch")]
|
||||
|
||||
all_file_counts = {}
|
||||
grand_total = defaultdict(int)
|
||||
@@ -203,9 +209,23 @@ def main():
|
||||
def get_counts_for_file(start_tag, end_tag, authors, fname):
|
||||
try:
|
||||
if end_tag:
|
||||
text = run(["git", "blame", f"{start_tag}..{end_tag}", "--", fname])
|
||||
text = run(
|
||||
[
|
||||
"git",
|
||||
"blame",
|
||||
"-M",
|
||||
"-C",
|
||||
"-C",
|
||||
"--abbrev=9",
|
||||
f"{start_tag}..{end_tag}",
|
||||
"--",
|
||||
fname,
|
||||
]
|
||||
)
|
||||
else:
|
||||
text = run(["git", "blame", f"{start_tag}..HEAD", "--", fname])
|
||||
text = run(
|
||||
["git", "blame", "-M", "-C", "-C", "--abbrev=9", f"{start_tag}..HEAD", "--", fname]
|
||||
)
|
||||
if not text:
|
||||
return None
|
||||
text = text.splitlines()
|
||||
|
||||
16
scripts/history_prompts.py
Normal file
16
scripts/history_prompts.py
Normal file
@@ -0,0 +1,16 @@
|
||||
history_prompt = """
|
||||
Update the history with changes shown in the diffs.
|
||||
Describe actual user-facing changes, not every single commit that was made implementing them.
|
||||
|
||||
Only add new items not already listed.
|
||||
Do NOT edit or update existing history entries.
|
||||
Do NOT add duplicate entries for changes that have existing history entries.
|
||||
|
||||
End each bullet with a period.
|
||||
|
||||
Be sure to attribute changes to the proper .x version.
|
||||
Changes in the .x-dev version should be listed under a "### main branch" heading
|
||||
|
||||
Also, add this as the last bullet under the "### main branch" section:
|
||||
{aider_line}
|
||||
""" # noqa
|
||||
@@ -46,6 +46,20 @@ CLOSE_STALE_COMMENT = (
|
||||
+ BOT_SUFFIX
|
||||
)
|
||||
|
||||
CLOSE_FIXED_ENHANCEMENT_COMMENT = (
|
||||
"""I'm closing this enhancement request since it has been marked as 'fixed' for over """
|
||||
"""3 weeks. The requested feature should now be available in recent versions of aider.\n\n"""
|
||||
"""If you find that this enhancement is still needed, please feel free to reopen this """
|
||||
"""issue or create a new one.""" + BOT_SUFFIX
|
||||
)
|
||||
|
||||
CLOSE_FIXED_BUG_COMMENT = (
|
||||
"""I'm closing this bug report since it has been marked as 'fixed' for over """
|
||||
"""3 weeks. This issue should be resolved in recent versions of aider.\n\n"""
|
||||
"""If you find that this bug is still present, please feel free to reopen this """
|
||||
"""issue or create a new one with steps to reproduce.""" + BOT_SUFFIX
|
||||
)
|
||||
|
||||
# GitHub API configuration
|
||||
GITHUB_API_URL = "https://api.github.com"
|
||||
REPO_OWNER = "Aider-AI"
|
||||
@@ -306,6 +320,68 @@ def handle_stale_closing(all_issues, auto_yes):
|
||||
print(f" Closed issue #{issue['number']}")
|
||||
|
||||
|
||||
def handle_fixed_issues(all_issues, auto_yes):
|
||||
print("\nChecking for fixed enhancement and bug issues to close...")
|
||||
|
||||
for issue in all_issues:
|
||||
# Skip if not open or doesn't have fixed label
|
||||
labels = [label["name"] for label in issue["labels"]]
|
||||
if issue["state"] != "open" or "fixed" not in labels:
|
||||
continue
|
||||
|
||||
# Check if it's an enhancement or bug
|
||||
is_enhancement = "enhancement" in labels
|
||||
is_bug = "bug" in labels
|
||||
if not (is_enhancement or is_bug):
|
||||
continue
|
||||
|
||||
# Find when the fixed label was added
|
||||
timeline_url = (
|
||||
f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/timeline"
|
||||
)
|
||||
response = requests.get(timeline_url, headers=headers)
|
||||
response.raise_for_status()
|
||||
events = response.json()
|
||||
|
||||
# Find the most recent fixed label addition
|
||||
fixed_events = [
|
||||
event
|
||||
for event in events
|
||||
if event.get("event") == "labeled" and event.get("label", {}).get("name") == "fixed"
|
||||
]
|
||||
|
||||
if not fixed_events:
|
||||
continue
|
||||
|
||||
latest_fixed = datetime.strptime(fixed_events[-1]["created_at"], "%Y-%m-%dT%H:%M:%SZ")
|
||||
days_fixed = (datetime.now() - latest_fixed).days
|
||||
|
||||
if days_fixed >= 21:
|
||||
issue_type = "enhancement" if is_enhancement else "bug"
|
||||
print(f"\nFixed {issue_type} ready for closing #{issue['number']}: {issue['title']}")
|
||||
print(f" Has been marked fixed for {days_fixed} days")
|
||||
|
||||
if not auto_yes:
|
||||
confirm = input("Close this issue? (y/n): ")
|
||||
if confirm.lower() != "y":
|
||||
print("Skipping this issue.")
|
||||
continue
|
||||
|
||||
# Add closing comment
|
||||
comment_url = (
|
||||
f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/comments"
|
||||
)
|
||||
comment = CLOSE_FIXED_ENHANCEMENT_COMMENT if is_enhancement else CLOSE_FIXED_BUG_COMMENT
|
||||
response = requests.post(comment_url, headers=headers, json={"body": comment})
|
||||
response.raise_for_status()
|
||||
|
||||
# Close the issue
|
||||
url = f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}"
|
||||
response = requests.patch(url, headers=headers, json={"state": "closed"})
|
||||
response.raise_for_status()
|
||||
print(f" Closed issue #{issue['number']}")
|
||||
|
||||
|
||||
def handle_duplicate_issues(all_issues, auto_yes):
|
||||
open_issues = [issue for issue in all_issues if issue["state"] == "open"]
|
||||
grouped_open_issues = group_issues_by_subject(open_issues)
|
||||
@@ -363,6 +439,7 @@ def main():
|
||||
handle_stale_issues(all_issues, args.yes)
|
||||
handle_stale_closing(all_issues, args.yes)
|
||||
handle_duplicate_issues(all_issues, args.yes)
|
||||
handle_fixed_issues(all_issues, args.yes)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
95
scripts/my_models.py
Executable file
95
scripts/my_models.py
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
from collections import defaultdict, deque
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def collect_model_stats(n_lines=1000):
|
||||
"""Collect model usage statistics from the analytics file."""
|
||||
analytics_path = Path.home() / ".aider" / "analytics.jsonl"
|
||||
model_stats = defaultdict(int)
|
||||
|
||||
with open(analytics_path) as f:
|
||||
lines = deque(f, n_lines)
|
||||
for line in lines:
|
||||
try:
|
||||
event = json.loads(line)
|
||||
if event["event"] == "message_send":
|
||||
properties = event["properties"]
|
||||
main_model = properties.get("main_model")
|
||||
total_tokens = properties.get("total_tokens", 0)
|
||||
if main_model:
|
||||
model_stats[main_model] += total_tokens
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
|
||||
return model_stats
|
||||
|
||||
|
||||
def format_text_table(model_stats):
|
||||
"""Format model statistics as a text table."""
|
||||
total_tokens = sum(model_stats.values())
|
||||
lines = []
|
||||
|
||||
lines.append("\nModel Token Usage Summary:")
|
||||
lines.append("-" * 80)
|
||||
lines.append(f"{'Model Name':<40} {'Total Tokens':>15} {'Percent':>10}")
|
||||
lines.append("-" * 80)
|
||||
|
||||
for model, tokens in sorted(model_stats.items(), key=lambda x: x[1], reverse=True):
|
||||
percentage = (tokens / total_tokens) * 100 if total_tokens > 0 else 0
|
||||
lines.append(f"{model:<40} {tokens:>15,} {percentage:>9.1f}%")
|
||||
|
||||
lines.append("-" * 80)
|
||||
lines.append(f"{'TOTAL':<40} {total_tokens:>15,} {100:>9.1f}%")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def format_html_table(model_stats):
|
||||
"""Format model statistics as an HTML table."""
|
||||
total_tokens = sum(model_stats.values())
|
||||
|
||||
html = [
|
||||
"<style>",
|
||||
"table { border-collapse: collapse; width: 100%; }",
|
||||
"th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }",
|
||||
"th { background-color: #f2f2f2; }",
|
||||
"tr:hover { background-color: #f5f5f5; }",
|
||||
".right { text-align: right; }",
|
||||
"</style>",
|
||||
"<table>",
|
||||
(
|
||||
"<tr><th>Model Name</th><th class='right'>Total Tokens</th><th"
|
||||
" class='right'>Percent</th></tr>"
|
||||
),
|
||||
]
|
||||
|
||||
for model, tokens in sorted(model_stats.items(), key=lambda x: x[1], reverse=True):
|
||||
percentage = (tokens / total_tokens) * 100 if total_tokens > 0 else 0
|
||||
html.append(
|
||||
f"<tr><td>{model}</td>"
|
||||
f"<td class='right'>{tokens:,}</td>"
|
||||
f"<td class='right'>{percentage:.1f}%</td></tr>"
|
||||
)
|
||||
|
||||
html.append("</table>")
|
||||
|
||||
# Add note about redacted models if any are present
|
||||
if any("REDACTED" in model for model in model_stats.keys()):
|
||||
html.extend(
|
||||
[
|
||||
"",
|
||||
"{: .note :}",
|
||||
"Some models show as REDACTED, because they are new or unpopular models.",
|
||||
'Aider\'s analytics only records the names of "well known" LLMs.',
|
||||
]
|
||||
)
|
||||
|
||||
return "\n".join(html)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
stats = collect_model_stats()
|
||||
print(format_text_table(stats))
|
||||
@@ -5,6 +5,7 @@ set -e
|
||||
|
||||
# First compile the base requirements
|
||||
pip-compile \
|
||||
--allow-unsafe \
|
||||
requirements/requirements.in \
|
||||
--output-file=requirements.txt \
|
||||
$1
|
||||
@@ -15,6 +16,7 @@ CONSTRAINTS="--constraint=requirements.txt"
|
||||
|
||||
for SUFFIX in "${SUFFIXES[@]}"; do
|
||||
pip-compile \
|
||||
--allow-unsafe \
|
||||
requirements/requirements-${SUFFIX}.in \
|
||||
--output-file=requirements/requirements-${SUFFIX}.txt \
|
||||
${CONSTRAINTS} \
|
||||
|
||||
@@ -3,4 +3,6 @@
|
||||
# exit when any command fails
|
||||
set -e
|
||||
|
||||
./scripts/blame.py v0.1.0 --all --output aider/website/_data/blame.yml
|
||||
# Use first argument as version if provided, otherwise default to v0.1.0
|
||||
VERSION=${1:-v0.1.0}
|
||||
./scripts/blame.py "$VERSION" --all --output aider/website/_data/blame.yml
|
||||
|
||||
@@ -20,6 +20,7 @@ cog $ARG \
|
||||
aider/website/HISTORY.md \
|
||||
aider/website/docs/usage/commands.md \
|
||||
aider/website/docs/languages.md \
|
||||
aider/website/docs/faq.md \
|
||||
aider/website/docs/config/dotenv.md \
|
||||
aider/website/docs/config/options.md \
|
||||
aider/website/docs/config/aider_conf.md \
|
||||
|
||||
@@ -5,6 +5,8 @@ import re
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
from history_prompts import history_prompt
|
||||
|
||||
from aider import __version__
|
||||
|
||||
|
||||
@@ -76,20 +78,7 @@ def main():
|
||||
aider_line = blame_result.stdout.strip().split("\n")[-1] # Get last line with percentage
|
||||
|
||||
# Construct and run the aider command
|
||||
message = f"""
|
||||
Update the history with changes shown in the diffs.
|
||||
Describe actual user-facing changes, not every single commit that was made implementing them.
|
||||
|
||||
Only add new items not already listed.
|
||||
Do NOT edit or update existing history entries.
|
||||
Do NOT add duplicate entries for changes that have existing history entries.
|
||||
|
||||
Be sure to attribute changes to the proper .x version.
|
||||
Changes in the .x-dev version should be listed under a "### main branch" heading
|
||||
|
||||
Also, add this as the last bullet under the "### main branch" section:
|
||||
{aider_line}
|
||||
""" # noqa
|
||||
message = history_prompt.format(aider_line=aider_line)
|
||||
|
||||
cmd = ["aider", hist_path, "--read", diff_path, "--msg", message, "--no-auto-commit"]
|
||||
subprocess.run(cmd)
|
||||
|
||||
@@ -10,15 +10,6 @@ import sys
|
||||
from packaging import version
|
||||
|
||||
|
||||
def check_cog_pyproject():
|
||||
result = subprocess.run(["cog", "--check", "pyproject.toml"], capture_output=True, text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
print("Error: cog --check pyproject.toml failed, updating.")
|
||||
subprocess.run(["cog", "-r", "pyproject.toml"])
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Bump version")
|
||||
parser.add_argument("new_version", help="New version in x.y.z format")
|
||||
@@ -82,7 +73,6 @@ def main():
|
||||
dry_run = args.dry_run
|
||||
|
||||
# Perform checks before proceeding
|
||||
check_cog_pyproject()
|
||||
check_branch()
|
||||
check_working_directory_clean()
|
||||
check_main_branch_up_to_date()
|
||||
|
||||
@@ -1468,6 +1468,39 @@ class TestCommands(TestCase):
|
||||
commands.cmd_drop("test_file.txt")
|
||||
self.assertEqual(len(coder.abs_read_only_fnames), 0)
|
||||
|
||||
def test_cmd_read_only_bulk_conversion(self):
|
||||
with GitTemporaryDirectory() as repo_dir:
|
||||
io = InputOutput(pretty=False, fancy_input=False, yes=False)
|
||||
coder = Coder.create(self.GPT35, None, io)
|
||||
commands = Commands(io, coder)
|
||||
|
||||
# Create and add some test files
|
||||
test_files = ["test1.txt", "test2.txt", "test3.txt"]
|
||||
for fname in test_files:
|
||||
Path(fname).write_text(f"Content of {fname}")
|
||||
commands.cmd_add(fname)
|
||||
|
||||
# Verify files are in editable mode
|
||||
self.assertEqual(len(coder.abs_fnames), 3)
|
||||
self.assertEqual(len(coder.abs_read_only_fnames), 0)
|
||||
|
||||
# Convert all files to read-only mode
|
||||
commands.cmd_read_only("")
|
||||
|
||||
# Verify all files were moved to read-only
|
||||
self.assertEqual(len(coder.abs_fnames), 0)
|
||||
self.assertEqual(len(coder.abs_read_only_fnames), 3)
|
||||
|
||||
# Check specific files
|
||||
for fname in test_files:
|
||||
abs_path = Path(repo_dir) / fname
|
||||
self.assertTrue(
|
||||
any(
|
||||
os.path.samefile(str(abs_path), ro_fname)
|
||||
for ro_fname in coder.abs_read_only_fnames
|
||||
)
|
||||
)
|
||||
|
||||
def test_cmd_read_only_with_multiple_files(self):
|
||||
with GitTemporaryDirectory() as repo_dir:
|
||||
io = InputOutput(pretty=False, fancy_input=False, yes=False)
|
||||
|
||||
@@ -91,9 +91,9 @@ class TestChatSummary(TestCase):
|
||||
# Check that both models were tried
|
||||
self.assertEqual(mock_send.call_count, 2)
|
||||
|
||||
# Check that the calls were made with the correct model names
|
||||
self.assertEqual(mock_send.call_args_list[0][0][0], "gpt-4")
|
||||
self.assertEqual(mock_send.call_args_list[1][0][0], "gpt-3.5-turbo")
|
||||
# Check that the calls were made with the correct models
|
||||
self.assertEqual(mock_send.call_args_list[0][0][0], mock_model1)
|
||||
self.assertEqual(mock_send.call_args_list[1][0][0], mock_model2)
|
||||
|
||||
# Check that we got a summary from the second model
|
||||
self.assertEqual(
|
||||
|
||||
@@ -220,6 +220,7 @@ class TestInputOutput(unittest.TestCase):
|
||||
|
||||
@patch("builtins.input", side_effect=["d"])
|
||||
def test_confirm_ask_allow_never(self, mock_input):
|
||||
"""Test the 'don't ask again' functionality in confirm_ask"""
|
||||
io = InputOutput(pretty=False, fancy_input=False)
|
||||
|
||||
# First call: user selects "Don't ask again"
|
||||
@@ -259,5 +260,24 @@ class TestInputOutput(unittest.TestCase):
|
||||
self.assertNotIn(("Do you want to proceed?", None), io.never_prompts)
|
||||
|
||||
|
||||
class TestInputOutputMultilineMode(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.io = InputOutput(fancy_input=True)
|
||||
self.io.prompt_session = MagicMock()
|
||||
|
||||
def test_toggle_multiline_mode(self):
|
||||
"""Test that toggling multiline mode works correctly"""
|
||||
# Start in single-line mode
|
||||
self.io.multiline_mode = False
|
||||
|
||||
# Toggle to multiline mode
|
||||
self.io.toggle_multiline_mode()
|
||||
self.assertTrue(self.io.multiline_mode)
|
||||
|
||||
# Toggle back to single-line mode
|
||||
self.io.toggle_multiline_mode()
|
||||
self.assertFalse(self.io.multiline_mode)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -672,6 +672,59 @@ class TestMain(TestCase):
|
||||
# Verify that environment variables from pytest.ini are properly set
|
||||
self.assertEqual(os.environ.get("AIDER_ANALYTICS"), "false")
|
||||
|
||||
def test_set_env_single(self):
|
||||
# Test setting a single environment variable
|
||||
with GitTemporaryDirectory():
|
||||
main(["--set-env", "TEST_VAR=test_value", "--exit", "--yes"])
|
||||
self.assertEqual(os.environ.get("TEST_VAR"), "test_value")
|
||||
|
||||
def test_set_env_multiple(self):
|
||||
# Test setting multiple environment variables
|
||||
with GitTemporaryDirectory():
|
||||
main(
|
||||
[
|
||||
"--set-env",
|
||||
"TEST_VAR1=value1",
|
||||
"--set-env",
|
||||
"TEST_VAR2=value2",
|
||||
"--exit",
|
||||
"--yes",
|
||||
]
|
||||
)
|
||||
self.assertEqual(os.environ.get("TEST_VAR1"), "value1")
|
||||
self.assertEqual(os.environ.get("TEST_VAR2"), "value2")
|
||||
|
||||
def test_set_env_with_spaces(self):
|
||||
# Test setting env var with spaces in value
|
||||
with GitTemporaryDirectory():
|
||||
main(["--set-env", "TEST_VAR=test value with spaces", "--exit", "--yes"])
|
||||
self.assertEqual(os.environ.get("TEST_VAR"), "test value with spaces")
|
||||
|
||||
def test_set_env_invalid_format(self):
|
||||
# Test invalid format handling
|
||||
with GitTemporaryDirectory():
|
||||
result = main(["--set-env", "INVALID_FORMAT", "--exit", "--yes"])
|
||||
self.assertEqual(result, 1)
|
||||
|
||||
def test_api_key_single(self):
|
||||
# Test setting a single API key
|
||||
with GitTemporaryDirectory():
|
||||
main(["--api-key", "anthropic=test-key", "--exit", "--yes"])
|
||||
self.assertEqual(os.environ.get("ANTHROPIC_API_KEY"), "test-key")
|
||||
|
||||
def test_api_key_multiple(self):
|
||||
# Test setting multiple API keys
|
||||
with GitTemporaryDirectory():
|
||||
main(["--api-key", "anthropic=key1", "--api-key", "openai=key2", "--exit", "--yes"])
|
||||
self.assertEqual(os.environ.get("ANTHROPIC_API_KEY"), "key1")
|
||||
self.assertEqual(os.environ.get("OPENAI_API_KEY"), "key2")
|
||||
|
||||
def test_api_key_invalid_format(self):
|
||||
# Test invalid format handling
|
||||
with GitTemporaryDirectory():
|
||||
result = main(["--api-key", "INVALID_FORMAT", "--exit", "--yes"])
|
||||
self.assertEqual(result, 1)
|
||||
|
||||
def test_invalid_edit_format(self):
|
||||
with GitTemporaryDirectory():
|
||||
with patch("aider.io.InputOutput.offer_url") as mock_offer_url:
|
||||
|
||||
@@ -125,9 +125,9 @@ class TestRepo(unittest.TestCase):
|
||||
# Check that simple_send_with_retries was called twice
|
||||
self.assertEqual(mock_send.call_count, 2)
|
||||
|
||||
# Check that it was called with the correct model names
|
||||
self.assertEqual(mock_send.call_args_list[0][0][0], model1.name)
|
||||
self.assertEqual(mock_send.call_args_list[1][0][0], model2.name)
|
||||
# Check that it was called with the correct models
|
||||
self.assertEqual(mock_send.call_args_list[0][0][0], model1)
|
||||
self.assertEqual(mock_send.call_args_list[1][0][0], model2)
|
||||
|
||||
# Check that the content of the messages is the same for both calls
|
||||
self.assertEqual(mock_send.call_args_list[0][0][1], mock_send.call_args_list[1][0][1])
|
||||
|
||||
@@ -3,6 +3,7 @@ from unittest.mock import MagicMock, patch
|
||||
|
||||
from aider.exceptions import LiteLLMExceptions
|
||||
from aider.llm import litellm
|
||||
from aider.models import Model
|
||||
from aider.sendchat import send_completion, simple_send_with_retries
|
||||
|
||||
|
||||
@@ -37,7 +38,7 @@ class TestSendChat(unittest.TestCase):
|
||||
]
|
||||
|
||||
# Call the simple_send_with_retries method
|
||||
simple_send_with_retries("model", ["message"])
|
||||
simple_send_with_retries(Model(self.mock_model), self.mock_messages)
|
||||
assert mock_print.call_count == 3
|
||||
|
||||
@patch("litellm.completion")
|
||||
@@ -74,7 +75,7 @@ class TestSendChat(unittest.TestCase):
|
||||
mock_completion.return_value.choices = None
|
||||
|
||||
# Should return None on AttributeError
|
||||
result = simple_send_with_retries(self.mock_model, self.mock_messages)
|
||||
result = simple_send_with_retries(Model(self.mock_model), self.mock_messages)
|
||||
assert result is None
|
||||
|
||||
@patch("litellm.completion")
|
||||
@@ -88,6 +89,7 @@ class TestSendChat(unittest.TestCase):
|
||||
message="Invalid request", llm_provider="test_provider", model="test_model"
|
||||
)
|
||||
|
||||
result = simple_send_with_retries(self.mock_model, self.mock_messages)
|
||||
result = simple_send_with_retries(Model(self.mock_model), self.mock_messages)
|
||||
assert result is None
|
||||
# Should only print the error message
|
||||
assert mock_print.call_count == 1
|
||||
|
||||
@@ -4,6 +4,63 @@ from aider.io import InputOutput
|
||||
from aider.watch import FileWatcher
|
||||
|
||||
|
||||
def test_gitignore_patterns():
|
||||
"""Test that gitignore patterns are properly loaded and matched"""
|
||||
from pathlib import Path
|
||||
|
||||
from aider.watch import load_gitignores
|
||||
|
||||
# Create a temporary gitignore file with test patterns
|
||||
tmp_gitignore = Path("test.gitignore")
|
||||
tmp_gitignore.write_text("custom_pattern\n*.custom")
|
||||
|
||||
gitignores = [tmp_gitignore]
|
||||
spec = load_gitignores(gitignores)
|
||||
|
||||
# Test built-in patterns
|
||||
assert spec.match_file(".aider.conf")
|
||||
assert spec.match_file(".git/config")
|
||||
assert spec.match_file("file~") # Emacs/vim backup
|
||||
assert spec.match_file("file.bak")
|
||||
assert spec.match_file("file.swp")
|
||||
assert spec.match_file("file.swo")
|
||||
assert spec.match_file("#temp#") # Emacs auto-save
|
||||
assert spec.match_file(".#lock") # Emacs lock
|
||||
assert spec.match_file("temp.tmp")
|
||||
assert spec.match_file("temp.temp")
|
||||
assert spec.match_file("conflict.orig")
|
||||
assert spec.match_file("script.pyc")
|
||||
assert spec.match_file("__pycache__/module.pyc")
|
||||
assert spec.match_file(".DS_Store")
|
||||
assert spec.match_file("Thumbs.db")
|
||||
assert spec.match_file(".idea/workspace.xml")
|
||||
assert spec.match_file(".vscode/settings.json")
|
||||
assert spec.match_file("project.sublime-workspace")
|
||||
assert spec.match_file(".project")
|
||||
assert spec.match_file(".settings/config.json")
|
||||
assert spec.match_file("workspace.code-workspace")
|
||||
assert spec.match_file(".env")
|
||||
assert spec.match_file(".venv/bin/python")
|
||||
assert spec.match_file("node_modules/package/index.js")
|
||||
assert spec.match_file("vendor/lib/module.py")
|
||||
assert spec.match_file("debug.log")
|
||||
assert spec.match_file(".cache/files")
|
||||
assert spec.match_file(".pytest_cache/v/cache")
|
||||
assert spec.match_file("coverage/lcov.info")
|
||||
|
||||
# Test custom patterns from gitignore file
|
||||
assert spec.match_file("custom_pattern")
|
||||
assert spec.match_file("file.custom")
|
||||
|
||||
# Test non-matching patterns
|
||||
assert not spec.match_file("regular_file.txt")
|
||||
assert not spec.match_file("src/main.py")
|
||||
assert not spec.match_file("docs/index.html")
|
||||
|
||||
# Cleanup
|
||||
tmp_gitignore.unlink()
|
||||
|
||||
|
||||
def test_ai_comment_pattern():
|
||||
# Create minimal IO and Coder instances for testing
|
||||
class MinimalCoder:
|
||||
@@ -32,13 +89,27 @@ def test_ai_comment_pattern():
|
||||
f"Expected {py_expected} unique AI comments in Python fixture, found"
|
||||
f" {len(unique_py_comments)}"
|
||||
)
|
||||
assert py_has_bang, "Expected at least one bang (!) comment in Python fixture"
|
||||
assert py_has_bang == "!", "Expected at least one bang (!) comment in Python fixture"
|
||||
|
||||
# Test JavaScript fixture
|
||||
js_path = fixtures_dir / "watch.js"
|
||||
js_lines, js_comments, js_has_bang = watcher.get_ai_comments(str(js_path))
|
||||
js_expected = 14
|
||||
js_expected = 16
|
||||
assert (
|
||||
len(js_lines) == js_expected
|
||||
), f"Expected {js_expected} AI comments in JavaScript fixture, found {len(js_lines)}"
|
||||
assert js_has_bang, "Expected at least one bang (!) comment in JavaScript fixture"
|
||||
assert js_has_bang == "!", "Expected at least one bang (!) comment in JavaScript fixture"
|
||||
|
||||
# Test watch_question.js fixture
|
||||
question_js_path = fixtures_dir / "watch_question.js"
|
||||
question_js_lines, question_js_comments, question_js_has_bang = watcher.get_ai_comments(
|
||||
str(question_js_path)
|
||||
)
|
||||
question_js_expected = 6
|
||||
assert len(question_js_lines) == question_js_expected, (
|
||||
f"Expected {question_js_expected} AI comments in watch_question.js fixture, found"
|
||||
f" {len(question_js_lines)}"
|
||||
)
|
||||
assert (
|
||||
question_js_has_bang == "?"
|
||||
), "Expected at least one bang (!) comment in watch_question.js fixture"
|
||||
|
||||
3
tests/fixtures/watch.js
vendored
3
tests/fixtures/watch.js
vendored
@@ -33,3 +33,6 @@ class Example {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// trailing whitespace ai
|
||||
// trailing whitespace ai!
|
||||
// 15-16
|
||||
|
||||
11
tests/fixtures/watch_question.js
vendored
Normal file
11
tests/fixtures/watch_question.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
// Regular AI comment
|
||||
//ai do 1 something
|
||||
//AI make 2 this better
|
||||
//ai! urgent 3 change needed
|
||||
//AI! another 4 urgent one
|
||||
// ai with 5 space
|
||||
// with questions AI?
|
||||
|
||||
// this is not an ai comment
|
||||
// aider is not an ai! comment
|
||||
|
||||
Reference in New Issue
Block a user