Check my work (third homework mode) - One model call with its own system prompt marks the student's own attempt: verdict, what's right, each issue with why + fix, and the corrected version that keeps everything the student got right. Unasked-for extras are never errors. The attempt is typed/pasted (photos of handwriting are documented as unsupported) and stored in the record so Redo re-checks the same work. - Server: mode "check" + solution on POST /api/homework (zod, 400 server.needSolution without one) and the same NDJSON stream; new checkHomework() pipeline with repair-once validation. Follow-ups - New POST /api/homework/refine (plain JSON, RATE_LIMIT_REFINE, zod, auth before body): shorter / more detail / explain, plain text back, language preserved. - Shorter + More detail + Original rewrite the finished answer and the corrected version in place (FollowUpBar); every guide step has Explain step N differently; failed calls say so without losing text. Turn into a study deck - Any result hands its content (answer, corrected version or assembled guide) to New deck through a one-shot sessionStorage seed with the options step pre-filled. UI - Phone step 2 gains the third card: tapping it reveals the solution field + submit; desktop has three cards and the solution field shows with the mode. Homework history labels and share/card previews cover the new mode. Verified: new phase-3 suite 20/20 against a stub Ollama (check payload, missing-solution 400, refine validation, phone + desktop check flows, shorter follow-up with restore, guide explain, deck hand-off) plus regression 74/74, mobile 52/52, declutter 116/116, wizard 80/80, animation 8/8, native 35/35, phase1 38/38, phase2 43/43, i18n 25/25. Key parity 734/734. Lint + build clean. SW freezmo-v27.
80 lines
3.8 KiB
Bash
80 lines
3.8 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
|
|
|
|
# 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
|
|
|
|
# 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 only, no personal data).
|
|
# PUSH_DIR=.freezmo/push
|
|
# The daily sender is a script you schedule yourself (cron/systemd timer):
|
|
# node scripts/send-reminders.mjs
|
|
# 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
|
|
# FREEZMO_DEFAULT_ACTIVITY_COUNT=10
|