Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 63 additions & 17 deletions src/helpers/ipcHandlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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 {
Expand Down