946946 </div >
947947 </div >
948948
949+ <!-- RPM Limit -->
950+ <div class =" rounded-lg border border-gray-200 p-4 dark:border-dark-600" >
951+ <div class =" mb-3 flex items-center justify-between" >
952+ <div >
953+ <label class =" input-label mb-0" >{{ t('admin.accounts.quotaControl.rpmLimit.label') }}</label >
954+ <p class =" mt-1 text-xs text-gray-500 dark:text-gray-400" >
955+ {{ t('admin.accounts.quotaControl.rpmLimit.hint') }}
956+ </p >
957+ </div >
958+ <button
959+ type =" button"
960+ @click =" rpmLimitEnabled = !rpmLimitEnabled"
961+ :class =" [
962+ 'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2',
963+ rpmLimitEnabled ? 'bg-primary-600' : 'bg-gray-200 dark:bg-dark-600'
964+ ]"
965+ >
966+ <span
967+ :class =" [
968+ 'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out',
969+ rpmLimitEnabled ? 'translate-x-5' : 'translate-x-0'
970+ ]"
971+ />
972+ </button >
973+ </div >
974+
975+ <div v-if =" rpmLimitEnabled" class =" grid grid-cols-2 gap-4" >
976+ <div >
977+ <label class =" input-label" >{{ t('admin.accounts.quotaControl.rpmLimit.baseRpm') }}</label >
978+ <input
979+ v-model.number =" baseRpm"
980+ type =" number"
981+ min =" 1"
982+ step =" 1"
983+ class =" input"
984+ :placeholder =" t('admin.accounts.quotaControl.rpmLimit.baseRpmPlaceholder')"
985+ />
986+ <p class =" input-hint" >{{ t('admin.accounts.quotaControl.rpmLimit.baseRpmHint') }}</p >
987+ </div >
988+ <div >
989+ <label class =" input-label" >{{ t('admin.accounts.quotaControl.rpmLimit.strategy') }}</label >
990+ <select v-model =" rpmStrategy" class =" input" >
991+ <option value =" tiered" >{{ t('admin.accounts.quotaControl.rpmLimit.strategyTiered') }}</option >
992+ <option value =" sticky_exempt" >{{ t('admin.accounts.quotaControl.rpmLimit.strategyStickyExempt') }}</option >
993+ </select >
994+ <p class =" input-hint" >{{ t('admin.accounts.quotaControl.rpmLimit.strategyHint') }}</p >
995+ </div >
996+ </div >
997+ </div >
998+
949999 <!-- TLS Fingerprint -->
9501000 <div class =" rounded-lg border border-gray-200 p-4 dark:border-dark-600" >
9511001 <div class =" flex items-center justify-between" >
@@ -1251,6 +1301,9 @@ const windowCostStickyReserve = ref<number | null>(null)
12511301const sessionLimitEnabled = ref (false )
12521302const maxSessions = ref <number | null >(null )
12531303const sessionIdleTimeout = ref <number | null >(null )
1304+ const rpmLimitEnabled = ref (false )
1305+ const baseRpm = ref <number | null >(null )
1306+ const rpmStrategy = ref <string >(' tiered' )
12541307const tlsFingerprintEnabled = ref (false )
12551308const sessionIdMaskingEnabled = ref (false )
12561309const cacheTTLOverrideEnabled = ref (false )
@@ -1710,6 +1763,9 @@ function loadQuotaControlSettings(account: Account) {
17101763 sessionLimitEnabled .value = false
17111764 maxSessions .value = null
17121765 sessionIdleTimeout .value = null
1766+ rpmLimitEnabled .value = false
1767+ baseRpm .value = null
1768+ rpmStrategy .value = ' tiered'
17131769 tlsFingerprintEnabled .value = false
17141770 sessionIdMaskingEnabled .value = false
17151771 cacheTTLOverrideEnabled .value = false
@@ -1733,6 +1789,13 @@ function loadQuotaControlSettings(account: Account) {
17331789 sessionIdleTimeout .value = account .session_idle_timeout_minutes ?? 5
17341790 }
17351791
1792+ // RPM limit
1793+ if (account .base_rpm != null && account .base_rpm > 0 ) {
1794+ rpmLimitEnabled .value = true
1795+ baseRpm .value = account .base_rpm
1796+ rpmStrategy .value = account .rpm_strategy || ' tiered'
1797+ }
1798+
17361799 // Load TLS fingerprint setting
17371800 if (account .enable_tls_fingerprint === true ) {
17381801 tlsFingerprintEnabled .value = true
@@ -2043,6 +2106,16 @@ const handleSubmit = async () => {
20432106 delete newExtra .session_idle_timeout_minutes
20442107 }
20452108
2109+ // RPM limit settings
2110+ if (rpmLimitEnabled .value && baseRpm .value != null && baseRpm .value > 0 ) {
2111+ newExtra .base_rpm = baseRpm .value
2112+ newExtra .rpm_strategy = rpmStrategy .value
2113+ } else {
2114+ delete newExtra .base_rpm
2115+ delete newExtra .rpm_strategy
2116+ delete newExtra .rpm_sticky_buffer
2117+ }
2118+
20462119 // TLS fingerprint setting
20472120 if (tlsFingerprintEnabled .value ) {
20482121 newExtra .enable_tls_fingerprint = true
0 commit comments