From d013b714928a66b787dcbcd223ec4eecd93f14da Mon Sep 17 00:00:00 2001 From: "Eunice(Eunyoung) Shin" Date: Sat, 4 Jul 2026 20:21:37 +0900 Subject: [PATCH] fix: raise chat send timeout and distinguish timeout errors in toast AI report-chat responses can take 30s+ (multi-tool agent chain), but the shared axios client used a 15s timeout for every request. The frontend aborted before the AI service replied and showed a generic failure toast even though the backend later completed with 200 OK. --- src/api/reports.ts | 8 +++++++- src/components/common/ReportChatPanel.tsx | 11 +++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/api/reports.ts b/src/api/reports.ts index 3ca3628..425279b 100644 --- a/src/api/reports.ts +++ b/src/api/reports.ts @@ -80,8 +80,14 @@ export const reportsApi = { download: (id: string) => apiClient.get(`/reports/${id}/download`, { responseType: 'blob' }), + // BE→AI 서비스 호출이 여러 도구 체인(문헌 검색 등)을 거치며 30초 이상 걸릴 수 있어 + // 공용 15초 타임아웃 대신 BE의 AI 서비스 타임아웃(60초)에 맞춘 값을 사용한다. sendChatMessage: (reportId: string, message: string) => - apiClient.post(`/reports/${reportId}/chat/messages`, { message }), + apiClient.post( + `/reports/${reportId}/chat/messages`, + { message }, + { timeout: 65_000 }, + ), applyPatch: (patchId: string) => apiClient.post(`/reports/patch-proposals/${patchId}/apply`), diff --git a/src/components/common/ReportChatPanel.tsx b/src/components/common/ReportChatPanel.tsx index 13d9def..cbd7765 100644 --- a/src/components/common/ReportChatPanel.tsx +++ b/src/components/common/ReportChatPanel.tsx @@ -1,4 +1,5 @@ import { useState, useRef, useEffect } from 'react' +import axios from 'axios' import { reportsApi, type Report, type PatchProposal } from '@/api/reports' import { Icon } from '@/components/common/Icon' import { useToast } from '@/hooks/useToast' @@ -53,8 +54,14 @@ export function ReportChatPanel({ report, onPatchApplied }: Props) { patch: data.patch_proposal ?? undefined, }, ]) - } catch { - showToast({ title: '메시지 전송에 실패했습니다', kind: 'error' }) + } catch (error) { + const isTimeout = axios.isAxiosError(error) && error.code === 'ECONNABORTED' + showToast({ + title: isTimeout + ? 'AI 응답이 지연되고 있습니다. 잠시 후 새로고침해 확인해주세요' + : '메시지 전송에 실패했습니다', + kind: 'error', + }) setMessages((prev) => prev.slice(0, -1)) setInput(trimmed) } finally {