This commit is contained in:
+27
-1
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user