diff --git a/openhands/runtime/browser/browser_env.py b/openhands/runtime/browser/browser_env.py index 55e3ce1890..c8d09d9c2b 100644 --- a/openhands/runtime/browser/browser_env.py +++ b/openhands/runtime/browser/browser_env.py @@ -1,8 +1,10 @@ import atexit import json import multiprocessing +import os import time import uuid +from pathlib import Path import browsergym.core # noqa F401 (we register the openended task as a gym environment) import gymnasium as gym @@ -67,6 +69,16 @@ class BrowserEnv: raise BrowserInitException('Failed to start browser environment.') def browser_process(self) -> None: + def _is_local_runtime() -> bool: + runtime_flag = os.getenv('RUNTIME', '').lower() + return runtime_flag == 'local' + + # Default Playwright cache for local runs only; do not override in docker + if _is_local_runtime() and 'PLAYWRIGHT_BROWSERS_PATH' not in os.environ: + os.environ['PLAYWRIGHT_BROWSERS_PATH'] = str( + Path.home() / '.cache' / 'playwright' + ) + if self.eval_mode: assert self.browsergym_eval_env is not None logger.info('Initializing browser env for web browsing evaluation.') @@ -87,6 +99,11 @@ class BrowserEnv: ) env = gym.make(self.browsergym_eval_env, tags_to_mark='all', timeout=100000) else: + downloads_path = os.getenv('BROWSERGYM_DOWNLOAD_DIR') + if not downloads_path and _is_local_runtime(): + downloads_path = str(Path.home() / '.cache' / 'browsergym-downloads') + if not downloads_path: + downloads_path = '/workspace/.downloads/' env = gym.make( 'browsergym/openended', task_kwargs={'start_url': 'about:blank', 'goal': 'PLACEHOLDER_GOAL'}, @@ -96,7 +113,7 @@ class BrowserEnv: tags_to_mark='all', timeout=100000, pw_context_kwargs={'accept_downloads': True}, - pw_chromium_kwargs={'downloads_path': '/workspace/.downloads/'}, + pw_chromium_kwargs={'downloads_path': downloads_path}, ) obs, info = env.reset() diff --git a/openhands/runtime/impl/local/local_runtime.py b/openhands/runtime/impl/local/local_runtime.py index f6ef26a1cf..cf81b222eb 100644 --- a/openhands/runtime/impl/local/local_runtime.py +++ b/openhands/runtime/impl/local/local_runtime.py @@ -249,7 +249,22 @@ class LocalRuntime(ActionExecutionClient): ) else: # Set up workspace directory + # For local runtime, prefer a stable host path over /workspace defaults. + if ( + self.config.workspace_base is None + and self.config.runtime + and self.config.runtime.lower() == 'local' + ): + env_base = os.getenv('LOCAL_WORKSPACE_BASE') + if env_base: + self.config.workspace_base = os.path.abspath(env_base) + else: + self.config.workspace_base = os.path.abspath( + os.path.join(os.getcwd(), 'workspace', 'local') + ) + if self.config.workspace_base is not None: + os.makedirs(self.config.workspace_base, exist_ok=True) logger.warning( f'Workspace base path is set to {self.config.workspace_base}. ' 'It will be used as the path for the agent to run in. '