mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 20:00:47 +00:00
feat: - Introduced per-provider strategy overrides in settings, allowing for more flexible connection management.
- Added new provider models: DeepSeek 3.1, DeepSeek 3.2, and Qwen3 Coder Next. - Implemented UI changes to support round-robin strategy with sticky limits in the provider detail page. - Improved logging to display connection names instead of IDs for better clarity.
This commit is contained in:
@@ -156,8 +156,7 @@ async function handleSingleModelChat(body, modelStr, clientRawRequest = null, re
|
||||
}
|
||||
|
||||
// Log account selection
|
||||
const accountId = credentials.connectionId.slice(0, 8);
|
||||
log.info("AUTH", `Using ${provider} account: ${accountId}...`);
|
||||
log.info("AUTH", `\x1b[32mUsing ${provider} account: ${credentials.connectionName}\x1b[0m`);
|
||||
|
||||
const refreshedCredentials = await checkAndRefreshToken(provider, credentials);
|
||||
|
||||
@@ -202,7 +201,7 @@ async function handleSingleModelChat(body, modelStr, clientRawRequest = null, re
|
||||
const { shouldFallback } = await markAccountUnavailable(credentials.connectionId, result.status, result.error, provider, model);
|
||||
|
||||
if (shouldFallback) {
|
||||
log.warn("AUTH", `Account ${accountId}... unavailable (${result.status}), trying fallback`);
|
||||
log.warn("AUTH", `Account ${credentials.connectionName} unavailable (${result.status}), trying fallback`);
|
||||
excludeConnectionId = credentials.connectionId;
|
||||
lastError = result.error;
|
||||
lastStatus = result.status;
|
||||
|
||||
@@ -103,8 +103,7 @@ export async function handleEmbeddings(request) {
|
||||
return errorResponse(lastStatus || HTTP_STATUS.SERVICE_UNAVAILABLE, lastError || "All accounts unavailable");
|
||||
}
|
||||
|
||||
const accountId = credentials.connectionId.slice(0, 8);
|
||||
log.info("AUTH", `Using ${provider} account: ${accountId}...`);
|
||||
log.info("AUTH", `\x1b[32mUsing ${provider} account: ${credentials.connectionName}\x1b[0m`);
|
||||
|
||||
const refreshedCredentials = await checkAndRefreshToken(provider, credentials);
|
||||
|
||||
@@ -131,7 +130,7 @@ export async function handleEmbeddings(request) {
|
||||
const { shouldFallback } = await markAccountUnavailable(credentials.connectionId, result.status, result.error, provider, model);
|
||||
|
||||
if (shouldFallback) {
|
||||
log.warn("AUTH", `Account ${accountId}... unavailable (${result.status}), trying fallback`);
|
||||
log.warn("AUTH", `Account ${credentials.connectionName} unavailable (${result.status}), trying fallback`);
|
||||
excludeConnectionId = credentials.connectionId;
|
||||
lastError = result.error;
|
||||
lastStatus = result.status;
|
||||
|
||||
@@ -72,11 +72,13 @@ export async function getProviderCredentials(provider, excludeConnectionId = nul
|
||||
}
|
||||
|
||||
const settings = await getSettings();
|
||||
const strategy = settings.fallbackStrategy || "fill-first";
|
||||
// Per-provider strategy overrides global setting
|
||||
const providerOverride = (settings.providerStrategies || {})[providerId] || {};
|
||||
const strategy = providerOverride.fallbackStrategy || settings.fallbackStrategy || "fill-first";
|
||||
|
||||
let connection;
|
||||
if (strategy === "round-robin") {
|
||||
const stickyLimit = settings.stickyRoundRobinLimit || 3;
|
||||
const stickyLimit = providerOverride.stickyRoundRobinLimit || settings.stickyRoundRobinLimit || 3;
|
||||
|
||||
// Sort by lastUsed (most recent first) to find current candidate
|
||||
const byRecency = [...availableConnections].sort((a, b) => {
|
||||
@@ -178,7 +180,8 @@ export async function markAccountUnavailable(connectionId, status, errorText, pr
|
||||
});
|
||||
|
||||
const lockKey = Object.keys(lockUpdate)[0];
|
||||
log.warn("AUTH", `${connectionId.slice(0, 8)} locked ${lockKey} for ${Math.round(cooldownMs / 1000)}s [${status}]`);
|
||||
const connName = conn?.displayName || conn?.name || conn?.email || connectionId.slice(0, 8);
|
||||
log.warn("AUTH", `${connName} locked ${lockKey} for ${Math.round(cooldownMs / 1000)}s [${status}]`);
|
||||
|
||||
if (provider && status && reason) {
|
||||
console.error(`❌ ${provider} [${status}]: ${reason}`);
|
||||
@@ -228,7 +231,8 @@ export async function clearAccountError(connectionId, currentConnection, model =
|
||||
}
|
||||
|
||||
await updateProviderConnection(connectionId, clearObj);
|
||||
log.info("AUTH", `Account ${connectionId.slice(0, 8)} cleared lock for model=${model || "__all"}`);
|
||||
const connName = conn?.displayName || conn?.name || conn?.email || connectionId.slice(0, 8);
|
||||
log.info("AUTH", `Account ${connName} cleared lock for model=${model || "__all"}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user