99052ada5f
Co-authored-by: Cursor <cursoragent@cursor.com>
34 lines
1.3 KiB
TypeScript
34 lines
1.3 KiB
TypeScript
/** Browser / WebView fetch failures are usually TypeError with an opaque message. */
|
|
|
|
export const AI_NETWORK_ERROR_CODE = "AI_UNREACHABLE";
|
|
|
|
const NETWORK_FETCH_HINTS = [
|
|
"failed to fetch",
|
|
"networkerror",
|
|
"network request failed",
|
|
"load failed",
|
|
"internet connection appears to be offline",
|
|
];
|
|
|
|
export function isLikelyNetworkFetchError(error: unknown): boolean {
|
|
const name = error instanceof Error ? error.name : "";
|
|
const msg = (error instanceof Error ? error.message : String(error ?? "")).toLowerCase();
|
|
if (msg === AI_NETWORK_ERROR_CODE.toLowerCase()) return true;
|
|
if (NETWORK_FETCH_HINTS.some((hint) => msg.includes(hint))) return true;
|
|
// Some WebViews surface a bare TypeError when fetch cannot complete.
|
|
return name === "TypeError" && !msg;
|
|
}
|
|
|
|
export function formatNetworkAwareMessage(
|
|
template: string,
|
|
error: unknown,
|
|
networkCopy: string,
|
|
): string {
|
|
const raw = error instanceof Error ? error.message : String(error ?? "");
|
|
const message = isLikelyNetworkFetchError(error) || isLikelyNetworkFetchError(raw) ? networkCopy : raw;
|
|
if (template.includes("{message}")) {
|
|
return template.split("{message}").join(String(message));
|
|
}
|
|
return isLikelyNetworkFetchError(error) || isLikelyNetworkFetchError(raw) ? networkCopy : template;
|
|
}
|