diff --git a/src/helpers/ipcHandlers.js b/src/helpers/ipcHandlers.js index ef657ab..7521a65 100644 --- a/src/helpers/ipcHandlers.js +++ b/src/helpers/ipcHandlers.js @@ -1032,24 +1032,70 @@ ${text} requestData }); - const response = await fetch(`${baseUrl}/chat/completions`, { - method: 'POST', - headers: { - 'Authorization': `Bearer ${apiKey}`, - 'Content-Type': 'application/json' - }, - body: JSON.stringify(requestData) - }); + // 重试配置:2秒超时,最多3次重试 + const MAX_RETRIES = 3; + const TIMEOUT_MS = 2000; // 2秒超时 + const RETRY_DELAY_MS = 1000; // 重试间隔1秒 - if (!response.ok) { - const errorText = await response.text(); - let errorData = { error: response.statusText }; + let lastError = null; + let response = null; + + for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) { try { - errorData = JSON.parse(errorText); - } catch { - errorData = { error: errorText || response.statusText }; + this.logger.info(`AI请求第 ${attempt}/${MAX_RETRIES} 次尝试, 超时: ${TIMEOUT_MS}ms`); + + // 使用 AbortController 实现超时 + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS); + + try { + response = await fetch(`${baseUrl}/chat/completions`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${apiKey}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(requestData), + signal: controller.signal + }); + clearTimeout(timeoutId); + + // 请求成功,跳出重试循环 + if (response.ok) { + this.logger.info(`AI请求第 ${attempt} 次成功`); + break; + } else { + // 非超时错误,也记录下来 + const errorText = await response.text(); + lastError = new Error(`API错误 ${response.status}: ${errorText}`); + this.logger.warn(`AI请求第 ${attempt} 次失败: ${lastError.message}`); + } + } catch (fetchError) { + clearTimeout(timeoutId); + + if (fetchError.name === 'AbortError') { + lastError = new Error(`请求超时 (${TIMEOUT_MS / 1000}秒)`); + this.logger.warn(`AI请求第 ${attempt} 次超时`); + } else { + lastError = fetchError; + this.logger.warn(`AI请求第 ${attempt} 次失败: ${fetchError.message}`); + } + } + + // 如果不是最后一次尝试,等待后重试 + if (attempt < MAX_RETRIES) { + this.logger.info(`等待 ${RETRY_DELAY_MS}ms 后重试...`); + await new Promise(resolve => setTimeout(resolve, RETRY_DELAY_MS)); + } + } catch (error) { + lastError = error; + this.logger.error(`AI请求第 ${attempt} 次异常: ${error.message}`); } - throw new Error(errorData.error?.message || errorData.error || `API error: ${response.status}`); + } + + // 检查是否所有重试都失败了 + if (!response || !response.ok) { + throw lastError || new Error('所有重试均失败'); } const data = await response.json(); @@ -1097,8 +1143,8 @@ ${text} } else { errorMessage = `API错误: ${error.response.status}`; } - } else if (error.code === 'ECONNABORTED') { - errorMessage = '请求超时,请检查网络连接'; + } else if (error.message.includes('超时')) { + errorMessage = '请求超时,已重试3次仍失败,请检查网络连接'; } else if (error.code === 'ENOTFOUND') { errorMessage = '无法连接到AI服务器,请检查网络'; } else {