feat: add configurable account selection strategies

Refactor account selection into a strategy pattern with three options:
- Sticky: cache-optimized, stays on same account until rate-limited
- Round-robin: load-balanced, rotates every request
- Hybrid (default): smart distribution using health scores, token buckets, and LRU

The hybrid strategy uses multiple signals for optimal account selection:
health tracking for reliability, client-side token buckets for rate limiting,
and LRU freshness to prefer rested accounts.

Includes WebUI settings for strategy selection and unit tests.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Badri Narayanan S
2026-01-18 03:48:43 +05:30
parent 973234372b
commit 5ae19a5b72
31 changed files with 2721 additions and 353 deletions

View File

@@ -270,6 +270,18 @@ window.translations.id = {
defaultCooldownDesc: "Cooldown bawaan jika API tidak memberikan waktu reset.",
maxWaitThreshold: "Batas Tunggu Maksimal",
maxWaitDesc: "Jika semua akun terkena rate limit lebih lama dari ini, langsung gagal.",
// Error Handling Tuning
errorHandlingTuning: "Penyetelan Penanganan Error",
rateLimitDedupWindow: "Jendela Deduplikasi Rate Limit",
rateLimitDedupWindowDesc: "Mencegah badai retry ketika beberapa permintaan terkena rate limit bersamaan.",
maxConsecutiveFailures: "Maks. Kegagalan Berturut-turut",
maxConsecutiveFailuresDesc: "Jumlah kegagalan berturut-turut sebelum menerapkan cooldown diperpanjang.",
extendedCooldown: "Cooldown Diperpanjang",
extendedCooldownDesc: "Durasi cooldown setelah mencapai maks. kegagalan berturut-turut.",
capacityRetryDelay: "Jeda Retry Kapasitas",
capacityRetryDelayDesc: "Jeda sebelum retry saat kapasitas model habis (bukan kuota).",
maxCapacityRetries: "Maks. Retry Kapasitas",
maxCapacityRetriesDesc: "Maksimum retry untuk kehabisan kapasitas sebelum ganti akun.",
saveConfigServer: "Simpan Konfigurasi",
serverRestartAlert: "Tersimpan ke {path}. Restart server untuk menerapkan.",
@@ -368,4 +380,17 @@ window.translations.id = {
mustBeAtMost: "{fieldName} maksimal {max}",
cannotBeEmpty: "{fieldName} tidak boleh kosong",
mustBeTrueOrFalse: "Nilai harus true atau false",
// Account Selection Strategy translations
accountSelectionStrategy: "Strategi Pemilihan Akun",
selectionStrategy: "Strategi Pemilihan",
strategyStickyLabel: "Tetap (Optimisasi Cache)",
strategyRoundRobinLabel: "Bergilir (Load Balanced)",
strategyHybridLabel: "Hibrida (Distribusi Cerdas)",
strategyStickyDesc: "Tetap di akun yang sama hingga terkena rate limit. Terbaik untuk cache prompt.",
strategyRoundRobinDesc: "Berputar ke akun berikutnya setiap permintaan. Throughput maksimum.",
strategyHybridDesc: "Pemilihan cerdas berdasarkan kesehatan, token, dan kesegaran.",
strategyUpdated: "Strategi diubah ke: {strategy}",
failedToUpdateStrategy: "Gagal memperbarui strategi",
invalidStrategy: "Strategi tidak valid dipilih",
};