import { generateObject } from "ai"; import { z } from "zod"; import { resolveModel, type AiConfig } from "../factory"; const VariationsOutputSchema = z.object({ variations: z.array(z.object({ title: z.string(), description: z.string(), changedIngredients: z.array(z.object({ original: z.string(), replacement: z.string(), note: z.string().optional(), })), changedSteps: z.array(z.object({ stepNumber: z.number().int(), change: z.string(), })).optional(), dietaryTags: z.object({ vegan: z.boolean().optional(), vegetarian: z.boolean().optional(), glutenFree: z.boolean().optional(), dairyFree: z.boolean().optional(), nutFree: z.boolean().optional(), halal: z.boolean().optional(), kosher: z.boolean().optional(), }).optional(), })), }); export type VariationSuggestion = z.infer["variations"][number]; const LANG: Record = { en: "English", fr: "French" }; export async function suggestVariations( recipe: { title: string; description?: string | null; ingredients: Array<{ rawName: string; quantity?: string | null; unit?: string | null }>; steps: Array<{ instruction: string }>; }, count = 3, config?: AiConfig & { userContext?: string }, directions?: string, locale?: string ): Promise { const model = resolveModel(config); const lang = LANG[locale ?? "en"] ?? "English"; const recipeText = [ `Recipe: ${recipe.title}`, recipe.description ? `Description: ${recipe.description}` : "", `Ingredients: ${recipe.ingredients.map((i) => `${i.quantity ?? ""} ${i.unit ?? ""} ${i.rawName}`.trim()).join(", ")}`, `Steps: ${recipe.steps.map((s, i) => `${i + 1}. ${s.instruction}`).join(" | ")}`, ].filter(Boolean).join("\n"); const directionsClause = directions?.trim() ? `\n\nUser directions: ${directions.trim()}` : ""; const { object } = await generateObject({ model, schema: VariationsOutputSchema, system: `You are a creative chef. Suggest meaningful variations of recipes — dietary adaptations, flavor profiles, technique changes. Each variation should be distinct and practical. Respond in ${lang}.${config?.userContext ? `\n\nUser preferences and context:\n${config.userContext}` : ""}`, prompt: `Suggest ${count} variations of this recipe:\n\n${recipeText}${directionsClause}`, }); return object.variations; }