File size: 5,509 Bytes
2f9dd8b 04be360 2f9dd8b 04be360 2f9dd8b 04be360 2f9dd8b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | #!/usr/bin/env python3
"""BeamArena CLI — Autonomous Coding & Evaluation Engine.
Run autonomous repairs, ingest 1M repositories, and evaluate benchmarks locally.
"""
import argparse
import json
import os
import sys
from core.client import BeamClient
from core.sandbox import Sandbox
from core.agent import AutonomousCodingAgent
from core.ingest import RepoIngestor
from scenarios import ALL_SCENARIOS
def cmd_solve(args):
client = BeamClient()
agent = AutonomousCodingAgent(client=client, max_turns=args.max_turns)
def on_start(turn_idx):
print(f"\n>>> TURN {turn_idx} STARTING...")
def on_complete(turn):
print(f">>> TURN {turn.turn_index} FINISHED. Tests Passed: {turn.passed}")
print(f" Reasoning Tokens: {turn.usage.reasoning_tokens} | Total: {turn.usage.total_tokens}")
for log in turn.edits_applied:
print(f" • {log}")
for cr in turn.command_results:
status = "PASS" if cr.exit_code == 0 else f"FAIL (code {cr.exit_code})"
print(f" $ {cr.command} -> {status}")
agent.on_turn_start = on_start
agent.on_turn_complete = on_complete
if args.task:
# Local custom repository repair mode
print("=" * 60)
print("⚡ [Beam-SWE] Autonomous Local Codebase Repair")
print(f"📋 Task: {args.task}")
print(f"🧪 Test Command: {args.test_cmd}")
print("=" * 60)
ingestor = RepoIngestor()
packed = ingestor.ingest_directory(".")
file_map = {p: packed.raw_files[p] for p in packed.files if p in packed.raw_files}
with Sandbox() as sb:
sb.load_files(file_map)
trace = agent.solve(
task_description=args.task,
sandbox=sb,
test_command=args.test_cmd,
scenario_id="local_custom",
)
print("\n" + "=" * 60)
print(f"RESULT: {'✅ SOLVED (TESTS GREEN)' if trace.resolved else '❌ FAILED'}")
print(f"Turns: {len(trace.turns)} | Time: {trace.wall_clock_seconds}s")
print(f"Total Tokens: {trace.total_tokens} (Reasoning: {trace.total_reasoning_tokens})")
print("=" * 60)
return
# Benchmark scenario mode
scen_id = args.scenario or "01_fastapi_auth"
scen = ALL_SCENARIOS.get(scen_id)
if not scen:
print(f"Error: Unknown scenario '{scen_id}'. Available: {list(ALL_SCENARIOS.keys())}")
sys.exit(1)
print("=" * 60)
print(f"⚡ [BeamArena] Solving Scenario: {scen.title}")
print(f"📁 Workspace: {len(scen.files)} files | Verification: {scen.test_command}")
print("=" * 60)
with Sandbox() as sb:
sb.load_files(scen.files)
trace = agent.solve(
task_description=scen.description,
sandbox=sb,
test_command=scen.test_command,
scenario_id=scen.id
)
print("\n" + "=" * 60)
print(f"RESULT: {'✅ SOLVED (TESTS GREEN)' if trace.resolved else '❌ FAILED'}")
print(f"Turns: {len(trace.turns)} | Time: {trace.wall_clock_seconds}s")
print(f"Total Tokens: {trace.total_tokens} (Reasoning: {trace.total_reasoning_tokens})")
print("=" * 60)
if not trace.resolved:
sys.exit(1)
def cmd_ingest(args):
target_dir = os.path.abspath(args.path)
if not os.path.exists(target_dir):
print(f"Error: Path does not exist: {target_dir}")
sys.exit(1)
print("=" * 60)
print(f"🌐 [BeamArena] Ingesting Codebase (1M Context Mode): {target_dir}")
print("=" * 60)
ingestor = RepoIngestor()
packed = ingestor.ingest_directory(target_dir)
print(f"Scanned Files: {len(packed.files)}")
print(f"Total Size: {round(packed.total_bytes / 1024, 2)} KB")
print(f"Estimated Tokens: ~{packed.estimated_tokens:,} tokens (Capacity: 1,048,576)")
print("\n--- File Tree Sample ---")
tree_preview = "\n".join(packed.file_tree.splitlines()[:25])
print(tree_preview)
if len(packed.file_tree.splitlines()) > 25:
print("... (truncated)")
def cmd_list(args):
print("Available Scenarios in BeamArena:")
for s_id, s in ALL_SCENARIOS.items():
print(f" • {s_id:25} [{s.difficulty:6}] {s.title}")
def main():
parser = argparse.ArgumentParser(description="BeamArena Autonomous CLI")
subparsers = parser.add_subparsers(dest="command")
# Solve
solve_parser = subparsers.add_parser("solve", help="Run autonomous self-healing on a scenario or local codebase")
solve_parser.add_argument("--scenario", "-s", help="Benchmark scenario ID to solve")
solve_parser.add_argument("--task", help="Custom task description to solve in current directory")
solve_parser.add_argument("--test-cmd", default="pytest", help="Verification command to execute (default: pytest)")
solve_parser.add_argument("--max-turns", "-t", type=int, default=3, help="Max repair turns")
# Ingest
ingest_parser = subparsers.add_parser("ingest", help="Ingest a local repository into 1M context")
ingest_parser.add_argument("path", help="Local directory path to ingest")
# List
subparsers.add_parser("list", help="List all benchmark scenarios")
args = parser.parse_args()
if args.command == "solve":
cmd_solve(args)
elif args.command == "ingest":
cmd_ingest(args)
elif args.command == "list":
cmd_list(args)
else:
parser.print_help()
if __name__ == "__main__":
main()
|