Skip to content

Latest commit

 

History

History
104 lines (90 loc) · 3 KB

File metadata and controls

104 lines (90 loc) · 3 KB

User clicks "Get AI Meal Plan" ↓ [Agent 1: Nutrition Analyzer]

  • Fetches today's logged meals from Supabase
  • Calculates total calories, protein, carbs, fats
  • Returns nutritional summary ↓ [Agent 2: Goal Evaluator]
  • Compares against user's daily goals
  • Determines: over/under/on-track ↓ [CONDITIONAL BRANCH 1: Calorie Status] IF remaining calories > 500: → Suggest larger, filling meals ELSE IF remaining calories < 100: → Suggest light snacks only ELSE: → Suggest balanced meals ↓ [Agent 3: Dietary Filter]
  • Checks user's dietary restrictions from settings ↓ [CONDITIONAL BRANCH 2: Diet Type] IF user is vegan: → Filter for plant-based only ELSE IF user is keto: → Filter for low-carb ELSE IF has allergies: → Exclude allergens ↓ [Agent 4: Recipe Recommender]
  • Calls Spoonacular API with filters
  • Returns 3-5 personalized recipe suggestions
  • Includes reasoning for each suggestion
// src/features/ai-meal-plan/api/route.ts
import Anthropic from "@anthropic-ai/sdk";

export async function POST(req: Request) {
  const { userId } = await req.json();

  // Agent 1: Get today's meals and analyze
  const todaysMeals = await getTodaysMeals(userId);
  const totalNutrition = calculateTotals(todaysMeals);

  // Agent 2: Evaluate against goals
  const userGoals = await getUserGoals(userId);
  const remaining = userGoals.calories - totalNutrition.calories;

  // CONDITIONAL BRANCH 1: Calorie status
  let calorieGuidance = "";
  if (remaining > 500) {
    calorieGuidance = "plenty of room for larger meals";
  } else if (remaining < 100) {
    calorieGuidance = "almost at goal, suggest light options";
  } else {
    calorieGuidance = "moderate room, balanced meals";
  }

  // Agent 3: Check dietary restrictions
  const userProfile = await getUserProfile(userId);

  // CONDITIONAL BRANCH 2: Diet type
  let dietFilter = "";
  if (userProfile.diet === "vegan") {
    dietFilter = "plant-based only, no animal products";
  } else if (userProfile.diet === "keto") {
    dietFilter = "low-carb, high-fat";
  }

  // Agent 4: Call Claude to generate meal plan
  const anthropic = new Anthropic({
    apiKey: process.env.ANTHROPIC_API_KEY,
  });

  const message = await anthropic.messages.create({
    model: "claude-sonnet-4-20250514",
    max_tokens: 1024,
    messages: [
      {
        role: "user",
        content: `You are a nutrition AI. Generate a meal plan.
      
      Current status:
      - Calories consumed: ${totalNutrition.calories}
      - Remaining: ${remaining} calories
      - Guidance: ${calorieGuidance}
      - Dietary restriction: ${dietFilter}
      
      Suggest 3 meals that fit the remaining calories and diet.
      Format as JSON array with: name, calories, reasoning.`,
      },
    ],
  });

  // Parse AI response and call Spoonacular for actual recipes
  const suggestions = JSON.parse(message.content[0].text);
  const recipes = await fetchRecipesFromSpoonacular(suggestions, dietFilter);

  return Response.json({ mealPlan: recipes });
}