openra-rl / openra_env /cli /main.py
github-actions[bot]
Sync from GitHub ac82c3e
02f4a63
"""CLI entry point for openra-rl."""
import argparse
import sys
def main() -> None:
parser = argparse.ArgumentParser(
prog="openra-rl",
description="Play Red Alert with AI agents",
)
parser.add_argument(
"--version", action="store_true",
help="Print version and exit",
)
subparsers = parser.add_subparsers(dest="command")
# โ”€โ”€ play โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
play_parser = subparsers.add_parser(
"play", help="Run the LLM agent against the game",
)
play_parser.add_argument(
"--provider", choices=["openrouter", "ollama", "lmstudio"],
help="LLM provider (overrides saved config)",
)
play_parser.add_argument("--model", help="Model ID")
play_parser.add_argument("--api-key", help="API key for LLM endpoint")
play_parser.add_argument(
"--difficulty", choices=["easy", "normal", "hard"], default="normal",
help="AI opponent difficulty (default: normal)",
)
play_parser.add_argument("--verbose", action="store_true", help="Verbose output")
play_parser.add_argument("--port", type=int, default=8000, help="Game server port (default: 8000)")
play_parser.add_argument("--server-url", help="Connect to existing server URL (skip Docker)")
play_parser.add_argument("--local", action="store_true", help="Run server locally instead of Docker (for developers)")
play_parser.add_argument("--version", dest="image_version", default=None, help="Docker image version to use (default: latest)")
# โ”€โ”€ config โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
subparsers.add_parser("config", help="Re-run the setup wizard")
# โ”€โ”€ server โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
server_parser = subparsers.add_parser("server", help="Manage the game server")
server_sub = server_parser.add_subparsers(dest="server_command")
start_parser = server_sub.add_parser("start", help="Start the game server")
start_parser.add_argument("--port", type=int, default=8000, help="Port (default: 8000)")
start_parser.add_argument(
"--difficulty", choices=["easy", "normal", "hard"], default="normal",
)
start_parser.add_argument("--detach", action="store_true", default=True, help="Run in background (default)")
server_sub.add_parser("stop", help="Stop the game server")
server_sub.add_parser("status", help="Show server status")
logs_parser = server_sub.add_parser("logs", help="Show server logs")
logs_parser.add_argument("--follow", "-f", action="store_true", help="Follow log output")
# โ”€โ”€ mcp-server โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
mcp_parser = subparsers.add_parser("mcp-server", help="Start MCP stdio server")
mcp_parser.add_argument("--server-url", help="Game server URL")
mcp_parser.add_argument("--port", type=int, default=8000, help="Game server port (default: 8000)")
# โ”€โ”€ replay โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
replay_parser = subparsers.add_parser("replay", help="Manage and watch game replays")
replay_sub = replay_parser.add_subparsers(dest="replay_command")
watch_parser = replay_sub.add_parser("watch", help="Watch a replay in your browser (via VNC)")
watch_parser.add_argument("file", nargs="?", default=None, help="Replay file (local path or container path; default: latest)")
watch_parser.add_argument("--port", type=int, default=6080, help="noVNC port (default: 6080)")
watch_parser.add_argument(
"--resolution", default=None,
help="Replay viewer resolution WxH (default: 1280x960)",
)
watch_parser.add_argument(
"--render", dest="render_mode", choices=["auto", "gpu", "cpu"], default=None,
help="Render backend: auto tries GPU then CPU (default: auto)",
)
watch_parser.add_argument(
"--vnc-quality", type=int, default=None,
help="VNC quality 0-9, higher = sharper (default: 8)",
)
watch_parser.add_argument(
"--vnc-compression", type=int, default=None,
help="VNC compression 0-9, higher = smaller (default: 4)",
)
watch_parser.add_argument(
"--cpus", type=int, default=None,
help="CPU cores for software rendering (default: 4, 0 = all available).",
)
replay_sub.add_parser("list", help="List available replays")
replay_sub.add_parser("copy", help="Copy replays from Docker to ~/.openra-rl/replays/")
replay_sub.add_parser("stop", help="Stop the replay viewer")
# โ”€โ”€ bench โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
bench_parser = subparsers.add_parser("bench", help="Benchmark leaderboard tools")
bench_sub = bench_parser.add_subparsers(dest="bench_command")
bench_submit_parser = bench_sub.add_parser("submit", help="Upload game result JSON to the leaderboard")
bench_submit_parser.add_argument("json_file", type=str, help="Path to bench export JSON file")
bench_submit_parser.add_argument("--agent-name", default=None, help="Override agent name")
bench_submit_parser.add_argument("--agent-type", default=None, help="Override agent type (Scripted/LLM/RL)")
bench_submit_parser.add_argument("--agent-url", default=None, help="GitHub/project URL")
bench_submit_parser.add_argument("--replay", default=None, help="Path to .orarep replay file")
bench_submit_parser.add_argument(
"--bench-url", default=None,
help="Bench leaderboard URL (default: https://openra-rl-openra-bench.hf.space)",
)
# โ”€โ”€ doctor โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
subparsers.add_parser("doctor", help="Check system prerequisites")
# โ”€โ”€ version โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
subparsers.add_parser("version", help="Print version")
args = parser.parse_args()
# Handle --version at top level
if args.version:
from openra_env.cli.commands import cmd_version
cmd_version()
return
if args.command is None:
parser.print_help()
sys.exit(0)
# Dispatch
from openra_env.cli import commands
if args.command == "play":
commands.cmd_play(
provider=args.provider,
model=args.model,
api_key=args.api_key,
difficulty=args.difficulty,
verbose=args.verbose,
port=args.port,
server_url=args.server_url,
local=args.local,
image_version=args.image_version,
)
elif args.command == "config":
commands.cmd_config()
elif args.command == "server":
if args.server_command == "start":
commands.cmd_server_start(
port=args.port,
difficulty=args.difficulty,
detach=args.detach,
)
elif args.server_command == "stop":
commands.cmd_server_stop()
elif args.server_command == "status":
commands.cmd_server_status()
elif args.server_command == "logs":
commands.cmd_server_logs(follow=args.follow)
else:
server_parser.print_help()
elif args.command == "replay":
if args.replay_command == "watch":
commands.cmd_replay_watch(
file=args.file,
port=args.port,
resolution=args.resolution,
render_mode=args.render_mode,
vnc_quality=args.vnc_quality,
vnc_compression=args.vnc_compression,
cpu_cores=args.cpus,
)
elif args.replay_command == "list":
commands.cmd_replay_list()
elif args.replay_command == "copy":
commands.cmd_replay_copy()
elif args.replay_command == "stop":
commands.cmd_replay_stop()
else:
replay_parser.print_help()
elif args.command == "mcp-server":
commands.cmd_mcp_server(
server_url=args.server_url,
port=args.port,
)
elif args.command == "bench":
if args.bench_command == "submit":
from openra_env.bench_submit import main as bench_submit_main
# Patch sys.argv so bench_submit's argparse sees the right args
submit_argv = ["openra-rl bench submit", args.json_file]
if args.agent_name:
submit_argv += ["--agent-name", args.agent_name]
if args.agent_type:
submit_argv += ["--agent-type", args.agent_type]
if args.agent_url:
submit_argv += ["--agent-url", args.agent_url]
if args.replay:
submit_argv += ["--replay", args.replay]
if args.bench_url:
submit_argv += ["--bench-url", args.bench_url]
sys.argv = submit_argv
bench_submit_main()
else:
bench_parser.print_help()
elif args.command == "doctor":
commands.cmd_doctor()
elif args.command == "version":
commands.cmd_version()
else:
parser.print_help()
if __name__ == "__main__":
main()