diff --git a/app/api/v1/public_api/imagine.py b/app/api/v1/public_api/imagine.py index ab235a2..1816fb5 100644 --- a/app/api/v1/public_api/imagine.py +++ b/app/api/v1/public_api/imagine.py @@ -16,6 +16,7 @@ from pydantic import BaseModel from app.core.auth import verify_public_key, get_public_api_key, is_public_enabled from app.core.config import get_config +from app.core.exceptions import AppException from app.core.logger import logger from app.api.v1.image import resolve_aspect_ratio from app.services.grok.services.image import ImageGenerationService @@ -913,11 +914,14 @@ async def public_imagine_edit(data: ImagineEditRequest, request: Request): ) raise except Exception as e: + message = str(e) + if not message: + message = "编辑失败,请稍后重试" await queue.put( { "type": "error", "payload": { - "message": str(e), + "message": message, }, } ) @@ -964,7 +968,12 @@ async def public_imagine_edit(data: ImagineEditRequest, request: Request): headers={"Cache-Control": "no-cache", "Connection": "keep-alive"}, ) - return await _run_once(progress_cb=None) + try: + return await _run_once(progress_cb=None) + except AppException as e: + raise HTTPException(status_code=e.status_code, detail=e.message) + except Exception: + raise HTTPException(status_code=500, detail="编辑失败,请稍后重试") class ImagineStopRequest(BaseModel): @@ -1155,11 +1164,14 @@ async def public_imagine_workbench_edit(data: ImagineWorkbenchEditRequest, reque ) raise except Exception as e: + message = str(e) + if not message: + message = "编辑失败,请稍后重试" await queue.put( { "type": "error", "payload": { - "message": str(e), + "message": message, }, } ) @@ -1207,4 +1219,9 @@ async def public_imagine_workbench_edit(data: ImagineWorkbenchEditRequest, reque headers={"Cache-Control": "no-cache", "Connection": "keep-alive"}, ) - return await _run_once(progress_cb=None) + try: + return await _run_once(progress_cb=None) + except AppException as e: + raise HTTPException(status_code=e.status_code, detail=e.message) + except Exception: + raise HTTPException(status_code=500, detail="编辑失败,请稍后重试") diff --git a/app/services/grok/services/image_edit.py b/app/services/grok/services/image_edit.py index 7f77842..ed880e2 100644 --- a/app/services/grok/services/image_edit.py +++ b/app/services/grok/services/image_edit.py @@ -40,6 +40,25 @@ class ImageEditResult: data: Union[AsyncGenerator[str, None], List[str]] +def _is_upload_rejected_error(exc: Exception) -> bool: + """判断是否为上游审核导致的上传拒绝。""" + msg = str(exc or "").lower() + if "content moderated" in msg or "content-moderated" in msg: + return True + if '"code":3' in msg or "'code': 3" in msg: + return True + + details = getattr(exc, "details", None) + if isinstance(details, dict): + body = str(details.get("body") or "").lower() + if "content moderated" in body or "content-moderated" in body: + return True + if '"code":3' in body or "'code': 3" in body: + return True + + return False + + class ImageEditService: """Image edit orchestration service.""" @@ -438,6 +457,20 @@ class ImageEditService: image_urls.append( f"https://assets.grok.com/{file_uri.lstrip('/')}" ) + except Exception as e: + if _is_upload_rejected_error(e): + raise AppException( + message="图片上传被拒绝,请更换图片后重试", + error_type=ErrorType.INVALID_REQUEST.value, + code="upload_rejected", + status_code=400, + ) + raise AppException( + message="图片上传失败,请稍后重试", + error_type=ErrorType.SERVER.value, + code="upload_failed", + status_code=502, + ) finally: await upload_service.close()