copilot-api-plus 1.2.50 → 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 +38 -0
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2266,6 +2266,7 @@ async function handleMultiAccountHttpError(error, account, retryContext) {
|
|
|
2266
2266
|
default:
|
|
2267
2267
|
if (error.response.status >= 500) {
|
|
2268
2268
|
accountManager.markAccountStatus(account.id, "error", `HTTP ${error.response.status}`);
|
|
2269
|
+
recordBreakerFailure(`HTTP ${error.response.status}`);
|
|
2269
2270
|
return null;
|
|
2270
2271
|
}
|
|
2271
2272
|
if (error.response.status === 400) {
|
|
@@ -2280,7 +2281,42 @@ async function handleMultiAccountHttpError(error, account, retryContext) {
|
|
|
2280
2281
|
return null;
|
|
2281
2282
|
}
|
|
2282
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
|
+
}
|
|
2283
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
|
+
}));
|
|
2284
2320
|
const triedAccountIds = /* @__PURE__ */ new Set();
|
|
2285
2321
|
let lastError;
|
|
2286
2322
|
let networkRetried = false;
|
|
@@ -2321,6 +2357,7 @@ async function createWithMultiAccount(payload) {
|
|
|
2321
2357
|
const result = await doFetch(payload, tokenSource, account.id);
|
|
2322
2358
|
account.lastRequestAt = Date.now();
|
|
2323
2359
|
accountManager.markAccountSuccess(account.id);
|
|
2360
|
+
recordBreakerSuccess();
|
|
2324
2361
|
if (Symbol.asyncIterator in result) result.__accountInfo = {
|
|
2325
2362
|
accountId: account.id,
|
|
2326
2363
|
accountProxy: account.proxy,
|
|
@@ -2346,6 +2383,7 @@ async function createWithMultiAccount(payload) {
|
|
|
2346
2383
|
continue;
|
|
2347
2384
|
}
|
|
2348
2385
|
consola.warn(`Account ${account.label}: network error after retry (giving up): ${errMsg}`);
|
|
2386
|
+
recordBreakerFailure(`network: ${errMsg.slice(0, 80)}`);
|
|
2349
2387
|
throw error;
|
|
2350
2388
|
}
|
|
2351
2389
|
consola.warn(`Account ${account.label} failed (attempt ${attempt + 1}), trying next...`);
|