better totp failure reason and error code (#3472)
This commit is contained in:
@@ -5,7 +5,7 @@ from datetime import datetime, timedelta
|
|||||||
import structlog
|
import structlog
|
||||||
|
|
||||||
from skyvern.config import settings
|
from skyvern.config import settings
|
||||||
from skyvern.exceptions import NoTOTPVerificationCodeFound
|
from skyvern.exceptions import FailedToGetTOTPVerificationCode, NoTOTPVerificationCodeFound
|
||||||
from skyvern.forge import app
|
from skyvern.forge import app
|
||||||
from skyvern.forge.sdk.core.aiohttp_helper import aiohttp_post
|
from skyvern.forge.sdk.core.aiohttp_helper import aiohttp_post
|
||||||
from skyvern.forge.sdk.core.security import generate_skyvern_signature
|
from skyvern.forge.sdk.core.security import generate_skyvern_signature
|
||||||
@@ -96,7 +96,17 @@ async def _get_verification_code_from_url(
|
|||||||
"x-skyvern-signature": signature,
|
"x-skyvern-signature": signature,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
}
|
}
|
||||||
json_resp = await aiohttp_post(url=url, data=request_data, headers=headers, raise_exception=False)
|
try:
|
||||||
|
json_resp = await aiohttp_post(url=url, data=request_data, headers=headers, raise_exception=False)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.error("Failed to get verification code from url", exc_info=True)
|
||||||
|
raise FailedToGetTOTPVerificationCode(
|
||||||
|
task_id=task_id,
|
||||||
|
workflow_run_id=workflow_run_id,
|
||||||
|
workflow_id=workflow_permanent_id,
|
||||||
|
totp_verification_url=url,
|
||||||
|
reason=str(e),
|
||||||
|
)
|
||||||
return json_resp.get("verification_code", None)
|
return json_resp.get("verification_code", None)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ class SkyvernDefinedError(BaseModel):
|
|||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f"{self.reasoning}(error_code={self.error_code})"
|
return f"{self.reasoning}(error_code={self.error_code})"
|
||||||
|
|
||||||
|
def to_user_defined_error(self) -> UserDefinedError:
|
||||||
|
return UserDefinedError(error_code=self.error_code, reasoning=self.reasoning, confidence_float=1.0)
|
||||||
|
|
||||||
|
|
||||||
class ReachMaxStepsError(SkyvernDefinedError):
|
class ReachMaxStepsError(SkyvernDefinedError):
|
||||||
error_code: str = "REACH_MAX_STEPS"
|
error_code: str = "REACH_MAX_STEPS"
|
||||||
@@ -26,3 +29,19 @@ class ReachMaxStepsError(SkyvernDefinedError):
|
|||||||
class ReachMaxRetriesError(SkyvernDefinedError):
|
class ReachMaxRetriesError(SkyvernDefinedError):
|
||||||
error_code: str = "REACH_MAX_RETRIES"
|
error_code: str = "REACH_MAX_RETRIES"
|
||||||
reasoning: str = "The agent has reached the maximum number of retries. It might be an issue with the agent. Please reach out to the Skyvern team for support."
|
reasoning: str = "The agent has reached the maximum number of retries. It might be an issue with the agent. Please reach out to the Skyvern team for support."
|
||||||
|
|
||||||
|
|
||||||
|
class GetTOTPVerificationCodeError(SkyvernDefinedError):
|
||||||
|
error_code: str = "OTP_ERROR"
|
||||||
|
reasoning: str = (
|
||||||
|
"Failed to get TOTP verification code. Please confirm the TOTP functionality is working correctly on your side."
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, *, reason: str | None = None) -> None:
|
||||||
|
reasoning = f"Failed to get TOTP verification code. Reason: {reason}" if reason else self.reasoning
|
||||||
|
super().__init__(reasoning=reasoning)
|
||||||
|
|
||||||
|
|
||||||
|
class TimeoutGetTOTPVerificationCodeError(SkyvernDefinedError):
|
||||||
|
error_code: str = "OTP_TIMEOUT"
|
||||||
|
reasoning: str = "Timeout getting TOTP verification code."
|
||||||
|
|||||||
@@ -695,6 +695,33 @@ class NoTOTPVerificationCodeFound(SkyvernHTTPException):
|
|||||||
super().__init__(msg)
|
super().__init__(msg)
|
||||||
|
|
||||||
|
|
||||||
|
class FailedToGetTOTPVerificationCode(SkyvernException):
|
||||||
|
reason: str | None = None
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
task_id: str | None = None,
|
||||||
|
workflow_run_id: str | None = None,
|
||||||
|
workflow_id: str | None = None,
|
||||||
|
totp_verification_url: str | None = None,
|
||||||
|
totp_identifier: str | None = None,
|
||||||
|
reason: str | None = None,
|
||||||
|
) -> None:
|
||||||
|
self.reason = reason
|
||||||
|
msg = "Failed to get TOTP verification code."
|
||||||
|
if task_id:
|
||||||
|
msg += f" task_id={task_id}"
|
||||||
|
if workflow_run_id:
|
||||||
|
msg += f" workflow_run_id={workflow_run_id}"
|
||||||
|
if workflow_id:
|
||||||
|
msg += f" workflow_id={workflow_id}"
|
||||||
|
if totp_verification_url:
|
||||||
|
msg += f" totp_verification_url={totp_verification_url}"
|
||||||
|
if totp_identifier:
|
||||||
|
msg += f" totp_identifier={totp_identifier}"
|
||||||
|
super().__init__(f"Failed to get TOTP verification code. reason: {reason}")
|
||||||
|
|
||||||
|
|
||||||
class SkyvernContextWindowExceededError(SkyvernException):
|
class SkyvernContextWindowExceededError(SkyvernException):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
message = "Context window exceeded. Please contact support@skyvern.com for help."
|
message = "Context window exceeded. Please contact support@skyvern.com for help."
|
||||||
|
|||||||
@@ -27,12 +27,19 @@ from skyvern.constants import (
|
|||||||
ScrapeType,
|
ScrapeType,
|
||||||
)
|
)
|
||||||
from skyvern.core.totp import poll_verification_code
|
from skyvern.core.totp import poll_verification_code
|
||||||
from skyvern.errors.errors import ReachMaxRetriesError, ReachMaxStepsError, UserDefinedError
|
from skyvern.errors.errors import (
|
||||||
|
GetTOTPVerificationCodeError,
|
||||||
|
ReachMaxRetriesError,
|
||||||
|
ReachMaxStepsError,
|
||||||
|
TimeoutGetTOTPVerificationCodeError,
|
||||||
|
UserDefinedError,
|
||||||
|
)
|
||||||
from skyvern.exceptions import (
|
from skyvern.exceptions import (
|
||||||
BrowserSessionNotFound,
|
BrowserSessionNotFound,
|
||||||
BrowserStateMissingPage,
|
BrowserStateMissingPage,
|
||||||
DownloadFileMaxWaitingTime,
|
DownloadFileMaxWaitingTime,
|
||||||
EmptyScrapePage,
|
EmptyScrapePage,
|
||||||
|
FailedToGetTOTPVerificationCode,
|
||||||
FailedToNavigateToUrl,
|
FailedToNavigateToUrl,
|
||||||
FailedToParseActionInstruction,
|
FailedToParseActionInstruction,
|
||||||
FailedToSendWebhook,
|
FailedToSendWebhook,
|
||||||
@@ -1012,6 +1019,21 @@ class ForgeAgent:
|
|||||||
action_order=0,
|
action_order=0,
|
||||||
reasoning="No TOTP verification code found. Going to terminate.",
|
reasoning="No TOTP verification code found. Going to terminate.",
|
||||||
intention="No TOTP verification code found. Going to terminate.",
|
intention="No TOTP verification code found. Going to terminate.",
|
||||||
|
errors=[TimeoutGetTOTPVerificationCodeError().to_user_defined_error()],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
except FailedToGetTOTPVerificationCode as e:
|
||||||
|
actions = [
|
||||||
|
TerminateAction(
|
||||||
|
reasoning=f"Failed to get TOTP verification code. Going to terminate. Reason: {e.reason}",
|
||||||
|
intention=f"Failed to get TOTP verification code. Going to terminate. Reason: {e.reason}",
|
||||||
|
organization_id=task.organization_id,
|
||||||
|
workflow_run_id=task.workflow_run_id,
|
||||||
|
task_id=task.task_id,
|
||||||
|
step_id=step.step_id,
|
||||||
|
step_order=step.order,
|
||||||
|
action_order=0,
|
||||||
|
errors=[GetTOTPVerificationCodeError(reason=e.reason).to_user_defined_error()],
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from pydantic import ValidationError
|
|||||||
|
|
||||||
from skyvern.constants import SCROLL_AMOUNT_MULTIPLIER
|
from skyvern.constants import SCROLL_AMOUNT_MULTIPLIER
|
||||||
from skyvern.core.totp import poll_verification_code
|
from skyvern.core.totp import poll_verification_code
|
||||||
from skyvern.exceptions import NoTOTPVerificationCodeFound, UnsupportedActionType
|
from skyvern.exceptions import FailedToGetTOTPVerificationCode, NoTOTPVerificationCodeFound, UnsupportedActionType
|
||||||
from skyvern.forge import app
|
from skyvern.forge import app
|
||||||
from skyvern.forge.prompts import prompt_engine
|
from skyvern.forge.prompts import prompt_engine
|
||||||
from skyvern.forge.sdk.core import skyvern_context
|
from skyvern.forge.sdk.core import skyvern_context
|
||||||
@@ -829,6 +829,13 @@ async def generate_cua_fallback_actions(
|
|||||||
reasoning=reasoning,
|
reasoning=reasoning,
|
||||||
intention=reasoning,
|
intention=reasoning,
|
||||||
)
|
)
|
||||||
|
except FailedToGetTOTPVerificationCode as e:
|
||||||
|
reasoning_suffix = f"Failed to get verification code. Reason: {e.reason}"
|
||||||
|
reasoning = f"{reasoning}. {reasoning_suffix}" if reasoning else reasoning_suffix
|
||||||
|
action = TerminateAction(
|
||||||
|
reasoning=reasoning,
|
||||||
|
intention=reasoning,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
action = TerminateAction(
|
action = TerminateAction(
|
||||||
reasoning=reasoning,
|
reasoning=reasoning,
|
||||||
|
|||||||
Reference in New Issue
Block a user