// In-memory cache of the most recent relay-reported credit balance + tier. // Updated every time a relay provider call lands (success or 4xx error // that includes the standard envelope). Exposed via /api/relay/status // so the UI can render the "N credits remaining · Tier: X" banner // without re-hitting the relay just for status. // // Not persisted to disk — the relay is the source of truth. We just cache // the last response so the UI doesn't have to wait for the next request // to refresh the display. On a fresh boot the cache is empty until the // first /api/relay/status call, which can optionally probe the relay. let lastSnapshot = { creditsRemaining: null, // number | null tier: null, // "core" | "pro" | "max" | null lastUpdated: null, // ms-epoch | null lastError: null, // string | null }; // Called by the relay provider on every response (including error // responses that the relay annotated with the standard envelope). // `envelope` is the parsed JSON shape: { credits_remaining, tier, ... }. export function updateRelayState(envelope) { if (!envelope || typeof envelope !== "object") return; if (typeof envelope.credits_remaining === "number") { lastSnapshot.creditsRemaining = envelope.credits_remaining; } if (typeof envelope.tier === "string") { lastSnapshot.tier = envelope.tier; } lastSnapshot.lastUpdated = Date.now(); lastSnapshot.lastError = null; } // Record a relay error (network failure, 5xx with no envelope, etc.). // Surfaced in the UI status so the user knows the balance display is stale. export function recordRelayError(message) { lastSnapshot.lastError = (message || "Unknown relay error").slice(0, 300); lastSnapshot.lastUpdated = Date.now(); } export function getRelayState() { return { ...lastSnapshot }; } export function resetRelayState() { lastSnapshot = { creditsRemaining: null, tier: null, lastUpdated: null, lastError: null, }; }