hanabhi/gridworld-env
0
1#!/usr/bin/env python32# Copyright (c) Meta Platforms, Inc. and affiliates.3# All rights reserved.4#5# This source code is licensed under the BSD-style license found in the6# LICENSE file in the root directory of this source tree.7 8"""9Example usage of the OpenApp Environment.10 11This script demonstrates how to use the OpenApp environment with OpenEnv.12It can be run in two modes:131. With Docker: Uses the Docker image to run the environment142. Local: Directly uses the OpenAppEnvironment class (requires OpenApps installed)15 16Usage:17 # Run with Docker (recommended)18 python examples/openapp_example.py --mode docker19 20 # Run locally without Docker21 python examples/openapp_example.py --mode local22 23 # Run with custom number of steps24 python examples/openapp_example.py --mode docker --num-steps 2025 26Visualization Options:27 # To SEE the browser window and watch agent interactions in real-time:28 #29 # Terminal 1: Start OpenApps server with visible browser30 cd OpenApps31 python OpenApps/launch.py browsergym_env_args.headless=False32 33 # Terminal 2: Run your agent code34 export OPENAPPS_URL=http://localhost:500135 python examples/openapp_example.py --mode local36 37 # Or access the web interface directly in your browser:38 # - OpenApps: http://localhost:500139 # - Calendar: http://localhost:5001/calendar40 # - Todo: http://localhost:5001/todo41 # - Messenger: http://localhost:5001/messages42 # - Maps: http://localhost:5001/maps43 44 # Docker mode web interface45 # - Web UI: http://localhost:8000/web46 # - API docs: http://localhost:8000/docs47 48Important:49 The browser visualization is controlled by the OpenApps SERVER, not the client.50 You must launch the server with 'browsergym_env_args.headless=False' to see51 the browser window.52"""53 54import argparse55import os56import sys57import time58from pathlib import Path59 60# Add src to path61sys.path.insert(0, str(Path(__file__).parent.parent))62 63 64def run_with_docker(num_steps: int = 15, headless: bool = True):65 """Run OpenApp environment using Docker container."""66 from openapp_env import OpenAppAction, OpenAppEnv67 68 print("=" * 70)69 print("Starting OpenApp environment with Docker...")70 print(f"Headless mode: {headless}")71 print("=" * 70)72 73 try:74 # Create environment from Docker image75 env = OpenAppEnv.from_docker_image("openapp-env:latest")76 77 # Reset to start a new session78 print("\n[1/4] Resetting environment...")79 result = env.reset()80 print(f"✓ Environment reset")81 print(f" Starting URL: {result.observation.url}")82 print(f" Open pages: {len(result.observation.open_pages_urls)}")83 print(f" HTML length: {len(result.observation.html)} characters")84 85 # Example actions to demonstrate different action types86 actions = [87 {88 "description": "Navigate to calendar app",89 "action": OpenAppAction(90 action_type="goto", url="http://localhost:5001/calendar"91 ),92 },93 {94 "description": "Scroll down to see more content",95 "action": OpenAppAction(action_type="scroll", direction="down"),96 },97 {98 "description": "Navigate to todo app",99 "action": OpenAppAction(100 action_type="goto", url="http://localhost:5001/todo"101 ),102 },103 {104 "description": "Navigate to messenger app",105 "action": OpenAppAction(106 action_type="goto", url="http://localhost:5001/messenger"107 ),108 },109 {110 "description": "Navigate to maps app",111 "action": OpenAppAction(112 action_type="goto", url="http://localhost:5001/maps"113 ),114 },115 {116 "description": "Navigate back to home",117 "action": OpenAppAction(118 action_type="goto", url="http://localhost:5001"119 ),120 },121 ]122 123 # Run demonstration steps124 print(f"\n[2/4] Running {min(num_steps, len(actions))} demonstration steps...")125 for i, action_info in enumerate(actions[:num_steps]):126 print(f"\nStep {i+1}: {action_info['description']}")127 print(f" Action type: {action_info['action'].action_type}")128 129 result = env.step(action_info["action"])130 131 print(f" ✓ Action executed")132 print(f" Current URL: {result.observation.url}")133 print(f" Reward: {result.reward}")134 print(f" Done: {result.done}")135 136 if result.observation.last_action_error:137 print(f" ⚠️ Error: {result.observation.last_action_error}")138 139 # Check app state if available140 if result.observation.app_state:141 print(142 f" App state keys: {list(result.observation.app_state.keys())}"143 )144 145 # Small delay for readability146 time.sleep(0.5)147 148 if result.done:149 print(f"\n✓ Episode finished at step {i+1}!")150 break151 152 # Get final state153 print(f"\n[3/4] Getting final environment state...")154 state = env.state()155 print(f"✓ Final state:")156 print(f" Episode ID: {state.episode_id}")157 print(f" Total steps: {state.step_count}")158 159 # Summary160 print(f"\n[4/4] Session Summary:")161 print(f" Steps taken: {state.step_count}")162 print(f" Final URL: {result.observation.url}")163 print(f" Episode complete: {result.done}")164 165 # Web interface info166 print(f"\n" + "=" * 70)167 print(f"💡 TIP: Access the web interface at http://localhost:8000/web")168 print(f" - Interactive UI for manual testing")169 print(f" - API documentation at http://localhost:8000/docs")170 print(f"=" * 70)171 172 except Exception as e:173 print(f"\n❌ Error: {e}")174 import traceback175 176 traceback.print_exc()177 return 1178 finally:179 print("\n[Cleanup] Closing environment...")180 env.close()181 print("✓ Environment closed")182 183 return 0184 185 186def run_local(num_steps: int = 15, headless: bool = True):187 """Run OpenApp environment locally without Docker."""188 189 # Check if OPENAPPS_URL is set190 if not os.environ.get("OPENAPPS_URL"):191 print("=" * 70)192 print("❌ ERROR: OPENAPPS_URL not set")193 print("=" * 70)194 print("\nLocal mode requires OpenApps server to be running.")195 print("\nPlease follow these steps:")196 print("\n1. Start OpenApps server in a separate terminal:")197 print(" cd /path/to/OpenApps")198 print(" uv run launch.py")199 print("\n2. Set the OPENAPPS_URL environment variable:")200 print(" export OPENAPPS_URL=http://localhost:5001")201 print("\n3. Run this script again:")202 print(" python examples/openapp_example.py --mode local")203 print("\nAlternatively, use Docker mode (recommended):")204 print(" python examples/openapp_example.py --mode docker")205 print("=" * 70)206 return 1207 208 try:209 # NOTE: This example imports from the server module directly for local development.210 # This is intentional for local testing/debugging where no HTTP server is involved.211 # In production, use the client API (OpenAppEnv) which communicates over HTTP/WebSocket.212 # See run_with_docker() for the recommended production pattern.213 from openapp_env.models import OpenAppAction214 from openapp_env.server.openapp_environment import OpenAppEnvironment215 except ImportError as e:216 print(f"❌ Error importing local modules: {e}")217 print("\nMake sure you have installed the environment:")218 print(" cd envs/openapp_env")219 print(" pip install -e .")220 return 1221 222 print("=" * 70)223 print("Starting OpenApp environment locally...")224 print(f"Using OpenApps server at: {os.environ.get('OPENAPPS_URL')}")225 print(f"Headless mode: {headless}")226 print("=" * 70)227 228 try:229 # Create environment locally230 print("\n[1/4] Initializing local environment...")231 env = OpenAppEnvironment(232 openapps_url=os.environ.get("OPENAPPS_URL"),233 headless=headless,234 max_steps=50,235 )236 237 # Reset environment238 print("\n[2/4] Resetting environment...")239 result = env.reset()240 print(f"✓ Environment reset")241 print(f" Starting URL: {result.url}")242 print(f" HTML length: {len(result.html)} characters")243 244 # Take some example steps245 print(f"\n[3/4] Running {num_steps} steps...")246 for i in range(num_steps):247 # Simple actions for demonstration248 actions = [249 OpenAppAction(250 action_type="goto", url=f"{os.environ.get('OPENAPPS_URL')}/calendar"251 ),252 OpenAppAction(action_type="scroll", direction="down"),253 OpenAppAction(254 action_type="goto", url=f"{os.environ.get('OPENAPPS_URL')}/todo"255 ),256 OpenAppAction(action_type="noop"),257 ]258 259 action = actions[i % len(actions)]260 result = env.step(action)261 262 if i % 5 == 0 or result.done:263 print(f"Step {i+1}:")264 print(f" Action: {action.action_type}")265 print(f" URL: {result.url}")266 print(f" Reward: {result.reward}")267 print(f" Done: {result.done}")268 269 if result.done:270 print(f"\n✓ Episode finished at step {i+1}!")271 break272 273 # Get final state274 print(f"\n[4/4] Final state:")275 print(f" Episode ID: {env.state.episode_id}")276 print(f" Total steps: {env.state.step_count}")277 278 except Exception as e:279 print(f"\n❌ Error: {e}")280 import traceback281 282 traceback.print_exc()283 return 1284 finally:285 print("\n[Cleanup] Closing environment...")286 env.close()287 print("✓ Environment closed")288 289 return 0290 291 292def main():293 parser = argparse.ArgumentParser(294 description="OpenApp Environment Example",295 formatter_class=argparse.RawDescriptionHelpFormatter,296 epilog="""297Examples:298 # Run with Docker (recommended)299 python examples/openapp_example.py --mode docker300 301 # Run locally without Docker302 python examples/openapp_example.py --mode local303 304 # Show browser window to visualize agent actions305 python examples/openapp_example.py --mode local --show-browser306 307 # Run with custom number of steps308 python examples/openapp_example.py --mode docker --num-steps 20309 310Visualization:311 - Use --show-browser to see the browser window and watch agent interactions312 - Access OpenApps web interface at http://localhost:5001 (when server is running)313 - Docker mode web interface: http://localhost:8000/web314 315Note:316 - Docker mode requires: docker build -t openapp-env:latest -f envs/openapp_env/server/Dockerfile envs/openapp_env317 - Local mode requires: pip install -e envs/openapp_env && playwright install chromium318 """,319 )320 321 parser.add_argument(322 "--mode",323 choices=["docker", "local"],324 default="docker",325 help="Run mode: 'docker' (recommended) or 'local'",326 )327 parser.add_argument(328 "--num-steps", type=int, default=15, help="Number of steps to run (default: 15)"329 )330 parser.add_argument(331 "--headless",332 action="store_true",333 default=False,334 help="Run browser in headless mode (no visible window)",335 )336 parser.add_argument(337 "--show-browser",338 action="store_true",339 default=False,340 help="Show browser window (opposite of --headless, easier to remember)",341 )342 343 args = parser.parse_args()344 345 # Determine headless mode: default to True unless --show-browser is used346 headless = not args.show_browser if args.show_browser else args.headless347 348 print("\n" + "=" * 70)349 print("OpenApp Environment Example")350 print("=" * 70)351 print(f"Mode: {args.mode}")352 print(f"Steps: {args.num_steps}")353 print(f"Headless: {headless}")354 355 if args.mode == "docker":356 return run_with_docker(args.num_steps, headless)357 else:358 return run_local(args.num_steps, headless)359 360 361if __name__ == "__main__":362 sys.exit(main())363 