fix(OpenCode 呼叫): 降低並行請求並重試暫時性錯誤
CI / AI Code Review (pull_request) Failing after 3s

This commit is contained in:
2026-06-26 09:36:33 +00:00
parent 6c3e7b9d37
commit 93be261b90
3 changed files with 56 additions and 7 deletions
+27 -1
View File
@@ -32,6 +32,10 @@ function opencodeAxiosOptions(headers) {
};
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* 從 OpenCode 訊息回應中抽取並串接所有文字片段。
*
@@ -66,6 +70,11 @@ function formatOpenCodeError(e) {
return response ? `${statusText}: ${response}` : statusText;
}
function isTransientOpenCodeError(e) {
const status = e.response?.status;
return status === 500 || status === 502 || status === 503 || status === 504 || status === 429;
}
/**
* 對 OpenCode server 執行一次完整對話:建立 session 後送出訊息並回傳結果。
*
@@ -104,6 +113,23 @@ async function chatOpenCode(baseURL, model, systemPrompt, userContent, headers)
return { content: extractOpenCodeContent(resp.data), data: resp.data };
}
async function chatOpenCodeWithRetry(baseURL, model, systemPrompt, userContent, headers) {
const maxAttempts = Number(process.env.OPENCODE_RETRY_ATTEMPTS || 3);
let lastError;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await chatOpenCode(baseURL, model, systemPrompt, userContent, headers);
} catch (e) {
lastError = e;
if (!isTransientOpenCodeError(e) || attempt === maxAttempts) throw e;
const delay = Math.min(1000 * 2 ** (attempt - 1), 8000);
line(`[LLM] OpenCode 暫時性錯誤,${delay}ms 後重試 (${attempt}/${maxAttempts}): ${formatOpenCodeError(e)}`);
await sleep(delay);
}
}
throw lastError;
}
/**
* 對 OpenCode server 送出一次對話請求並回傳模型純文字回應。
*
@@ -125,7 +151,7 @@ export async function chat(systemPrompt, userContent) {
const headers = { 'Content-Type': 'application/json' };
try {
const { content, data } = await chatOpenCode(baseURL, model, systemPrompt, userContent, headers);
const { content, data } = await chatOpenCodeWithRetry(baseURL, model, systemPrompt, userContent, headers);
recordUsage(data);
return content;
} catch (e) {