diff --git a/agent_logs.txt b/agent_logs.txt new file mode 100644 index 0000000..e69de29 diff --git a/cli.py b/cli.py old mode 100644 new mode 100755 diff --git a/install_globally.sh b/install_globally.sh new file mode 100755 index 0000000..5a02b19 --- /dev/null +++ b/install_globally.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# Script to install the agent-cli globally + +# Get the absolute path to the virtual environment +VENV_PATH="$(pwd)/.venv" +ACTIVATE_PATH="$VENV_PATH/bin/activate" +AGENT_CLI_PATH="$VENV_PATH/bin/agent-cli" + +# Check if the virtual environment exists +if [ ! -f "$ACTIVATE_PATH" ]; then + echo "Virtual environment not found. Running setup first..." + ./setup.sh +fi + +# Create a wrapper script in /usr/local/bin +WRAPPER_SCRIPT="/usr/local/bin/agent-cli" + +echo "Creating wrapper script at $WRAPPER_SCRIPT..." +cat > /tmp/agent-cli-wrapper << EOF +#!/bin/bash +# Wrapper script for agent-cli + +# Source the virtual environment +source "$ACTIVATE_PATH" + +# Run the agent-cli with all arguments passed to this script +"$AGENT_CLI_PATH" "\$@" +EOF + +# Make the wrapper script executable +chmod +x /tmp/agent-cli-wrapper + +# Move the wrapper script to /usr/local/bin (requires sudo) +echo "Installing wrapper script to $WRAPPER_SCRIPT (requires sudo)..." +sudo mv /tmp/agent-cli-wrapper "$WRAPPER_SCRIPT" + +echo "Installation complete! You can now run 'agent-cli' from anywhere." \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 08f2f0b..77dd9f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,12 @@ dependencies = [ "termcolor>=2.5.0", ] +[tool.setuptools] +packages = ["swebench_system", "tools", "utils", "prompts"] + +[project.scripts] +agent-cli = "swebench_system.cli:main" + [dependency-groups] dev = [ "ruff>=0.11.2", diff --git a/swebench_system/__init__.py b/swebench_system/__init__.py new file mode 100644 index 0000000..3dfa676 --- /dev/null +++ b/swebench_system/__init__.py @@ -0,0 +1,5 @@ +""" +SWE-bench System package. +""" + +__version__ = "0.1.0" \ No newline at end of file diff --git a/swebench_system/cli.py b/swebench_system/cli.py new file mode 100755 index 0000000..f50caa9 --- /dev/null +++ b/swebench_system/cli.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python3 +""" +CLI interface for the Agent. + +This script provides a command-line interface for interacting with the Agent. +It instantiates an Agent and prompts the user for input, which is then passed to the Agent. +""" + +import os +import argparse +from pathlib import Path +import sys +import logging + +from rich.console import Console +from rich.panel import Panel +from prompt_toolkit import prompt +from prompt_toolkit.history import InMemoryHistory + +import sys +import os +# Add the parent directory to sys.path +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) + +from tools.agent import Agent +from utils.workspace_manager import WorkspaceManager +from utils.llm_client import get_client +from prompts.instruction import INSTRUCTION_PROMPT + +MAX_OUTPUT_TOKENS_PER_TURN = 32768 +MAX_TURNS = 200 + + +def main(): + """Main entry point for the CLI.""" + # Parse command-line arguments + parser = argparse.ArgumentParser(description="CLI for interacting with the Agent") + parser.add_argument( + "--workspace", + type=str, + default=".", + help="Path to the workspace", + ) + parser.add_argument( + "--problem-statement", + type=str, + default=None, + help="Problem statement to pass to the agent. Makes the agent non-interactive.", + ) + parser.add_argument( + "--logs-path", + type=str, + default="agent_logs.txt", + help="Path to save logs", + ) + parser.add_argument( + "--needs-permission", + "-p", + help="Ask for permission before executing commands", + action="store_true", + default=False, + ) + parser.add_argument( + "--use-container-workspace", + type=str, + default=None, + help="(Optional) Path to the container workspace to run commands in.", + ) + parser.add_argument( + "--docker-container-id", + type=str, + default=None, + help="(Optional) Docker container ID to run commands in.", + ) + parser.add_argument( + "--minimize-stdout-logs", + help="Minimize the amount of logs printed to stdout.", + action="store_true", + default=False, + ) + + args = parser.parse_args() + + if os.path.exists(args.logs_path): + os.remove(args.logs_path) + logger_for_agent_logs = logging.getLogger("agent_logs") + logger_for_agent_logs.setLevel(logging.DEBUG) + logger_for_agent_logs.addHandler(logging.FileHandler(args.logs_path)) + if not args.minimize_stdout_logs: + logger_for_agent_logs.addHandler(logging.StreamHandler()) + else: + logger_for_agent_logs.propagate = False + + # Check if ANTHROPIC_API_KEY is set + if "ANTHROPIC_API_KEY" not in os.environ: + print("Error: ANTHROPIC_API_KEY environment variable is not set.") + print("Please set it to your Anthropic API key.") + sys.exit(1) + + # Initialize console + console = Console() + + # Print welcome message + if not args.minimize_stdout_logs: + console.print( + Panel( + "[bold]Agent CLI[/bold]\n\n" + + "Type your instructions to the agent. Press Ctrl+C to exit.\n" + + "Type 'exit' or 'quit' to end the session.", + title="[bold blue]Agent CLI[/bold blue]", + border_style="blue", + padding=(1, 2), + ) + ) + else: + logger_for_agent_logs.info( + "Agent CLI started. Waiting for user input. Press Ctrl+C to exit. Type 'exit' or 'quit' to end the session." + ) + + # Initialize LLM client + client = get_client( + "anthropic-direct", + model_name="claude-3-7-sonnet-20250219", + use_caching=True, + ) + + # Initialize workspace manager + workspace_path = Path(args.workspace).resolve() + workspace_manager = WorkspaceManager( + root=workspace_path, container_workspace=args.use_container_workspace + ) + + # Initialize agent + agent = Agent( + client=client, + workspace_manager=workspace_manager, + console=console, + logger_for_agent_logs=logger_for_agent_logs, + max_output_tokens_per_turn=MAX_OUTPUT_TOKENS_PER_TURN, + max_turns=MAX_TURNS, + ask_user_permission=args.needs_permission, + docker_container_id=args.docker_container_id, + ) + + if args.problem_statement is not None: + instruction = INSTRUCTION_PROMPT.format( + location=( + workspace_path + if args.use_container_workspace is None + else args.use_container_workspace + ), + pr_description=args.problem_statement, + ) + else: + instruction = None + + history = InMemoryHistory() + # Main interaction loop + try: + while True: + # Get user input + if instruction is None: + user_input = prompt("User input: ", history=history) + history.append_string(user_input) + + # Check for exit commands + if user_input.lower() in ["exit", "quit"]: + console.print("[bold]Exiting...[/bold]") + logger_for_agent_logs.info("Exiting...") + break + else: + user_input = instruction + logger_for_agent_logs.info( + f"User instruction:\n{user_input}\n-------------" + ) + + # Run the agent with the user input + logger_for_agent_logs.info("\nAgent is thinking...") + try: + result = agent.run_agent(user_input, resume=True) + logger_for_agent_logs.info(f"Agent: {result}") + except Exception as e: + logger_for_agent_logs.info(f"Error: {str(e)}") + + logger_for_agent_logs.info("\n" + "-" * 40 + "\n") + + if instruction is not None: + break + + except KeyboardInterrupt: + console.print("\n[bold]Session interrupted. Exiting...[/bold]") + + console.print("[bold]Goodbye![/bold]") + + +if __name__ == "__main__": + main()