fix(ai): 网络失败时显示友好提示,不再直接展示 Failed to fetch

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
fucheng
2026-09-20 09:59:35 +08:00
parent b008307f82
commit 99052ada5f
11 changed files with 92 additions and 21 deletions
+13 -10
View File
@@ -39,6 +39,7 @@ import {
streamQuestion,
updateMessageApplied,
} from "@/lib/aiApi";
import { formatNetworkAwareMessage, isLikelyNetworkFetchError } from "@/lib/networkError";
import { buildPeqSvgCurveData, getFilterType, PeqBandForResponse } from "@/lib/peqAudio";
import { cn } from "@/lib/utils";
@@ -305,7 +306,7 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
const list = await listChats(mac);
setChats(list);
} catch (e: any) {
toast.error(formatText(aiText.loadHistoryFailed, { message: e?.message ?? e }));
toast.error(formatNetworkAwareMessage(aiText.loadHistoryFailed, e, aiText.aiUnreachable));
}
}, [aiText, mac]);
@@ -357,7 +358,7 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
setChatId(id);
if (opts?.closePanel !== false) setHistoryOpen(false);
} catch (e: any) {
toast.error(formatText(aiText.loadChatFailed, { message: e?.message ?? e }));
toast.error(formatNetworkAwareMessage(aiText.loadChatFailed, e, aiText.aiUnreachable));
}
},
[aiText, mapRowsToUI, settleRiskyConfirm],
@@ -429,7 +430,7 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
newChat();
toast.success(aiText.cleared);
} catch (e: any) {
toast.error(formatText(aiText.clearFailed, { message: e?.message ?? e }));
toast.error(formatNetworkAwareMessage(aiText.clearFailed, e, aiText.aiUnreachable));
}
}, [aiText, chatId, newChat]);
@@ -445,7 +446,7 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
toast.success(aiText.history.deleted);
} catch (e: any) {
toast.error(
formatText(aiText.history.deleteFailed, { message: e?.message ?? e }),
formatNetworkAwareMessage(aiText.history.deleteFailed, e, aiText.aiUnreachable),
);
}
}, [aiText, chatId]);
@@ -514,14 +515,15 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
msgCount: deviceState.msgCount ?? 0,
};
} catch (e: any) {
const text = isLikelyNetworkFetchError(e) ? aiText.deviceUnreachable : aiText.requestFailed;
updateAssistant((m) => ({
...m,
pending: false,
error: true,
text: aiText.requestFailed,
text,
}));
setSending(false);
toast.error(formatText(aiText.requestFailed, { message: e?.message ?? e }));
toast.error(text);
return;
}
@@ -560,15 +562,16 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
try {
await sendToolResult(block.id, result);
} catch (e: any) {
toast.error(formatText(aiText.toolResultFailed, { message: e?.message ?? e }));
toast.error(formatNetworkAwareMessage(aiText.toolResultFailed, e, aiText.aiUnreachable));
}
},
onError: (msg) => {
const text = isLikelyNetworkFetchError(msg) ? aiText.aiUnreachable : (msg || aiText.requestFailed);
updateAssistant((m) => ({
...m,
pending: false,
error: true,
text: m.text || msg || aiText.requestFailed,
text: m.text || text,
}));
setSending(false);
},
@@ -779,7 +782,7 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
nextApplied ? aiText.optimize.applySuccess : aiText.optimize.rollbackSuccess,
);
} catch (e: any) {
toast.error(formatText(aiText.optimize.applyFailed, { message: e?.message ?? e }));
toast.error(formatNetworkAwareMessage(aiText.optimize.applyFailed, e, aiText.deviceUnreachable));
} finally {
setApplyingId(null);
}
@@ -812,7 +815,7 @@ export default function AIPage({ variant = "page", onClose }: AIPageProps = {})
await updateSetting(bypassOn ? { peqEnable: 1, dsp_enable: 1 } : { peqEnable: 1 });
await executeApplyToggle(msg);
} catch (e: any) {
toast.error(formatText(aiText.optimize.applyFailed, { message: e?.message ?? e }));
toast.error(formatNetworkAwareMessage(aiText.optimize.applyFailed, e, aiText.deviceUnreachable));
}
},
[aiText, deviceState?.dsp_enable, executeApplyToggle, updateSetting],