SDK: support file download in launch_local_browser (#4199)
This commit is contained in:
committed by
GitHub
parent
fadfe0848c
commit
32fb2315f0
@@ -1,5 +1,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import os
|
import os
|
||||||
|
import pathlib
|
||||||
|
import tempfile
|
||||||
from typing import Any, overload
|
from typing import Any, overload
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
@@ -389,6 +391,7 @@ class Skyvern(AsyncSkyvern):
|
|||||||
headless: bool = False,
|
headless: bool = False,
|
||||||
port: int = DEFAULT_CDP_PORT,
|
port: int = DEFAULT_CDP_PORT,
|
||||||
args: list[str] | None = None,
|
args: list[str] | None = None,
|
||||||
|
user_data_dir: str | None = None,
|
||||||
) -> SkyvernBrowser:
|
) -> SkyvernBrowser:
|
||||||
"""Launch a new local Chromium browser with Chrome DevTools Protocol (CDP) enabled.
|
"""Launch a new local Chromium browser with Chrome DevTools Protocol (CDP) enabled.
|
||||||
|
|
||||||
@@ -404,13 +407,26 @@ class Skyvern(AsyncSkyvern):
|
|||||||
Returns:
|
Returns:
|
||||||
SkyvernBrowser: A browser instance with Skyvern capabilities.
|
SkyvernBrowser: A browser instance with Skyvern capabilities.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
playwright = await self._get_playwright()
|
playwright = await self._get_playwright()
|
||||||
launch_args = [f"--remote-debugging-port={port}"]
|
|
||||||
|
if user_data_dir:
|
||||||
|
user_data_path = pathlib.Path(user_data_dir)
|
||||||
|
else:
|
||||||
|
user_data_path = pathlib.Path(tempfile.gettempdir()) / "skyvern-browser"
|
||||||
|
|
||||||
|
launch_args = [
|
||||||
|
f"--remote-debugging-port={port}",
|
||||||
|
]
|
||||||
if args:
|
if args:
|
||||||
launch_args.extend(args)
|
launch_args.extend(args)
|
||||||
browser = await playwright.chromium.launch(headless=headless, args=launch_args)
|
|
||||||
|
browser_context = await playwright.chromium.launch_persistent_context(
|
||||||
|
user_data_dir=str(user_data_path),
|
||||||
|
headless=headless,
|
||||||
|
args=launch_args,
|
||||||
|
)
|
||||||
browser_address = f"http://localhost:{port}"
|
browser_address = f"http://localhost:{port}"
|
||||||
browser_context = browser.contexts[0] if browser.contexts else await browser.new_context()
|
|
||||||
return SkyvernBrowser(self, browser_context, browser_address=browser_address)
|
return SkyvernBrowser(self, browser_context, browser_address=browser_address)
|
||||||
|
|
||||||
async def connect_to_browser_over_cdp(self, cdp_url: str) -> SkyvernBrowser:
|
async def connect_to_browser_over_cdp(self, cdp_url: str) -> SkyvernBrowser:
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from urllib.parse import parse_qsl, urlparse
|
|||||||
|
|
||||||
import psutil
|
import psutil
|
||||||
import structlog
|
import structlog
|
||||||
from playwright.async_api import BrowserContext, ConsoleMessage, Download, Page, Playwright
|
from playwright.async_api import Browser, BrowserContext, ConsoleMessage, Download, Page, Playwright
|
||||||
|
|
||||||
from skyvern.config import settings
|
from skyvern.config import settings
|
||||||
from skyvern.constants import (
|
from skyvern.constants import (
|
||||||
@@ -33,7 +33,6 @@ from skyvern.webeye.browser_artifacts import BrowserArtifacts, VideoArtifact
|
|||||||
|
|
||||||
LOG = structlog.get_logger()
|
LOG = structlog.get_logger()
|
||||||
|
|
||||||
|
|
||||||
BrowserCleanupFunc = Callable[[], None] | None
|
BrowserCleanupFunc = Callable[[], None] | None
|
||||||
|
|
||||||
|
|
||||||
@@ -148,6 +147,23 @@ def initialize_download_dir() -> str:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def _apply_download_behaviour(browser: Browser) -> None:
|
||||||
|
context = ensure_context()
|
||||||
|
download_dir = get_download_dir(
|
||||||
|
context.run_id if context and context.run_id else context.workflow_run_id or context.task_id
|
||||||
|
)
|
||||||
|
cdp_session = await browser.new_browser_cdp_session()
|
||||||
|
await cdp_session.send(
|
||||||
|
"Browser.setDownloadBehavior",
|
||||||
|
{
|
||||||
|
"behavior": "allow",
|
||||||
|
"downloadPath": download_dir,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
LOG.info("setDownloadBehavior applied", download_dir=download_dir)
|
||||||
|
|
||||||
|
|
||||||
class BrowserContextCreator(Protocol):
|
class BrowserContextCreator(Protocol):
|
||||||
def __call__(
|
def __call__(
|
||||||
self, playwright: Playwright, proxy_location: ProxyLocation | None = None, **kwargs: dict[str, Any]
|
self, playwright: Playwright, proxy_location: ProxyLocation | None = None, **kwargs: dict[str, Any]
|
||||||
@@ -401,6 +417,7 @@ async def _create_headless_chromium(
|
|||||||
playwright,
|
playwright,
|
||||||
remote_browser_url=str(browser_address),
|
remote_browser_url=str(browser_address),
|
||||||
extra_http_headers=extra_http_headers,
|
extra_http_headers=extra_http_headers,
|
||||||
|
apply_download_behaviour=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
user_data_dir = make_temp_directory(prefix="skyvern_browser_")
|
user_data_dir = make_temp_directory(prefix="skyvern_browser_")
|
||||||
@@ -436,6 +453,7 @@ async def _create_headful_chromium(
|
|||||||
playwright,
|
playwright,
|
||||||
remote_browser_url=str(browser_address),
|
remote_browser_url=str(browser_address),
|
||||||
extra_http_headers=extra_http_headers,
|
extra_http_headers=extra_http_headers,
|
||||||
|
apply_download_behaviour=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
user_data_dir = make_temp_directory(prefix="skyvern_browser_")
|
user_data_dir = make_temp_directory(prefix="skyvern_browser_")
|
||||||
@@ -499,6 +517,7 @@ async def _create_cdp_connection_browser(
|
|||||||
playwright,
|
playwright,
|
||||||
remote_browser_url=str(browser_address),
|
remote_browser_url=str(browser_address),
|
||||||
extra_http_headers=extra_http_headers,
|
extra_http_headers=extra_http_headers,
|
||||||
|
apply_download_behaviour=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
browser_type = settings.BROWSER_TYPE
|
browser_type = settings.BROWSER_TYPE
|
||||||
@@ -555,6 +574,7 @@ async def _connect_to_cdp_browser(
|
|||||||
playwright: Playwright,
|
playwright: Playwright,
|
||||||
remote_browser_url: str,
|
remote_browser_url: str,
|
||||||
extra_http_headers: dict[str, str] | None = None,
|
extra_http_headers: dict[str, str] | None = None,
|
||||||
|
apply_download_behaviour: bool = False,
|
||||||
) -> tuple[BrowserContext, BrowserArtifacts, BrowserCleanupFunc]:
|
) -> tuple[BrowserContext, BrowserArtifacts, BrowserCleanupFunc]:
|
||||||
browser_args = BrowserContextFactory.build_browser_args(extra_http_headers=extra_http_headers)
|
browser_args = BrowserContextFactory.build_browser_args(extra_http_headers=extra_http_headers)
|
||||||
|
|
||||||
@@ -565,6 +585,9 @@ async def _connect_to_cdp_browser(
|
|||||||
LOG.info("Connecting browser CDP connection", remote_browser_url=remote_browser_url)
|
LOG.info("Connecting browser CDP connection", remote_browser_url=remote_browser_url)
|
||||||
browser = await playwright.chromium.connect_over_cdp(remote_browser_url)
|
browser = await playwright.chromium.connect_over_cdp(remote_browser_url)
|
||||||
|
|
||||||
|
if apply_download_behaviour:
|
||||||
|
await _apply_download_behaviour(browser)
|
||||||
|
|
||||||
contexts = browser.contexts
|
contexts = browser.contexts
|
||||||
browser_context = None
|
browser_context = None
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user