Merge pull request #5 from leonj1/feat_aider_args
FEAT support future aider flags
This commit is contained in:
commit
90e5924ab2
35
README.md
35
README.md
|
|
@ -1,15 +1,15 @@
|
||||||
```ascii
|
```ascii
|
||||||
|
|
||||||
██▀███ ▄▄▄ ▄▄▄ ██▓▓█████▄
|
██▀███ ▄▄▄ ▄▄▄ ██▓▓█████▄
|
||||||
▓██ ▒ ██▒▒████▄ ▒████▄ ▓██▒▒██▀ ██▌
|
▓██ ▒ ██▒▒████▄ ▒████▄ ▓██▒▒██▀ ██▌
|
||||||
▓██ ░▄█ ▒▒██ ▀█▄ ▒██ ▀█▄ ▒██▒░██ █▌
|
▓██ ░▄█ ▒▒██ ▀█▄ ▒██ ▀█▄ ▒██▒░██ █▌
|
||||||
▒██▀▀█▄ ░██▄▄▄▄██ ░██▄▄▄▄██ ░██░░▓█▄ ▌
|
▒██▀▀█▄ ░██▄▄▄▄██ ░██▄▄▄▄██ ░██░░▓█▄ ▌
|
||||||
░██▓ ▒██▒ ▓█ ▓██▒ ██▓ ▓█ ▓██▒░██░░▒████▓
|
░██▓ ▒██▒ ▓█ ▓██▒ ██▓ ▓█ ▓██▒░██░░▒████▓
|
||||||
░ ▒▓ ░▒▓░ ▒▒ ▓▒█░ ▒▓▒ ▒▒ ▓▒█░░▓ ▒▒▓ ▒
|
░ ▒▓ ░▒▓░ ▒▒ ▓▒█░ ▒▓▒ ▒▒ ▓▒█░░▓ ▒▒▓ ▒
|
||||||
░▒ ░ ▒░ ▒ ▒▒ ░ ░▒ ▒ ▒▒ ░ ▒ ░ ░ ▒ ▒
|
░▒ ░ ▒░ ▒ ▒▒ ░ ░▒ ▒ ▒▒ ░ ▒ ░ ░ ▒ ▒
|
||||||
░░ ░ ░ ▒ ░ ░ ▒ ▒ ░ ░ ░ ░
|
░░ ░ ░ ▒ ░ ░ ▒ ▒ ░ ░ ░ ░
|
||||||
░ ░ ░ ░ ░ ░ ░ ░
|
░ ░ ░ ░ ░ ░ ░ ░
|
||||||
░ ░
|
░ ░
|
||||||
```
|
```
|
||||||
|
|
||||||
[](https://www.python.org)
|
[](https://www.python.org)
|
||||||
|
|
@ -76,7 +76,7 @@ What sets RA.Aid apart is its ability to handle complex programming tasks that e
|
||||||
1. **Research** 🔍 - Gather and analyze information
|
1. **Research** 🔍 - Gather and analyze information
|
||||||
2. **Planning** 📋 - Develop execution strategy
|
2. **Planning** 📋 - Develop execution strategy
|
||||||
3. **Implementation** ⚡ - Execute the plan with AI assistance
|
3. **Implementation** ⚡ - Execute the plan with AI assistance
|
||||||
|
|
||||||
Each stage is powered by dedicated AI agents and specialized toolsets.
|
Each stage is powered by dedicated AI agents and specialized toolsets.
|
||||||
- **Advanced AI Integration**: Built on LangChain and leverages the latest LLMs for natural language understanding and generation.
|
- **Advanced AI Integration**: Built on LangChain and leverages the latest LLMs for natural language understanding and generation.
|
||||||
- **Human-in-the-Loop Interaction**: Optional mode that enables the agent to ask you questions during task execution, ensuring higher accuracy and better handling of complex tasks that may require your input or clarification
|
- **Human-in-the-Loop Interaction**: Optional mode that enables the agent to ask you questions during task execution, ensuring higher accuracy and better handling of complex tasks that may require your input or clarification
|
||||||
|
|
@ -260,7 +260,7 @@ RA.Aid supports multiple providers through environment variables:
|
||||||
Expert Tool Environment Variables:
|
Expert Tool Environment Variables:
|
||||||
- `EXPERT_OPENAI_API_KEY`: API key for expert tool using OpenAI provider
|
- `EXPERT_OPENAI_API_KEY`: API key for expert tool using OpenAI provider
|
||||||
- `EXPERT_ANTHROPIC_API_KEY`: API key for expert tool using Anthropic provider
|
- `EXPERT_ANTHROPIC_API_KEY`: API key for expert tool using Anthropic provider
|
||||||
- `EXPERT_OPENROUTER_API_KEY`: API key for expert tool using OpenRouter provider
|
- `EXPERT_OPENROUTER_API_KEY`: API key for expert tool using OpenRouter provider
|
||||||
- `EXPERT_OPENAI_API_BASE`: Base URL for expert tool using OpenAI-compatible provider
|
- `EXPERT_OPENAI_API_BASE`: Base URL for expert tool using OpenAI-compatible provider
|
||||||
|
|
||||||
You can set these permanently in your shell's configuration file (e.g., `~/.bashrc` or `~/.zshrc`):
|
You can set these permanently in your shell's configuration file (e.g., `~/.bashrc` or `~/.zshrc`):
|
||||||
|
|
@ -279,9 +279,7 @@ export OPENROUTER_API_KEY=your_api_key_here
|
||||||
export OPENAI_API_BASE=your_api_base_url
|
export OPENAI_API_BASE=your_api_base_url
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: The expert tool defaults to OpenAI's o1-preview model with the OpenAI provider, but this can be configured using the --expert-provider flag along with the corresponding EXPERT_*_KEY environment variables.
|
### Custom Model Examples
|
||||||
|
|
||||||
#### Custom Model Examples
|
|
||||||
|
|
||||||
1. **Using Anthropic (Default)**
|
1. **Using Anthropic (Default)**
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -320,6 +318,17 @@ Note: The expert tool defaults to OpenAI's o1-preview model with the OpenAI prov
|
||||||
ra-aid -m "Your task" --expert-provider openai --expert-model o1-preview
|
ra-aid -m "Your task" --expert-provider openai --expert-model o1-preview
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Aider specific Environment Variables you can add:
|
||||||
|
|
||||||
|
- `AIDER_FLAGS`: Optional comma-separated list of flags to pass to the underlying aider tool (e.g., "yes-always,dark-mode")
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Optional: Configure aider behavior
|
||||||
|
export AIDER_FLAGS="yes-always,dark-mode,no-auto-commits"
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: For `AIDER_FLAGS`, you can specify flags with or without the leading `--`. Multiple flags should be comma-separated, and spaces around flags are automatically handled. For example, both `"yes-always,dark-mode"` and `"--yes-always, --dark-mode"` are valid.
|
||||||
|
|
||||||
**Important Notes:**
|
**Important Notes:**
|
||||||
- Performance varies between models. The default Claude 3 Sonnet model currently provides the best and most reliable results.
|
- Performance varies between models. The default Claude 3 Sonnet model currently provides the best and most reliable results.
|
||||||
- Model configuration is done via command line arguments: `--provider` and `--model`
|
- Model configuration is done via command line arguments: `--provider` and `--model`
|
||||||
|
|
@ -329,7 +338,7 @@ Note: The expert tool defaults to OpenAI's o1-preview model with the OpenAI prov
|
||||||
|
|
||||||
RA.Aid implements a three-stage architecture for handling development and research tasks:
|
RA.Aid implements a three-stage architecture for handling development and research tasks:
|
||||||
|
|
||||||
1. **Research Stage**:
|
1. **Research Stage**:
|
||||||
- Gathers information and context
|
- Gathers information and context
|
||||||
- Analyzes requirements
|
- Analyzes requirements
|
||||||
- Identifies key components and dependencies
|
- Identifies key components and dependencies
|
||||||
|
|
|
||||||
|
|
@ -44,54 +44,91 @@ Returns: { "output": stdout+stderr, "return_code": 0 if success, "success": True
|
||||||
"--no-auto-commits",
|
"--no-auto-commits",
|
||||||
"--dark-mode",
|
"--dark-mode",
|
||||||
"--no-suggest-shell-commands",
|
"--no-suggest-shell-commands",
|
||||||
"-m"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# if environment variable AIDER_FLAGS exists then parse
|
||||||
|
if 'AIDER_FLAGS' in os.environ:
|
||||||
|
# wrap in try catch in case of any error and log the error
|
||||||
|
try:
|
||||||
|
command.extend(parse_aider_flags(os.environ['AIDER_FLAGS']))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error parsing AIDER_FLAGS: {e}")
|
||||||
|
|
||||||
|
# ensure message aider argument is always present
|
||||||
|
command.append("-m")
|
||||||
|
|
||||||
command.append(input.instructions)
|
command.append(input.instructions)
|
||||||
|
|
||||||
if input.files:
|
if input.files:
|
||||||
command.extend(input.files)
|
command.extend(input.files)
|
||||||
|
|
||||||
# Create a pretty display of what we're doing
|
# Create a pretty display of what we're doing
|
||||||
task_display = [
|
task_display = [
|
||||||
"## Instructions\n",
|
"## Instructions\n",
|
||||||
f"{input.instructions}\n"
|
f"{input.instructions}\n"
|
||||||
]
|
]
|
||||||
|
|
||||||
if input.files:
|
if input.files:
|
||||||
task_display.extend([
|
task_display.extend([
|
||||||
"\n## Files\n",
|
"\n## Files\n",
|
||||||
*[f"- `{file}`\n" for file in input.files]
|
*[f"- `{file}`\n" for file in input.files]
|
||||||
])
|
])
|
||||||
|
|
||||||
markdown_content = "".join(task_display)
|
markdown_content = "".join(task_display)
|
||||||
console.print(Panel(Markdown(markdown_content), title="🤖 Aider Task", border_style="bright_blue"))
|
console.print(Panel(Markdown(markdown_content), title="🤖 Aider Task", border_style="bright_blue"))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Run the command interactively
|
# Run the command interactively
|
||||||
print()
|
print()
|
||||||
output, return_code = run_interactive_command(command)
|
output, return_code = run_interactive_command(command)
|
||||||
print()
|
print()
|
||||||
|
|
||||||
# Return structured output
|
# Return structured output
|
||||||
return {
|
return {
|
||||||
"output": truncate_output(output.decode() if output else ""),
|
"output": truncate_output(output.decode() if output else ""),
|
||||||
"return_code": return_code,
|
"return_code": return_code,
|
||||||
"success": return_code == 0
|
"success": return_code == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print()
|
print()
|
||||||
error_text = Text()
|
error_text = Text()
|
||||||
error_text.append("Error running programming task:\n", style="bold red")
|
error_text.append("Error running programming task:\n", style="bold red")
|
||||||
error_text.append(str(e), style="red")
|
error_text.append(str(e), style="red")
|
||||||
console.print(error_text)
|
console.print(error_text)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"output": str(e),
|
"output": str(e),
|
||||||
"return_code": 1,
|
"return_code": 1,
|
||||||
"success": False
|
"success": False
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def parse_aider_flags(aider_flags: str) -> List[str]:
|
||||||
|
"""Parse a string of aider flags into a list of flags.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
aider_flags: A string containing comma-separated flags, with or without leading dashes.
|
||||||
|
Can contain spaces around flags and commas.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of flags with proper '--' prefix.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
>>> parse_aider_flags("yes-always,dark-mode")
|
||||||
|
['--yes-always', '--dark-mode']
|
||||||
|
>>> parse_aider_flags("--yes-always, --dark-mode")
|
||||||
|
['--yes-always', '--dark-mode']
|
||||||
|
>>> parse_aider_flags("")
|
||||||
|
[]
|
||||||
|
"""
|
||||||
|
if not aider_flags.strip():
|
||||||
|
return []
|
||||||
|
|
||||||
|
# Split by comma and strip whitespace
|
||||||
|
flags = [flag.strip() for flag in aider_flags.split(",")]
|
||||||
|
|
||||||
|
# Add '--' prefix if not present and filter out empty flags
|
||||||
|
return [f"--{flag.lstrip('-')}" for flag in flags if flag.strip()]
|
||||||
|
|
||||||
# Export the functions
|
# Export the functions
|
||||||
__all__ = ['run_programming_task']
|
__all__ = ['run_programming_task']
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
import pytest
|
||||||
|
from ra_aid.tools.programmer import parse_aider_flags
|
||||||
|
|
||||||
|
# Test cases for parse_aider_flags function
|
||||||
|
test_cases = [
|
||||||
|
# Test case format: (input_string, expected_output, test_description)
|
||||||
|
(
|
||||||
|
"yes-always,dark-mode",
|
||||||
|
["--yes-always", "--dark-mode"],
|
||||||
|
"basic comma separated flags without dashes"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"--yes-always,--dark-mode",
|
||||||
|
["--yes-always", "--dark-mode"],
|
||||||
|
"comma separated flags with dashes"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"yes-always, dark-mode",
|
||||||
|
["--yes-always", "--dark-mode"],
|
||||||
|
"comma separated flags with space"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"--yes-always, --dark-mode",
|
||||||
|
["--yes-always", "--dark-mode"],
|
||||||
|
"comma separated flags with dashes and space"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"",
|
||||||
|
[],
|
||||||
|
"empty string"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
" yes-always , dark-mode ",
|
||||||
|
["--yes-always", "--dark-mode"],
|
||||||
|
"flags with extra whitespace"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"--yes-always",
|
||||||
|
["--yes-always"],
|
||||||
|
"single flag with dashes"
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"yes-always",
|
||||||
|
["--yes-always"],
|
||||||
|
"single flag without dashes"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("input_flags,expected,description", test_cases)
|
||||||
|
def test_parse_aider_flags(input_flags, expected, description):
|
||||||
|
"""Table-driven test for parse_aider_flags function."""
|
||||||
|
result = parse_aider_flags(input_flags)
|
||||||
|
assert result == expected, f"Failed test case: {description}"
|
||||||
Loading…
Reference in New Issue