|
1536 | 1536 | </div> |
1537 | 1537 | </div> |
1538 | 1538 |
|
| 1539 | + <!-- RPM Limit --> |
| 1540 | + <div class="rounded-lg border border-gray-200 p-4 dark:border-dark-600"> |
| 1541 | + <div class="mb-3 flex items-center justify-between"> |
| 1542 | + <div> |
| 1543 | + <label class="input-label mb-0">{{ t('admin.accounts.quotaControl.rpmLimit.label') }}</label> |
| 1544 | + <p class="mt-1 text-xs text-gray-500 dark:text-gray-400"> |
| 1545 | + {{ t('admin.accounts.quotaControl.rpmLimit.hint') }} |
| 1546 | + </p> |
| 1547 | + </div> |
| 1548 | + <button |
| 1549 | + type="button" |
| 1550 | + @click="rpmLimitEnabled = !rpmLimitEnabled" |
| 1551 | + :class="[ |
| 1552 | + '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', |
| 1553 | + rpmLimitEnabled ? 'bg-primary-600' : 'bg-gray-200 dark:bg-dark-600' |
| 1554 | + ]" |
| 1555 | + > |
| 1556 | + <span |
| 1557 | + :class="[ |
| 1558 | + 'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out', |
| 1559 | + rpmLimitEnabled ? 'translate-x-5' : 'translate-x-0' |
| 1560 | + ]" |
| 1561 | + /> |
| 1562 | + </button> |
| 1563 | + </div> |
| 1564 | + |
| 1565 | + <div v-if="rpmLimitEnabled" class="grid grid-cols-2 gap-4"> |
| 1566 | + <div> |
| 1567 | + <label class="input-label">{{ t('admin.accounts.quotaControl.rpmLimit.baseRpm') }}</label> |
| 1568 | + <input |
| 1569 | + v-model.number="baseRpm" |
| 1570 | + type="number" |
| 1571 | + min="1" |
| 1572 | + step="1" |
| 1573 | + class="input" |
| 1574 | + :placeholder="t('admin.accounts.quotaControl.rpmLimit.baseRpmPlaceholder')" |
| 1575 | + /> |
| 1576 | + <p class="input-hint">{{ t('admin.accounts.quotaControl.rpmLimit.baseRpmHint') }}</p> |
| 1577 | + </div> |
| 1578 | + <div> |
| 1579 | + <label class="input-label">{{ t('admin.accounts.quotaControl.rpmLimit.strategy') }}</label> |
| 1580 | + <select v-model="rpmStrategy" class="input"> |
| 1581 | + <option value="tiered">{{ t('admin.accounts.quotaControl.rpmLimit.strategyTiered') }}</option> |
| 1582 | + <option value="sticky_exempt">{{ t('admin.accounts.quotaControl.rpmLimit.strategyStickyExempt') }}</option> |
| 1583 | + </select> |
| 1584 | + <p class="input-hint">{{ t('admin.accounts.quotaControl.rpmLimit.strategyHint') }}</p> |
| 1585 | + </div> |
| 1586 | + </div> |
| 1587 | + </div> |
| 1588 | + |
1539 | 1589 | <!-- TLS Fingerprint --> |
1540 | 1590 | <div class="rounded-lg border border-gray-200 p-4 dark:border-dark-600"> |
1541 | 1591 | <div class="flex items-center justify-between"> |
@@ -2393,6 +2443,9 @@ const windowCostStickyReserve = ref<number | null>(null) |
2393 | 2443 | const sessionLimitEnabled = ref(false) |
2394 | 2444 | const maxSessions = ref<number | null>(null) |
2395 | 2445 | const sessionIdleTimeout = ref<number | null>(null) |
| 2446 | +const rpmLimitEnabled = ref(false) |
| 2447 | +const baseRpm = ref<number | null>(null) |
| 2448 | +const rpmStrategy = ref<string>('tiered') |
2396 | 2449 | const tlsFingerprintEnabled = ref(false) |
2397 | 2450 | const sessionIdMaskingEnabled = ref(false) |
2398 | 2451 | const cacheTTLOverrideEnabled = ref(false) |
@@ -3017,6 +3070,9 @@ const resetForm = () => { |
3017 | 3070 | sessionLimitEnabled.value = false |
3018 | 3071 | maxSessions.value = null |
3019 | 3072 | sessionIdleTimeout.value = null |
| 3073 | + rpmLimitEnabled.value = false |
| 3074 | + baseRpm.value = null |
| 3075 | + rpmStrategy.value = 'tiered' |
3020 | 3076 | tlsFingerprintEnabled.value = false |
3021 | 3077 | sessionIdMaskingEnabled.value = false |
3022 | 3078 | cacheTTLOverrideEnabled.value = false |
@@ -3926,6 +3982,12 @@ const handleAnthropicExchange = async (authCode: string) => { |
3926 | 3982 | extra.session_idle_timeout_minutes = sessionIdleTimeout.value ?? 5 |
3927 | 3983 | } |
3928 | 3984 |
|
| 3985 | + // Add RPM limit settings |
| 3986 | + if (rpmLimitEnabled.value && baseRpm.value != null && baseRpm.value > 0) { |
| 3987 | + extra.base_rpm = baseRpm.value |
| 3988 | + extra.rpm_strategy = rpmStrategy.value |
| 3989 | + } |
| 3990 | +
|
3929 | 3991 | // Add TLS fingerprint settings |
3930 | 3992 | if (tlsFingerprintEnabled.value) { |
3931 | 3993 | extra.enable_tls_fingerprint = true |
@@ -4024,6 +4086,12 @@ const handleCookieAuth = async (sessionKey: string) => { |
4024 | 4086 | extra.session_idle_timeout_minutes = sessionIdleTimeout.value ?? 5 |
4025 | 4087 | } |
4026 | 4088 |
|
| 4089 | + // Add RPM limit settings |
| 4090 | + if (rpmLimitEnabled.value && baseRpm.value != null && baseRpm.value > 0) { |
| 4091 | + extra.base_rpm = baseRpm.value |
| 4092 | + extra.rpm_strategy = rpmStrategy.value |
| 4093 | + } |
| 4094 | +
|
4027 | 4095 | // Add TLS fingerprint settings |
4028 | 4096 | if (tlsFingerprintEnabled.value) { |
4029 | 4097 | extra.enable_tls_fingerprint = true |
|
0 commit comments