// // AIInsight.swift // Reflect // // Created by Claude Code on 12/13/24. // import Foundation import FoundationModels /// Represents a single AI-generated insight using @Generable for structured LLM output @available(iOS 26, *) @Generable struct AIInsight: Equatable { @Guide(description: "A brief, engaging title for the insight (3-6 words)") var title: String @Guide(description: "A detailed, personalized description of the insight (1-2 sentences)") var description: String @Guide(description: "The type of insight: pattern (observed trend), advice (recommendation), prediction (future forecast), achievement (milestone), or trend (direction analysis)") var insightType: String @Guide(description: "The primary mood associated with this insight: great, good, average, bad, horrible, or none") var associatedMood: String @Guide(description: "SF Symbol name for the insight icon (e.g., star.fill, chart.line.uptrend.xyaxis, heart.fill)") var iconName: String @Guide(description: "Sentiment of the insight: positive, neutral, or negative") var sentiment: String } /// Container for period-specific insights - the LLM generates this structure @available(iOS 26, *) @Generable struct AIInsightsResponse: Equatable { @Guide(description: "Array of exactly 5 diverse insights covering patterns, advice, and predictions") var insights: [AIInsight] } // MARK: - Conversion to App's Insight Model @available(iOS 26, *) extension AIInsight { /// Converts AI-generated insight to the app's existing Insight model func toInsight() -> Insight { let mood: Mood? = switch associatedMood.lowercased() { case "great": .great case "good": .good case "average": .average case "bad": .bad case "horrible": .horrible default: nil } return Insight( icon: iconName, title: title, description: description, mood: mood ) } } @available(iOS 26, *) extension AIInsightsResponse { /// Converts all AI insights to app's Insight models func toInsights() -> [Insight] { insights.map { $0.toInsight() } } }