copilot-api-plus 1.2.49 → 1.2.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +51 -1
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2259,9 +2259,14 @@ async function handleMultiAccountHttpError(error, account, retryContext) {
|
|
|
2259
2259
|
case 429:
|
|
2260
2260
|
accountManager.markAccountStatus(account.id, "rate_limited", "429 Rate limited");
|
|
2261
2261
|
return null;
|
|
2262
|
+
case 408:
|
|
2263
|
+
consola.warn(`Account ${account.label}: 408 request timeout (network issue, not rotating)`);
|
|
2264
|
+
error.__nonAccountError = true;
|
|
2265
|
+
return null;
|
|
2262
2266
|
default:
|
|
2263
2267
|
if (error.response.status >= 500) {
|
|
2264
2268
|
accountManager.markAccountStatus(account.id, "error", `HTTP ${error.response.status}`);
|
|
2269
|
+
recordBreakerFailure(`HTTP ${error.response.status}`);
|
|
2265
2270
|
return null;
|
|
2266
2271
|
}
|
|
2267
2272
|
if (error.response.status === 400) {
|
|
@@ -2276,9 +2281,45 @@ async function handleMultiAccountHttpError(error, account, retryContext) {
|
|
|
2276
2281
|
return null;
|
|
2277
2282
|
}
|
|
2278
2283
|
}
|
|
2284
|
+
const CB_THRESHOLD = 3;
|
|
2285
|
+
const CB_OPEN_MS = 3e4;
|
|
2286
|
+
const breaker = {
|
|
2287
|
+
failures: 0,
|
|
2288
|
+
openedAt: 0
|
|
2289
|
+
};
|
|
2290
|
+
function breakerOpenRemainingMs() {
|
|
2291
|
+
if (breaker.openedAt === 0) return 0;
|
|
2292
|
+
const elapsed = Date.now() - breaker.openedAt;
|
|
2293
|
+
return elapsed >= CB_OPEN_MS ? 0 : CB_OPEN_MS - elapsed;
|
|
2294
|
+
}
|
|
2295
|
+
function recordBreakerSuccess() {
|
|
2296
|
+
if (breaker.failures !== 0 || breaker.openedAt !== 0) consola.info("Circuit breaker: closing (request succeeded)");
|
|
2297
|
+
breaker.failures = 0;
|
|
2298
|
+
breaker.openedAt = 0;
|
|
2299
|
+
}
|
|
2300
|
+
function recordBreakerFailure(reason) {
|
|
2301
|
+
breaker.failures += 1;
|
|
2302
|
+
if (breaker.failures >= CB_THRESHOLD && breaker.openedAt === 0) {
|
|
2303
|
+
breaker.openedAt = Date.now();
|
|
2304
|
+
consola.warn(`Circuit breaker OPEN for ${CB_OPEN_MS / 1e3}s after ${breaker.failures} consecutive failures (last: ${reason})`);
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2279
2307
|
async function createWithMultiAccount(payload) {
|
|
2308
|
+
const remaining = breakerOpenRemainingMs();
|
|
2309
|
+
if (remaining > 0) throw new HTTPError("Upstream temporarily unavailable", new Response(JSON.stringify({ error: {
|
|
2310
|
+
type: "service_unavailable",
|
|
2311
|
+
message: `Upstream (or proxy) is failing repeatedly. Circuit breaker open; will retry probe in ${Math.ceil(remaining / 1e3)}s.`
|
|
2312
|
+
} }), {
|
|
2313
|
+
status: 503,
|
|
2314
|
+
statusText: "Service Unavailable",
|
|
2315
|
+
headers: {
|
|
2316
|
+
"content-type": "application/json",
|
|
2317
|
+
"retry-after": String(Math.ceil(remaining / 1e3))
|
|
2318
|
+
}
|
|
2319
|
+
}));
|
|
2280
2320
|
const triedAccountIds = /* @__PURE__ */ new Set();
|
|
2281
2321
|
let lastError;
|
|
2322
|
+
let networkRetried = false;
|
|
2282
2323
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
2283
2324
|
const account = accountManager.getActiveAccount();
|
|
2284
2325
|
if (!account || triedAccountIds.has(account.id)) break;
|
|
@@ -2316,6 +2357,7 @@ async function createWithMultiAccount(payload) {
|
|
|
2316
2357
|
const result = await doFetch(payload, tokenSource, account.id);
|
|
2317
2358
|
account.lastRequestAt = Date.now();
|
|
2318
2359
|
accountManager.markAccountSuccess(account.id);
|
|
2360
|
+
recordBreakerSuccess();
|
|
2319
2361
|
if (Symbol.asyncIterator in result) result.__accountInfo = {
|
|
2320
2362
|
accountId: account.id,
|
|
2321
2363
|
accountProxy: account.proxy,
|
|
@@ -2333,7 +2375,15 @@ async function createWithMultiAccount(payload) {
|
|
|
2333
2375
|
if (error.__nonAccountError) throw error;
|
|
2334
2376
|
} else {
|
|
2335
2377
|
const errMsg = error.message || String(error);
|
|
2336
|
-
|
|
2378
|
+
if (!networkRetried) {
|
|
2379
|
+
networkRetried = true;
|
|
2380
|
+
consola.warn(`Account ${account.label}: network error, resetting pool and retrying once: ${errMsg}`);
|
|
2381
|
+
resetAccountConnections(account.id);
|
|
2382
|
+
triedAccountIds.delete(account.id);
|
|
2383
|
+
continue;
|
|
2384
|
+
}
|
|
2385
|
+
consola.warn(`Account ${account.label}: network error after retry (giving up): ${errMsg}`);
|
|
2386
|
+
recordBreakerFailure(`network: ${errMsg.slice(0, 80)}`);
|
|
2337
2387
|
throw error;
|
|
2338
2388
|
}
|
|
2339
2389
|
consola.warn(`Account ${account.label} failed (attempt ${attempt + 1}), trying next...`);
|