diff --git a/README.md b/README.md index c51a1b1..f7d9095 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ The app uses a vertical scrolling learning experience inspired by modern short-f - Track progress, bookmarks, and study activity - Navigate with keyboard shortcuts - Use offline sandbox fallback when backend is unavailable +- Show user-safe fallback messages when AI generation is unavailable ## Stellar/Soroban Exploration Roadmap diff --git a/backend/main.py b/backend/main.py index b0ab609..c2bf486 100644 --- a/backend/main.py +++ b/backend/main.py @@ -24,6 +24,10 @@ APP_VERSION = "1.0.0" MAX_PDF_BYTES = 10 * 1024 * 1024 MAX_NOTES_CHARS = 15000 +AI_FALLBACK_MESSAGE = ( + "AI generation is temporarily unavailable, so Study Copilot is showing offline practice cards instead." +) +AI_FALLBACK_GUIDANCE = "You can keep studying now and try live AI generation again later." GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY") MODEL_CANDIDATES = [ @@ -121,8 +125,7 @@ def get_fallback_cards(topic: str) -> list[dict[str, Any]]: "type": "concept", "title": f"Introduction to {topic}", "content": ( - f"Welcome to {topic}. This fallback card appears when Gemini is unavailable. " - "Set GOOGLE_API_KEY to enable live AI-generated study cards." + f"Welcome to {topic}. {AI_FALLBACK_MESSAGE} {AI_FALLBACK_GUIDANCE}" ), "timestamp": now_iso(), }, diff --git a/docs/ai-error-message-policy.md b/docs/ai-error-message-policy.md new file mode 100644 index 0000000..9f0f737 --- /dev/null +++ b/docs/ai-error-message-policy.md @@ -0,0 +1,32 @@ +# AI Error Message Policy + +Study Copilot should keep learning flows usable when AI generation is unavailable while avoiding technical or sensitive details in user-facing responses. + +## Current User-Facing Behavior + +- The backend starts in offline sandbox mode when no AI provider is configured or provider setup fails. +- Topic, notes, and PDF study-card generation return offline fallback cards when live AI generation cannot be used. +- Fallback cards explain that live AI generation is temporarily unavailable and that offline practice cards are being shown instead. +- Responses do not expose API keys, environment variable values, provider stack traces, raw model errors, or internal exception text. + +## Safe Message Pattern + +Use concise messages that tell the learner what happened and what they can do next: + +> AI generation is temporarily unavailable, so Study Copilot is showing offline practice cards instead. You can keep studying now and try live AI generation again later. + +This wording is intentionally provider-neutral. It avoids naming secrets, configuration keys, internal model IDs, request payloads, or exception details. + +## Implementation Notes + +- Keep provider setup and generation exceptions out of API response bodies. +- Prefer stable fallback content over passing raw exception messages to the frontend. +- If structured error metadata is added later, use stable reason codes such as `ai_generation_unavailable` instead of raw exception strings. +- Backend logs may include operational details for maintainers, but logs should still avoid API key values and full prompt payloads. + +## Review Checklist + +- Does the message help the user continue or retry? +- Does it avoid stack traces, raw exception text, and secret names or values? +- Does it avoid exposing full prompts, notes, uploaded document text, or generated provider responses? +- Does offline fallback still work without a real AI API key?