normalize/dedupe files for programmer tool

This commit is contained in:
AI Christianson 2025-02-13 09:45:32 -05:00
parent 972ea5284a
commit 1084faaf0b
2 changed files with 47 additions and 11 deletions

View File

@ -1,4 +1,5 @@
import os
import os
import sys
from pathlib import Path
from typing import Dict, List, Union
@ -77,13 +78,6 @@ def run_programming_task(
Returns: { "output": stdout+stderr, "return_code": 0 if success, "success": True/False }
"""
# Get related files if no specific files provided
file_paths = (
list(_global_memory["related_files"].values())
if "related_files" in _global_memory
else []
)
# Build command
aider_exe = get_aider_executable()
command = [
@ -96,6 +90,13 @@ def run_programming_task(
"--no-check-update",
]
# Get combined list of files (explicit + related) with normalized paths
# and deduplicated using set operations
files_to_use = list({os.path.abspath(f) for f in (files or [])} | {
os.path.abspath(f) for f in _global_memory["related_files"].values()
if "related_files" in _global_memory
})
# Add config file if specified
if "config" in _global_memory and _global_memory["config"].get("aider_config"):
command.extend(["--config", _global_memory["config"]["aider_config"]])
@ -112,9 +113,6 @@ def run_programming_task(
command.append("-m")
command.append(instructions)
# Add files to command
files_to_use = file_paths + (files or [])
if files_to_use:
command.extend(files_to_use)

View File

@ -1,5 +1,6 @@
import pytest
from pathlib import Path
from langchain_core.tools import Tool
from ra_aid.tools.programmer import parse_aider_flags, run_programming_task, get_aider_executable
@ -88,7 +89,7 @@ def test_aider_config_flag(mocker):
"ra_aid.tools.programmer.run_interactive_command", return_value=(b"", 0)
)
run_programming_task("test instruction")
run_programming_task.invoke({"instructions": "test instruction"})
args = mock_run.call_args[0][0] # Get the first positional arg (command list)
assert "--config" in args
@ -96,6 +97,43 @@ def test_aider_config_flag(mocker):
assert args[config_index + 1] == "/path/to/config.yml"
def test_path_normalization_and_deduplication(mocker, tmp_path):
"""Test path normalization and deduplication in run_programming_task."""
# Create a temporary test file
test_file = tmp_path / "test.py"
test_file.write_text("")
new_file = tmp_path / "new.py"
# Mock dependencies
mocker.patch("ra_aid.tools.programmer._global_memory", {"related_files": {}})
mocker.patch("ra_aid.tools.programmer.get_aider_executable", return_value="/path/to/aider")
mock_run = mocker.patch("ra_aid.tools.programmer.run_interactive_command", return_value=(b"", 0))
# Test duplicate paths
run_programming_task.invoke({
"instructions": "test instruction",
"files": [str(test_file), str(test_file)] # Same path twice
})
# Get the command list passed to run_interactive_command
cmd_args = mock_run.call_args[0][0]
# Count occurrences of test_file path in command
test_file_count = sum(1 for arg in cmd_args if arg == str(test_file))
assert test_file_count == 1, "Expected exactly one instance of test_file path"
# Test mixed paths
run_programming_task.invoke({
"instructions": "test instruction",
"files": [str(test_file), str(new_file)] # Two different paths
})
# Get the command list from the second call
cmd_args = mock_run.call_args[0][0]
# Verify both paths are present exactly once
assert sum(1 for arg in cmd_args if arg == str(test_file)) == 1, "Expected one instance of test_file"
assert sum(1 for arg in cmd_args if arg == str(new_file)) == 1, "Expected one instance of new_file"
def test_get_aider_executable(mocker):
"""Test the get_aider_executable function."""
mock_sys = mocker.patch("ra_aid.tools.programmer.sys")