Skip to content

Add Gemini AI resilience: error handling, response caching, and fallback mode#64

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/improve-ai-resilience
Draft

Add Gemini AI resilience: error handling, response caching, and fallback mode#64
Copilot wants to merge 2 commits intomainfrom
copilot/improve-ai-resilience

Conversation

Copy link

Copilot AI commented Feb 23, 2026

The app had no handling for Gemini API quota exhaustion (429/RESOURCE_EXHAUSTED), causing crashes and blank UI. This PR builds out the full budgeting app with resilient AI integration: typed error classification, localStorage caching, and a local-computation fallback when AI is unavailable.

Error handling (services/aiErrors.ts, services/geminiService.ts)

  • AIError type with kind: 'quota' | 'invalid_key' | 'network' | 'server' | 'unknown'
  • classifyHttpError() detects 429, RESOURCE_EXHAUSTED payloads, auth failures, and 5xx separately
  • Exponential backoff + jitter for transient (server/network) errors; no retry on quota/invalid_key
  • Guarded hasAIStudioKey() / openAIStudioKeySelector() — safe when window.aistudio is absent
// quota errors are returned immediately, never retried
if (err.kind === 'quota' || err.kind === 'invalid_key') {
  return { ok: false, error: err };
}

Response caching (services/aiCache.ts)

  • localStorage cache with versioned keys (rag7:ai-cache:v1:...), 12 h default TTL
  • Entries keyed by djb2 fingerprint of input data — financial snapshot changes automatically invalidate
  • Manual "Clear AI Cache" control in AI Advisor

Fallback mode (services/localInsights.ts, components/FallbackInsights.tsx)

  • When AI is unavailable, computes local insights from raw data: top spend categories, largest expense, bills due in 7 days, savings rate
  • FallbackInsights renders reason-specific messages (quota / network / disabled) with recovery CTA
  • "Disable AI features" toggle persisted in localStorage

Components

  • Dashboard: fingerprint-based deduplication prevents redundant API calls on re-render; shows cached badge () when served from cache
  • AIAdvisor: cache-first with manual cache clear and fallback on error
  • ChatWidget: floating chat with per-message cache hits and quota error bar

Tests (Vitest)

26 unit tests covering:

  • Error classification for all kind variants
  • Cache get/set/TTL expiry/fingerprint mismatch/clear-all
  • Fingerprint determinism and key-order stability
Original prompt

Goal

Create a pull request that improves resilience of the AI features in the budgeting/bill paying app by adding:

  1. Additional error handling and quota management for Gemini API calls (especially 429 RESOURCE_EXHAUSTED).
  2. Response caching to reduce API calls.
  3. A fallback mode that keeps the app usable when AI is unavailable or quota is exceeded.

Repository

Work in Stacey77/rag7.

Context

The app currently integrates Gemini (Gemini 3 Flash Preview) via services/geminiService.ts and AI UI components such as components/AIAdvisor.tsx, and possibly components/ChatWidget.tsx / voice-related components.
Users can hit the error:

Gemini API Error:
{"error":{"code":429,"message":"You exceeded your current quota, please check your plan and billing details...","status":"RESOURCE_EXHAUSTED"}}

The app should gracefully handle this state and guide users to connect/select their own API key where applicable.

Requirements

A) Robust error handling + quota management

  • Detect quota/rate-limit conditions reliably:
    • HTTP 429 and/or Gemini error payloads with status: "RESOURCE_EXHAUSTED".
    • Handle transient errors separately (5xx, network timeouts) vs hard quota.
  • Implement a retry strategy for transient errors:
    • Exponential backoff with jitter.
    • Max attempts configurable.
    • Do not retry on hard quota errors (429/RESOURCE_EXHAUSTED) beyond perhaps a single short retry.
  • Normalize errors from geminiService into a typed error structure (e.g., AIError with kind: 'quota' | 'network' | 'server' | 'invalid_key' | 'unknown', message, and raw info).
  • Ensure UI components can render a consistent error state.
  • If the environment supports AI Studio key selection (e.g., window.aistudio.hasSelectedApiKey() / window.aistudio.openSelectKey()), surface a clear CTA button to select/connect a key when quota is exhausted.
    • Guard these calls so the app doesn’t crash when window.aistudio is absent.

B) Response caching to reduce API calls

  • Add caching for AI outputs (at least for Dashboard insight summary and AI Advisor outputs).
  • Cache should:
    • Use localStorage (or another simple client-side store) with versioned keys.
    • Support TTL (e.g., 6–24 hours; choose a sensible default).
    • Be keyed by an input hash/fingerprint so different prompts or materially different financial snapshots produce distinct cache entries.
      • For example, fingerprint can include: last N transactions summary, upcoming bills summary, goals snapshot, and the prompt type.
  • Provide a way to invalidate cache:
    • Automatically invalidate when underlying financial data changes (e.g., transactions/bills updated) by including a data signature in the key.
    • Also provide a manual “Clear AI cache” action in UI settings if there is a settings area; otherwise add a small control in AI Advisor.
  • Ensure caching is used before making network calls.

C) Fallback mode (No-AI mode)

  • When AI is unavailable (quota exhausted, missing key, offline), the app should:
    • Continue to load pages without crashing.
    • Replace AI cards with a fallback component that provides basic, non-AI insights computed locally from existing app data:
      • Example: spending top categories, largest expense in last 30 days, bills due soon, simple savings rate.
    • Clearly indicate that AI is temporarily unavailable and why (quota/offline).
    • Offer steps to restore AI (select key / try later).
  • Add a user-controlled toggle “Disable AI features” (optional but preferred) to avoid any AI calls.
    • Persist this preference.

D) Testing & quality

  • Add unit tests for:
    • Error classification (quota vs transient vs unknown).
    • Cache get/set/TTL behavior.
    • Fingerprint stability.
  • If the repo lacks a test framework, add lightweight tests consistent with the existing stack (likely Vite + React + TypeScript; use Vitest if present).
  • Ensure TypeScript types are correct and build passes.

E) Documentation

  • Update README (or a short in-app help section) describing:
    • Why quota errors happen.
    • How caching works.
    • How to connect/select an API key.
    • How fallback mode behaves.

Implementation hints (not strict)

  • Add a module like services/aiCache.ts and services/aiErrors.ts.
  • Update geminiService.ts to use these utilities and return typed results.
  • Update AI UI components (AIAdvisor, Dashboard AI card, ChatWidget/VoiceCoach if they call AI) to:
    • Use cache-first.
    • Use fallback UI on failure.
    • Avoid repeated calls on re-render (useMemo/useEffect deps carefully).

Acceptance criteria

  • When a 429/RESOURCE_EXHAUSTED occurs, the UI shows a friendly message, does not loop requests, and offers “Connect/Select API Key” if supported.
  • Re-opening the Dashboard/AIAdvisor within the TTL uses cached insights (verify by not issuing new API calls).
  • When AI is disabled/unavailable, fallback insights show and the rest of the app works normally.
  • Tests added and passing.

This pull request was created from Copilot chat.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…k mode, and tests

Co-authored-by: Stacey77 <54900383+Stacey77@users.noreply.github.com>
Copilot AI changed the title [WIP] Improve resilience of AI features in budgeting app Add Gemini AI resilience: error handling, response caching, and fallback mode Feb 23, 2026
Copilot AI requested a review from Stacey77 February 23, 2026 01:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants