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 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
- consola.warn(`Account ${account.label}: network error (not rotating): ${errMsg}`);
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...`);