Merge branch 'master' of https://github.com/decolua/9router
This commit is contained in:
commit
f8d2a9ff76
8 changed files with 160 additions and 24 deletions
|
|
@ -223,6 +223,24 @@ export default function ProfilePage() {
|
|||
}
|
||||
};
|
||||
|
||||
const updateComboStickyLimit = async (limit) => {
|
||||
const numLimit = parseInt(limit);
|
||||
if (isNaN(numLimit) || numLimit < 1) return;
|
||||
|
||||
try {
|
||||
const res = await fetch("/api/settings", {
|
||||
method: "PATCH",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ comboStickyRoundRobinLimit: numLimit }),
|
||||
});
|
||||
if (res.ok) {
|
||||
setSettings(prev => ({ ...prev, comboStickyRoundRobinLimit: numLimit }));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to update combo sticky limit:", err);
|
||||
}
|
||||
};
|
||||
|
||||
const updateRequireLogin = async (requireLogin) => {
|
||||
try {
|
||||
const res = await fetch("/api/settings", {
|
||||
|
|
@ -550,10 +568,34 @@ export default function ProfilePage() {
|
|||
/>
|
||||
</div>
|
||||
|
||||
{/* Combo Sticky Round Robin Limit */}
|
||||
{settings.comboStrategy === "round-robin" && (
|
||||
<div className="flex items-center justify-between pt-2 border-t border-border/50">
|
||||
<div>
|
||||
<p className="font-medium">Combo Sticky Limit</p>
|
||||
<p className="text-sm text-text-muted">
|
||||
Calls per combo model before switching
|
||||
</p>
|
||||
</div>
|
||||
<Input
|
||||
type="number"
|
||||
min="1"
|
||||
max="100"
|
||||
value={settings.comboStickyRoundRobinLimit || 1}
|
||||
onChange={(e) => updateComboStickyLimit(e.target.value)}
|
||||
disabled={loading}
|
||||
className="w-20 text-center"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<p className="text-xs text-text-muted italic pt-2 border-t border-border/50">
|
||||
{settings.fallbackStrategy === "round-robin"
|
||||
? `Currently distributing requests across all available accounts with ${settings.stickyRoundRobinLimit || 3} calls per account.`
|
||||
: "Currently using accounts in priority order (Fill First)."}
|
||||
{settings.comboStrategy === "round-robin"
|
||||
? ` Combos rotate after ${settings.comboStickyRoundRobinLimit || 1} call${(settings.comboStickyRoundRobinLimit || 1) === 1 ? "" : "s"} per model.`
|
||||
: " Combos always start with their first model."}
|
||||
</p>
|
||||
</div>
|
||||
</Card>
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ export async function PATCH(request) {
|
|||
// Invalidate combo rotation state when strategy settings change
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(body, "comboStrategy") ||
|
||||
Object.prototype.hasOwnProperty.call(body, "comboStickyRoundRobinLimit") ||
|
||||
Object.prototype.hasOwnProperty.call(body, "comboStrategies")
|
||||
) {
|
||||
resetComboRotation();
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ const DEFAULT_SETTINGS = {
|
|||
stickyRoundRobinLimit: 3,
|
||||
providerStrategies: {},
|
||||
comboStrategy: "fallback",
|
||||
comboStickyRoundRobinLimit: 1,
|
||||
comboStrategies: {},
|
||||
requireLogin: true,
|
||||
tunnelDashboardAccess: true,
|
||||
|
|
|
|||
|
|
@ -97,14 +97,16 @@ export async function handleChat(request, clientRawRequest = null) {
|
|||
const comboSpecificStrategy = comboStrategies[modelStr]?.fallbackStrategy;
|
||||
const comboStrategy = comboSpecificStrategy || settings.comboStrategy || "fallback";
|
||||
|
||||
log.info("CHAT", `Combo "${modelStr}" with ${comboModels.length} models (strategy: ${comboStrategy})`);
|
||||
const comboStickyLimit = settings.comboStickyRoundRobinLimit;
|
||||
log.info("CHAT", `Combo "${modelStr}" with ${comboModels.length} models (strategy: ${comboStrategy}, sticky: ${comboStickyLimit})`);
|
||||
return handleComboChat({
|
||||
body,
|
||||
models: comboModels,
|
||||
handleSingleModel: (b, m) => handleSingleModelChat(b, m, clientRawRequest, request, apiKey),
|
||||
log,
|
||||
comboName: modelStr,
|
||||
comboStrategy
|
||||
comboStrategy,
|
||||
comboStickyLimit
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -128,14 +130,16 @@ async function handleSingleModelChat(body, modelStr, clientRawRequest = null, re
|
|||
const comboSpecificStrategy = comboStrategies[modelStr]?.fallbackStrategy;
|
||||
const comboStrategy = comboSpecificStrategy || chatSettings.comboStrategy || "fallback";
|
||||
|
||||
log.info("CHAT", `Combo "${modelStr}" with ${comboModels.length} models (strategy: ${comboStrategy})`);
|
||||
const comboStickyLimit = chatSettings.comboStickyRoundRobinLimit;
|
||||
log.info("CHAT", `Combo "${modelStr}" with ${comboModels.length} models (strategy: ${comboStrategy}, sticky: ${comboStickyLimit})`);
|
||||
return handleComboChat({
|
||||
body,
|
||||
models: comboModels,
|
||||
handleSingleModel: (b, m) => handleSingleModelChat(b, m, clientRawRequest, request, apiKey),
|
||||
log,
|
||||
comboName: modelStr,
|
||||
comboStrategy
|
||||
comboStrategy,
|
||||
comboStickyLimit
|
||||
});
|
||||
}
|
||||
log.warn("CHAT", "Invalid model format", { model: modelStr });
|
||||
|
|
|
|||
|
|
@ -84,14 +84,16 @@ export async function handleFetch(request) {
|
|||
if (comboModels) {
|
||||
const comboStrategies = settings.comboStrategies || {};
|
||||
const comboStrategy = comboStrategies[providerInput]?.fallbackStrategy || settings.comboStrategy || "fallback";
|
||||
log.info("FETCH", `Combo "${providerInput}" with ${comboModels.length} providers (strategy: ${comboStrategy})`);
|
||||
const comboStickyLimit = settings.comboStickyRoundRobinLimit;
|
||||
log.info("FETCH", `Combo "${providerInput}" with ${comboModels.length} providers (strategy: ${comboStrategy}, sticky: ${comboStickyLimit})`);
|
||||
return handleComboChat({
|
||||
body,
|
||||
models: comboModels,
|
||||
handleSingleModel: (b, m) => handleSingleProviderFetch(b, m, request, apiKey, settings),
|
||||
log,
|
||||
comboName: providerInput,
|
||||
comboStrategy
|
||||
comboStrategy,
|
||||
comboStickyLimit
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,14 +74,16 @@ export async function handleSearch(request) {
|
|||
if (comboModels) {
|
||||
const comboStrategies = settings.comboStrategies || {};
|
||||
const comboStrategy = comboStrategies[providerInput]?.fallbackStrategy || settings.comboStrategy || "fallback";
|
||||
log.info("SEARCH", `Combo "${providerInput}" with ${comboModels.length} providers (strategy: ${comboStrategy})`);
|
||||
const comboStickyLimit = settings.comboStickyRoundRobinLimit;
|
||||
log.info("SEARCH", `Combo "${providerInput}" with ${comboModels.length} providers (strategy: ${comboStrategy}, sticky: ${comboStickyLimit})`);
|
||||
return handleComboChat({
|
||||
body,
|
||||
models: comboModels,
|
||||
handleSingleModel: (b, m) => handleSingleProviderSearch(b, m, request, apiKey, settings),
|
||||
log,
|
||||
comboName: providerInput,
|
||||
comboStrategy
|
||||
comboStrategy,
|
||||
comboStickyLimit
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue