feat(proxy-fitness): pool fitness registry + Smart rotation + pool-scoped retry

Pool/IP fitness registry (globalThis-backed, provider::model scopes, 5-min
cooldown, provider::* wildcard) fed by pool-scoped failures: freebuff
limited-IP / model-locked gates and opencode free per-IP limits. chatCore
retries a failed pool via another pool without locking the account; new
Smart rotation strategy (per-connection + no-auth providers) skips unfit
pools. Proxy Fitness dashboard page: active-block table with provider/IP
filters, per-record Clear and provider-scoped Clear All; egress column via
pool geo enrichment. Unit tests for the registry.
This commit is contained in:
MUH. IQRAM BAHRING committed 2026-08-07 03:51:19 +08:00
1 parent 90ff8191ff
commit fd22290a34
17 files changed
+1000 -35

No files matched your search

+18
View File
@@ -17,6 +17,7 @@ import { errorResponse, unavailableResponse } from "open-sse/utils/error.js";
import { handleComboChat, handleFusionChat, detectRequiredCapabilities } from "open-sse/services/combo.js";
import { augmentModelsWithCapacityAdapter, withCapacityAdapterStripping, getActiveAdapterStrategy } from "open-sse/services/capacityAdapter.js";
import { handleBypassRequest } from "open-sse/utils/bypassHandler.js";
import { resolveConnectionProxyConfig } from "@/lib/network/connectionProxy";
import { HTTP_STATUS } from "open-sse/config/runtimeConfig.js";
import { detectFormatByEndpoint } from "open-sse/translator/formats.js";
import * as log from "../utils/logger.js";
@@ -284,6 +285,23 @@ async function handleSingleModelChat(body, modelStr, clientRawRequest = null, re
pxpipeTransform: chatSettings.pxpipeEnabled ? await getPxpipeTransform() : null,
onPxpipeEvent: appendPxpipeEvent,
providerThinking,
// Pool-scoped failure recovery: re-resolve proxy config excluding the
// failed pool so the request retries via another pool, not a dead end.
resolveProxyConfig: async (creds, excludePoolIds = []) => {
const psd = { ...(creds?.providerSpecificData || {}) };
if (psd.proxyPoolIds?.length) psd.proxyPoolScope = `${provider}::${model}`;
const resolved = await resolveConnectionProxyConfig(psd, creds?.connectionId || creds?.id, excludePoolIds);
if (!resolved?.proxyPoolId) return null;
return {
connectionProxyEnabled: resolved.connectionProxyEnabled,
connectionProxyUrl: resolved.connectionProxyUrl,
connectionNoProxy: resolved.connectionNoProxy,
connectionProxyPoolId: resolved.proxyPoolId || null,
vercelRelayUrl: resolved.vercelRelayUrl || "",
proxyPoolId: resolved.proxyPoolId || null,
strictProxy: resolved.strictProxy === true,
};
},
// Detect source format by endpoint + body
sourceFormatOverride: request?.url ? detectFormatByEndpoint(new URL(request.url).pathname, body) : null,
onCredentialsRefreshed: async (newCreds) => {