From e9a0719eb259ee04a98c6cbfac26a79d60159592 Mon Sep 17 00:00:00 2001 From: Jon Michael Aanes Date: Mon, 21 Apr 2025 12:15:13 +0200 Subject: [PATCH] Stuff --- aider_gitea/__init__.py | 98 +++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 39 deletions(-) diff --git a/aider_gitea/__init__.py b/aider_gitea/__init__.py index 210519c..c458c6b 100644 --- a/aider_gitea/__init__.py +++ b/aider_gitea/__init__.py @@ -149,10 +149,11 @@ AIDER_LINT = bash_cmd( ) -LLM_MESSAGE_FORMAT = """/code {issue}""" +LLM_MESSAGE_FORMAT = """{issue}\nDo not wait for explicit approval before working on code changes.""" -#MODEL = 'ollama/gemma3:27b' -MODEL = 'ollama/gemma3:4b' +#CODE_MODEL = 'ollama/gemma3:4b' +CODE_MODEL = None +EVALUATOR_MODEL = 'ollama/gemma3:27b' def create_aider_command(issue: str) -> list[str]: l = [ @@ -161,15 +162,13 @@ def create_aider_command(issue: str) -> list[str]: 'english', '--no-stream', '--no-analytics', - '--no-check-update', + #'--no-check-update', '--test-cmd', AIDER_TEST, '--lint-cmd', AIDER_LINT, '--auto-test', '--no-auto-lint', - '--message', - LLM_MESSAGE_FORMAT.format(issue=issue), '--yes', ] @@ -186,9 +185,16 @@ def create_aider_command(issue: str) -> list[str]: if False: l.append('--architect') - if MODEL: + if CODE_MODEL: l.append('--model') - l.append(MODEL) + l.append(CODE_MODEL) + + if CODE_MODEL.startswith('ollama/'): + l.append('--auto-lint') + + if True: + l.append('--message') + l.append(LLM_MESSAGE_FORMAT.format(issue=issue)) return l @@ -310,8 +316,10 @@ def run_cmd(cmd: list[str], cwd: Path | None = None, check=True) -> bool: def issue_solution_round(repository_path, issue_content): # Primary Aider command + aider_command = create_aider_command(issue_content) + print(aider_command) aider_did_not_crash = run_cmd( - create_aider_command(issue_content), + aider_command, repository_path, check=False, ) @@ -326,7 +334,7 @@ def issue_solution_round(repository_path, issue_content): return True def run_ollama(cwd: Path, texts: list[str]) -> str: - cmd = ['ollama', 'run', MODEL.removeprefix('ollama/')] + cmd = ['ollama', 'run', EVALUATOR_MODEL.removeprefix('ollama/')] print(cmd) process = subprocess.Popen( cmd, @@ -337,21 +345,30 @@ def run_ollama(cwd: Path, texts: list[str]) -> str: text=True, ) stdout, stderr = process.communicate('\n'.join(texts)) + print(stdout) return stdout +def parse_yes_no_answer(text: str) -> bool | None: + text = text.lower().strip() + words = text.split('\n \t.,?-') + print(words) + if words[-1] in {'yes', 'agree'}: + return True + if words[-1] in {'no', 'disagree'}: + return False + return None + def run_ollama_and_get_yes_or_no(cwd, initial_texts: list[str]) -> bool: texts = list(initial_texts) - texts.append('Think through your answer, and end it with "yes" or "no".') + texts.append('Think through your answer.') while True: - result = run_ollama(cwd, texts).lower().removesuffix('.').strip() - print(result) - if result.endswith('yes'): - return True - elif result.endswith('no'): - return False + response = run_ollama(cwd, texts) + yes_or_no = parse_yes_no_answer(response) + if yes_or_no is not None: + return yes_or_no else: - texts.append(result) - texts.append('Please answer either yes or no.') + texts.append(response) + texts.append('Please answer either "yes" or "no".') def verify_solution(repository_path: Path, issue_content: str) -> bool: summary = run_ollama( @@ -360,17 +377,25 @@ def verify_solution(repository_path: Path, issue_content: str) -> bool: get_diff(repository_path, 'HEAD', 'main') ]) - print(summary) - return run_ollama_and_get_yes_or_no( repository_path, - ['Does this changeset the task?', + ['Does this changeset accomplish the entire task?', '# Change set', summary, '# Issue', issue_content, ]) +def get_head_commit_hash(repository_path: Path) -> str: + return subprocess.run( + ['git', 'rev-parse', 'HEAD'], + check=True, + cwd=repository_path, + capture_output=True, + text=True, + ).stdout.strip() + + def solve_issue_in_repository( repository_config: RepositoryConfig, repository_path: Path, @@ -393,36 +418,31 @@ def solve_issue_in_repository( run_cmd(['git', 'add', '.'], repository_path) run_cmd(['git', 'commit', '-m', 'Initial ruff pass'], repository_path, check=False) - # Save the commit hash after ruff but before aider - pre_aider_commit = subprocess.run( - ['git', 'rev-parse', 'HEAD'], - check=True, - cwd=repository_path, - capture_output=True, - text=True, - ).stdout.strip() - # Run aider issue_content = f'# {issue_title}\n{issue_description}' while True: + # Save the commit hash after ruff but before aider + pre_aider_commit = get_head_commit_hash(repository_path) + + # Run aider aider_did_not_crash = issue_solution_round(repository_path, issue_content) if not aider_did_not_crash: logger.error('Aider invocation failed for issue #%s', issue_number) return IssueResolution(False) + # Check if aider made any changes beyond the initial ruff pass + if not has_commits_on_branch(repository_path, pre_aider_commit, 'HEAD'): + logger.error( + 'Aider did not make any changes beyond the initial ruff pass for issue #%s', + issue_number, + ) + return IssueResolution(False) + # Verify whether this is a satisfactory solution if verify_solution(repository_path, issue_content): break - # Check if aider made any changes beyond the initial ruff pass - if not has_commits_on_branch(repository_path, repository_config.base_branch, branch_name): - logger.info( - 'Aider did not make any changes beyond the initial ruff pass for issue #%s', - issue_number, - ) - return IssueResolution(False) - # Push changes return push_changes( repository_config,