copilot-api-plus 1.2.50 → 1.2.52
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 +67 -10
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2184,9 +2184,12 @@ async function createWithSingleAccount(payload) {
|
|
|
2184
2184
|
}
|
|
2185
2185
|
if (!response.ok) {
|
|
2186
2186
|
const errorBody = await response.text();
|
|
2187
|
-
if (response.status === 400)
|
|
2188
|
-
|
|
2189
|
-
|
|
2187
|
+
if (response.status === 400) {
|
|
2188
|
+
const isExpectedReasoningError = errorBody.includes("reasoning_effort") || errorBody.includes("invalid_reasoning_effort") || errorBody.includes("does not support reasoning");
|
|
2189
|
+
const isModelNotSupported = errorBody.includes("model_not_supported");
|
|
2190
|
+
if (isExpectedReasoningError || isModelNotSupported) consola.debug(`400 (auto-handled): ${errorBody}`);
|
|
2191
|
+
else consola.warn(`400: ${errorBody}`);
|
|
2192
|
+
} else consola.error("Failed to create chat completions", {
|
|
2190
2193
|
status: response.status,
|
|
2191
2194
|
statusText: response.statusText,
|
|
2192
2195
|
body: errorBody
|
|
@@ -2266,6 +2269,7 @@ async function handleMultiAccountHttpError(error, account, retryContext) {
|
|
|
2266
2269
|
default:
|
|
2267
2270
|
if (error.response.status >= 500) {
|
|
2268
2271
|
accountManager.markAccountStatus(account.id, "error", `HTTP ${error.response.status}`);
|
|
2272
|
+
recordBreakerFailure(`HTTP ${error.response.status}`);
|
|
2269
2273
|
return null;
|
|
2270
2274
|
}
|
|
2271
2275
|
if (error.response.status === 400) {
|
|
@@ -2280,7 +2284,42 @@ async function handleMultiAccountHttpError(error, account, retryContext) {
|
|
|
2280
2284
|
return null;
|
|
2281
2285
|
}
|
|
2282
2286
|
}
|
|
2287
|
+
const CB_THRESHOLD = 3;
|
|
2288
|
+
const CB_OPEN_MS = 3e4;
|
|
2289
|
+
const breaker = {
|
|
2290
|
+
failures: 0,
|
|
2291
|
+
openedAt: 0
|
|
2292
|
+
};
|
|
2293
|
+
function breakerOpenRemainingMs() {
|
|
2294
|
+
if (breaker.openedAt === 0) return 0;
|
|
2295
|
+
const elapsed = Date.now() - breaker.openedAt;
|
|
2296
|
+
return elapsed >= CB_OPEN_MS ? 0 : CB_OPEN_MS - elapsed;
|
|
2297
|
+
}
|
|
2298
|
+
function recordBreakerSuccess() {
|
|
2299
|
+
if (breaker.failures !== 0 || breaker.openedAt !== 0) consola.info("Circuit breaker: closing (request succeeded)");
|
|
2300
|
+
breaker.failures = 0;
|
|
2301
|
+
breaker.openedAt = 0;
|
|
2302
|
+
}
|
|
2303
|
+
function recordBreakerFailure(reason) {
|
|
2304
|
+
breaker.failures += 1;
|
|
2305
|
+
if (breaker.failures >= CB_THRESHOLD && breaker.openedAt === 0) {
|
|
2306
|
+
breaker.openedAt = Date.now();
|
|
2307
|
+
consola.warn(`Circuit breaker OPEN for ${CB_OPEN_MS / 1e3}s after ${breaker.failures} consecutive failures (last: ${reason})`);
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2283
2310
|
async function createWithMultiAccount(payload) {
|
|
2311
|
+
const remaining = breakerOpenRemainingMs();
|
|
2312
|
+
if (remaining > 0) throw new HTTPError("Upstream temporarily unavailable", new Response(JSON.stringify({ error: {
|
|
2313
|
+
type: "service_unavailable",
|
|
2314
|
+
message: `Upstream (or proxy) is failing repeatedly. Circuit breaker open; will retry probe in ${Math.ceil(remaining / 1e3)}s.`
|
|
2315
|
+
} }), {
|
|
2316
|
+
status: 503,
|
|
2317
|
+
statusText: "Service Unavailable",
|
|
2318
|
+
headers: {
|
|
2319
|
+
"content-type": "application/json",
|
|
2320
|
+
"retry-after": String(Math.ceil(remaining / 1e3))
|
|
2321
|
+
}
|
|
2322
|
+
}));
|
|
2284
2323
|
const triedAccountIds = /* @__PURE__ */ new Set();
|
|
2285
2324
|
let lastError;
|
|
2286
2325
|
let networkRetried = false;
|
|
@@ -2321,6 +2360,7 @@ async function createWithMultiAccount(payload) {
|
|
|
2321
2360
|
const result = await doFetch(payload, tokenSource, account.id);
|
|
2322
2361
|
account.lastRequestAt = Date.now();
|
|
2323
2362
|
accountManager.markAccountSuccess(account.id);
|
|
2363
|
+
recordBreakerSuccess();
|
|
2324
2364
|
if (Symbol.asyncIterator in result) result.__accountInfo = {
|
|
2325
2365
|
accountId: account.id,
|
|
2326
2366
|
accountProxy: account.proxy,
|
|
@@ -2346,6 +2386,7 @@ async function createWithMultiAccount(payload) {
|
|
|
2346
2386
|
continue;
|
|
2347
2387
|
}
|
|
2348
2388
|
consola.warn(`Account ${account.label}: network error after retry (giving up): ${errMsg}`);
|
|
2389
|
+
recordBreakerFailure(`network: ${errMsg.slice(0, 80)}`);
|
|
2349
2390
|
throw error;
|
|
2350
2391
|
}
|
|
2351
2392
|
consola.warn(`Account ${account.label} failed (attempt ${attempt + 1}), trying next...`);
|
|
@@ -2388,9 +2429,12 @@ async function doFetch(payload, source, accountId) {
|
|
|
2388
2429
|
});
|
|
2389
2430
|
if (!response.ok) {
|
|
2390
2431
|
const errorBody = await response.text();
|
|
2391
|
-
if (response.status === 400)
|
|
2392
|
-
|
|
2393
|
-
|
|
2432
|
+
if (response.status === 400) {
|
|
2433
|
+
const isExpectedReasoningError = errorBody.includes("reasoning_effort") || errorBody.includes("invalid_reasoning_effort") || errorBody.includes("does not support reasoning");
|
|
2434
|
+
const isModelNotSupported = errorBody.includes("model_not_supported");
|
|
2435
|
+
if (isExpectedReasoningError || isModelNotSupported) consola.debug(`400 (auto-handled): ${errorBody}`);
|
|
2436
|
+
else consola.warn(`400: ${errorBody}`);
|
|
2437
|
+
} else consola.error("Failed to create chat completions", {
|
|
2394
2438
|
status: response.status,
|
|
2395
2439
|
statusText: response.statusText,
|
|
2396
2440
|
body: errorBody
|
|
@@ -2737,11 +2781,20 @@ function translateModelName(model) {
|
|
|
2737
2781
|
const supportedModels = state.models?.data.map((m) => m.id) ?? [];
|
|
2738
2782
|
if (supportedModels.includes(model)) return model;
|
|
2739
2783
|
const modelBase = model.replace(/-\d{8}$/, "");
|
|
2740
|
-
if (supportedModels.includes(modelBase))
|
|
2784
|
+
if (supportedModels.includes(modelBase)) {
|
|
2785
|
+
consola.debug(`Model name: "${model}" → "${modelBase}" (stripped date suffix)`);
|
|
2786
|
+
return modelBase;
|
|
2787
|
+
}
|
|
2741
2788
|
const modelWithDot = modelBase.replace(/-(\d+)-(\d+)$/, "-$1.$2");
|
|
2742
|
-
if (supportedModels.includes(modelWithDot))
|
|
2789
|
+
if (supportedModels.includes(modelWithDot)) {
|
|
2790
|
+
consola.debug(`Model name: "${model}" → "${modelWithDot}" (dash→dot)`);
|
|
2791
|
+
return modelWithDot;
|
|
2792
|
+
}
|
|
2743
2793
|
const modelWithDash = model.replace(/(\d+)\.(\d+)/, "$1-$2");
|
|
2744
|
-
if (supportedModels.includes(modelWithDash))
|
|
2794
|
+
if (supportedModels.includes(modelWithDash)) {
|
|
2795
|
+
consola.debug(`Model name: "${model}" → "${modelWithDash}" (dot→dash)`);
|
|
2796
|
+
return modelWithDash;
|
|
2797
|
+
}
|
|
2745
2798
|
for (const [oldFormat, newFormat] of Object.entries({
|
|
2746
2799
|
"claude-3-5-sonnet": "claude-sonnet-4.5",
|
|
2747
2800
|
"claude-3-sonnet": "claude-sonnet-4",
|
|
@@ -2749,7 +2802,11 @@ function translateModelName(model) {
|
|
|
2749
2802
|
"claude-3-opus": "claude-opus-4.5",
|
|
2750
2803
|
"claude-3-5-haiku": "claude-haiku-4.5",
|
|
2751
2804
|
"claude-3-haiku": "claude-haiku-4.5"
|
|
2752
|
-
})) if (modelBase.startsWith(oldFormat) && supportedModels.includes(newFormat))
|
|
2805
|
+
})) if (modelBase.startsWith(oldFormat) && supportedModels.includes(newFormat)) {
|
|
2806
|
+
consola.debug(`Model name: "${model}" → "${newFormat}" (legacy mapping)`);
|
|
2807
|
+
return newFormat;
|
|
2808
|
+
}
|
|
2809
|
+
consola.warn(`Model name: "${model}" not found in supported models list, passing as-is`);
|
|
2753
2810
|
return model;
|
|
2754
2811
|
}
|
|
2755
2812
|
function translateAnthropicMessagesToOpenAI(anthropicMessages, system) {
|