diff --git a/.changeset/spectral-labrador-of-tolerance.md b/.changeset/spectral-labrador-of-tolerance.md new file mode 100644 index 0000000..68cb094 --- /dev/null +++ b/.changeset/spectral-labrador-of-tolerance.md @@ -0,0 +1,5 @@ +--- +"stagehand": patch +--- + +Fixing downloads behavior for use_api=false diff --git a/pyproject.toml b/pyproject.toml index fbc5ab1..24eb8e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ dependencies = [ "rich>=13.7.0", "openai>=1.83.0,<1.99.6", "anthropic>=0.51.0", - "litellm>=1.72.0", + "litellm>=1.72.0,<1.75.0", "nest-asyncio>=1.6.0", ] [[project.authors]] diff --git a/stagehand/main.py b/stagehand/main.py index 4a201ad..063efb0 100644 --- a/stagehand/main.py +++ b/stagehand/main.py @@ -29,7 +29,7 @@ from .logging import StagehandLogger, default_log_handler from .metrics import StagehandFunctionName, StagehandMetrics from .page import StagehandPage -from .utils import make_serializable +from .utils import get_download_path, make_serializable load_dotenv() @@ -511,6 +511,7 @@ async def init(self): self.logger, ) self._playwright_page = self._page._page + except Exception: await self.close() raise @@ -531,6 +532,7 @@ async def init(self): self.logger, ) self._playwright_page = self._page._page + except Exception: await self.close() raise @@ -538,6 +540,23 @@ async def init(self): # Should not happen due to __init__ validation raise RuntimeError(f"Invalid env value: {self.env}") + # Set up download behavior via CDP + try: + # Create CDP session for the page + cdp_session = await self._context.new_cdp_session(self._playwright_page) + # Enable download behavior + await cdp_session.send( + "Browser.setDownloadBehavior", + { + "behavior": "allow", + "downloadPath": get_download_path(self), + "eventsEnabled": True, + }, + ) + self.logger.debug("Set up CDP download behavior") + except Exception as e: + self.logger.warning(f"Failed to set up CDP download behavior: {str(e)}") + self._initialized = True def agent(self, **kwargs) -> Agent: diff --git a/stagehand/utils.py b/stagehand/utils.py index 7a69a63..37f4978 100644 --- a/stagehand/utils.py +++ b/stagehand/utils.py @@ -1,4 +1,5 @@ import inspect +import os from typing import Any, Union, get_args, get_origin from pydantic import AnyUrl, BaseModel, Field, HttpUrl, create_model @@ -530,3 +531,15 @@ def make_serializable(obj): elif isinstance(obj, dict): return {key: make_serializable(value) for key, value in obj.items()} return obj + + +def get_download_path(stagehand): + if stagehand.env == "BROWSERBASE": + return "downloads" + else: + if stagehand.local_browser_launch_options.get("downloadPath"): + return stagehand.local_browser_launch_options["downloadPath"] + else: + path = os.path.join(os.getcwd(), "downloads") + os.makedirs(path, exist_ok=True) + return path