fix(review-resolve): 支援 wrapper findings 並修正輸出格式

This commit is contained in:
2026-08-07 16:41:47 +00:00
parent 605d557455
commit 65dcb52777
8 changed files with 184 additions and 109 deletions
+14 -30
View File
@@ -31,24 +31,9 @@ export async function mapWithConcurrency(items, limit, fn) {
const workers = (!Number.isFinite(n) || n <= 0) ? list.length : Math.min(n, list.length);
let cursor = 0;
/**
* mapWithConcurrency 的工作者(worker)迴圈:從共用游標 `cursor` 依序搶下一個尚未
* 處理的索引,呼叫外層傳入的 `fn`,並把結果寫入外層 `results` 陣列對應位置;直到
* `cursor` 到達 `list.length` 為止。
* 內部 worker:從共用游標依序搶下一個索引,呼叫 `fn` 後把結果寫回對應位置。
*
* 多個 `run()` 會被同時啟動(依 `workers` 數量),透過共用的 `cursor` 變數達到
* 「限制併發數、動態搶下一筆」的效果——先完成者會先搶到下一個索引,因此各次 `fn`
* 呼叫的完成順序不保證,但因寫入位置以原始索引 `i` 為準,`results` 仍能保持與
* `items` 相同順序。
*
* 本函式為 `mapWithConcurrency` 內部使用的閉包(closure),依賴外層作用域的
* `list`、`results`、`fn`、`cursor` 變數運作;不接受參數,也不可、不應在外部
* 單獨呼叫或匯出。
*
* @returns {Promise<void>} 無回傳值;副作用為寫入外層 `results` 陣列與推進 `cursor`。
* @throws 若某次 `fn(list[i], i)` reject,本函式會原樣向外拋出該錯誤(不吞例外),
* 使 `mapWithConcurrency` 的 `Promise.all` 立即 reject;但其他已啟動、尚在執行
* 中的 `run()` 實例不會被取消,仍會在背景繼續搬移 `cursor` 並寫入 `results`,
* 只是其結果最終會被捨棄。
* @returns {Promise<void>} 無回傳值。
*/
async function run() {
while (cursor < list.length) {
@@ -132,10 +117,10 @@ function summarizeApiError(e) {
|| responseData?.message
|| responseData?.error
|| '';
const stderr = String(e.stderr || '').trim();
const stdout = String(e.stdout || '').trim();
const stderr = String(e?.stderr || '').trim();
const stdout = String(e?.stdout || '').trim();
const status = e?.response?.status ? `HTTP ${e.response.status}` : '';
const message = extractMeaningfulError(responseText || stderr || stdout || e.message || String(e));
const message = extractMeaningfulError(responseText || stderr || stdout || e?.message || String(e));
return [status, message].filter(Boolean).join(' ').trim();
}
@@ -164,18 +149,17 @@ async function runProxyAPI({ provider, baseURL, apiKeys, model }, prompt) {
const maxBuffer = Number(process.env.AI_ASSISTANT_MAX_BUFFER || 20 * 1024 * 1024);
const root = String(baseURL || '').trim().replace(/\/$/, '');
const apiKey = Array.isArray(apiKeys) ? apiKeys[0] : '';
const body = {
messages: [
{ role: 'system', content: '請依照以下系統指示處理使用者內容,並只輸出要求的最終結果。' },
{ role: 'user', content: prompt },
],
temperature: 0,
stream: false,
};
if (model) body.model = model;
const resp = await axios.post(
`${root}/v1/chat/completions`,
body,
{
messages: [
{ role: 'system', content: '請依照以下系統指示處理使用者內容,並只輸出要求的最終結果。' },
{ role: 'user', content: prompt },
],
temperature: 0,
stream: false,
...(model ? { model } : {}),
},
{
timeout,
maxBodyLength: maxBuffer,