Files
Reflect/Shared/Models/AIInsight.swift
Trey t b2b6931d7c Lower deployment target from iOS 26 to iOS 18, gate Foundation Models behind @available
Broadens installable audience to iOS 18+ while keeping AI insights available on iOS 26.
Foundation Models types and service wrapped in @available(iOS 26, *), InsightsViewModel
conditionally instantiates the service with fallback UI on older versions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:21:45 -06:00

73 lines
2.2 KiB
Swift

//
// AIInsight.swift
// Feels
//
// 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() }
}
}