Skip to content
File

Blob: src/worker/lib/ai/client-error.ts

typescript35 lines
1import type { AiErrorCode } from "@/shared/ai";
2import { AiBackendError, AiMisconfiguredError } from "@/worker/lib/ai/types";
3 
4const SAFE_MESSAGES: Record<AiErrorCode, string> = {
5 ai_misconfigured: "AI backend unavailable",
6 ai_not_entitled: "AI action not permitted on this page",
7 ai_chat_failed: "Upstream AI service failed",
8 ai_chat_no_stream: "Upstream AI service did not return a stream",
9 ai_summarize_failed: "Upstream AI service failed",
10 ai_summarize_empty: "Upstream AI service returned an empty response",
11 ai_backend_failed: "Upstream AI service failed",
12 ai_failed: "AI request failed",
13 page_empty: "Page has no body text yet",
14 rate_limited: "Rate limit exceeded",
15 unauthorized: "Authentication required",
16 not_found: "Not found",
17 request_failed: "AI request failed",
18 validation_error: "Invalid request",
19};
20 
21// Routes must use this when sending error text to clients. Raw upstream bodies
22// can include prompts or provider details, so they never leave the worker
23// boundary; only a fixed code-keyed string does. `errorContext(err)` continues
24// to capture whatever the underlying Error carries for server logs.
25export function clientAiErrorMessage(err: unknown): { code: AiErrorCode; message: string } {
26 const code = aiErrorCode(err);
27 return { code, message: SAFE_MESSAGES[code] ?? SAFE_MESSAGES.ai_failed };
28}
29 
30function aiErrorCode(err: unknown): AiErrorCode {
31 if (err instanceof AiBackendError) return err.code;
32 if (err instanceof AiMisconfiguredError) return err.code;
33 return "ai_failed";
34}