From 5d3423bec13f6da2498bdc5b288c9ee2507fd3ef Mon Sep 17 00:00:00 2001
From: Seefs <40468931+seefs001@users.noreply.github.com>
Date: Mon, 10 Aug 2026 12:47:44 +0800
Subject: [PATCH] feat(channels): add auto-disable-only channel test mode
(#6728)
---
controller/channel-test.go | 3 ++
controller/channel_test_internal_test.go | 18 +++++++
setting/operation_setting/monitor_setting.go | 5 +-
.../operation_setting/monitor_setting_test.go | 14 ++++++
.../models/routing-reliability-section.tsx | 49 +++++++++++++++----
web/src/features/system-settings/types.ts | 5 +-
web/src/i18n/locales/en.json | 9 ++++
web/src/i18n/locales/fr.json | 9 ++++
web/src/i18n/locales/ja.json | 9 ++++
web/src/i18n/locales/ru.json | 9 ++++
web/src/i18n/locales/vi.json | 9 ++++
web/src/i18n/locales/zh-TW.json | 9 ++++
web/src/i18n/locales/zh.json | 9 ++++
13 files changed, 146 insertions(+), 11 deletions(-)
diff --git a/controller/channel-test.go b/controller/channel-test.go
index f494af04..a13ed5d6 100644
--- a/controller/channel-test.go
+++ b/controller/channel-test.go
@@ -1049,6 +1049,9 @@ func selectChannelsForAutomaticTest(channels []*model.Channel, mode string) []*m
if channel.Status == common.ChannelStatusManuallyDisabled {
continue
}
+ if mode == operation_setting.ChannelTestModeAutoBanOnly && !channel.GetAutoBan() {
+ continue
+ }
if mode == operation_setting.ChannelTestModePassiveRecovery && channel.Status != common.ChannelStatusAutoDisabled {
continue
}
diff --git a/controller/channel_test_internal_test.go b/controller/channel_test_internal_test.go
index abbd2d23..fa69f852 100644
--- a/controller/channel_test_internal_test.go
+++ b/controller/channel_test_internal_test.go
@@ -312,6 +312,24 @@ func TestSelectChannelsForAutomaticTestScheduledSkipsManualDisabled(t *testing.T
require.Equal(t, 2, selected[1].Id)
}
+func TestSelectChannelsForAutomaticTestAutoBanOnlyUsesEligibleChannels(t *testing.T) {
+ autoBanEnabled := 1
+ autoBanDisabled := 0
+ channels := []*model.Channel{
+ {Id: 1, Status: common.ChannelStatusEnabled, AutoBan: &autoBanEnabled},
+ {Id: 2, Status: common.ChannelStatusEnabled, AutoBan: &autoBanDisabled},
+ {Id: 3, Status: common.ChannelStatusAutoDisabled, AutoBan: &autoBanEnabled},
+ {Id: 4, Status: common.ChannelStatusManuallyDisabled, AutoBan: &autoBanEnabled},
+ {Id: 5, Status: common.ChannelStatusEnabled},
+ }
+
+ selected := selectChannelsForAutomaticTest(channels, operation_setting.ChannelTestModeAutoBanOnly)
+
+ require.Len(t, selected, 2)
+ require.Equal(t, 1, selected[0].Id)
+ require.Equal(t, 3, selected[1].Id)
+}
+
func TestTestAllChannelsRejectsExistingActiveTask(t *testing.T) {
db := setupModelListControllerTestDB(t)
require.NoError(t, db.AutoMigrate(&model.SystemTask{}, &model.SystemTaskLock{}))
diff --git a/setting/operation_setting/monitor_setting.go b/setting/operation_setting/monitor_setting.go
index 8593d834..a88087f2 100644
--- a/setting/operation_setting/monitor_setting.go
+++ b/setting/operation_setting/monitor_setting.go
@@ -15,6 +15,7 @@ type MonitorSetting struct {
const (
ChannelTestModeScheduledAll = "scheduled_all"
+ ChannelTestModeAutoBanOnly = "auto_ban_only"
ChannelTestModePassiveRecovery = "passive_recovery"
)
@@ -45,7 +46,9 @@ func GetMonitorSetting() *MonitorSetting {
monitorSetting.AutoTestChannelEnabled = parsed
}
}
- if monitorSetting.ChannelTestMode != ChannelTestModePassiveRecovery {
+ switch monitorSetting.ChannelTestMode {
+ case ChannelTestModeAutoBanOnly, ChannelTestModePassiveRecovery:
+ default:
monitorSetting.ChannelTestMode = ChannelTestModeScheduledAll
}
return &monitorSetting
diff --git a/setting/operation_setting/monitor_setting_test.go b/setting/operation_setting/monitor_setting_test.go
index 7aef7eaa..c31023e8 100644
--- a/setting/operation_setting/monitor_setting_test.go
+++ b/setting/operation_setting/monitor_setting_test.go
@@ -41,3 +41,17 @@ func TestGetMonitorSetting_ChannelTestEnabledEnvCanEnableDisabledConfig(t *testi
assert.True(t, setting.AutoTestChannelEnabled)
assert.Equal(t, float64(12), setting.AutoTestChannelMinutes)
}
+
+func TestGetMonitorSettingPreservesAutoBanOnlyMode(t *testing.T) {
+ orig := monitorSetting
+ t.Cleanup(func() { monitorSetting = orig })
+
+ t.Setenv("CHANNEL_TEST_ENABLED", "")
+ t.Setenv("CHANNEL_TEST_FREQUENCY", "")
+ monitorSetting = MonitorSetting{ChannelTestMode: ChannelTestModeAutoBanOnly}
+
+ setting := GetMonitorSetting()
+
+ require.NotNil(t, setting)
+ assert.Equal(t, ChannelTestModeAutoBanOnly, setting.ChannelTestMode)
+}
diff --git a/web/src/features/system-settings/models/routing-reliability-section.tsx b/web/src/features/system-settings/models/routing-reliability-section.tsx
index efc8092a..1b8527ec 100644
--- a/web/src/features/system-settings/models/routing-reliability-section.tsx
+++ b/web/src/features/system-settings/models/routing-reliability-section.tsx
@@ -63,7 +63,11 @@ const numericString = z.string().refine((value) => {
return !Number.isNaN(Number(trimmed)) && Number(trimmed) >= 0
}, 'Enter a non-negative number or leave empty')
-const channelTestModes = ['scheduled_all', 'passive_recovery'] as const
+const channelTestModes = [
+ 'scheduled_all',
+ 'auto_ban_only',
+ 'passive_recovery',
+] as const
type ChannelTestMode = (typeof channelTestModes)[number]
const routingReliabilitySchema = z
@@ -148,7 +152,10 @@ type NormalizedRoutingReliabilityValues = {
}
function normalizeChannelTestMode(value?: string): ChannelTestMode {
- return value === 'passive_recovery' ? 'passive_recovery' : 'scheduled_all'
+ if (value === 'auto_ban_only' || value === 'passive_recovery') {
+ return value
+ }
+ return 'scheduled_all'
}
const buildFormDefaults = (
@@ -250,6 +257,23 @@ export function RoutingReliabilitySection({
const autoDisableStatusCodes = form.watch('AutomaticDisableStatusCodes')
const autoRetryStatusCodes = form.watch('AutomaticRetryStatusCodes')
const channelTestMode = form.watch('monitor_setting.channel_test_mode')
+ let channelTestModeDescription: string
+ switch (channelTestMode) {
+ case 'auto_ban_only':
+ channelTestModeDescription = t(
+ 'Periodically checks only channels with auto-disable enabled, excluding manually disabled channels.'
+ )
+ break
+ case 'passive_recovery':
+ channelTestModeDescription = t(
+ 'Does not check healthy channels. It only rechecks auto-disabled channels and restores them after they recover.'
+ )
+ break
+ default:
+ channelTestModeDescription = t(
+ 'Periodically checks all channels except manually disabled ones to detect failures and recover channels automatically.'
+ )
+ }
const autoDisableParsed = useMemo(
() => parseHttpStatusCodeRules(autoDisableStatusCodes),
[autoDisableStatusCodes]
@@ -391,11 +415,17 @@ export function RoutingReliabilitySection({
items={[
{
value: 'scheduled_all',
- label: t('Scheduled full test'),
+ label: t('Actively check all channels'),
+ },
+ {
+ value: 'auto_ban_only',
+ label: t(
+ 'Actively check auto-disable-enabled channels'
+ ),
},
{
value: 'passive_recovery',
- label: t('Passive recovery only'),
+ label: t('Check channels awaiting recovery only'),
},
]}
value={field.value}
@@ -409,18 +439,19 @@ export function RoutingReliabilitySection({
- {t('Scheduled full test')}
+ {t('Actively check all channels')}
+
+
+ {t('Actively check auto-disable-enabled channels')}
- {t('Passive recovery only')}
+ {t('Check channels awaiting recovery only')}
- {t(
- 'Scheduled full test probes non-manually-disabled channels; passive recovery only checks auto-disabled channels after real request failures.'
- )}
+ {channelTestModeDescription}
diff --git a/web/src/features/system-settings/types.ts b/web/src/features/system-settings/types.ts
index 6bb6f2db..d9445e54 100644
--- a/web/src/features/system-settings/types.ts
+++ b/web/src/features/system-settings/types.ts
@@ -235,7 +235,10 @@ export type ModelSettings = {
AutomaticRetryStatusCodes: string
'monitor_setting.auto_test_channel_enabled': boolean
'monitor_setting.auto_test_channel_minutes': number
- 'monitor_setting.channel_test_mode': 'scheduled_all' | 'passive_recovery'
+ 'monitor_setting.channel_test_mode':
+ | 'scheduled_all'
+ | 'auto_ban_only'
+ | 'passive_recovery'
'channel_affinity_setting.enabled': boolean
'channel_affinity_setting.switch_on_success': boolean
'channel_affinity_setting.keep_on_channel_disabled': boolean
diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json
index b48096a7..ce02e9ce 100644
--- a/web/src/i18n/locales/en.json
+++ b/web/src/i18n/locales/en.json
@@ -151,6 +151,8 @@
"Active models": "Active models",
"Active Tasks": "Active Tasks",
"active users": "active users",
+ "Actively check all channels": "Actively check all channels",
+ "Actively check auto-disable-enabled channels": "Actively check auto-disable-enabled channels",
"Actual Amount": "Actual Amount",
"Actual Model": "Actual Model",
"Actual Model:": "Actual Model:",
@@ -512,6 +514,8 @@
"Auto Sync Upstream Models": "Auto Sync Upstream Models",
"Auto-disable rules": "Auto-disable rules",
"Auto-disable status codes": "Auto-disable status codes",
+ "Auto-disable-enabled channels only": "Auto-disable-enabled channels only",
+ "Auto-disable-enabled mode probes non-manually-disabled channels with auto-disable enabled.": "Auto-disable-enabled mode probes non-manually-disabled channels with auto-disable enabled.",
"Auto-discover": "Auto-discover",
"Auto-discovers endpoints from the provider": "Auto-discovers endpoints from the provider",
"Auto-fill when one field exists and another is missing": "Auto-fill when one field exists and another is missing",
@@ -783,6 +787,7 @@
"Chat session management": "Chat session management",
"ChatCompletions -> Responses Compatibility": "ChatCompletions -> Responses Compatibility",
"ChatGPT Subscription (Codex)": "ChatGPT Subscription (Codex)",
+ "Check channels awaiting recovery only": "Check channels awaiting recovery only",
"Check for updates": "Check for updates",
"Check in daily to receive random quota rewards": "Check in daily to receive random quota rewards",
"Check in now": "Check in now",
@@ -1437,6 +1442,7 @@
"Docs": "Docs",
"Documentation Link": "Documentation Link",
"Documentation or external knowledge base.": "Documentation or external knowledge base.",
+ "Does not check healthy channels. It only rechecks auto-disabled channels and restores them after they recover.": "Does not check healthy channels. It only rechecks auto-disabled channels and restores them after they recover.",
"does not exist or might have been removed.": "does not exist or might have been removed.",
"Domain": "Domain",
"Domain Filter Mode": "Domain Filter Mode",
@@ -3358,6 +3364,8 @@
"Performed {{action}} on user {{username}} (ID: {{id}})": "Performed {{action}} on user {{username}} (ID: {{id}})",
"Period": "Period",
"Periodically check for upstream model changes": "Periodically check for upstream model changes",
+ "Periodically checks all channels except manually disabled ones to detect failures and recover channels automatically.": "Periodically checks all channels except manually disabled ones to detect failures and recover channels automatically.",
+ "Periodically checks only channels with auto-disable enabled, excluding manually disabled channels.": "Periodically checks only channels with auto-disable enabled, excluding manually disabled channels.",
"Periodically send ping frames to keep streaming connections active.": "Periodically send ping frames to keep streaming connections active.",
"Permanently delete your account and all data": "Permanently delete your account and all data",
"Permit Passkey registration on non-HTTPS origins (only recommended for development)": "Permit Passkey registration on non-HTTPS origins (only recommended for development)",
@@ -3673,6 +3681,7 @@
"Recommended to keep this high to avoid upstream throttling.": "Recommended to keep this high to avoid upstream throttling.",
"Record IP Address": "Record IP Address",
"Record quota usage": "Record quota usage",
+ "Recover auto-disabled channels only": "Recover auto-disabled channels only",
"Recursion Strategy": "Recursion Strategy",
"Recursive": "Recursive",
"Redeem": "Redeem",
diff --git a/web/src/i18n/locales/fr.json b/web/src/i18n/locales/fr.json
index 638cf9ab..9954c18a 100644
--- a/web/src/i18n/locales/fr.json
+++ b/web/src/i18n/locales/fr.json
@@ -151,6 +151,8 @@
"Active models": "Modèles actifs",
"Active Tasks": "Tâches actives",
"active users": "utilisateurs actifs",
+ "Actively check all channels": "Vérifier activement tous les canaux",
+ "Actively check auto-disable-enabled channels": "Vérifier activement les canaux avec désactivation automatique",
"Actual Amount": "Montant réel",
"Actual Model": "Modèle réel",
"Actual Model:": "Modèle réel :",
@@ -512,6 +514,8 @@
"Auto Sync Upstream Models": "Synchronisation automatique des modèles en amont",
"Auto-disable rules": "Règles de désactivation automatique",
"Auto-disable status codes": "Codes de statut de désactivation auto",
+ "Auto-disable-enabled channels only": "Canaux avec désactivation automatique uniquement",
+ "Auto-disable-enabled mode probes non-manually-disabled channels with auto-disable enabled.": "Ce mode sonde uniquement les canaux dont la désactivation automatique est activée et qui ne sont pas désactivés manuellement.",
"Auto-discover": "Découverte automatique",
"Auto-discovers endpoints from the provider": "Découvre automatiquement les points de terminaison du fournisseur",
"Auto-fill when one field exists and another is missing": "Remplissage automatique si un champ existe et l'autre est manquant",
@@ -783,6 +787,7 @@
"Chat session management": "Gestion des sessions de chat",
"ChatCompletions -> Responses Compatibility": "Compatibilité ChatCompletions -> Réponses",
"ChatGPT Subscription (Codex)": "ChatGPT Subscription (Codex)",
+ "Check channels awaiting recovery only": "Vérifier uniquement les canaux en attente de rétablissement",
"Check for updates": "Vérifier les mises à jour",
"Check in daily to receive random quota rewards": "Connectez-vous quotidiennement pour recevoir des récompenses de quota aléatoires",
"Check in now": "Se connecter maintenant",
@@ -1437,6 +1442,7 @@
"Docs": "Documents",
"Documentation Link": "Lien de la documentation",
"Documentation or external knowledge base.": "Documentation ou base de connaissances externe.",
+ "Does not check healthy channels. It only rechecks auto-disabled channels and restores them after they recover.": "Ne vérifie pas les canaux opérationnels. Revérifie uniquement les canaux désactivés automatiquement et les réactive après leur rétablissement.",
"does not exist or might have been removed.": "n'existe pas ou a peut-être été supprimé.",
"Domain": "Domaine",
"Domain Filter Mode": "Mode de filtre de domaine",
@@ -3358,6 +3364,8 @@
"Performed {{action}} on user {{username}} (ID: {{id}})": "Action {{action}} effectuée sur l'utilisateur {{username}} (ID : {{id}})",
"Period": "Période",
"Periodically check for upstream model changes": "Vérifier périodiquement les changements de modèles en amont",
+ "Periodically checks all channels except manually disabled ones to detect failures and recover channels automatically.": "Vérifie périodiquement tous les canaux sauf ceux désactivés manuellement afin de détecter les pannes et de rétablir automatiquement les canaux.",
+ "Periodically checks only channels with auto-disable enabled, excluding manually disabled channels.": "Vérifie périodiquement uniquement les canaux dont la désactivation automatique est activée, en excluant les canaux désactivés manuellement.",
"Periodically send ping frames to keep streaming connections active.": "Envoyer périodiquement des trames ping pour maintenir les connexions de streaming actives.",
"Permanently delete your account and all data": "Supprimer définitivement votre compte et toutes les données",
"Permit Passkey registration on non-HTTPS origins (only recommended for development)": "Autoriser l'enregistrement de Passkey sur des origines non-HTTPS (recommandé uniquement pour le développement)",
@@ -3673,6 +3681,7 @@
"Recommended to keep this high to avoid upstream throttling.": "Il est recommandé de maintenir cette valeur élevée pour éviter la limitation en amont.",
"Record IP Address": "Enregistrer l'adresse IP",
"Record quota usage": "Enregistrer l'utilisation du quota",
+ "Recover auto-disabled channels only": "Restaurer uniquement les canaux désactivés automatiquement",
"Recursion Strategy": "Stratégie de récursion",
"Recursive": "Récursif",
"Redeem": "Utiliser",
diff --git a/web/src/i18n/locales/ja.json b/web/src/i18n/locales/ja.json
index 3b9d4ce6..3394a33d 100644
--- a/web/src/i18n/locales/ja.json
+++ b/web/src/i18n/locales/ja.json
@@ -151,6 +151,8 @@
"Active models": "アクティブなモデル",
"Active Tasks": "進行中のタスク",
"active users": "アクティブユーザー",
+ "Actively check all channels": "すべてのチャネルを定期チェック",
+ "Actively check auto-disable-enabled channels": "自動無効化が有効なチャネルを定期チェック",
"Actual Amount": "実際の金額",
"Actual Model": "実際のモデル",
"Actual Model:": "実際のモデル:",
@@ -512,6 +514,8 @@
"Auto Sync Upstream Models": "アップストリームモデルの自動同期",
"Auto-disable rules": "自動無効化ルール",
"Auto-disable status codes": "自動無効化するステータスコード",
+ "Auto-disable-enabled channels only": "自動無効化が有効なチャネルのみ",
+ "Auto-disable-enabled mode probes non-manually-disabled channels with auto-disable enabled.": "このモードでは、自動無効化が有効で、手動で無効化されていないチャネルのみを検査します。",
"Auto-discover": "自動検出",
"Auto-discovers endpoints from the provider": "プロバイダーからエンドポイントを自動検出します",
"Auto-fill when one field exists and another is missing": "一方のフィールドがあり他方が欠けている場合に自動補完",
@@ -783,6 +787,7 @@
"Chat session management": "チャットセッション管理",
"ChatCompletions -> Responses Compatibility": "ChatCompletions → レスポンス互換",
"ChatGPT Subscription (Codex)": "ChatGPT Subscription (Codex)",
+ "Check channels awaiting recovery only": "復旧待ちのチャネルのみチェック",
"Check for updates": "更新を確認",
"Check in daily to receive random quota rewards": "毎日チェックインして、ランダムなノルマ報酬を受け取りましょう",
"Check in now": "今すぐチェックイン",
@@ -1437,6 +1442,7 @@
"Docs": "ドキュメント",
"Documentation Link": "ドキュメントリンク",
"Documentation or external knowledge base.": "ドキュメントまたは外部知識ベース。",
+ "Does not check healthy channels. It only rechecks auto-disabled channels and restores them after they recover.": "正常なチャネルはチェックしません。自動無効化されたチャネルのみを再チェックし、復旧後に再び有効化します。",
"does not exist or might have been removed.": "存在しないか、削除された可能性があります。",
"Domain": "ドメイン",
"Domain Filter Mode": "ドメインフィルターモード",
@@ -3358,6 +3364,8 @@
"Performed {{action}} on user {{username}} (ID: {{id}})": "ユーザー {{username}}(ID: {{id}})に対して {{action}} を実行しました",
"Period": "期間",
"Periodically check for upstream model changes": "アップストリームモデルの変更を定期的にチェック",
+ "Periodically checks all channels except manually disabled ones to detect failures and recover channels automatically.": "手動で無効化されたものを除くすべてのチャネルを定期チェックし、障害の検出と自動復旧を行います。",
+ "Periodically checks only channels with auto-disable enabled, excluding manually disabled channels.": "自動無効化が有効なチャネルのみを定期チェックします。手動で無効化されたチャネルは対象外です。",
"Periodically send ping frames to keep streaming connections active.": "ストリーミング接続をアクティブに保つために、定期的にpingフレームを送信します。",
"Permanently delete your account and all data": "アカウントとすべてのデータを永久に削除",
"Permit Passkey registration on non-HTTPS origins (only recommended for development)": "非HTTPSオリジンでのパスキー登録を許可する(開発でのみ推奨)",
@@ -3673,6 +3681,7 @@
"Recommended to keep this high to avoid upstream throttling.": "アップストリームのスロットリングを避けるため、これを高く保つことを推奨します。",
"Record IP Address": "IPアドレスを記録",
"Record quota usage": "クォータ使用量を記録",
+ "Recover auto-disabled channels only": "自動無効化されたチャネルの復旧のみ",
"Recursion Strategy": "再帰戦略",
"Recursive": "再帰",
"Redeem": "引き換え",
diff --git a/web/src/i18n/locales/ru.json b/web/src/i18n/locales/ru.json
index 853dc874..41f5285f 100644
--- a/web/src/i18n/locales/ru.json
+++ b/web/src/i18n/locales/ru.json
@@ -151,6 +151,8 @@
"Active models": "Активные модели",
"Active Tasks": "Активные задачи",
"active users": "активных пользователей",
+ "Actively check all channels": "Активно проверять все каналы",
+ "Actively check auto-disable-enabled channels": "Активно проверять каналы с автоотключением",
"Actual Amount": "Фактическая сумма",
"Actual Model": "Фактическая модель",
"Actual Model:": "Фактическая модель:",
@@ -512,6 +514,8 @@
"Auto Sync Upstream Models": "Автоматическая синхронизация моделей провайдера",
"Auto-disable rules": "Правила автоотключения",
"Auto-disable status codes": "Коды автоотключения",
+ "Auto-disable-enabled channels only": "Только каналы с автовыключением",
+ "Auto-disable-enabled mode probes non-manually-disabled channels with auto-disable enabled.": "В этом режиме проверяются только каналы с включённым автоматическим отключением, которые не были отключены вручную.",
"Auto-discover": "Автообнаружение",
"Auto-discovers endpoints from the provider": "Автоматически обнаруживает конечные точки от провайдера",
"Auto-fill when one field exists and another is missing": "Автозаполнение, когда одно поле есть, а другое отсутствует",
@@ -783,6 +787,7 @@
"Chat session management": "Управление сессиями чата",
"ChatCompletions -> Responses Compatibility": "Совместимость ChatCompletions → Ответы",
"ChatGPT Subscription (Codex)": "ChatGPT Subscription (Codex)",
+ "Check channels awaiting recovery only": "Проверять только каналы, ожидающие восстановления",
"Check for updates": "Проверить обновления",
"Check in daily to receive random quota rewards": "Регистрируйтесь ежедневно, чтобы получать случайные вознаграждения по квоте",
"Check in now": "Войдите сейчас",
@@ -1437,6 +1442,7 @@
"Docs": "Документы",
"Documentation Link": "Ссылка на документацию",
"Documentation or external knowledge base.": "Документация или внешняя база знаний.",
+ "Does not check healthy channels. It only rechecks auto-disabled channels and restores them after they recover.": "Рабочие каналы не проверяются. Повторно проверяются только автоматически отключённые каналы, которые включаются после восстановления.",
"does not exist or might have been removed.": "не существует или, возможно, был удален.",
"Domain": "Домен",
"Domain Filter Mode": "Режим фильтра домена",
@@ -3358,6 +3364,8 @@
"Performed {{action}} on user {{username}} (ID: {{id}})": "Выполнено действие {{action}} над пользователем {{username}} (ID: {{id}})",
"Period": "Период",
"Periodically check for upstream model changes": "Периодически проверять изменения моделей провайдера",
+ "Periodically checks all channels except manually disabled ones to detect failures and recover channels automatically.": "Периодически проверяет все каналы, кроме отключённых вручную, чтобы выявлять сбои и автоматически восстанавливать каналы.",
+ "Periodically checks only channels with auto-disable enabled, excluding manually disabled channels.": "Периодически проверяет только каналы с включённым автоотключением, исключая отключённые вручную.",
"Periodically send ping frames to keep streaming connections active.": "Периодически отправлять пинг-кадры для поддержания активности потоковых соединений.",
"Permanently delete your account and all data": "Безвозвратно удалить ваш аккаунт и все данные",
"Permit Passkey registration on non-HTTPS origins (only recommended for development)": "Разрешить регистрацию Passkey на не-HTTPS источниках (рекомендуется только для разработки)",
@@ -3673,6 +3681,7 @@
"Recommended to keep this high to avoid upstream throttling.": "Рекомендуется поддерживать это значение высоким, чтобы избежать регулирования со стороны вышестоящего поставщика.",
"Record IP Address": "Записывать IP-адрес",
"Record quota usage": "Записывать использование квоты",
+ "Recover auto-disabled channels only": "Только восстанавливать автоотключённые каналы",
"Recursion Strategy": "Стратегия рекурсии",
"Recursive": "Рекурсивно",
"Redeem": "Обменять квоту",
diff --git a/web/src/i18n/locales/vi.json b/web/src/i18n/locales/vi.json
index cdc1a126..16f5b195 100644
--- a/web/src/i18n/locales/vi.json
+++ b/web/src/i18n/locales/vi.json
@@ -151,6 +151,8 @@
"Active models": "Mô hình đang hoạt động",
"Active Tasks": "Tác vụ đang hoạt động",
"active users": "Người dùng tích cực",
+ "Actively check all channels": "Chủ động kiểm tra tất cả kênh",
+ "Actively check auto-disable-enabled channels": "Chủ động kiểm tra kênh đã bật tự động vô hiệu hóa",
"Actual Amount": "Số tiền thực tế",
"Actual Model": "Mô hình thực tế",
"Actual Model:": "Mô hình thực tế:",
@@ -512,6 +514,8 @@
"Auto Sync Upstream Models": "Tự động đồng bộ mô hình nguồn",
"Auto-disable rules": "Quy tắc tự động tắt",
"Auto-disable status codes": "Mã trạng thái tự tắt",
+ "Auto-disable-enabled channels only": "Chỉ kênh đã bật tự động vô hiệu hóa",
+ "Auto-disable-enabled mode probes non-manually-disabled channels with auto-disable enabled.": "Chế độ này chỉ kiểm tra các kênh đã bật tự động vô hiệu hóa và không bị vô hiệu hóa thủ công.",
"Auto-discover": "Tự động khám phá",
"Auto-discovers endpoints from the provider": "Tự động khám phá các điểm cuối từ nhà cung cấp",
"Auto-fill when one field exists and another is missing": "Tự động điền khi một trường có giá trị và trường khác thiếu",
@@ -783,6 +787,7 @@
"Chat session management": "Quản lý phiên trò chuyện",
"ChatCompletions -> Responses Compatibility": "Tương thích ChatCompletions -> Phản hồi",
"ChatGPT Subscription (Codex)": "ChatGPT Subscription (Codex)",
+ "Check channels awaiting recovery only": "Chỉ kiểm tra các kênh đang chờ khôi phục",
"Check for updates": "Kiểm tra cập nhật",
"Check in daily to receive random quota rewards": "Nhận phòng hàng ngày để nhận phần thưởng theo hạn ngạch ngẫu nhiên",
"Check in now": "Điểm danh ngay",
@@ -1437,6 +1442,7 @@
"Docs": "Tài liệu",
"Documentation Link": "Liên kết tài liệu",
"Documentation or external knowledge base.": "Tài liệu hoặc cơ sở kiến thức bên ngoài.",
+ "Does not check healthy channels. It only rechecks auto-disabled channels and restores them after they recover.": "Không kiểm tra kênh đang hoạt động bình thường. Chỉ kiểm tra lại kênh bị hệ thống tự động vô hiệu hóa và bật lại sau khi khôi phục.",
"does not exist or might have been removed.": "không tồn tại hoặc có thể đã bị xóa.",
"Domain": "Miền",
"Domain Filter Mode": "Chế độ lọc miền",
@@ -3358,6 +3364,8 @@
"Performed {{action}} on user {{username}} (ID: {{id}})": "Đã thực hiện {{action}} trên người dùng {{username}} (ID: {{id}})",
"Period": "Khoảng thời gian",
"Periodically check for upstream model changes": "Kiểm tra định kỳ các thay đổi mô hình nguồn",
+ "Periodically checks all channels except manually disabled ones to detect failures and recover channels automatically.": "Định kỳ kiểm tra tất cả kênh trừ kênh bị vô hiệu hóa thủ công để phát hiện lỗi và tự động khôi phục.",
+ "Periodically checks only channels with auto-disable enabled, excluding manually disabled channels.": "Chỉ định kỳ kiểm tra kênh đã bật tự động vô hiệu hóa, không kiểm tra kênh bị vô hiệu hóa thủ công.",
"Periodically send ping frames to keep streaming connections active.": "Định kỳ gửi các khung ping để duy trì các kết nối truyền phát hoạt động.",
"Permanently delete your account and all data": "Xóa vĩnh viễn tài khoản của bạn và tất cả dữ liệu",
"Permit Passkey registration on non-HTTPS origins (only recommended for development)": "Cho phép đăng ký Passkey trên các nguồn gốc không phải HTTPS (chỉ khuyến nghị cho mục đích phát triển)",
@@ -3673,6 +3681,7 @@
"Recommended to keep this high to avoid upstream throttling.": "Khuyến nghị giữ mức này cao để tránh điều tiết từ phía thượng nguồn.",
"Record IP Address": "Ghi lại địa chỉ IP",
"Record quota usage": "Ghi lại mức sử dụng hạn mức",
+ "Recover auto-disabled channels only": "Chỉ khôi phục kênh bị tự động vô hiệu hóa",
"Recursion Strategy": "Chiến lược đệ quy",
"Recursive": "Đệ quy",
"Redeem": "Đổi",
diff --git a/web/src/i18n/locales/zh-TW.json b/web/src/i18n/locales/zh-TW.json
index f8b5fafd..16ff3cd7 100644
--- a/web/src/i18n/locales/zh-TW.json
+++ b/web/src/i18n/locales/zh-TW.json
@@ -151,6 +151,8 @@
"Active models": "活躍模型",
"Active Tasks": "進行中任務",
"active users": "活躍用戶",
+ "Actively check all channels": "主動檢查全部渠道",
+ "Actively check auto-disable-enabled channels": "主動檢查已啟用自動停用的渠道",
"Actual Amount": "實付金額",
"Actual Model": "實際模型",
"Actual Model:": "實際模型:",
@@ -512,6 +514,8 @@
"Auto Sync Upstream Models": "自動同步上游模型",
"Auto-disable rules": "自動停用規則",
"Auto-disable status codes": "自動停用狀態碼",
+ "Auto-disable-enabled channels only": "僅測試已啟用自動停用的渠道",
+ "Auto-disable-enabled mode probes non-manually-disabled channels with auto-disable enabled.": "此模式僅探測已啟用自動停用且未被手動停用的渠道。",
"Auto-discover": "自動發現",
"Auto-discovers endpoints from the provider": "自動從供應商發現端點",
"Auto-fill when one field exists and another is missing": "在一個欄位有值、另一個缺失時自動補齊",
@@ -783,6 +787,7 @@
"Chat session management": "聊天對話管理",
"ChatCompletions -> Responses Compatibility": "ChatCompletions → 回應兼容",
"ChatGPT Subscription (Codex)": "ChatGPT Subscription (Codex)",
+ "Check channels awaiting recovery only": "僅檢查被自動停用的渠道",
"Check for updates": "檢查更新",
"Check in daily to receive random quota rewards": "每日簽到可獲得隨機額度獎勵",
"Check in now": "立即簽到",
@@ -1437,6 +1442,7 @@
"Docs": "文件",
"Documentation Link": "文件連結",
"Documentation or external knowledge base.": "文件或外部知識庫。",
+ "Does not check healthy channels. It only rechecks auto-disabled channels and restores them after they recover.": "不檢查正常渠道,只複查被系統自動停用的渠道,並在恢復後重新啟用。",
"does not exist or might have been removed.": "不存在或可能已被移除。",
"Domain": "域名",
"Domain Filter Mode": "域名過濾模式",
@@ -3358,6 +3364,8 @@
"Performed {{action}} on user {{username}} (ID: {{id}})": "對用戶 {{username}}(ID: {{id}})執行 {{action}}",
"Period": "時間範圍",
"Periodically check for upstream model changes": "定期檢查上游模型是否有變更",
+ "Periodically checks all channels except manually disabled ones to detect failures and recover channels automatically.": "定時檢查除手動停用外的全部渠道,用於主動發現故障並自動恢復渠道。",
+ "Periodically checks only channels with auto-disable enabled, excluding manually disabled channels.": "只定時檢查已啟用「自動停用」的渠道;未啟用該選項和手動停用的渠道不會被檢查。",
"Periodically send ping frames to keep streaming connections active.": "定期發送 ping 幀以保持串流連接處於活動狀態。",
"Permanently delete your account and all data": "永久刪除您的用戶和所有數據",
"Permit Passkey registration on non-HTTPS origins (only recommended for development)": "允許在非 HTTPS 源上註冊通行金鑰(僅建議用於開發)",
@@ -3673,6 +3681,7 @@
"Recommended to keep this high to avoid upstream throttling.": "建議保持此值較高,以避免上游限流。",
"Record IP Address": "記錄 IP 地址",
"Record quota usage": "記錄配額使用量",
+ "Recover auto-disabled channels only": "僅恢復自動停用的渠道",
"Recursion Strategy": "遞迴策略",
"Recursive": "遞迴",
"Redeem": "兌換額度",
diff --git a/web/src/i18n/locales/zh.json b/web/src/i18n/locales/zh.json
index 842991e7..9cabd02d 100644
--- a/web/src/i18n/locales/zh.json
+++ b/web/src/i18n/locales/zh.json
@@ -151,6 +151,8 @@
"Active models": "活跃模型",
"Active Tasks": "进行中任务",
"active users": "活跃用户",
+ "Actively check all channels": "主动检查全部渠道",
+ "Actively check auto-disable-enabled channels": "主动检查已开启自动禁用的渠道",
"Actual Amount": "实付金额",
"Actual Model": "实际模型",
"Actual Model:": "实际模型:",
@@ -512,6 +514,8 @@
"Auto Sync Upstream Models": "自动同步上游模型",
"Auto-disable rules": "自动禁用规则",
"Auto-disable status codes": "自动禁用状态码",
+ "Auto-disable-enabled channels only": "仅测试已开启自动禁用的渠道",
+ "Auto-disable-enabled mode probes non-manually-disabled channels with auto-disable enabled.": "此模式仅探测已开启自动禁用且未被手动禁用的渠道。",
"Auto-discover": "自动发现",
"Auto-discovers endpoints from the provider": "自动从提供商发现端点",
"Auto-fill when one field exists and another is missing": "在一个字段有值、另一个缺失时自动补齐",
@@ -783,6 +787,7 @@
"Chat session management": "聊天会话管理",
"ChatCompletions -> Responses Compatibility": "ChatCompletions → 响应兼容",
"ChatGPT Subscription (Codex)": "ChatGPT Subscription (Codex)",
+ "Check channels awaiting recovery only": "仅检查被自动禁用的渠道",
"Check for updates": "检查更新",
"Check in daily to receive random quota rewards": "每日签到可获得随机额度奖励",
"Check in now": "立即签到",
@@ -1437,6 +1442,7 @@
"Docs": "文档",
"Documentation Link": "文档链接",
"Documentation or external knowledge base.": "文档或外部知识库。",
+ "Does not check healthy channels. It only rechecks auto-disabled channels and restores them after they recover.": "不检查正常渠道,只复查被系统自动禁用的渠道,并在恢复后重新启用。",
"does not exist or might have been removed.": "不存在或可能已被移除。",
"Domain": "域名",
"Domain Filter Mode": "域名过滤模式",
@@ -3358,6 +3364,8 @@
"Performed {{action}} on user {{username}} (ID: {{id}})": "对用户 {{username}}(ID: {{id}})执行 {{action}}",
"Period": "时间范围",
"Periodically check for upstream model changes": "定期检查上游模型是否有变更",
+ "Periodically checks all channels except manually disabled ones to detect failures and recover channels automatically.": "定时检查除手动禁用外的全部渠道,用于主动发现故障并自动恢复渠道。",
+ "Periodically checks only channels with auto-disable enabled, excluding manually disabled channels.": "只定时检查已开启“自动禁用”的渠道;未开启该选项和手动禁用的渠道不会被检查。",
"Periodically send ping frames to keep streaming connections active.": "定期发送 ping 帧以保持流连接处于活动状态。",
"Permanently delete your account and all data": "永久删除您的帐户和所有数据",
"Permit Passkey registration on non-HTTPS origins (only recommended for development)": "允许在非 HTTPS 源上注册通行密钥(仅建议用于开发)",
@@ -3673,6 +3681,7 @@
"Recommended to keep this high to avoid upstream throttling.": "建议保持此值较高,以避免上游限流。",
"Record IP Address": "记录 IP 地址",
"Record quota usage": "记录配额使用量",
+ "Recover auto-disabled channels only": "仅恢复自动禁用的渠道",
"Recursion Strategy": "递归策略",
"Recursive": "递归",
"Redeem": "兑换额度",