# .env.example — zmienne środowiskowe Knowli / Umiem! # # Skopiuj do pliku .env (gitignore go chroni) i uzupełnij sekrety. # Klucze API nigdy nie trafiają do repo, czatu ani NEXT_PUBLIC_*. # # Domyślna konfiguracja (providerzy, modele, głos, ton lektora, limity) żyje w # repozytorium: packages/server/src/config-defaults.ts. Ten plik zawiera tylko # to, czego nie ma w domyślnych (sekrety, baza), i nadpisania — wpisz zmienną # tylko wtedy, gdy chcesz inną wartość niż domyślna. Pusta wartość (`X=`) # znaczy „nie ustawiono”, czyli przywraca domyślną, a nie wyłącza. # # Kto czyta ten plik lokalnie: # - Docker Compose czyta .env z korzenia repozytorium i przekazuje go webowi i # workerowi (te same wartości, więc fingerprinty mediów się zgadzają). # - web (`pnpm --filter web dev`): Next.js sam czyta apps/web/.env.local, # plik z korzenia jest dla niego niewidoczny. # - worker (`pnpm --filter worker start`): czyta wyłącznie zmienne shella — # wyeksportuj je przed startem (np. `set -a; . ./.env; set +a`). # ══ Do uzupełnienia ══════════════════════════════════════════════════════════ # Hasło superusera PostgreSQL w kontenerze bazy; wymagane przez compose. POSTGRES_PASSWORD= # Klucz OpenAI: wyłącznie obrazy (ilustracje, okładki). Trafia tylko do # https://api.openai.com; klucz OpenRouter (sk-or-…) tutaj to błąd startu. Bez # niego worker nie wystartuje, chyba że UMIEM_FAKE_PROVIDERS=1. OPENAI_API_KEY= # Klucz OpenRouter: generator materiału (LLM), nagrania (TTS) i model oceniający # odpowiedzi lekcji z oceną aktywności sesji (web). Trafia wyłącznie po https na openrouter.ai (także # eu./us.). Bez niego worker nie wystartuje (domyślne LLM i TTS są na # OpenRouter). Osobne UMIEM_LLM_API_KEY / UMIEM_TTS_API_KEY / UMIEM_GRADER_API_KEY # nadpisują go dla jednej usługi (np. osobne limity lub koszty). OPENROUTER_API_KEY= # Model oceniający wysyła do OpenRouter odpowiedzi dzieci (bez imion i # identyfikatorów). Zasady przechowywania danych ustawisz w koncie OpenRouter # albo przez UMIEM_GRADER_PROVIDER_DATA_COLLECTION=deny (sekcja nadpisań). # ── Baza danych ────────────────────────────────────────────────────────────── # Wymagana zawsze: web, worker i migracje (drizzle.config.ts). Compose wewnątrz # kontenerów sam ją nadpisuje (db:5432) — ta wartość dotyczy lokalnego dev. DATABASE_URL=postgres://postgres:postgres@localhost:5432/knowli # ── Trwały wolumen mediów ──────────────────────────────────────────────────── # Worker zapisuje wygenerowane audio/obrazy, web wydaje gotowe pliki. # Domyślnie ./data/media liczony względem katalogu roboczego KAŻDEGO procesu # (apps/web i apps/worker to różne katalogi!) — lokalnie podaj jedną wspólną # ścieżkę bezwzględną dla obu procesów. Compose sam ustawia /data/media. MEDIA_ROOT=./data/media UMIEM_MCP_ALLOWED_ORIGINS= # ── Opcjonalne usługi (bez domyślnej konfiguracji) ─────────────────────────── # Tylko web: Azure Speech — STT treści wypowiedzi + ocena wymowy (próby ustne). # Bez obu wartości próby ustne kończą się wynikiem technicznym, nie fałszywą # oceną. Region to identyfikator z Azure, np. westeurope. AZURE_SPEECH_KEY= AZURE_SPEECH_REGION= # Dyktowanie odpowiedzi otwartych w zestawach szkolnych (bez oceny wymowy): # głos dziecka, więc wymaga własnego klucza (bez OPENROUTER_API_KEY). Endpoint # transkrypcji w formacie OpenAI (`/audio/transcriptions`); dla OpenRouter # adapter zawsze wymusza Zero Data Retention. Brak = bez mikrofonu. #UMIEM_LESSON_STT_BASE_URL=https://openrouter.ai/api/v1 #UMIEM_LESSON_STT_API_KEY= #UMIEM_LESSON_STT_MODEL=elevenlabs/scribe-v2 # ══ Nadpisania (opcjonalne) ══════════════════════════════════════════════════ # Wartości domyślne: packages/server/src/config-defaults.ts. Poniżej przykłady. # # Ustawienia medialne (UMIEM_TTS_*, UMIEM_IMAGE_*) wchodzą do fingerprintów # zasobów: web i worker muszą mieć identyczne wartości (Compose to zapewnia), a # zmiana po wygenerowaniu materiału oznacza nowe nagrania (płatne): komunikaty # Kid UI od razu przy starcie workera, materiał przy następnym zapisie. # Opublikowane lekcje grają dotychczasowe nagrania. # Ton lektora (komunikaty Kid UI, pytania i karty lekcji): none wyłącza. #UMIEM_TTS_STYLE=none # Głos TTS (musi należeć do `supported_voices` modelu: # https://openrouter.ai/api/v1/models?output_modalities=speech) i głos per # język treści (UMIEM_TTS_VOICE__). Instrukcja wymowy per język # (UMIEM_TTS_INSTRUCTIONS__) to osobne pole, nie jest czytana. #UMIEM_TTS_VOICE=Kore #UMIEM_TTS_VOICE_EN_GB=Kore #UMIEM_TTS_INSTRUCTIONS_PL_PL=Mów po polsku, z polską wymową. # Powrót TTS na OpenAI (klucz OPENAI_API_KEY): wszystkie pięć wierszy — pusty # BASE_URL przywróciłby domyślny OpenRouter. #UMIEM_TTS_PROVIDER=openai #UMIEM_TTS_MODEL=gpt-4o-mini-tts #UMIEM_TTS_VOICE=alloy #UMIEM_TTS_FORMAT=mp3 #UMIEM_TTS_BASE_URL=https://api.openai.com/v1 # Generator materiału (zestawy słówek i pule ćwiczeń lekcji, worker). Powrót na # OpenAI: BASE_URL api.openai.com i model OpenAI (klucz OPENAI_API_KEY). #UMIEM_LLM_MODEL=google/gemini-3.8-flash #UMIEM_LLM_BASE_URL=https://api.openai.com/v1 #UMIEM_LLM_MODEL=gpt-4o-mini # Grader: inny model lub endpoint zgodny z OpenAI (wtedy z UMIEM_GRADER_API_KEY; # BASE_URL musi być https:// poza NODE_ENV test/development). Limity: timeout # jednego wywołania i budżet wywołań na sesję. #UMIEM_GRADER_MODEL=google/gemini-3.8-flash #UMIEM_GRADER_BASE_URL=https://grader.example/v1 #UMIEM_GRADER_API_KEY= #UMIEM_GRADER_TIMEOUT_MS=8000 #UMIEM_GRADER_MAX_CALLS_PER_SESSION=20 #UMIEM_SESSION_ACTIVITY_TIMEOUT_MS=60000 # Krytyk lekcji (automatyczna kontrola jakości świeżych ćwiczeń, worker): domyślnie # wyłączony. Bez UMIEM_REVIEWER_API_KEY bierze wspólny OPENROUTER_API_KEY (tylko https # OpenRouter). Prywatność: materiał lekcji i gotowe ćwiczenia trafiają do Anthropic przez # OpenRouter; bez danych dziecka (imienia, wieku, odpowiedzi, tematów zdań). #UMIEM_REVIEWER_ENABLED=true #UMIEM_REVIEWER_API_KEY= #UMIEM_REVIEWER_MODEL=anthropic/claude-sonnet-5.5 #UMIEM_REVIEWER_PROVIDER_DATA_COLLECTION=deny # Opcje pośrednika OpenRouter (tylko z BASE_URL na openrouter.ai — przy innym # endpoincie start kończy się błędem). Domyślnie REASONING=low dla LLM i gradera. # REASONING: off | minimal | low | medium | high (nie każdy model pozwala na off). # PROVIDER_*: routing do dostawców modelu; ustawienie dowolnej opcji wymusza # dostawców obsługujących wysyłane parametry (ścisły json_schema puli lekcji). # PROVIDER_DATA_COLLECTION=deny wyklucza dostawców zbierających dane z zapytań — # zalecane dla gradera (odpowiedzi dzieci); sprawdź, że model nadal ma endpoint. #UMIEM_LLM_REASONING=off #UMIEM_LLM_PROVIDER_ORDER=Nebius,DeepInfra #UMIEM_LLM_PROVIDER_QUANTIZATIONS=fp8 #UMIEM_LLM_PROVIDER_ALLOW_FALLBACKS=false #UMIEM_LLM_PROVIDER_DATA_COLLECTION=deny #UMIEM_GRADER_REASONING=medium #UMIEM_GRADER_PROVIDER_DATA_COLLECTION=deny # Obrazy (OpenAI). #UMIEM_IMAGE_MODEL=gpt-image-2.5-sunburst #UMIEM_IMAGE_SIZE=1024x1024 #UMIEM_IMAGE_QUALITY=low #UMIEM_IMAGE_FORMAT=webp # Ceny (USD) — `none` wyłącza stawkę (koszty takich wywołań są „nieznane”). # Stawki obrazu i TTS obowiązują domyślnie tylko przy domyślnym modelu obrazów # (z jakością i rozmiarem) oraz TTS; po zmianie modelu ustaw własną albo koszt # będzie nieznany. Obie są przybliżeniem (rozliczenie tokenowe). #UMIEM_PRICE_IMAGE_USD=0.006 #UMIEM_PRICE_TTS_USD_PER_MINUTE=0.0135 #UMIEM_PRICE_AZURE_STT_USD_PER_HOUR=1 #UMIEM_PRICE_AZURE_PRONUNCIATION_USD_PER_HOUR=1 # Generacja lekcji (worker): czas jednego requestu i całej wielocelowej lekcji. # Retry nie jest automatyczne po timeout; ręczne ponowienie tworzy nową próbę. #UMIEM_LESSON_GENERATION_REQUEST_TIMEOUT_MS=90000 #UMIEM_LESSON_GENERATION_RUN_TIMEOUT_MS=600000 #UMIEM_LESSON_GENERATION_CANCEL_POLL_MS=1000 # Worker: okres odpytywania kolejki i próg health (503, gdy od ostatniego # zakończonego lub trwającego przelotu minęło więcej ms). #WORKER_POLL_MS=2000 #WORKER_HEALTH_STALE_MS=900000 # Tryb bez sieciowych providerów (E2E, środowisko bez kluczy). Odkomentuj tylko # celowo; zsh/PowerShell: usuń wiersz zamiast zostawiać pustej wartości. #UMIEM_FAKE_PROVIDERS=1 #UMIEM_FAKE_DELAY_MS=3000 # ── Docker Compose (deploy/compose.yaml) ───────────────────────────────────── # Nazwa bazy (domyślnie knowli) i port hosta aplikacji web (domyślnie 8080). # HTTPS zapewnia reverse proxy przed webem (w domu Coolify) — sam compose # wystawia zwykłe HTTP. #POSTGRES_DB=knowli #WEB_PORT=8080