AI coaching service (backend/app/services/ai_provider.py):
- Two code paths: OpenAI-compatible (6 providers) + Anthropic (Claude)
- Streaming SSE responses via httpx async
- System prompt built from AGENT_GUIDE + live user context
- Graceful error handling for all provider failures
- Gemini adapter for Google's generateContent API
Chat endpoint (backend/app/routers/ai_chat.py):
- POST /api/ai/chat — SSE streaming response
- GET /api/ai/status — check configured provider
- History capped at 20 messages, content at 4K chars
Provider registry expanded to 20 providers:
- 9 device integrations (strava, polar, garmin, whoop, oura, coros, fitbit, withings, suunto)
- 8 AI providers (openai, openrouter, huggingface, groq, ollama, claude, gemini, custom_ai)
- 3 other (usda, nutritionix, telegram)
- Categorized: device, ai_provider, nutrition, notifications
- COROS: MCP bridge approach (no API integration needed)
- Strava: AI/ML warning per their ToS
Frontend ChatCoach.jsx to follow in next commit.
Catalog stores only the template (typically week 1) but programs span
many weeks. The schedule endpoint was returning only the literal stored
rows, so after day 3 of StrongLifts a user would see no upcoming
workout despite being mid-program.
Changes:
- Add week_number column to workout_logs (migration in main.py) so the
same template workout can be completed once per real week
- Synthetic workout IDs: '{template_uuid}::{real_week}' — frontend
treats opaquely, backend parses on every endpoint
- get_program_schedule rotates the template across catalog.duration_weeks
real weeks and returns synthetic IDs
- today_workout: first uncompleted non-rest entry in current real week
(more flexible than literal day-of-week match)
- complete_workout / get_workout_detail parse synthetic IDs and track
completion per (template_id, real_week) pair
- check_weekly_bonus filters by workout_logs.week_number for the real week
- check_completion_bonus and progress endpoint compute total as
template_per_week * total_weeks, not just template count
Coolify does not pass environment variables to non-build services (image-only).
PostgreSQL initializes with trust authentication by default in this case.
Solution: connect without password, explicitly set POSTGRES_HOST_AUTH_METHOD=trust.
Also removed debug endpoint.