mirror of
https://github.com/Aider-AI/aider.git
synced 2025-06-02 18:54:59 +00:00
Merge branch 'main' into indent-bad-edit
This commit is contained in:
commit
77be993708
14 changed files with 150 additions and 49 deletions
|
@ -1,8 +1,13 @@
|
||||||
# Release history
|
# Release history
|
||||||
|
|
||||||
### main branch
|
### v0.11.1
|
||||||
|
|
||||||
- Fixed /commit bug from repo refactor, added test coverage
|
- Added a progress bar when initially creating a repo map.
|
||||||
|
- Fixed bad commit message when adding new file to empty repo.
|
||||||
|
- Fixed corner case of pending chat history summarization when dirty committing.
|
||||||
|
- Fixed corner case of undefined `text` when using `--no-pretty`.
|
||||||
|
- Fixed /commit bug from repo refactor, added test coverage.
|
||||||
|
- [Benchmarked](https://aider.chat/docs/benchmarks.html) at 53.4% for gpt-3.5/whole (no regression).
|
||||||
|
|
||||||
### v0.11.0
|
### v0.11.0
|
||||||
|
|
||||||
|
|
20
README.md
20
README.md
|
@ -1,12 +1,14 @@
|
||||||
# aider is GPT powered coding in your terminal
|
# aider is AI pair programming in your terminal
|
||||||
|
|
||||||
`aider` is a command-line chat tool that allows you to write and edit
|
Aider is a command line tool that lets you pair program with GPT-3.5/GPT-4,
|
||||||
code with OpenAI's GPT models. You can ask GPT to help you start
|
to edit code stored in your local git repository.
|
||||||
a new project, or modify code in your existing git repo.
|
You can start a new project or work with an existing repo.
|
||||||
Aider makes it easy to
|
And you can fluidly switch back and forth between the aider chat where you ask
|
||||||
[git commit, diff & undo changes](https://aider.chat/docs/faq.html#how-does-aider-use-git)
|
GPT to edit the code and your own editor to make changes yourself.
|
||||||
proposed by GPT without copy/pasting.
|
Aider makes sure edits from you and GPT are
|
||||||
It also has features that [help GPT-4 understand and modify larger codebases](https://aider.chat/docs/ctags.html).
|
[committed to git](https://aider.chat/docs/faq.html#how-does-aider-use-git)
|
||||||
|
with sensible commit messages.
|
||||||
|
Aider is unique in that it [works well with pre-existing, larger codebases](https://aider.chat/docs/ctags.html).
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="assets/screencast.svg" alt="aider screencast">
|
<img src="assets/screencast.svg" alt="aider screencast">
|
||||||
|
@ -43,7 +45,7 @@ $ aider hello.js
|
||||||
Using git repo: .git
|
Using git repo: .git
|
||||||
Added hello.js to the chat.
|
Added hello.js to the chat.
|
||||||
|
|
||||||
hello.js> write a js app that prints hello world
|
hello.js> write a js script that prints hello world
|
||||||
```
|
```
|
||||||
|
|
||||||
## Example chat transcripts
|
## Example chat transcripts
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<header class="page-header" role="banner">
|
<header class="page-header" role="banner">
|
||||||
{% if page.url == "/" %}
|
{% if page.url == "/" %}
|
||||||
<h1 class="project-name">aider</h1>
|
<h1 class="project-name">aider</h1>
|
||||||
<h2 class="project-tagline">GPT powered coding in your terminal</h2>
|
<h2 class="project-tagline">AI pair programming in your terminal</h2>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h1 class="project-name">{{ page.title | default: site.title | default: site.github.repository_name }}</h1>
|
<h1 class="project-name">{{ page.title | default: site.title | default: site.github.repository_name }}</h1>
|
||||||
<h2 class="project-tagline">{{ page.description | default: site.description | default: site.github.project_tagline }}</h2>
|
<h2 class="project-tagline">{{ page.description | default: site.description | default: site.github.project_tagline }}</h2>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
__version__ = "0.11.1-dev"
|
__version__ = "0.11.2-dev"
|
||||||
|
|
|
@ -365,8 +365,8 @@ class Coder:
|
||||||
if not self.summarizer.too_big(self.done_messages):
|
if not self.summarizer.too_big(self.done_messages):
|
||||||
return
|
return
|
||||||
|
|
||||||
assert self.summarizer_thread is None
|
self.summarize_end()
|
||||||
assert self.summarized_done_messages is None
|
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
self.io.tool_output("Starting to summarize chat history.")
|
self.io.tool_output("Starting to summarize chat history.")
|
||||||
|
|
||||||
|
@ -653,6 +653,9 @@ class Coder:
|
||||||
live.start()
|
live.start()
|
||||||
|
|
||||||
for chunk in completion:
|
for chunk in completion:
|
||||||
|
if len(chunk.choices) == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
if chunk.choices[0].finish_reason == "length":
|
if chunk.choices[0].finish_reason == "length":
|
||||||
raise ExhaustedContextWindow()
|
raise ExhaustedContextWindow()
|
||||||
|
|
||||||
|
@ -672,11 +675,11 @@ class Coder:
|
||||||
if text:
|
if text:
|
||||||
self.partial_response_content += text
|
self.partial_response_content += text
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
text = None
|
||||||
|
|
||||||
if self.pretty:
|
if self.pretty:
|
||||||
self.live_incremental_response(live, False)
|
self.live_incremental_response(live, False)
|
||||||
else:
|
elif text:
|
||||||
sys.stdout.write(text)
|
sys.stdout.write(text)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
finally:
|
finally:
|
||||||
|
|
|
@ -350,8 +350,9 @@ class Commands:
|
||||||
combined_output = None
|
combined_output = None
|
||||||
try:
|
try:
|
||||||
parsed_args = shlex.split("git " + args)
|
parsed_args = shlex.split("git " + args)
|
||||||
|
env = dict(GIT_EDITOR="true", **subprocess.os.environ)
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
parsed_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True
|
parsed_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, env=env
|
||||||
)
|
)
|
||||||
combined_output = result.stdout
|
combined_output = result.stdout
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
@ -126,19 +126,11 @@ class GitRepo:
|
||||||
return commit_message
|
return commit_message
|
||||||
|
|
||||||
def get_diffs(self, pretty, *args):
|
def get_diffs(self, pretty, *args):
|
||||||
try:
|
# we always want diffs of working-dir + index versus repo
|
||||||
commits = self.repo.iter_commits(self.repo.active_branch)
|
args = ["--cached"] + list(args)
|
||||||
current_branch_has_commits = any(commits)
|
|
||||||
except git.exc.GitCommandError:
|
|
||||||
current_branch_has_commits = False
|
|
||||||
|
|
||||||
if not current_branch_has_commits:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
if pretty:
|
if pretty:
|
||||||
args = ["--color"] + list(args)
|
args = ["--color"] + list(args)
|
||||||
if not args:
|
|
||||||
args = ["HEAD"]
|
|
||||||
|
|
||||||
diffs = self.repo.git.diff(*args)
|
diffs = self.repo.git.diff(*args)
|
||||||
return diffs
|
return diffs
|
||||||
|
|
|
@ -307,6 +307,10 @@ class RepoMap:
|
||||||
self.cache_missing = False
|
self.cache_missing = False
|
||||||
|
|
||||||
for fname in fnames:
|
for fname in fnames:
|
||||||
|
if not Path(fname).is_file():
|
||||||
|
self.io.tool_error(f"Repo-map can't include {fname}")
|
||||||
|
continue
|
||||||
|
|
||||||
# dump(fname)
|
# dump(fname)
|
||||||
rel_fname = os.path.relpath(fname, self.root)
|
rel_fname = os.path.relpath(fname, self.root)
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,10 @@
|
||||||
color: #00FFFF;
|
color: #00FFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-transcript h1 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.chat-transcript h4 {
|
.chat-transcript h4 {
|
||||||
color: #32FF32;
|
color: #32FF32;
|
||||||
border-top: 1px solid #32FF32;
|
border-top: 1px solid #32FF32;
|
||||||
|
|
31
docs/faq.md
31
docs/faq.md
|
@ -107,41 +107,30 @@ In these cases, here are some things you might try:
|
||||||
|
|
||||||
## Can I use aider with other LLMs, local LLMs, etc?
|
## Can I use aider with other LLMs, local LLMs, etc?
|
||||||
|
|
||||||
Aider does not officially support use with LLMs other than OpenAI's gpt-3.5-turbo and gpt-4
|
Aider only has experimental support for LLMs other than OpenAI's GPT-3.5 and GPT-4. This is for two reasons:
|
||||||
and their variants.
|
|
||||||
This is because while it's "easy" to connect aider to a new LLM, it's "hard"
|
|
||||||
to actually teach new LLMs to *edit* code.
|
|
||||||
|
|
||||||
GPT-3.5 is just barely able to understand how to modify existing source code files,
|
- GPT-3.5 is just barely capable of *editing code* to provide aider's interactive "pair programming" style workflow. None of the other models seem to be as capable as GPT-3.5.
|
||||||
and GPT-4 is quite good at it.
|
- Just "hooking up" aider to a new model by connecting to its API is almost certainly not enough to get it working in a useful way. Getting aider working well with GPT-3.5 and GPT-4 was a significant undertaking, involving [specific code editing prompts and backends for each model and extensive benchmarking](https://aider.chat/docs/benchmarks.html). Officially supporting each new LLM will probably require a similar effort to tailor the prompts and editing backends.
|
||||||
Getting them working that well was a significant undertaking, involving
|
|
||||||
[specific code editing prompts and backends for each model and extensive benchmarking](https://aider.chat/docs/benchmarks.html).
|
|
||||||
Officially supporting new LLMs will probably require a similar effort to tailor the
|
|
||||||
prompts and editing backends.
|
|
||||||
|
|
||||||
That said, aider does provide some features to experiment with other models.
|
That said, aider does provide features to experiment with other models. Numerous users have already done experiments with numerous models. None of these experiments have yet identified other models that look like they are capable of working with aider.
|
||||||
Numerous users have already done experiments with numerous models.
|
|
||||||
So far, no one has reported much success in working with them the way aider
|
|
||||||
can work with GPT-3.5 and GPT-4.
|
|
||||||
|
|
||||||
Once we see signs that a *particular* model is capable of code editing,
|
Once we see signs that a *particular* model is capable of code editing, it would be reasonable for aider to attempt to officially support such a model. Until then, aider will simply maintain experimental support for using alternative models.
|
||||||
it would be reasonable for aider to attempt to officially support such a model.
|
|
||||||
Until then, aider will simply maintain experimental support for using alternative models.
|
There are ongoing discussions about [LLM integrations in the aider discord](https://discord.com/channels/1131200896827654144/1133060780649087048).
|
||||||
|
|
||||||
|
Here are some [GitHub issues which may contain relevant information](https://github.com/paul-gauthier/aider/issues?q=is%3Aissue+%23172).
|
||||||
|
|
||||||
### OpenAI API compatible LLMs
|
### OpenAI API compatible LLMs
|
||||||
|
|
||||||
If you can make the model accessible via an OpenAI compatible API,
|
If you can make the model accessible via an OpenAI compatible API,
|
||||||
you can use `--openai-api-base` to connect to a different API endpoint.
|
you can use `--openai-api-base` to connect to a different API endpoint.
|
||||||
|
|
||||||
Here are some
|
|
||||||
[GitHub issues which may contain relevant information](https://github.com/paul-gauthier/aider/issues?q=is%3Aissue+%22openai-api-base%22+).
|
|
||||||
|
|
||||||
### Local LLMs
|
### Local LLMs
|
||||||
|
|
||||||
[LocalAI](https://github.com/go-skynet/LocalAI)
|
[LocalAI](https://github.com/go-skynet/LocalAI)
|
||||||
and
|
and
|
||||||
[SimpleAI](https://github.com/lhenault/simpleAI)
|
[SimpleAI](https://github.com/lhenault/simpleAI)
|
||||||
look like relevant tools to serve local models via a compatible API:
|
look like relevant tools to serve local models via a compatible API.
|
||||||
|
|
||||||
|
|
||||||
### Azure
|
### Azure
|
||||||
|
|
0
hello.py
Normal file
0
hello.py
Normal file
69
share/index.md
Normal file
69
share/index.md
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
|
||||||
|
# Shared aider chat transcript
|
||||||
|
|
||||||
|
A user has shared the following transcript of a pair programming chat session
|
||||||
|
created using <a href="https://aider.chat">aider</a>.
|
||||||
|
Aider is a command line tool that lets you pair program with GPT-3.5 or
|
||||||
|
GPT-4, to edit code stored in your local git repository.
|
||||||
|
|
||||||
|
## Transcript format
|
||||||
|
|
||||||
|
<div class="chat-transcript" markdown="1">
|
||||||
|
|
||||||
|
> This is output from the aider tool.
|
||||||
|
|
||||||
|
#### These are chat messages written by the user.
|
||||||
|
|
||||||
|
Chat responses from GPT are in a blue font like this,
|
||||||
|
and often include colorized "diffs" where GPT is editing code:
|
||||||
|
|
||||||
|
|
||||||
|
```python
|
||||||
|
hello.py
|
||||||
|
<<<<<<< ORIGINAL
|
||||||
|
print("hello")
|
||||||
|
=======
|
||||||
|
print("goodbye")
|
||||||
|
>>>>>>> UPDATED
|
||||||
|
```
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Shared chat transcript
|
||||||
|
|
||||||
|
<div class="chat-transcript" id="shared-transcript">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||||
|
<script>
|
||||||
|
window.onload = function() {
|
||||||
|
var urlParams = new URLSearchParams(window.location.search);
|
||||||
|
var conv = urlParams.get('mdurl');
|
||||||
|
if (!conv) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check if the URL is a non-raw GitHub gist
|
||||||
|
var gistRegex = /^https:\/\/gist\.github\.com\/([^\/]+)\/([a-f0-9]+)$/;
|
||||||
|
var match = gistRegex.exec(conv);
|
||||||
|
if (match) {
|
||||||
|
// If it is, convert it into a raw URL
|
||||||
|
conv = 'https://gist.githubusercontent.com/' + match[1] + '/' + match[2] + '/raw';
|
||||||
|
}
|
||||||
|
fetch(conv)
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(markdown => {
|
||||||
|
// Ensure every line that starts with '>' ends with exactly 2 spaces
|
||||||
|
markdown = markdown.split('\n').map(function(line) {
|
||||||
|
if (line.startsWith('>')) {
|
||||||
|
return line.trimEnd() + ' ';
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}).join('\n');
|
||||||
|
var html = marked.parse(markdown);
|
||||||
|
var divElement = document.querySelector('#shared-transcript');
|
||||||
|
divElement.innerHTML = html;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error fetching markdown:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -22,6 +22,25 @@ class TestCoder(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.patcher.stop()
|
self.patcher.stop()
|
||||||
|
|
||||||
|
def test_new_file_commit_message(self):
|
||||||
|
with GitTemporaryDirectory():
|
||||||
|
repo = git.Repo()
|
||||||
|
fname = Path("foo.txt")
|
||||||
|
|
||||||
|
io = InputOutput(yes=True)
|
||||||
|
# Initialize the Coder object with the mocked IO and mocked repo
|
||||||
|
coder = Coder.create(models.GPT4, None, io, fnames=[str(fname)])
|
||||||
|
|
||||||
|
self.assertTrue(fname.exists())
|
||||||
|
|
||||||
|
# Mock the get_commit_message method to return "I added str(fname)"
|
||||||
|
repo.get_commit_message = MagicMock(return_value=f"I added {str(fname)}")
|
||||||
|
# Get the latest commit message
|
||||||
|
commit_message = repo.get_commit_message()
|
||||||
|
# Check that the latest commit message is "I added str(fname)"
|
||||||
|
self.assertEqual(commit_message, f"I added {str(fname)}")
|
||||||
|
|
||||||
|
|
||||||
def test_allowed_to_edit(self):
|
def test_allowed_to_edit(self):
|
||||||
with GitTemporaryDirectory():
|
with GitTemporaryDirectory():
|
||||||
repo = git.Repo(Path.cwd())
|
repo = git.Repo(Path.cwd())
|
||||||
|
|
|
@ -13,6 +13,19 @@ from tests.utils import GitTemporaryDirectory
|
||||||
|
|
||||||
|
|
||||||
class TestRepo(unittest.TestCase):
|
class TestRepo(unittest.TestCase):
|
||||||
|
def test_diffs_empty_repo(self):
|
||||||
|
with GitTemporaryDirectory():
|
||||||
|
repo = git.Repo()
|
||||||
|
fname = Path("foo.txt")
|
||||||
|
fname.touch()
|
||||||
|
|
||||||
|
repo.git.add(str(fname))
|
||||||
|
|
||||||
|
git_repo = GitRepo(InputOutput(), None, ".")
|
||||||
|
diffs = git_repo.get_diffs(False)
|
||||||
|
self.assertNotEqual(diffs, "")
|
||||||
|
self.assertIsNotNone(diffs)
|
||||||
|
|
||||||
@patch("aider.repo.simple_send_with_retries")
|
@patch("aider.repo.simple_send_with_retries")
|
||||||
def test_get_commit_message(self, mock_send):
|
def test_get_commit_message(self, mock_send):
|
||||||
mock_send.return_value = "a good commit message"
|
mock_send.return_value = "a good commit message"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue