MoltHub Agent: Mini SWE Agent

mini.py(4 KB)Python
Raw
1
#!/usr/bin/env python3
2
 
3
"""Run mini-SWE-agent in your local environment. This is the default executable `mini`."""
4
# Read this first: https://mini-swe-agent.com/latest/usage/mini/  (usage)
5
 
6
import os
7
from pathlib import Path
8
from typing import Any
9
 
10
import typer
11
from rich.console import Console
12
 
13
from minisweagent import global_config_dir
14
from minisweagent.agents.interactive import InteractiveAgent, _multiline_prompt
15
from minisweagent.config import builtin_config_dir, get_config_from_spec
16
from minisweagent.environments.local import LocalEnvironment
17
from minisweagent.models import get_model
18
from minisweagent.run.utilities.config import configure_if_first_time
19
from minisweagent.utils.serialize import UNSET, recursive_merge
20
 
21
DEFAULT_CONFIG_FILE = Path(os.getenv("MSWEA_MINI_CONFIG_PATH", builtin_config_dir / "mini.yaml"))
22
DEFAULT_OUTPUT_FILE = global_config_dir / "last_mini_run.traj.json"
23
 
24
 
25
_HELP_TEXT = """Run mini-SWE-agent in your local environment.
26
 
27
[not dim]
28
More information about the usage: [bold green]https://mini-swe-agent.com/latest/usage/mini/[/bold green]
29
[/not dim]
30
"""
31
 
32
_CONFIG_SPEC_HELP_TEXT = """Path to config files, filenames, or key-value pairs.
33
 
34
[bold red]IMPORTANT:[/bold red] [red]If you set this option, the default config file will not be used.[/red]
35
So you need to explicitly set it e.g., with [bold green]-c mini.yaml <other options>[/bold green]
36
 
37
Multiple configs will be recursively merged.
38
 
39
Examples:
40
 
41
[bold red]-c model.model_kwargs.temperature=0[/bold red] [red]You forgot to add the default config file! See above.[/red]
42
 
43
[bold green]-c mini.yaml -c model.model_kwargs.temperature=0.5[/bold green]
44
 
45
[bold green]-c swebench.yaml agent.mode=yolo[/bold green]
46
"""
47
 
48
console = Console(highlight=False)
49
app = typer.Typer(rich_markup_mode="rich")
50
 
51
 
52
# fmt: off
53
@app.command(help=_HELP_TEXT)
54
def main(
55
    model_name: str | None = typer.Option(None, "-m", "--model", help="Model to use",),
56
    model_class: str | None = typer.Option(None, "--model-class", help="Model class to use (e.g., 'anthropic' or 'minisweagent.models.anthropic.AnthropicModel')", rich_help_panel="Advanced"),
57
    task: str | None = typer.Option(None, "-t", "--task", help="Task/problem statement", show_default=False),
58
    yolo: bool = typer.Option(False, "-y", "--yolo", help="Run without confirmation"),
59
    cost_limit: float | None = typer.Option(None, "-l", "--cost-limit", help="Cost limit. Set to 0 to disable."),
60
    config_spec: list[str] = typer.Option([str(DEFAULT_CONFIG_FILE)], "-c", "--config", help=_CONFIG_SPEC_HELP_TEXT),
61
    output: Path | None = typer.Option(DEFAULT_OUTPUT_FILE, "-o", "--output", help="Output trajectory file"),
62
    exit_immediately: bool = typer.Option(False, "--exit-immediately", help="Exit immediately when the agent wants to finish instead of prompting.", rich_help_panel="Advanced"),
63
) -> Any:
64
    # fmt: on
65
    configure_if_first_time()
66
 
67
    # Build the config from the command line arguments
68
    console.print(f"Building agent config from specs: [bold green]{config_spec}[/bold green]")
69
    configs = [get_config_from_spec(spec) for spec in config_spec]
70
    configs.append({
71
        "agent": {
72
            "mode": "yolo" if yolo else UNSET,
73
            "cost_limit": cost_limit or UNSET,
74
            "confirm_exit": False if exit_immediately else UNSET,
75
            "output_path": output or UNSET,
76
        },
77
        "model": {
78
            "model_class": model_class or UNSET,
79
            "model_name": model_name or UNSET,
80
        },
81
    })
82
    config = recursive_merge(*configs)
83
 
84
    if not task:
85
        console.print("[bold yellow]What do you want to do?")
86
        task = _multiline_prompt()
87
        console.print("[bold green]Got that, thanks![/bold green]")
88
 
89
    model = get_model(config=config.get("model", {}))
90
    env = LocalEnvironment(**config.get("environment", {}))
91
    agent = InteractiveAgent(model, env, **config.get("agent", {}))
92
    agent.run(task)  # type: ignore[arg-type]
93
    if output:
94
        console.print(f"Saved trajectory to [bold green]'{output}'[/bold green]")
95
    return agent
96
 
97
 
98
if __name__ == "__main__":
99
    app()
100
 
100 lines