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.
94 lines
4.6 KiB
Bash
94 lines
4.6 KiB
Bash
# ---------------------------------------------------------------------------
|
||
# 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
|