fix: normalize aspect ratio per model, surface invalid_params in errors
Models like mystic, flux-pro-1.1, and seedream-v4/v4-5 require named aspect ratio slugs (e.g. "square_1_1", "widescreen_16_9") while other models accept the "W:H" format directly. - Add normalize_aspect_ratio() mapping W:H strings to slugs for affected models - Apply normalization in generate-image before building the request payload - Improve FreepikAPIError to surface invalid_params field details from the API response, so "Validation error" now also shows which field failed and why Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -34,10 +34,17 @@ class FreepikAPIError(Exception):
|
||||
or f"HTTP {response.status_code}"
|
||||
)
|
||||
|
||||
# Append individual field validation errors when present
|
||||
invalid = body.get("invalid_params", [])
|
||||
if invalid:
|
||||
details = "\n".join(
|
||||
f" • {p.get('field', '?')}: {p.get('reason', '')}" for p in invalid
|
||||
)
|
||||
message = f"{message}\n\n{details}"
|
||||
|
||||
hints = {
|
||||
401: "Check your API key — set FREEPIK_API_KEY or use --api-key.",
|
||||
403: "Your plan may not support this feature. Check your Freepik subscription.",
|
||||
422: "Invalid request parameters. Check the options you provided.",
|
||||
429: "Rate limit exceeded. Please wait before retrying.",
|
||||
}
|
||||
hint = hints.get(response.status_code)
|
||||
|
||||
@@ -124,6 +124,45 @@ VIDEO_UPSCALE_POST_ENDPOINTS: dict[VideoUpscaleMode, str] = {
|
||||
VIDEO_UPSCALE_STATUS_ENDPOINT = "/v1/ai/video-upscaler/{task_id}"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Aspect ratio normalization
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Models that require named slug aspect ratios instead of "W:H" strings
|
||||
SLUG_ASPECT_RATIO_MODELS: set[ImageModel] = {
|
||||
ImageModel.MYSTIC,
|
||||
ImageModel.FLUX_PRO_1_1,
|
||||
ImageModel.SEEDREAM_V4,
|
||||
ImageModel.SEEDREAM_V4_5,
|
||||
}
|
||||
|
||||
# User-friendly "W:H" → API slug mapping
|
||||
_RATIO_TO_SLUG: dict[str, str] = {
|
||||
"1:1": "square_1_1",
|
||||
"16:9": "widescreen_16_9",
|
||||
"9:16": "social_story_9_16",
|
||||
"4:3": "classic_4_3",
|
||||
"3:4": "traditional_3_4",
|
||||
"3:2": "standard_3_2",
|
||||
"2:3": "portrait_2_3",
|
||||
"2:1": "horizontal_2_1",
|
||||
"1:2": "vertical_1_2",
|
||||
"4:5": "social_post_4_5",
|
||||
"21:9": "widescreen_16_9", # closest match
|
||||
}
|
||||
|
||||
|
||||
def normalize_aspect_ratio(ratio: str, model: ImageModel) -> str:
|
||||
"""Convert a user-facing aspect ratio to the format required by the model."""
|
||||
if model not in SLUG_ASPECT_RATIO_MODELS:
|
||||
return ratio # free-form models accept "1:1" directly
|
||||
slug = _RATIO_TO_SLUG.get(ratio)
|
||||
if slug:
|
||||
return slug
|
||||
# Already a slug (user passed "square_1_1" directly) — pass through
|
||||
return ratio
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Response normalization helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user