freezmo/.env.example
Martin Dvorak e3b7bbbd6c Bigger decks: pick up to 30 activities, built in batches
The create wizard stopped at 15 activities because the API, the prompt and
the salvage path all capped at 18: one reply must be one valid JSON object,
and past ~18 activities models truncate or drop cards. Raising the cap alone
would have shipped decks that came back short.

- The count picker offers 8 / 10 / 12 / 15 / 20 / 30; a deck's "add more" row
  gained +15. The help line says bigger decks take longer.
- /api/generate accepts up to 30 (FREEZMO_DEFAULT_ACTIVITY_COUNT now clamps
  to 30 as well) and sizes its overall deadline from the number of model
  calls instead of a fixed two.
- generateActivities splits anything above 18 evenly across calls (30 → 15 +
  15, 25 → 13 + 12) and merges them into one deck. The first call keeps the
  "add to this deck" contract; later calls are told the title, the types
  already used and the topics already covered. A normalised content signature
  drops a card that repeats an earlier one, so the same idea never ships
  twice. requested/generated still travel in the stream meta.
- phase1-test: a stub Ollama answers two 15-card batches (the second repeats
  one card on purpose) → two calls, the even split, the "already covered"
  prompt, 29 merged cards, the duplicate shipped once, title from the first
  reply, and count 31 answered 400 (59 checks).
- wizard-test: the picker offers 30, the wizard sends count: 30, and the
  30-card deck is stored and opened (99 checks).

Version 0.8.4, SW v106.
2026-10-28 19:11:39 +00:00

94 lines
4.6 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ---------------------------------------------------------------------------
# Freezmo - Ollama configuration
# Copy this file to `.env.local` and adjust if needed.
# ---------------------------------------------------------------------------
# WHO PROVIDES THE API KEY -----------------------------------------------------
# user-key (default) Every browser supplies its own key. The key is typed
# into the settings dialog, kept in that browser's local
# storage and sent with each request in the
# `x-ollama-key` header. The server never stores it.
# Point OLLAMA_BASE_URL at https://ollama.com.
# server One key for everyone, read from OLLAMA_API_KEY below
# (single-user installs). Nothing is sent from the client.
# local No key at all: a local daemon signed in with
# `ollama signin` proxies the cloud models.
OLLAMA_AUTH=user-key
# Ollama endpoint. https://ollama.com for cloud, http://localhost:11434 for a
# local daemon. In user-key mode this is the endpoint the browser's key is sent
# to; in server/local mode it is used directly.
OLLAMA_BASE_URL=https://ollama.com
# Only used when OLLAMA_AUTH=server. Never commit a real key.
OLLAMA_API_KEY=
# Model used for the vision/transcription step (reads photos of notes).
# Must be multimodal — gpt-oss and other text-only models cannot be used here.
# Free-tier friendly: gemma4:31b-cloud, kimi-k3:cloud (paid), mistral-large-3 (paid).
VISION_MODEL=gemma4:31b-cloud
# Model used to generate activities, grade short answers and restore the
# language if a transcription came back translated. gpt-oss:120b is free-tier
# friendly, very good at strict JSON and the strongest multilingual model in the
# free plan. NOTE: it is text-only, so it can't be used as VISION_MODEL.
# Free alternatives: nemotron-3-super:cloud, gpt-oss:20b-cloud.
# Paid/credit: glm-5.3-flash:cloud, kimi-k3:cloud.
TEXT_MODEL=gpt-oss:120b-cloud
# CHAT MODELS (optional) -------------------------------------------------------
# The allowlist the chat model picker offers, comma-separated. The server never
# accepts a model name outside this list. The first entry is the default.
# When unset, the configured TEXT_MODEL and VISION_MODEL are used.
# Example: CHAT_MODELS=gemma4:31b-cloud,gpt-oss:120b-cloud
# CHAT_MODELS=
# RATE LIMITS (per client IP, sliding window, in-memory) ----------------------
# Generation decks are expensive, so they are limited tightly by default.
# RATE_LIMIT_WINDOW_MS=300000
# RATE_LIMIT_GENERATE=12
# RATE_LIMIT_GRADE=40
# RATE_LIMIT_HOMEWORK=12
# Homework follow-ups (short rewrites).
# RATE_LIMIT_REFINE=30
# RATE_LIMIT_HEALTH=90
# Encrypted sync (no model calls, but shouldn't be hammered).
# RATE_LIMIT_SYNC=60
# Push subscription changes and test sends.
# RATE_LIMIT_PUSH=30
# Chat turns (one model call each; users send them in bursts).
# RATE_LIMIT_CHAT=60
# PUSH REMINDERS (optional) ----------------------------------------------------
# Web Push reminders only appear in the UI when BOTH VAPID keys are set.
# Generate them once with: npx web-push generate-vapid-keys
# VAPID_PUBLIC_KEY=
# VAPID_PRIVATE_KEY=
# VAPID_SUBJECT=mailto:you@example.com
# Where subscriptions are stored (endpoint, keys, and the reminder text the
# browser composed for that device — it may name one of its decks).
# PUSH_DIR=.freezmo/push
# The daily sender is a script you schedule yourself — cron, or the shipped
# systemd timer (deploy/freezmo-reminders.timer):
# node scripts/send-reminders.mjs
# A device's own reminder text wins; these generic lines are the fallback for
# subscriptions that never synced one (same words the app uses without notes).
# PUSH_REMINDER_TITLE=Time to review
# PUSH_REMINDER_BODY=Your decks are waiting — a few due cards keep the streak alive.
# ENCRYPTED SYNC STORAGE -------------------------------------------------------
# Opt-in sync uploads an opaque AES-GCM blob; the server can't read it and
# never sees the passphrase or the API key. One small JSON file per sync ID.
# SYNC_DIR=.freezmo/sync
# Per-blob cap in bytes (larger uploads are refused with HTTP 413).
# SYNC_MAX_BYTES=12582912
# Total cap for the directory in bytes (new blobs refused with HTTP 507).
# SYNC_TOTAL_BYTES=1073741824
# Optional tuning ------------------------------------------------------------
# OLLAMA_TIMEOUT_MS=300000
# OLLAMA_HEALTH_TIMEOUT_MS=8000
# Send `think: false` to thinking models for faster JSON output.
# OLLAMA_THINK=false
# Deck size when the request does not send one (6–30; the wizard offers 8–30).
# FREEZMO_DEFAULT_ACTIVITY_COUNT=10