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:
1 parent
90ff8191ff
commit
fd22290a34
17 files changed
+1000
-35
No files matched your search
@@ -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) => {
|
||||
|
||||
Reference in new issue
Block a user