kiwi/app/api/endpoints/recipes.py

46 lines
1.7 KiB
Python

"""Recipe suggestion endpoints."""
from __future__ import annotations
import asyncio
from fastapi import APIRouter, Depends, HTTPException
from app.cloud_session import CloudUser, get_session
from app.db.session import get_store
from app.db.store import Store
from app.models.schemas.recipe import RecipeRequest, RecipeResult
from app.services.recipe.recipe_engine import RecipeEngine
from app.tiers import can_use
router = APIRouter()
@router.post("/suggest", response_model=RecipeResult)
async def suggest_recipes(
req: RecipeRequest,
session: CloudUser = Depends(get_session),
store: Store = Depends(get_store),
) -> RecipeResult:
if req.level == 4 and not req.wildcard_confirmed:
raise HTTPException(
status_code=400,
detail="Level 4 (Wildcard) requires wildcard_confirmed=true.",
)
if req.level in (3, 4) and not can_use("recipe_suggestions", session.tier, session.has_byok):
raise HTTPException(
status_code=403,
detail="LLM recipe levels require Paid tier or a configured LLM backend.",
)
if req.style_id and not can_use("style_picker", session.tier):
raise HTTPException(status_code=403, detail="Style picker requires Paid tier.")
req = req.model_copy(update={"tier": session.tier, "has_byok": session.has_byok})
engine = RecipeEngine(store)
return await asyncio.to_thread(engine.suggest, req)
@router.get("/{recipe_id}")
async def get_recipe(recipe_id: int, store: Store = Depends(get_store)) -> dict:
recipe = await asyncio.to_thread(store.get_recipe, recipe_id)
if not recipe:
raise HTTPException(status_code=404, detail="Recipe not found.")
return recipe