diff --git a/docs-site/src/content/docs/fr/guides/claude-code.md b/docs-site/src/content/docs/fr/guides/claude-code.md index 8a5ccf79b2..671c22c233 100644 --- a/docs-site/src/content/docs/fr/guides/claude-code.md +++ b/docs-site/src/content/docs/fr/guides/claude-code.md @@ -15,7 +15,8 @@ ajouter un compte). Par défaut, chaque requête utilise uniquement le compte ** Un groupe de comptes Claude **expérimental et facultatif** (`anthropicAccountPool.enabled`) ajoute l'affinité de session et le basculement en cas de délai de récupération 429 entre ces comptes OAuth. Pour les **nouvelles** sessions uniquement, `anthropicAccountPool.strategy` sélectionne un compte éligible : `quota` (par défaut) -choisit la plus faible utilisation connue sur 5 heures lorsqu'elle dépasse `autoSwitchThreshold` ; `round-robin` +choisit la plus faible utilisation connue dans la fenêtre configurée par `anthropicAccountPool.quotaWindow` +(`five-hour` par défaut, `weekly` ou `max-utilization`) lorsqu'elle dépasse `autoSwitchThreshold` ; `round-robin` répartit les sessions uniformément (`stickyLimit`, `1` par défaut) ; `fill-first` utilise le compte actif jusqu'à un délai de récupération, une réauthentification ou le seuil, puis passe au suivant. Cette fonction est **désactivée par défaut**, affiche un avertissement dans l'interface et n'a pas été éprouvée en production. @@ -31,6 +32,9 @@ Comportement lorsque cette option est activée : sélection jusqu'à sa réauthentification. - Si chaque compte éligible est en temporisation, le proxy renvoie **429** (et non 401) avec `Retry-After` lorsqu'il est connu. +- La récupération, y compris le basculement 429, utilise `quotaWindow` pour classer les comptes de + remplacement admissibles, sans modifier les limites existantes de temporisation ou de basculement ; + `round-robin` ignore `quotaWindow`. Voir [Configuration](/fr/reference/configuration/providers/#anthropicaccountpool-expérimental). diff --git a/docs-site/src/content/docs/fr/reference/configuration/providers.md b/docs-site/src/content/docs/fr/reference/configuration/providers.md index 822c7ba47c..68205d6059 100644 --- a/docs-site/src/content/docs/fr/reference/configuration/providers.md +++ b/docs-site/src/content/docs/fr/reference/configuration/providers.md @@ -193,8 +193,9 @@ rotation automatique peut déclencher des restrictions du fournisseur. | Clé | Type | Par défaut | Description | | --- | --- | --- | --- | | `anthropicAccountPool.enabled?` | `boolean` | `false` | Active l'affinité persistante et le basculement après une temporisation 429. | -| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | Pour les nouvelles sessions, choisir la plus faible utilisation connue et mise en cache sur 5 heures qui atteint ou dépasse ce seuil. `0` désactive la sélection selon le quota. | -| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | Stratégie des nouvelles sessions ; quota utilise uniquement les barres sur 5 heures. | +| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | Pour les nouvelles sessions, lorsque le compte actif atteint ce seuil, choisir la plus faible utilisation connue et mise en cache dans la fenêtre configurée. `0` désactive la sélection selon le quota. | +| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | Stratégie des nouvelles sessions ; `quota` classe les comptes selon la fenêtre définie par `quotaWindow`, par défaut les barres sur 5 heures, et `fill-first` évalue son seuil d'évacuation dans cette même fenêtre. | +| `anthropicAccountPool.quotaWindow?` | `"five-hour" \| "weekly" \| "max-utilization"` | `"five-hour"` | Barre d'utilisation mise en cache utilisée pour classer les comptes. `five-hour` conserve le comportement actuel. `weekly` utilise la barre hebdomadaire et ignore les comptes dont la barre sur 5 heures est épuisée. `max-utilization` utilise la plus élevée des deux barres. Dans les deux modes, les égalités sont départagées par la plus faible utilisation sur 5 heures. `round-robin` ignore ce réglage. Une session saine avec affinité n'est pas rééquilibrée de manière proactive ; la récupération après une erreur terminale, y compris le basculement 429, classe néanmoins les remplaçants avec cette fenêtre sans modifier les limites de temporisation ou de basculement. Les barres hebdomadaires ne sont connues qu'après leur interrogation dans la page Fournisseurs du tableau de bord. | | `anthropicAccountPool.stickyLimit?` | `number` | `1` | Liaisons de nouvelle session réussies conservées sur une sélection à tour de rôle. Portée 1–100. | Lorsque cette option est activée, un 429 enregistre une temporisation bornée à partir de `Retry-After` ou d'un délai de repli, puis peut diff --git a/docs-site/src/content/docs/guides/claude-code.md b/docs-site/src/content/docs/guides/claude-code.md index 81d0e0eaea..85d49c5cc9 100644 --- a/docs-site/src/content/docs/guides/claude-code.md +++ b/docs-site/src/content/docs/guides/claude-code.md @@ -13,9 +13,10 @@ You can log in multiple Claude accounts via the Providers dashboard (`ocx login add-account). By default every request uses the **active** account only. An **experimental, opt-in** Claude account pool (`anthropicAccountPool.enabled`) adds sticky -session affinity and 429 cooldown failover across those OAuth accounts. For **new** sessions -only, `anthropicAccountPool.strategy` selects among eligible accounts: `quota` (default) picks -lowest known 5-hour usage when above `autoSwitchThreshold`; `round-robin` spreads evenly +session affinity and 429 cooldown failover across those OAuth accounts. For **new** sessions, +`anthropicAccountPool.strategy` selects among eligible accounts: `quota` (default) picks the +lowest known usage in the window set by `quotaWindow` (`five-hour` by default, or `weekly` / +`max-utilization`) when above `autoSwitchThreshold`; `round-robin` spreads evenly (`stickyLimit`, default `1`); `fill-first` drains the active account until cooldown, reauthentication, or threshold, then advances. It is **off by default**, shows a GUI warning, and is not battle-tested — Anthropic may restrict accounts that look like automated rotation; @@ -31,6 +32,8 @@ Operational contract when enabled: selection until re-authenticated. - If every eligible account is cooling, the proxy returns **429** (not 401) with `Retry-After` when known. +- Recovery, including 429 failover, uses `quotaWindow` to rank eligible replacements without + changing the existing cooldown or failover limits; `round-robin` ignores `quotaWindow`. See [Configuration](/reference/configuration/#anthropicaccountpool-experimental). diff --git a/docs-site/src/content/docs/ja/reference/configuration/providers.md b/docs-site/src/content/docs/ja/reference/configuration/providers.md index f1210892a5..02009f0832 100644 --- a/docs-site/src/content/docs/ja/reference/configuration/providers.md +++ b/docs-site/src/content/docs/ja/reference/configuration/providers.md @@ -159,8 +159,9 @@ affinity を維持します。これらの戦略は provider enforcement を回 |キー |タイプ |デフォルト |説明 | | --- | --- | --- | --- | | `anthropicAccountPool.enabled?` | `boolean` | `false` |スティッキー アフィニティと 429 クールダウン フェイルオーバーを有効にします。 | -| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` |新しいセッションの場合は、このしきい値以上の、既知の最も低いキャッシュされた 5 時間の使用量を選択します。 `0` はクォータの選択を無効にします。 | -| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` |新しいセッション戦略。クォータでは 5 時間足のみを使用します。 | +| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` |新しいセッションでは、アクティブなアカウントがこのしきい値に達すると、設定した期間で既知のキャッシュ使用量が最も低いアカウントを選択します。 `0` はクォータ選択を無効にします。 | +| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` |新しいセッション戦略。`quota` は `quotaWindow` で指定した期間(既定は 5 時間足)でアカウントを順位付けし、`fill-first` も同じ期間で使い切りのしきい値を判定します。 | +| `anthropicAccountPool.quotaWindow?` | `"five-hour" \| "weekly" \| "max-utilization"` | `"five-hour"` |使用量ベースのアカウント選択で評価するキャッシュ済み使用量です。`five-hour` は従来の動作を維持します。`weekly` は週次使用量を使いますが、5 時間使用量が上限に達したアカウントを除外します。`max-utilization` は 2 つの値のうち高い方を使います。どちらのモードでも同点の場合は 5 時間使用量が低い方を優先します。`round-robin` はこの設定を無視します。正常な affinity セッションを先回りして再配置することはありませんが、429 フェイルオーバーを含む終端エラーからの復旧では、既存のクールダウンとフェイルオーバー上限を変えずに、この期間で代替アカウントを順位付けします。アカウント別の週次使用量は、ダッシュボードのプロバイダーページで取得した後にのみ利用できます。 | | `anthropicAccountPool.stickyLimit?` | `number` | `1` |成功した新しいセッションのバインドは 1 つのラウンドロビン選択で保持されます。範囲は 1 ~ 100。 | 有効にすると、429 レコードは `Retry-After` またはデフォルトのバックオフからの制限されたクールダウンを記録し、リクエスト内でローテーションする可能性があります。アフィニティはプロセスローカルであり、サイズ制限があります。資格情報 401/403 は、アカウントに再認証が必要であることをマークします。すべての対象となるアカウントが冷却されている場合、クライアントは、既知の場合、認証エラーではなく、`Retry-After` を含む 429 を受け取ります。 diff --git a/docs-site/src/content/docs/ko/reference/configuration/providers.md b/docs-site/src/content/docs/ko/reference/configuration/providers.md index ccacb0a94f..64433c5c2e 100644 --- a/docs-site/src/content/docs/ko/reference/configuration/providers.md +++ b/docs-site/src/content/docs/ko/reference/configuration/providers.md @@ -163,8 +163,9 @@ affinity 초기화 뒤의 기존 작업도 포함될 수 있습니다. 출력 | 키 | 타입 | 기본값 | 설명 | | --- | --- | --- | --- | | `anthropicAccountPool.enabled?` | `boolean` | `false` | sticky 결속과 429 쿨다운 failover를 켭니다. | -| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | 새 세션에서는 이 임계값 이상에서 알려진 캐시 5시간 사용량이 가장 낮은 계정을 고릅니다. `0`이면 quota 선택을 끕니다. | -| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | 새 세션 전략입니다. quota는 5시간 막대만 사용합니다. | +| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | 새 세션에서는 활성 계정이 이 임계값에 도달하면 설정된 창의 알려진 캐시 사용량이 가장 낮은 계정을 고릅니다. `0`이면 quota 선택을 끕니다. | +| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | 새 세션 전략입니다. `quota`는 `quotaWindow`로 지정한 창(기본값은 5시간 막대)으로 계정 순위를 매기고, `fill-first`도 같은 창에서 소진 임계값을 판정합니다. | +| `anthropicAccountPool.quotaWindow?` | `"five-hour" \| "weekly" \| "max-utilization"` | `"five-hour"` | 사용량 기반 계정 선택이 점수화할 캐시 사용량 막대입니다. `five-hour`는 기존 동작을 유지합니다. `weekly`는 주간 막대를 사용하되 5시간 막대가 소진된 계정을 건너뜁니다. `max-utilization`은 두 막대 중 더 높은 값을 사용합니다. 두 모드 모두 동점이면 5시간 사용량이 낮은 계정을 우선합니다. `round-robin`은 이 설정을 무시합니다. 정상 affinity 세션을 선제적으로 재배치하지 않지만, 429 failover를 포함한 종료 오류 복구에서는 기존 쿨다운과 failover 한도를 바꾸지 않은 채 이 창으로 대체 계정의 순위를 매깁니다. 계정별 주간 막대는 대시보드의 프로바이더 페이지에서 조회한 뒤에만 알 수 있습니다. | | `anthropicAccountPool.stickyLimit?` | `number` | `1` | 성공한 새 세션 결속이 한 번의 라운드로빈 선택에 유지되는 횟수입니다. 범위는 1–100입니다. | 활성화되면 429 레코드가 `Retry-After` 또는 기본 backoff에서 제한된 쿨다운을 기록하고, 요청 안에서 회전할 수 있습니다. 결속은 프로세스 로컬이며 크기가 제한됩니다. 자격 증명 401/403은 해당 계정이 재인증이 필요함을 표시합니다. 적격한 계정이 모두 쿨다운 중이면, 클라이언트는 인증 오류가 아니라 알려진 경우 `Retry-After`가 포함된 429를 받습니다. diff --git a/docs-site/src/content/docs/reference/configuration/providers.md b/docs-site/src/content/docs/reference/configuration/providers.md index 85cef14e1e..749f739f06 100644 --- a/docs-site/src/content/docs/reference/configuration/providers.md +++ b/docs-site/src/content/docs/reference/configuration/providers.md @@ -265,8 +265,9 @@ rotation may trigger provider restrictions. | Key | Type | Default | Description | | --- | --- | --- | --- | | `anthropicAccountPool.enabled?` | `boolean` | `false` | Enable sticky affinity and 429 cooldown failover. | -| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | For new sessions, choose the lowest known cached 5-hour usage at or above this threshold. `0` disables quota picking. | -| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | New-session strategy; quota uses 5-hour bars only. | +| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | For new sessions, when the active account reaches this threshold, choose the lowest known cached usage in the configured window; the account chosen does not itself have to be at or above the threshold. `0` disables quota picking. | +| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | New-session strategy; `quota` ranks accounts by the window set by `quotaWindow`, and `fill-first` evaluates its drain threshold in that same window. | +| `anthropicAccountPool.quotaWindow?` | `"five-hour" \| "weekly" \| "max-utilization"` | `"five-hour"` | Which cached usage bar usage-aware account selection scores. `five-hour` keeps the original behavior. `weekly` scores the weekly bar but still skips accounts whose 5-hour bar is exhausted. `max-utilization` scores whichever of the two bars is higher. Ties in either mode prefer lower 5-hour usage. `round-robin` ignores this setting. A healthy affinity-bound session is not proactively rebalanced; terminal recovery, including 429 failover, still ranks eligible replacement accounts with this window without changing cooldown or failover limits. Per-account weekly bars are only known once the dashboard Providers page has polled them. | | `anthropicAccountPool.stickyLimit?` | `number` | `1` | Successful new-session binds retained on one round-robin selection. Range 1–100. | When enabled, 429 records bounded cooldown from `Retry-After` or a default backoff and may rotate diff --git a/docs-site/src/content/docs/ru/reference/configuration/providers.md b/docs-site/src/content/docs/ru/reference/configuration/providers.md index c415517074..985f573cc8 100644 --- a/docs-site/src/content/docs/ru/reference/configuration/providers.md +++ b/docs-site/src/content/docs/ru/reference/configuration/providers.md @@ -194,8 +194,9 @@ reauth или порога исчерпания; здоровые привяза | Ключ | Тип | По умолчанию | Описание | | --- | --- | --- | --- | | `anthropicAccountPool.enabled?` | `boolean` | `false` | Включить sticky affinity и cooldown failover на 429. | -| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | Для новых сессий выбирать аккаунт с наименьшим известным cached 5-hour usage, если активный аккаунт достиг порога. `0` отключает выбор по quota. | -| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | Стратегия для новых сессий; quota смотрит только на 5-hour bar'ы. | +| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | Для новых сессий выбирать аккаунт с наименьшим известным cached usage в настроенном окне, если активный аккаунт достиг порога. `0` отключает выбор по quota. | +| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | Стратегия для новых сессий; `quota` ранжирует аккаунты по окну, заданному в `quotaWindow` (по умолчанию это 5-hour bar'ы), а `fill-first` в этом же окне оценивает свой порог исчерпания. | +| `anthropicAccountPool.quotaWindow?` | `"five-hour" \| "weekly" \| "max-utilization"` | `"five-hour"` | Cached usage bar для оценки при выборе аккаунта по использованию. `five-hour` сохраняет прежнее поведение. `weekly` использует недельный bar, но пропускает аккаунты с исчерпанным 5-hour bar. `max-utilization` использует большее из двух значений. При равенстве в обоих режимах выбирается меньший 5-hour usage. `round-robin` игнорирует настройку. Здоровая сессия с affinity не перебалансируется заранее; восстановление после терминальной ошибки, включая 429 failover, всё равно ранжирует доступные замены по этому окну, не меняя лимиты cooldown и failover. Недельные bar'ы аккаунтов известны только после опроса на странице Providers в dashboard. | | `anthropicAccountPool.stickyLimit?` | `number` | `1` | Сколько успешных bind'ов новых сессий удерживать на одном выборе round-robin. Диапазон 1–100. | Если функция включена, 429 записывает ограниченный cooldown из `Retry-After` или из default diff --git a/docs-site/src/content/docs/tr/guides/claude-code.md b/docs-site/src/content/docs/tr/guides/claude-code.md index e335bea33e..1fe4fd0393 100644 --- a/docs-site/src/content/docs/tr/guides/claude-code.md +++ b/docs-site/src/content/docs/tr/guides/claude-code.md @@ -19,7 +19,8 @@ fazla Claude hesabına giriş yapabilirsiniz. Varsayılan olarak her istek yaln bağlılığı ve 429 bekleme süresi (cooldown) yük devretmesi ekler. Yalnızca **yeni** oturumlar için `anthropicAccountPool.strategy` uygun hesaplar arasından seçim yapar: `quota` (varsayılan), `autoSwitchThreshold` üzerinde olduğunda -bilinen en düşük 5 saatlik kullanımı seçer; `round-robin` eşit olarak dağıtır +`anthropicAccountPool.quotaWindow` ile yapılandırılan penceredeki bilinen en düşük kullanımı +seçer (`five-hour` varsayılandır; `weekly` ve `max-utilization` da kullanılabilir); `round-robin` eşit olarak dağıtır (`stickyLimit`, varsayılan `1`); `fill-first`, bekleme süresi, yeniden kimlik doğrulama veya eşiğe kadar aktif hesabı tüketir, ardından ilerler. **Varsayılan olarak kapalıdır**, bir GUI uyarısı gösterir ve sahada kapsamlı olarak test @@ -37,6 +38,9 @@ Etkinleştirildiğinde operasyonel sözleşme: böylece yeniden kimlik doğrulanana kadar seçimden hariç tutulur. - Uygun tüm hesaplar soğutuluyorsa, proxy bilindiğinde `Retry-After` ile birlikte **429** (401 değil) döndürür. +- 429 yük devretmesi dahil kurtarma, mevcut soğuma ve yük devretme sınırlarını + değiştirmeden uygun yedek hesapları sıralamak için `quotaWindow` kullanır; + `round-robin` ise `quotaWindow` ayarını yok sayar. Bkz. [Yapılandırma](/tr/reference/configuration/#anthropicaccountpool-experimental). @@ -607,4 +611,3 @@ modellerde opencodex varsayılan olarak bunu taslakla değiştirir (`blockedSkil aracının `model` argümanını değil, `` yönergelerini kullanır. Yönergenin hedeflenen rotayla eşleştiğinden emin olun. Model yer tutucusu olarak `"haiku"` iletin. - diff --git a/docs-site/src/content/docs/tr/reference/configuration/providers.md b/docs-site/src/content/docs/tr/reference/configuration/providers.md index 4db3211bc5..e5489ecdf5 100644 --- a/docs-site/src/content/docs/tr/reference/configuration/providers.md +++ b/docs-site/src/content/docs/tr/reference/configuration/providers.md @@ -219,8 +219,9 @@ ve otomatik rotasyon sağlayıcı kısıtlamalarını tetikleyebilir. | Anahtar | Tip | Varsayılan | Açıklama | | --- | --- | --- | --- | | `anthropicAccountPool.enabled?` | `boolean` | `false` | Yapışkan bağlılığı ve 429 soğuma yük devretmesini etkinleştirin. | -| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | Yeni oturumlar için bu eşikte veya üzerinde bilinen en düşük önbelleğe alınmış 5 saatlik kullanımı seçin. `0` kota seçimini devre dışı bırakır. | -| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | Yeni oturum stratejisi; kota yalnızca 5 saatlik çubukları kullanır. | +| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | Yeni oturumlarda etkin hesap bu eşiğe ulaştığında, yapılandırılan penceredeki bilinen en düşük önbelleğe alınmış kullanımı seçin. `0` kota seçimini devre dışı bırakır. | +| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | Yeni oturum stratejisi; `quota`, `quotaWindow` ile belirlenen pencereye (varsayılan 5 saatlik çubuklar) göre hesapları sıralar ve `fill-first` de tükenme eşiğini aynı pencerede değerlendirir. | +| `anthropicAccountPool.quotaWindow?` | `"five-hour" \| "weekly" \| "max-utilization"` | `"five-hour"` | Kullanıma dayalı hesap seçiminin puanladığı önbelleğe alınmış kullanım çubuğu. `five-hour` mevcut davranışı korur. `weekly` haftalık çubuğu kullanır, ancak 5 saatlik çubuğu tükenmiş hesapları atlar. `max-utilization` iki çubuktan yüksek olanı kullanır. Her iki moddaki eşitliklerde daha düşük 5 saatlik kullanım tercih edilir. `round-robin` bu ayarı yok sayar. Sağlıklı affinity oturumları önceden yeniden dengelenmez; 429 yük devretmesi dahil terminal hata kurtarması, mevcut soğuma ve yük devretme sınırlarını değiştirmeden uygun yedek hesapları bu pencereye göre sıralar. Hesap başına haftalık çubuklar ancak dashboard Sağlayıcılar sayfasında sorgulandıktan sonra bilinir. | | `anthropicAccountPool.stickyLimit?` | `number` | `1` | Bir round-robin seçiminde tutulan başarılı yeni oturum bağlamaları. Aralık 1–100. | Etkinleştirildiğinde 429, `Retry-After`'dan veya varsayılan bir geri çekilmeden @@ -480,4 +481,3 @@ bildirir; senkronize edilen katalog `xhigh`'ı ayrı tutarken `max` bildirir. "visionSidecar": { "enabled": true } } ``` - diff --git a/docs-site/src/content/docs/zh-cn/reference/configuration/providers.md b/docs-site/src/content/docs/zh-cn/reference/configuration/providers.md index 3630a9ba6c..bb4c827260 100644 --- a/docs-site/src/content/docs/zh-cn/reference/configuration/providers.md +++ b/docs-site/src/content/docs/zh-cn/reference/configuration/providers.md @@ -157,8 +157,9 @@ affinity。这些策略不能规避 provider enforcement。 | 键 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | `anthropicAccountPool.enabled?` | `boolean` | `false` | 启用粘性亲和性和 429 冷却故障转移。 | -| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | 对于新会话,选择已知缓存的、5 小时使用率最低且达到或超过此阈值的账户。`0` 会禁用配额选择。 | -| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | 新会话策略;quota 只使用 5 小时条形数据。 | +| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | 对于新会话,当活动账户达到此阈值时,选择配置窗口中已知缓存使用率最低的账户。`0` 会禁用配额选择。 | +| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | 新会话策略;`quota` 按 `quotaWindow` 指定的窗口(默认是 5 小时条形数据)对账户排序,`fill-first` 也在同一窗口中判定其耗尽阈值。 | +| `anthropicAccountPool.quotaWindow?` | `"five-hour" \| "weekly" \| "max-utilization"` | `"five-hour"` | 基于用量选择账户时用于评分的缓存用量条。`five-hour` 保持原有行为。`weekly` 使用每周用量条,但仍会跳过 5 小时用量已耗尽的账户。`max-utilization` 使用两条用量中较高的值。两种模式分数相同时,都优先选择 5 小时用量较低的账户。`round-robin` 会忽略此设置。不会主动重新平衡健康且已建立亲和性的会话;遇到终止性错误进行恢复时(包括 429 故障转移),仍会按此窗口对可用替代账户排序,但不会改变现有冷却或故障转移上限。各账户的每周用量只有在控制面板的提供商页面完成查询后才可用。 | | `anthropicAccountPool.stickyLimit?` | `number` | `1` | 在一次轮询选择中保留的成功新会话绑定次数。范围 1–100。 | 启用后,429 会根据 `Retry-After` 记录有界冷却,或者使用默认退避,并且可能在同一请求内轮换。亲和性是进程本地的,并且有大小上限。凭据 401/403 会将账户标记为需要重新认证。如果所有合格账户都在冷却,客户端会在已知时收到带 `Retry-After` 的 429,而不是身份验证错误。 diff --git a/docs-site/src/content/docs/zh-tw/guides/claude-code.md b/docs-site/src/content/docs/zh-tw/guides/claude-code.md index be06746fba..2663cb3647 100644 --- a/docs-site/src/content/docs/zh-tw/guides/claude-code.md +++ b/docs-site/src/content/docs/zh-tw/guides/claude-code.md @@ -14,7 +14,9 @@ Code 可以使用每一個已路由的供應商——包括 OAuth 登入、帳 **實驗性、opt-in** 的 Claude 帳號池(`anthropicAccountPool.enabled`)會在這些 OAuth 帳號之間加入 sticky session affinity 與 429 冷卻故障轉移。僅對**新**工作階段,`anthropicAccountPool.strategy` -會在合格帳號之間選擇:`quota`(預設)在用量高於 `autoSwitchThreshold` 時挑選已知 5 小時用量最低者; +會在合格帳號之間選擇:`quota`(預設)在用量高於 `autoSwitchThreshold` 時,依 +`anthropicAccountPool.quotaWindow` 所設定的視窗挑選已知用量最低者(`five-hour` 為預設,亦可選 +`weekly` 或 `max-utilization`); `round-robin` 平均分散(`stickyLimit`,預設 `1`);`fill-first` 一直使用作用中帳號直到冷卻、重新認證 或達到閾值,然後前進。它**預設關閉**、會在 GUI 顯示警告,而且尚未經過實戰驗證——Anthropic 可能 限制看起來像自動輪換的帳號;輪換並不能保護你免受供應商執行機制的處置。 @@ -26,6 +28,8 @@ sticky session affinity 與 429 冷卻故障轉移。僅對**新**工作階段 - Affinity 是**程序本機**的(proxy 重啟後就會遺失)。 - **401/403** 憑證失敗會隔離該帳號(`needsReauth`),直到重新認證前都不會參與選擇。 - 如果每個合格帳號都在冷卻,proxy 會回傳 **429**(不是 401),並在已知時附上 `Retry-After`。 +- 復原(包括 429 容錯移轉)會使用 `quotaWindow` 為合格的替代帳號排序,且不改變現有的冷卻或 + 容錯移轉上限;`round-robin` 會忽略 `quotaWindow`。 請見 [Configuration](/zh-tw/reference/configuration/#anthropicaccountpool-experimental)。 diff --git a/docs-site/src/content/docs/zh-tw/reference/configuration/providers.md b/docs-site/src/content/docs/zh-tw/reference/configuration/providers.md index b0a46f49ec..b7c9eacbac 100644 --- a/docs-site/src/content/docs/zh-tw/reference/configuration/providers.md +++ b/docs-site/src/content/docs/zh-tw/reference/configuration/providers.md @@ -126,8 +126,9 @@ API-key 供應商可持有字面值金鑰或環境參考。OAuth 供應商使用 | Key | 型別 | 預設值 | 說明 | | --- | --- | --- | --- | | `anthropicAccountPool.enabled?` | `boolean` | `false` | 啟用 sticky 親和性與 429 冷卻容錯移轉。 | -| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | 對於新 session,選擇在此閾值或以上的最低已知快取 5 小時用量。`0` 停用量量挑選。 | -| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | 新 session 策略;quota 僅使用 5 小時列。 | +| `anthropicAccountPool.autoSwitchThreshold?` | `number` | `80` | 對於新 session,當目前帳號達到此閾值時,選擇設定視窗中最低的已知快取用量。`0` 停用配額挑選。 | +| `anthropicAccountPool.strategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | 新 session 策略;`quota` 依 `quotaWindow` 指定的視窗(預設為 5 小時列)為帳號排序,`fill-first` 也在同一視窗中判定其排空閾值。 | +| `anthropicAccountPool.quotaWindow?` | `"five-hour" \| "weekly" \| "max-utilization"` | `"five-hour"` | 使用量型帳號選擇所評分的快取用量列。`five-hour` 保留原有行為。`weekly` 使用每週用量列,但仍會略過 5 小時用量已耗盡的帳號。`max-utilization` 使用兩個用量中較高的值。兩種模式分數相同時,都優先選擇 5 小時用量較低的帳號。`round-robin` 會忽略此設定。不會主動重新平衡健康且已有 affinity 的 session;遇到終止錯誤進行復原時(包括 429 容錯移轉),仍會按此視窗排序合格的替代帳號,但不改變現有冷卻或容錯移轉上限。每個帳號的每週用量只有在 dashboard 的供應商頁面完成查詢後才可得知。 | | `anthropicAccountPool.stickyLimit?` | `number` | `1` | 在一次 round-robin 選擇上保留的成功新 session 綁定。範圍 1–100。 | 啟用時,429 記錄來自 `Retry-After` 或預設 backoff 的有界冷卻,並可能在請求內輪換。親和性為行程本地且有界。憑證 401/403 將帳號標記為需要重新認證。若所有合格帳號都在冷卻,客戶端收到附帶已知 `Retry-After` 的 429,而非認證錯誤。 diff --git a/gui/src/account-pool-strategy.ts b/gui/src/account-pool-strategy.ts index 4ff6b860c2..4dbc7b9e2b 100644 --- a/gui/src/account-pool-strategy.ts +++ b/gui/src/account-pool-strategy.ts @@ -6,12 +6,23 @@ export const ACCOUNT_POOL_STRATEGIES: readonly AccountPoolStrategy[] = [ "fill-first", ] as const; +/** Which cached usage bar the `quota` strategy scores. Mirrors `OcxAccountPoolQuotaWindow`. */ +export type AccountPoolQuotaWindow = "five-hour" | "weekly" | "max-utilization"; + +export const ACCOUNT_POOL_QUOTA_WINDOWS: readonly AccountPoolQuotaWindow[] = [ + "five-hour", + "weekly", + "max-utilization", +] as const; + export const DEFAULT_ACCOUNT_POOL_STRATEGY: AccountPoolStrategy = "quota"; +export const DEFAULT_ACCOUNT_POOL_QUOTA_WINDOW: AccountPoolQuotaWindow = "five-hour"; export const DEFAULT_ACCOUNT_POOL_STICKY_LIMIT = 1; export const MIN_ACCOUNT_POOL_STICKY_LIMIT = 1; export const MAX_ACCOUNT_POOL_STICKY_LIMIT = 100; const STRATEGY_SET = new Set(ACCOUNT_POOL_STRATEGIES); +const QUOTA_WINDOW_SET = new Set(ACCOUNT_POOL_QUOTA_WINDOWS); export function normalizeAccountPoolStrategy(value: unknown): AccountPoolStrategy { return typeof value === "string" && STRATEGY_SET.has(value) @@ -19,6 +30,12 @@ export function normalizeAccountPoolStrategy(value: unknown): AccountPoolStrateg : DEFAULT_ACCOUNT_POOL_STRATEGY; } +export function normalizeAccountPoolQuotaWindow(value: unknown): AccountPoolQuotaWindow { + return typeof value === "string" && QUOTA_WINDOW_SET.has(value) + ? value as AccountPoolQuotaWindow + : DEFAULT_ACCOUNT_POOL_QUOTA_WINDOW; +} + export function normalizeAccountPoolStickyLimit(value: unknown): number { return typeof value === "number" && Number.isInteger(value) diff --git a/gui/src/components/provider-workspace/AnthropicAccountPoolSettings.tsx b/gui/src/components/provider-workspace/AnthropicAccountPoolSettings.tsx index d0ef91fab5..f7f3e8df00 100644 --- a/gui/src/components/provider-workspace/AnthropicAccountPoolSettings.tsx +++ b/gui/src/components/provider-workspace/AnthropicAccountPoolSettings.tsx @@ -5,20 +5,32 @@ import { useCallback, useEffect, useState } from "react"; import { useT } from "../../i18n/shared"; import { + ACCOUNT_POOL_QUOTA_WINDOWS, + DEFAULT_ACCOUNT_POOL_QUOTA_WINDOW, DEFAULT_ACCOUNT_POOL_STICKY_LIMIT, DEFAULT_ACCOUNT_POOL_STRATEGY, + normalizeAccountPoolQuotaWindow, normalizeAccountPoolStickyLimit, normalizeAccountPoolStrategy, parseAccountPoolStickyLimitDraft, + type AccountPoolQuotaWindow, type AccountPoolStrategy, } from "../../account-pool-strategy"; import AccountPoolStrategyControls from "../AccountPoolStrategyControls"; +import { Select } from "../../ui"; + +const QUOTA_WINDOW_LABEL_KEYS = { + "five-hour": "accountPool.quotaWindowFiveHour", + weekly: "accountPool.quotaWindowWeekly", + "max-utilization": "accountPool.quotaWindowMaxUtilization", +} as const; type PoolState = { enabled: boolean; threshold: number; strategy: AccountPoolStrategy; stickyLimit: number; + quotaWindow: AccountPoolQuotaWindow; }; export default function AnthropicAccountPoolSettings({ @@ -56,6 +68,7 @@ export default function AnthropicAccountPoolSettings({ autoSwitchThreshold?: number; strategy?: unknown; stickyLimit?: unknown; + quotaWindow?: unknown; }>; }) .then(json => { @@ -67,6 +80,7 @@ export default function AnthropicAccountPoolSettings({ threshold: nextThreshold, strategy: normalizeAccountPoolStrategy(json.strategy), stickyLimit: nextSticky, + quotaWindow: normalizeAccountPoolQuotaWindow(json.quotaWindow), }); setDraft(String(nextThreshold)); setStickyDraft(String(nextSticky)); @@ -87,6 +101,7 @@ export default function AnthropicAccountPoolSettings({ threshold: number; strategy: AccountPoolStrategy; stickyLimit: number; + quotaWindow: AccountPoolQuotaWindow; }) => { const previousState = state; setState({ @@ -94,6 +109,7 @@ export default function AnthropicAccountPoolSettings({ threshold: next.threshold, strategy: next.strategy, stickyLimit: next.stickyLimit, + quotaWindow: next.quotaWindow, }); setSaving(true); setError(null); @@ -107,20 +123,24 @@ export default function AnthropicAccountPoolSettings({ autoSwitchThreshold: next.threshold, strategy: next.strategy, stickyLimit: next.stickyLimit, + quotaWindow: next.quotaWindow, }), }); if (!res.ok) throw new Error("save"); const json = await res.json().catch(() => null) as { strategy?: unknown; stickyLimit?: unknown; + quotaWindow?: unknown; } | null; const savedStrategy = normalizeAccountPoolStrategy(json?.strategy ?? next.strategy); const savedSticky = normalizeAccountPoolStickyLimit(json?.stickyLimit ?? next.stickyLimit); + const savedWindow = normalizeAccountPoolQuotaWindow(json?.quotaWindow ?? next.quotaWindow); setState({ enabled: next.enabled, threshold: next.threshold, strategy: savedStrategy, stickyLimit: savedSticky, + quotaWindow: savedWindow, }); setDraft(String(next.threshold)); setStickyDraft(String(savedSticky)); @@ -140,6 +160,10 @@ export default function AnthropicAccountPoolSettings({ const threshold = state?.threshold ?? 80; const strategy = state?.strategy ?? DEFAULT_ACCOUNT_POOL_STRATEGY; const stickyLimit = state?.stickyLimit ?? DEFAULT_ACCOUNT_POOL_STICKY_LIMIT; + const quotaWindow = state?.quotaWindow ?? DEFAULT_ACCOUNT_POOL_QUOTA_WINDOW; + // Only quota scores a usage bar; fill-first scores one too, but a 0 threshold turns its + // drain point off. Neither reads a bar under round-robin, so the window is inert there. + const quotaWindowInert = strategy !== "quota" && !(strategy === "fill-first" && threshold > 0); const loading = state === null && !loadError; // Always allow turning the pool off; only block enabling when fewer than 2 accounts. const toggleDisabled = loading || saving || loadError || (!enabled && accountCount < 2); @@ -155,7 +179,10 @@ export default function AnthropicAccountPoolSettings({ : loading ? t("common.loading") : enabled - ? t("anthropicPool.enabledDesc", { threshold }) + ? t("anthropicPool.enabledDesc", { + threshold, + window: t(QUOTA_WINDOW_LABEL_KEYS[quotaWindow]), + }) : t("anthropicPool.disabledDesc")} @@ -172,6 +199,7 @@ export default function AnthropicAccountPoolSettings({ threshold, strategy, stickyLimit, + quotaWindow, }); }} > @@ -214,6 +242,7 @@ export default function AnthropicAccountPoolSettings({ threshold: parsed, strategy, stickyLimit, + quotaWindow, }); } }} @@ -234,6 +263,7 @@ export default function AnthropicAccountPoolSettings({ threshold, strategy: next, stickyLimit, + quotaWindow, }); }} onStickyDraftChange={setStickyDraft} @@ -253,9 +283,39 @@ export default function AnthropicAccountPoolSettings({ threshold, strategy, stickyLimit: parsed, + quotaWindow, }); }} /> + +
+ {t("accountPool.quotaWindow")} +