From e4110cf2dbe192b35a9a743266e23c51a41807a2 Mon Sep 17 00:00:00 2001 From: m Date: Fri, 8 May 2026 02:19:48 +0200 Subject: [PATCH] feat(t-paliad-151) frontend: friendly errors for remote-Paliadin codes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extends the SSE error switch in frontend/src/client/paliadin.ts' friendlyErrorMessage to map four new error codes from RemotePaliadin Service into localised messages: - mriver_unreachable: mRiver is offline / paliadin-shim unreachable (DE: "mRiver ist offline — Paliadin nicht erreichbar. Mach mRiver an, oder nutze Paliadin lokal mit ./paliad." EN: "mRiver is offline — Paliadin can't reach it. Wake mRiver, or run Paliadin locally with ./paliad.") - shim_auth_failed: SSH key / authorized_keys mismatch (Permission denied) - shim_error / bootstrap_failed: generic remote-shim failure - timeout: Claude didn't write the response file in 60 s Adds the matching i18n keys (DE + EN) plus the type-union entries in i18n-keys.ts so the t() typecheck stays sound. The old codes (tmux_unavailable, connection_lost, upstream) are unchanged — local-PoC deployments keep their existing UX. Frontend `bun run build` clean: 1886 keys (unchanged sync). Refs m/paliad#12 --- frontend/src/client/i18n.ts | 8 ++++++++ frontend/src/client/paliadin.ts | 20 ++++++++++++++++++-- frontend/src/i18n-keys.ts | 4 ++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/frontend/src/client/i18n.ts b/frontend/src/client/i18n.ts index 97fd575..dbe7214 100644 --- a/frontend/src/client/i18n.ts +++ b/frontend/src/client/i18n.ts @@ -1558,6 +1558,10 @@ const translations: Record> = { "paliadin.stop": "Stop", "paliadin.reset": "Neue Unterhaltung", "paliadin.error.local_only": "Paliadin läuft nur lokal. Diese Instanz hat kein tmux/claude installiert — lokal mit ./paliad starten.", + "paliadin.error.mriver_unreachable": "mRiver ist offline — Paliadin nicht erreichbar. Mach mRiver an, oder nutze Paliadin lokal mit ./paliad.", + "paliadin.error.shim_auth_failed": "Paliadin-Authentifizierung fehlgeschlagen. SSH-Schlüssel oder Berechtigung auf mRiver prüfen.", + "paliadin.error.shim_error": "Paliadin-Fehler auf mRiver. tmux/claude-Pane prüfen.", + "paliadin.error.timeout": "Paliadin antwortet nicht (Timeout 60s). Nochmal versuchen.", "paliadin.error.connection_lost": "Verbindung verloren.", "paliadin.error.upstream": "Fehler beim Senden.", "nav.admin.paliadin": "Paliadin Monitor", @@ -3553,6 +3557,10 @@ const translations: Record> = { "paliadin.stop": "Stop", "paliadin.reset": "New conversation", "paliadin.error.local_only": "Paliadin only runs locally. This instance has no tmux/claude installed — start it locally via ./paliad.", + "paliadin.error.mriver_unreachable": "mRiver is offline — Paliadin can't reach it. Wake mRiver, or run Paliadin locally with ./paliad.", + "paliadin.error.shim_auth_failed": "Paliadin auth failed. Check the SSH key or authorized_keys on mRiver.", + "paliadin.error.shim_error": "Paliadin error on mRiver. Check the tmux/claude pane.", + "paliadin.error.timeout": "Paliadin didn't respond in time (60s). Try again.", "paliadin.error.connection_lost": "Connection lost.", "paliadin.error.upstream": "Send failed.", "nav.admin.paliadin": "Paliadin Monitor", diff --git a/frontend/src/client/paliadin.ts b/frontend/src/client/paliadin.ts index acde8d1..d3c174e 100644 --- a/frontend/src/client/paliadin.ts +++ b/frontend/src/client/paliadin.ts @@ -210,8 +210,24 @@ function friendlyErrorMessage(data: unknown): string { } try { const parsed = JSON.parse(data) as { code?: string }; - if (parsed.code === "tmux_unavailable") { - return t("paliadin.error.local_only"); + switch (parsed.code) { + case "tmux_unavailable": + // Local PoC path: paliad is running on a host without tmux/claude + // (typically the legacy laptop-only build). + return t("paliadin.error.local_only"); + case "mriver_unreachable": + // t-paliad-151: prod path's mRiver is offline (laptop asleep, off + // tailnet, or paliadin-shim missing). + return t("paliadin.error.mriver_unreachable"); + case "shim_auth_failed": + // SSH key wrong or authorized_keys drifted. + return t("paliadin.error.shim_auth_failed"); + case "shim_error": + case "bootstrap_failed": + // Generic remote shim failure or system-prompt bootstrap error. + return t("paliadin.error.shim_error"); + case "timeout": + return t("paliadin.error.timeout"); } } catch { // Not JSON — fall through to the generic connection-lost message diff --git a/frontend/src/i18n-keys.ts b/frontend/src/i18n-keys.ts index ad85ce8..706ab7e 100644 --- a/frontend/src/i18n-keys.ts +++ b/frontend/src/i18n-keys.ts @@ -1423,6 +1423,10 @@ export type I18nKey = | "paliadin.empty" | "paliadin.error.connection_lost" | "paliadin.error.local_only" + | "paliadin.error.mriver_unreachable" + | "paliadin.error.shim_auth_failed" + | "paliadin.error.shim_error" + | "paliadin.error.timeout" | "paliadin.error.upstream" | "paliadin.heading" | "paliadin.input.placeholder"