mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 13:22:14 +00:00
feat(ai): durable provider-health ledger and credential-expired surfacing
Promote the volatile per-worker last-working cache to a Postgres provider-health ledger so the fallback chain shares one health signal across every instance, modelled on the atomic-upsert rate limiter. The ledger holds a durable negative cache: an auth-class failure (401/403) benches that provider for a cooldown instead of re-burning the dead round-trip on every generation; a sustained hard failure backs off briefly. The local model is never benched — it stays the guaranteed floor of the chain. Every ledger interaction fails open, so a DB error falls back to today's chain walk exactly. When the user's primary provider fails auth-class, the Coach emits a distinct credential_expired frame that deep-links to reconnect rather than a generic "try again later". Adds the provider_health table (migration 0112) and the errorCredentialExpired copy across all locales.
This commit is contained in:
1 parent
6db3bef413
commit
fbd45f3044
15 files changed
+949
-3
No files matched your search
@@ -543,6 +543,14 @@ describe("errorCodeToI18nKey", () => {
|
||||
);
|
||||
});
|
||||
|
||||
// v1.11.0 W1 — a dead primary credential gets the reconnect copy, not
|
||||
// the generic provider-unavailable copy.
|
||||
it("maps coach.provider.credential_expired to the reconnect key", () => {
|
||||
expect(errorCodeToI18nKey("coach.provider.credential_expired")).toBe(
|
||||
"insights.coach.errorCredentialExpired",
|
||||
);
|
||||
});
|
||||
|
||||
it("forward-compats unknown codes with the namespaced key", () => {
|
||||
expect(errorCodeToI18nKey("errorProvider")).toBe(
|
||||
"insights.coach.errorProvider",
|
||||
|
||||
@@ -88,6 +88,11 @@ export function errorCodeToI18nKey(code: string): string {
|
||||
// than a provider failure ("try again in a moment"). Split out
|
||||
// so the user sees the actionable copy in the offline branch.
|
||||
return "insights.coach.errorNetwork";
|
||||
case "coach.provider.credential_expired":
|
||||
// v1.11.0 W1 — the user's primary AI provider credential is dead
|
||||
// (auth-class failure). The next action is "reconnect", not "try
|
||||
// again later", so it carries its own copy pointing at Settings.
|
||||
return "insights.coach.errorCredentialExpired";
|
||||
case "coach.provider.unavailable":
|
||||
case "coach.provider.empty":
|
||||
case "coach.provider.none":
|
||||
|
||||
Reference in new issue
Block a user