mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-21 16:18:55 +00:00
Fix headed browser sessions being killed after every turn
The per-turn `_cleanup_task_resources` unconditionally calls `cleanup_browser`, closing the browser window immediately after each bot reply. This makes headed mode (`AGENT_BROWSER_HEADED=1`) unusable — the window flashes up and disappears on every response. This mirrors the existing VM persistence pattern: skip per-turn cleanup when headed mode is active and let the inactivity reaper handle idle sessions instead. Full-session teardown on gateway shutdown remains unconditional. Also adds `browser.headed` config.yaml support and passes `--headed` to agent-browser in local mode when configured, so users don't need to rely solely on the `AGENT_BROWSER_HEADED` env var. Closes #11020 (lead bug)
This commit is contained in:
parent
581e92e42c
commit
29899c2aa9
2 changed files with 50 additions and 2 deletions
|
|
@ -2125,6 +2125,11 @@ def cleanup_task_resources(agent, task_id: str) -> None:
|
|||
``terminal.lifetime_seconds`` is exceeded. Non-persistent backends are
|
||||
torn down per-turn as before to prevent resource leakage (the original
|
||||
intent of this hook for the Morph backend, see commit fbd3a2fd).
|
||||
|
||||
Skips ``cleanup_browser`` in headed mode so the browser window stays
|
||||
visible between turns. The inactivity reaper in
|
||||
``browser_tool._cleanup_inactive_browser_sessions`` still handles
|
||||
idle sessions.
|
||||
"""
|
||||
try:
|
||||
if is_persistent_env(task_id):
|
||||
|
|
@ -2139,7 +2144,14 @@ def cleanup_task_resources(agent, task_id: str) -> None:
|
|||
if agent.verbose_logging:
|
||||
logger.warning(f"Failed to cleanup VM for task {task_id}: {e}")
|
||||
try:
|
||||
_ra().cleanup_browser(task_id)
|
||||
if os.environ.get("AGENT_BROWSER_HEADED"):
|
||||
if agent.verbose_logging:
|
||||
logging.debug(
|
||||
f"Skipping per-turn cleanup_browser for headed session {task_id}; "
|
||||
f"idle reaper will handle it."
|
||||
)
|
||||
else:
|
||||
_ra().cleanup_browser(task_id)
|
||||
except Exception as e:
|
||||
if agent.verbose_logging:
|
||||
logger.warning(f"Failed to cleanup browser for task {task_id}: {e}")
|
||||
|
|
|
|||
|
|
@ -885,6 +885,40 @@ def _get_browser_engine() -> str:
|
|||
return _cached_browser_engine
|
||||
|
||||
|
||||
_cached_headed_mode: Optional[bool] = None
|
||||
_headed_mode_resolved = False
|
||||
|
||||
|
||||
def _is_headed_mode() -> bool:
|
||||
"""Return True when the browser should launch in headed (visible) mode.
|
||||
|
||||
Reads ``config["browser"]["headed"]`` with ``AGENT_BROWSER_HEADED`` env
|
||||
var as fallback. Result is cached after the first call.
|
||||
"""
|
||||
global _cached_headed_mode, _headed_mode_resolved
|
||||
if _headed_mode_resolved:
|
||||
return _cached_headed_mode # type: ignore[return-value]
|
||||
|
||||
_headed_mode_resolved = True
|
||||
_cached_headed_mode = False
|
||||
|
||||
try:
|
||||
from hermes_cli.config import read_raw_config
|
||||
cfg = read_raw_config()
|
||||
val = cfg.get("browser", {}).get("headed")
|
||||
if val is not None:
|
||||
_cached_headed_mode = str(val).strip().lower() in ("true", "1", "yes")
|
||||
except Exception as e:
|
||||
logger.debug("Could not read browser.headed from config: %s", e)
|
||||
|
||||
if not _cached_headed_mode:
|
||||
env_val = os.environ.get("AGENT_BROWSER_HEADED", "").strip()
|
||||
if env_val and env_val.lower() in ("true", "1", "yes"):
|
||||
_cached_headed_mode = True
|
||||
|
||||
return _cached_headed_mode
|
||||
|
||||
|
||||
def _should_inject_engine(engine: str) -> bool:
|
||||
"""Return True when the engine flag should be added to agent-browser commands.
|
||||
|
||||
|
|
@ -2347,8 +2381,10 @@ def _run_browser_command(
|
|||
# --session creates a local browser instance and silently ignores --cdp.
|
||||
backend_args = ["--cdp", session_info["cdp_url"]]
|
||||
else:
|
||||
# Local mode — launch a headless Chromium instance
|
||||
# Local mode — launch Chromium (headless by default, headed when configured)
|
||||
backend_args = ["--session", session_info["session_name"]]
|
||||
if _is_headed_mode():
|
||||
backend_args.append("--headed")
|
||||
|
||||
# Lightpanda engine injection (local mode only, agent-browser v0.25.3+).
|
||||
# Use the resolved session backend rather than global cloud-provider state:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue