Initial project import
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
|
||||
def _message_from_value(value: object) -> str:
|
||||
if isinstance(value, str):
|
||||
return value
|
||||
if not isinstance(value, dict):
|
||||
return ""
|
||||
message = value.get("message")
|
||||
if isinstance(message, str) and message:
|
||||
return message
|
||||
return _message_from_value(value.get("error"))
|
||||
|
||||
|
||||
def error_message_from_detail(detail: object) -> str:
|
||||
if isinstance(detail, list):
|
||||
messages = []
|
||||
for item in detail:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
location = ".".join(str(part) for part in item.get("loc", []) if part != "body")
|
||||
message = str(item.get("msg") or "").strip()
|
||||
if location and message:
|
||||
messages.append(f"{location}: {message}")
|
||||
elif message:
|
||||
messages.append(message)
|
||||
return "; ".join(messages)
|
||||
if isinstance(detail, dict):
|
||||
message = _message_from_value(detail.get("error")) or _message_from_value(detail)
|
||||
if message:
|
||||
return message
|
||||
return str(detail or "").strip()
|
||||
|
||||
|
||||
def _default_error_type(status_code: int) -> str:
|
||||
if status_code == 401:
|
||||
return "authentication_error"
|
||||
if status_code == 403:
|
||||
return "permission_error"
|
||||
if status_code == 429:
|
||||
return "rate_limit_error"
|
||||
if 400 <= status_code < 500:
|
||||
return "invalid_request_error"
|
||||
return "server_error"
|
||||
|
||||
|
||||
def _default_error_code(status_code: int) -> str:
|
||||
if status_code == 401:
|
||||
return "invalid_api_key"
|
||||
if status_code == 403:
|
||||
return "permission_denied"
|
||||
if status_code == 429:
|
||||
return "rate_limit_exceeded"
|
||||
if 400 <= status_code < 500:
|
||||
return "bad_request"
|
||||
return "upstream_error"
|
||||
|
||||
|
||||
def openai_error_payload(
|
||||
detail: object,
|
||||
status_code: int,
|
||||
*,
|
||||
error_type: str | None = None,
|
||||
code: object | None = None,
|
||||
param: object | None = None,
|
||||
) -> dict[str, Any]:
|
||||
error_detail = detail.get("error") if isinstance(detail, dict) else None
|
||||
if isinstance(error_detail, dict):
|
||||
return {
|
||||
"error": {
|
||||
"message": error_message_from_detail(error_detail) or "request failed",
|
||||
"type": str(error_detail.get("type") or error_type or _default_error_type(status_code)),
|
||||
"param": error_detail.get("param", param),
|
||||
"code": error_detail.get("code", code if code is not None else _default_error_code(status_code)),
|
||||
}
|
||||
}
|
||||
return {
|
||||
"error": {
|
||||
"message": error_message_from_detail(detail) or "request failed",
|
||||
"type": error_type or _default_error_type(status_code),
|
||||
"param": param,
|
||||
"code": code if code is not None else _default_error_code(status_code),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def openai_error_response(
|
||||
detail: object,
|
||||
status_code: int,
|
||||
*,
|
||||
headers: dict[str, str] | None = None,
|
||||
error_type: str | None = None,
|
||||
code: object | None = None,
|
||||
param: object | None = None,
|
||||
) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
status_code=status_code,
|
||||
content=openai_error_payload(detail, status_code, error_type=error_type, code=code, param=param),
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
|
||||
def anthropic_error_response(
|
||||
detail: object,
|
||||
status_code: int,
|
||||
*,
|
||||
headers: dict[str, str] | None = None,
|
||||
) -> JSONResponse:
|
||||
error_type = "api_error" if status_code >= 500 else _default_error_type(status_code)
|
||||
return JSONResponse(
|
||||
status_code=status_code,
|
||||
content={
|
||||
"type": "error",
|
||||
"error": {
|
||||
"type": error_type,
|
||||
"message": error_message_from_detail(detail) or "request failed",
|
||||
},
|
||||
},
|
||||
headers=headers,
|
||||
)
|
||||
Reference in New Issue
Block a user