feat: AI 调用稳定性增强(可重试错误分类 + 指数退避 + 修复链路错误透传)
- providers/base.ts 引入 ApiRequestError 与 isRetryableError,按 429/5xx/超时/网络错误/401 分类 - chatWithRetry 升级为最多 3 次指数退避(1s/2s/4s),非重试错误立即上抛;新增 setRetryBaseDelayForTest 钩子 - aiFixEngine/customFixEngine 不再吞错,修复失败原因透传为 ai-error: <原因> - 扩展 ai-empty-response/customFixEngine 测试覆盖重试与分类
This commit is contained in:
+23
-7
@@ -1,5 +1,5 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { EmptyContentError } from './providers/base';
|
||||
import { isRetryableError } from './providers/base';
|
||||
import type { AIProvider, ChatOptions } from './providers/base';
|
||||
import { createProvider } from './factory';
|
||||
import { getAIProvider, getAIModel, getAIBaseUrl, getAITemperature, getAITimeout, getAIMaxTokens, getAIOutputLanguage, getApiKey } from '../config';
|
||||
@@ -83,20 +83,36 @@ export function parseJsonResponse(raw: string): object {
|
||||
}
|
||||
}
|
||||
|
||||
const RETRY_MAX_ATTEMPTS = 3;
|
||||
const RETRY_BASE_DELAY_MS = 1000;
|
||||
|
||||
let retryBaseDelayMs = RETRY_BASE_DELAY_MS;
|
||||
|
||||
export function setRetryBaseDelayForTest(ms: number): void {
|
||||
retryBaseDelayMs = ms;
|
||||
}
|
||||
|
||||
function sleep(ms: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
export async function chatWithRetry(
|
||||
provider: AIProvider,
|
||||
systemPrompt: string,
|
||||
userPrompt: string,
|
||||
options: ChatOptions
|
||||
): Promise<string> {
|
||||
try {
|
||||
return await provider.chat(systemPrompt, userPrompt, options);
|
||||
} catch (err) {
|
||||
if (err instanceof EmptyContentError) {
|
||||
return provider.chat(systemPrompt, userPrompt, options);
|
||||
for (let attempt = 0; attempt <= RETRY_MAX_ATTEMPTS; attempt++) {
|
||||
try {
|
||||
return await provider.chat(systemPrompt, userPrompt, options);
|
||||
} catch (err) {
|
||||
if (attempt === RETRY_MAX_ATTEMPTS || !isRetryableError(err)) {
|
||||
throw err;
|
||||
}
|
||||
await sleep(retryBaseDelayMs * 2 ** attempt);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
throw new Error('unreachable');
|
||||
}
|
||||
|
||||
function buildCustomRuleSystemPrompt(): string {
|
||||
|
||||
Reference in New Issue
Block a user