diff --git a/aider/__init__.py b/aider/__init__.py index 49e0fc1e0..a5f830a2c 100644 --- a/aider/__init__.py +++ b/aider/__init__.py @@ -1 +1 @@ -__version__ = "0.7.0" +__version__ = "0.7.1" diff --git a/aider/coders/wholefile_coder.py b/aider/coders/wholefile_coder.py index a7cd11e01..ecb0e0fcb 100644 --- a/aider/coders/wholefile_coder.py +++ b/aider/coders/wholefile_coder.py @@ -44,7 +44,7 @@ class WholeFileCoder(Coder): full_path = (Path(self.root) / fname).absolute() if mode == "diff" and full_path.exists(): - orig_lines = full_path.read_text().splitlines() + orig_lines = full_path.read_text().splitlines(keepends=True) show_diff = diffs.diff_partial_update( orig_lines, @@ -99,7 +99,7 @@ class WholeFileCoder(Coder): full_path = (Path(self.root) / fname).absolute() if mode == "diff" and full_path.exists(): - orig_lines = full_path.read_text().splitlines() + orig_lines = full_path.read_text().splitlines(keepends=True) show_diff = diffs.diff_partial_update( orig_lines, diff --git a/aider/coders/wholefile_prompts.py b/aider/coders/wholefile_prompts.py index b44446c98..eaea54336 100644 --- a/aider/coders/wholefile_prompts.py +++ b/aider/coders/wholefile_prompts.py @@ -14,7 +14,8 @@ Once you understand the request you MUST: 3. If changes are needed, output a copy of each file that needs changes. """ - system_reminder = """To return code you MUST use this *file listing* format: + system_reminder = """To suggest changes to a file you MUST return the entire content of the updated file. +You MUST use this *file listing* format: path/to/filename.js {fence}javascript diff --git a/aider/diffs.py b/aider/diffs.py index a2a8c52f6..4608e8e18 100644 --- a/aider/diffs.py +++ b/aider/diffs.py @@ -33,6 +33,13 @@ def create_progress_bar(percentage): return bar +def assert_newlines(lines): + if not lines: + return + for line in lines: + assert line and line[-1] == "\n", line + + def diff_partial_update(lines_orig, lines_updated, final=False, fname=None): """ Given only the first part of an updated file, show the diff while @@ -43,6 +50,9 @@ def diff_partial_update(lines_orig, lines_updated, final=False, fname=None): # dump(lines_orig) # dump(lines_updated) + assert_newlines(lines_orig) + assert_newlines(lines_orig) + num_orig_lines = len(lines_orig) if final: diff --git a/scripts/benchmark.py b/scripts/benchmark.py index a1dddd205..d9833e6fe 100644 --- a/scripts/benchmark.py +++ b/scripts/benchmark.py @@ -10,6 +10,7 @@ from collections import defaultdict from json.decoder import JSONDecodeError from pathlib import Path +import git import lox from rich.console import Console @@ -26,6 +27,11 @@ assert ORIGINAL_DNAME.exists() and ORIGINAL_DNAME.is_dir() def main(): + repo = git.Repo(search_parent_directories=True) + commit_hash = repo.head.object.hexsha[:7] + if repo.is_dirty(): + commit_hash += "-dirty" + parser = argparse.ArgumentParser(description="Aider Benchmark") parser.add_argument("dirname", type=str, help="Directory name") parser.add_argument("--model", "-m", type=str, help="Model name", default="gpt-3.5-turbo") @@ -117,6 +123,7 @@ def main(): args.no_test, args.verbose, args.stats_only, + commit_hash, ) all_results.append(results) @@ -133,6 +140,7 @@ def main(): args.no_test, args.verbose, args.stats_only, + commit_hash, ) all_results = run_test_threaded.gather(tqdm=True) @@ -172,11 +180,10 @@ def summarize_results(dirname, all_results, total_tests=None): total_cost += results["cost"] duration += results["duration"] - for key in "model edit_format".split(): - if key in results: - variants[key].add(results[key]) + for key in "model edit_format commit_hash".split(): + val = results.get(key) + variants[key].add(val) - dump(completed_tests) if not completed_tests: return @@ -189,7 +196,7 @@ def summarize_results(dirname, all_results, total_tests=None): style = "red" else: style = None - val = ", ".join(val) + val = ", ".join(map(str, val)) console.print(f"{key}: {val}", style=style) console.print() @@ -213,7 +220,7 @@ def summarize_results(dirname, all_results, total_tests=None): console.rule() -def run_test(testdir, model_name, edit_format, retries, no_test, verbose, stats_only): +def run_test(testdir, model_name, edit_format, retries, no_test, verbose, stats_only, commit_hash): if not stats_only: dump(testdir) @@ -248,12 +255,18 @@ def run_test(testdir, model_name, edit_format, retries, no_test, verbose, stats_ shutil.copy(original_fname, fname) file_list = " ".join(fname.name for fname in fnames) - instructions = (testdir / ".docs/instructions.md").read_text() - instructions += ( - "\n\n=====\n\nModify these files according to the above instructions. Only use standard" - " python libraries, don't suggest installing any packages.\n" - ) - instructions += file_list + intro = testdir / ".docs/introduction.md" + if intro.exists(): + instructions = intro.read_text() + "\n\n" + else: + instructions = "" + instructions += (testdir / ".docs/instructions.md").read_text() + instructions += f""" +===== +Use the above instructions to modify the supplied files: {file_list} +Keep and implement the existing function or class stubs, they will be called from unit tests. +Only use standard python libraries, don't suggest installing any packages. +""" io = InputOutput( pretty=True, @@ -319,6 +332,7 @@ def run_test(testdir, model_name, edit_format, retries, no_test, verbose, stats_ tests_outcomes=test_outcomes, cost=coder.total_cost, duration=dur, + commit_hash=commit_hash, ) dump(results)