# GymLogAI GymLogAI is a minimal multi-project skeleton for importing workout messages, parsing them into structured training history, and generating workout recommendations. ## Architecture - `GymLogAI.Core`: domain entities, enums, and primitive abstractions like `IClock` and `IIdGenerator` - `GymLogAI.Application`: repository contracts, AI contracts, DTOs, and use-case handlers - `GymLogAI.Persistence`: EF Core `AppDbContext`, PostgreSQL mappings, repositories, infrastructure services, and the first migration - `GymLogAI.AI`: OpenRouter-ready options and stubbed AI implementations for parsing, recommendations, and embeddings - `GymLogAI.API`: minimal API composition root with Swagger, import/recommend/history endpoints, and database migration on startup - `GymLogAI.TelegramBot`: Telegram long-polling host with `/start`, `/today`, and text message import - `GymLogAI.Worker`: background worker that polls pending telegram messages and parses them into workouts ## Runtime Flow 1. API or Telegram bot imports a raw Telegram message into `telegram_messages` with `Pending` status. 2. Worker polls pending messages and runs `ParseTelegramMessageHandler`. 3. Parsed workouts are stored in `workouts`, `workout_exercises`, and `exercise_sets`. 4. API and Telegram bot can request workout recommendations from the application layer. ## Key Endpoints - `POST /api/messages/import` - `POST /api/workouts/recommend` - `GET /api/workouts/history?userId=` - Swagger UI: `/swagger` ## Database - Provider: PostgreSQL - Migration project: `GymLogAI.Persistence` - Initial migration is included in `GymLogAI.Persistence/Migrations` - `Exercise` includes an `Embedding` field stored as nullable `real[]` ## Run ```bash dotnet build dotnet run --project GymLogAI.API/ dotnet run --project GymLogAI.TelegramBot/ dotnet run --project GymLogAI.Worker/ docker compose -f compose.yaml up --build ``` ## Configuration - Connection string: `ConnectionStrings:Postgres` - Telegram bot token: `TelegramBot:BotToken` - OpenRouter settings: `OpenRouter:*` - Worker polling settings: `Worker:BatchSize`, `Worker:PollingIntervalSeconds`