fix(agent): improve error handling for get_agent_soul method
This commit is contained in:
@@ -1429,11 +1429,25 @@ async def get_agent_soul(
|
||||
target_agent_id=agent_id,
|
||||
)
|
||||
coordination = GatewayCoordinationService(session)
|
||||
try:
|
||||
return await coordination.get_agent_soul(
|
||||
board=board,
|
||||
target_agent_id=agent_id,
|
||||
correlation_id=f"soul.read:{board.id}:{agent_id}",
|
||||
)
|
||||
except HTTPException as exc:
|
||||
# Keep explicit auth/not-found responses, but avoid relaying internal 5xx details.
|
||||
if exc.status_code >= status.HTTP_500_INTERNAL_SERVER_ERROR:
|
||||
raise HTTPException(
|
||||
status_code=exc.status_code,
|
||||
detail="Gateway SOUL read failed",
|
||||
) from exc
|
||||
raise
|
||||
except Exception as exc: # pragma: no cover - defensive API boundary guard
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_502_BAD_GATEWAY,
|
||||
detail="Gateway SOUL read failed",
|
||||
) from exc
|
||||
|
||||
|
||||
@router.put(
|
||||
|
||||
@@ -237,7 +237,6 @@ async def _authenticate_clerk_request(request: Request) -> RequestState:
|
||||
|
||||
async def _fetch_clerk_profile(clerk_user_id: str) -> tuple[str | None, str | None]:
|
||||
secret = settings.clerk_secret_key.strip()
|
||||
secret_kind = secret.split("_", maxsplit=1)[0] if "_" in secret else "unknown"
|
||||
server_url = _normalize_clerk_server_url(settings.clerk_api_url or "")
|
||||
clerk_user_id_log = clerk_user_id[-6:] if clerk_user_id else ""
|
||||
|
||||
@@ -252,28 +251,24 @@ async def _fetch_clerk_profile(clerk_user_id: str) -> tuple[str | None, str | No
|
||||
return email, name
|
||||
except ClerkErrors as exc:
|
||||
logger.warning(
|
||||
"auth.clerk.profile.fetch_failed clerk_user_id=%s reason=clerk_errors "
|
||||
"secret_kind=%s error_type=%s",
|
||||
"auth.clerk.profile.fetch_failed clerk_user_id=%s reason=clerk_errors " "error_type=%s",
|
||||
clerk_user_id_log,
|
||||
secret_kind,
|
||||
exc.__class__.__name__,
|
||||
)
|
||||
except SDKError as exc:
|
||||
logger.warning(
|
||||
"auth.clerk.profile.fetch_failed clerk_user_id=%s status=%s reason=sdk_error "
|
||||
"server_url=%s secret_kind=%s",
|
||||
"server_url=%s",
|
||||
clerk_user_id_log,
|
||||
exc.status_code,
|
||||
server_url,
|
||||
secret_kind,
|
||||
)
|
||||
except httpx.TimeoutException as exc:
|
||||
logger.warning(
|
||||
"auth.clerk.profile.fetch_failed clerk_user_id=%s reason=timeout "
|
||||
"server_url=%s secret_kind=%s error=%s",
|
||||
"server_url=%s error=%s",
|
||||
clerk_user_id_log,
|
||||
server_url,
|
||||
secret_kind,
|
||||
str(exc) or exc.__class__.__name__,
|
||||
)
|
||||
except Exception as exc:
|
||||
@@ -293,7 +288,6 @@ async def delete_clerk_user(clerk_user_id: str) -> None:
|
||||
return
|
||||
|
||||
secret = settings.clerk_secret_key.strip()
|
||||
secret_kind = secret.split("_", maxsplit=1)[0] if "_" in secret else "unknown"
|
||||
server_url = _normalize_clerk_server_url(settings.clerk_api_url or "")
|
||||
clerk_user_id_log = clerk_user_id[-6:] if clerk_user_id else ""
|
||||
|
||||
@@ -307,10 +301,8 @@ async def delete_clerk_user(clerk_user_id: str) -> None:
|
||||
logger.info("auth.clerk.user.delete clerk_user_id=%s", clerk_user_id_log)
|
||||
except ClerkErrors as exc:
|
||||
logger.warning(
|
||||
"auth.clerk.user.delete_failed clerk_user_id=%s reason=clerk_errors "
|
||||
"secret_kind=%s error_type=%s",
|
||||
"auth.clerk.user.delete_failed clerk_user_id=%s reason=clerk_errors " "error_type=%s",
|
||||
clerk_user_id_log,
|
||||
secret_kind,
|
||||
exc.__class__.__name__,
|
||||
)
|
||||
raise HTTPException(
|
||||
@@ -323,11 +315,10 @@ async def delete_clerk_user(clerk_user_id: str) -> None:
|
||||
return
|
||||
logger.warning(
|
||||
"auth.clerk.user.delete_failed clerk_user_id=%s status=%s reason=sdk_error "
|
||||
"server_url=%s secret_kind=%s",
|
||||
"server_url=%s",
|
||||
clerk_user_id_log,
|
||||
exc.status_code,
|
||||
server_url,
|
||||
secret_kind,
|
||||
)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_502_BAD_GATEWAY,
|
||||
|
||||
@@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import re
|
||||
from datetime import date, datetime
|
||||
from functools import lru_cache
|
||||
from typing import Literal, Self
|
||||
from urllib.parse import urlparse
|
||||
from uuid import UUID
|
||||
@@ -297,6 +298,12 @@ def _parse_iso_datetime(value: str) -> datetime:
|
||||
return datetime.fromisoformat(normalized)
|
||||
|
||||
|
||||
@lru_cache(maxsize=256)
|
||||
def _compiled_validation_regex(pattern: str) -> re.Pattern[str]:
|
||||
"""Compile and cache validation regex patterns for value checks."""
|
||||
return re.compile(pattern)
|
||||
|
||||
|
||||
def validate_custom_field_value(
|
||||
*,
|
||||
field_type: TaskCustomFieldType,
|
||||
@@ -346,7 +353,11 @@ def validate_custom_field_value(
|
||||
if validation_regex is not None and field_type in STRING_FIELD_TYPES:
|
||||
if not isinstance(value, str):
|
||||
raise ValueError("must be a string for regex validation")
|
||||
if re.fullmatch(validation_regex, value) is None:
|
||||
try:
|
||||
pattern = _compiled_validation_regex(validation_regex)
|
||||
except re.error as exc:
|
||||
raise ValueError(f"validation_regex is invalid: {exc}") from exc
|
||||
if pattern.fullmatch(value) is None:
|
||||
raise ValueError("does not match validation_regex")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user