fix embed pdf frame bug (#4613)
This commit is contained in:
@@ -113,14 +113,6 @@ class ImaginaryFileUrl(SkyvernException):
|
|||||||
super().__init__(f"File url {file_url} is imaginary.")
|
super().__init__(f"File url {file_url} is imaginary.")
|
||||||
|
|
||||||
|
|
||||||
class DownloadedFileNotFound(SkyvernException):
|
|
||||||
def __init__(self, downloaded_path: str, download_url: str | None = None) -> None:
|
|
||||||
message = f"Downloaded file does not exist at path: {downloaded_path}. This may indicate the download failed silently or the file was removed."
|
|
||||||
if download_url:
|
|
||||||
message += f" Download URL: {download_url}"
|
|
||||||
super().__init__(message)
|
|
||||||
|
|
||||||
|
|
||||||
class MissingBrowserState(SkyvernException):
|
class MissingBrowserState(SkyvernException):
|
||||||
def __init__(self, task_id: str | None = None, workflow_run_id: str | None = None) -> None:
|
def __init__(self, task_id: str | None = None, workflow_run_id: str | None = None) -> None:
|
||||||
task_str = f"task_id={task_id}" if task_id else ""
|
task_str = f"task_id={task_id}" if task_id else ""
|
||||||
|
|||||||
@@ -263,6 +263,7 @@ class UploadFileAction(WebAction):
|
|||||||
# This action is deprecated in 'extract-actions' prompt. Only used for the download action triggered by the code.
|
# This action is deprecated in 'extract-actions' prompt. Only used for the download action triggered by the code.
|
||||||
class DownloadFileAction(Action):
|
class DownloadFileAction(Action):
|
||||||
action_type: ActionType = ActionType.DOWNLOAD_FILE
|
action_type: ActionType = ActionType.DOWNLOAD_FILE
|
||||||
|
download: bool = True
|
||||||
file_name: str
|
file_name: str
|
||||||
byte: Annotated[bytes | None, Field(exclude=True)] = None # bytes data
|
byte: Annotated[bytes | None, Field(exclude=True)] = None # bytes data
|
||||||
download_url: str | None = None # URL to download file from
|
download_url: str | None = None # URL to download file from
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import asyncio
|
|||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import shutil
|
|
||||||
import time
|
import time
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import uuid
|
import uuid
|
||||||
@@ -26,7 +25,6 @@ from skyvern.constants import (
|
|||||||
)
|
)
|
||||||
from skyvern.errors.errors import TOTPExpiredError
|
from skyvern.errors.errors import TOTPExpiredError
|
||||||
from skyvern.exceptions import (
|
from skyvern.exceptions import (
|
||||||
DownloadedFileNotFound,
|
|
||||||
EmptySelect,
|
EmptySelect,
|
||||||
ErrEmptyTweakValue,
|
ErrEmptyTweakValue,
|
||||||
ErrFoundSelectableElement,
|
ErrFoundSelectableElement,
|
||||||
@@ -63,9 +61,6 @@ from skyvern.forge import app
|
|||||||
from skyvern.forge.prompts import prompt_engine
|
from skyvern.forge.prompts import prompt_engine
|
||||||
from skyvern.forge.sdk.api.files import (
|
from skyvern.forge.sdk.api.files import (
|
||||||
check_downloading_files_and_wait_for_download_to_complete,
|
check_downloading_files_and_wait_for_download_to_complete,
|
||||||
)
|
|
||||||
from skyvern.forge.sdk.api.files import download_file as download_file_api
|
|
||||||
from skyvern.forge.sdk.api.files import (
|
|
||||||
get_download_dir,
|
get_download_dir,
|
||||||
list_files_in_directory,
|
list_files_in_directory,
|
||||||
)
|
)
|
||||||
@@ -95,6 +90,7 @@ from skyvern.webeye.actions.actions import (
|
|||||||
CheckboxAction,
|
CheckboxAction,
|
||||||
ClickAction,
|
ClickAction,
|
||||||
CompleteVerifyResult,
|
CompleteVerifyResult,
|
||||||
|
DownloadFileAction,
|
||||||
InputOrSelectContext,
|
InputOrSelectContext,
|
||||||
InputTextAction,
|
InputTextAction,
|
||||||
ScrapeResult,
|
ScrapeResult,
|
||||||
@@ -401,7 +397,9 @@ class ActionHandler:
|
|||||||
) -> list[ActionResult]:
|
) -> list[ActionResult]:
|
||||||
browser_state = app.BROWSER_MANAGER.get_for_task(task.task_id, workflow_run_id=task.workflow_run_id)
|
browser_state = app.BROWSER_MANAGER.get_for_task(task.task_id, workflow_run_id=task.workflow_run_id)
|
||||||
# TODO: maybe support all action types in the future(?)
|
# TODO: maybe support all action types in the future(?)
|
||||||
trigger_download_action = isinstance(action, (SelectOptionAction, ClickAction)) and action.download
|
trigger_download_action = (
|
||||||
|
isinstance(action, (SelectOptionAction, ClickAction, DownloadFileAction)) and action.download
|
||||||
|
)
|
||||||
if not trigger_download_action:
|
if not trigger_download_action:
|
||||||
results = await ActionHandler._handle_action(
|
results = await ActionHandler._handle_action(
|
||||||
scraped_page=scraped_page,
|
scraped_page=scraped_page,
|
||||||
@@ -1632,35 +1630,20 @@ async def handle_download_file_action(
|
|||||||
full_file_path=full_file_path,
|
full_file_path=full_file_path,
|
||||||
file_size=len(action.byte),
|
file_size=len(action.byte),
|
||||||
)
|
)
|
||||||
return [ActionSuccess(download_triggered=True)]
|
return [ActionSuccess()]
|
||||||
|
|
||||||
# Priority 2: If download_url is provided, download from URL
|
# Priority 2: If download_url is provided, download from URL
|
||||||
if action.download_url is not None:
|
if action.download_url is not None:
|
||||||
downloaded_path = await download_file_api(action.download_url)
|
# the URL is usally requiring login credentials/cookides, so we should use browser navigation to access the URL instead of downloading the file directly
|
||||||
# Check if the downloaded file actually exists
|
try:
|
||||||
if not os.path.exists(downloaded_path):
|
await page.goto(action.download_url, timeout=settings.BROWSER_LOADING_TIMEOUT_MS)
|
||||||
LOG.error(
|
except Exception as e:
|
||||||
"DownloadFileAction: Downloaded file path does not exist",
|
error = str(e)
|
||||||
action=action,
|
# some cases use this method to download a file. but it will be redirected away soon
|
||||||
downloaded_path=downloaded_path,
|
# and agent will run into ABORTED error.
|
||||||
download_url=action.download_url,
|
# some cases playwright will raise error like "Page.goto: Download is starting"
|
||||||
full_file_path=full_file_path,
|
if "net::ERR_ABORTED" not in error and "Page.goto: Download is starting" not in error:
|
||||||
)
|
raise e
|
||||||
return [ActionFailure(DownloadedFileNotFound(downloaded_path, action.download_url))]
|
|
||||||
|
|
||||||
# Move the downloaded file to the target location
|
|
||||||
# If the downloaded file has a different name, use it; otherwise use the specified file_name
|
|
||||||
if os.path.basename(downloaded_path) != file_name:
|
|
||||||
# Copy to target location with specified file_name
|
|
||||||
shutil.copy2(downloaded_path, full_file_path)
|
|
||||||
# Optionally remove the temporary file
|
|
||||||
try:
|
|
||||||
os.remove(downloaded_path)
|
|
||||||
except Exception:
|
|
||||||
pass # Ignore errors when removing temp file
|
|
||||||
else:
|
|
||||||
# Move to target location
|
|
||||||
shutil.move(downloaded_path, full_file_path)
|
|
||||||
|
|
||||||
LOG.info(
|
LOG.info(
|
||||||
"DownloadFileAction: Downloaded file from URL",
|
"DownloadFileAction: Downloaded file from URL",
|
||||||
@@ -1668,9 +1651,9 @@ async def handle_download_file_action(
|
|||||||
full_file_path=full_file_path,
|
full_file_path=full_file_path,
|
||||||
download_url=action.download_url,
|
download_url=action.download_url,
|
||||||
)
|
)
|
||||||
return [ActionSuccess(download_triggered=True)]
|
return [ActionSuccess()]
|
||||||
|
|
||||||
return [ActionSuccess(download_triggered=False)]
|
return [ActionSuccess()]
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.exception(
|
LOG.exception(
|
||||||
|
|||||||
Reference in New Issue
Block a user