from __future__ import annotations import yaml from pathlib import Path from tracker.config import TrackerConfig from tracker.constants import MealPattern from tracker.models import AgentProfileYaml, RecipeSearchDefaults, ResolvedAgentProfile def load_agent_profile_yaml(path: Path) -> AgentProfileYaml: if not path.exists(): return AgentProfileYaml() raw = yaml.safe_load(path.read_text()) if raw is None: return AgentProfileYaml() if not isinstance(raw, dict): return AgentProfileYaml() return AgentProfileYaml.model_validate(raw) def resolve_agent_profile(cfg: TrackerConfig) -> ResolvedAgentProfile: """Merge config.yaml with agent_profile.yaml into one machine-readable profile.""" partial = load_agent_profile_yaml(cfg.agent_profile_resolved_path) recipe_defaults = partial.recipe_search_defaults or RecipeSearchDefaults() meal_pattern = partial.meal_pattern or MealPattern.BD_ONLY default_tz = partial.default_timezone or "America/Chicago" costco_label = partial.costco_event_label or "Costco" costco_minutes = partial.costco_duration_minutes if partial.costco_duration_minutes is not None else 90 calorie = partial.calorie_policy or "moderate_deficit" pantry_uid = partial.pantry_user_id if partial.pantry_user_id is not None else 5 add_ins = list(partial.raw_addins_defaults) return ResolvedAgentProfile( pantry_user_id=pantry_uid, active_program_id=cfg.active_program_id, meal_pattern=meal_pattern, default_timezone=default_tz, costco_event_label=costco_label, costco_duration_minutes=costco_minutes, weekly_climbing_sessions_target=partial.weekly_climbing_sessions_target, calorie_policy=calorie, recipe_search_defaults=recipe_defaults, raw_addins_defaults=add_ins, parser_data_dir=cfg.parser_data_dir, default_calendar_id=cfg.default_calendar_id, chores_calendar_id=cfg.chores_calendar_id, workout_calendar_id=cfg.workout_calendar_id, tracker_app_url=cfg.tracker_app_url, )