Skip to content

Commit bf6db04

Browse files
committed
feat(config): expose quota cache refresh interval
1 parent 7976608 commit bf6db04

6 files changed

Lines changed: 84 additions & 26 deletions

File tree

src/components/config/VisualConfigEditor.tsx

Lines changed: 62 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ export function VisualConfigEditor({
187187
const routingStrategyLabelId = useId();
188188
const routingStrategyHintId = `${routingStrategyLabelId}-hint`;
189189
const stickyTTLInputId = useId();
190+
const quotaRefreshIntervalInputId = useId();
191+
const quotaRefreshIntervalHintId = `${quotaRefreshIntervalInputId}-hint`;
192+
const quotaRefreshIntervalErrorId = `${quotaRefreshIntervalInputId}-error`;
190193
const keepaliveInputId = useId();
191194
const keepaliveHintId = `${keepaliveInputId}-hint`;
192195
const keepaliveErrorId = `${keepaliveInputId}-error`;
@@ -220,6 +223,10 @@ export function VisualConfigEditor({
220223
);
221224
const maxRetryCredentialsError = getValidationMessage(t, validationErrors?.maxRetryCredentials);
222225
const maxRetryIntervalError = getValidationMessage(t, validationErrors?.maxRetryInterval);
226+
const quotaCacheRefreshIntervalError = getValidationMessage(
227+
t,
228+
validationErrors?.quotaCacheRefreshInterval
229+
);
223230
const routingStickyTTLError = getValidationMessage(t, validationErrors?.routingStickyTTL);
224231
const keepaliveError = getValidationMessage(t, validationErrors?.['streaming.keepaliveSeconds']);
225232
const bootstrapRetriesError = getValidationMessage(
@@ -317,7 +324,7 @@ export function VisualConfigEditor({
317324
title: t('config_management.visual.sections.quota.title'),
318325
description: t('config_management.visual.sections.quota.description'),
319326
icon: IconTimer,
320-
errorCount: 0,
327+
errorCount: countErrors(['quotaCacheRefreshInterval']),
321328
},
322329
{
323330
id: 'streaming',
@@ -982,31 +989,60 @@ export function VisualConfigEditor({
982989
title={t('config_management.visual.sections.quota.title')}
983990
description={t('config_management.visual.sections.quota.description')}
984991
>
985-
<SectionGrid>
986-
<ToggleRow
987-
title={t('config_management.visual.sections.quota.switch_project')}
988-
description={t('config_management.visual.sections.quota.switch_project_desc')}
989-
checked={values.quotaSwitchProject}
990-
disabled={disabled}
991-
onChange={(quotaSwitchProject) => onChange({ quotaSwitchProject })}
992-
/>
993-
<ToggleRow
994-
title={t('config_management.visual.sections.quota.switch_preview_model')}
995-
description={t('config_management.visual.sections.quota.switch_preview_model_desc')}
996-
checked={values.quotaSwitchPreviewModel}
997-
disabled={disabled}
998-
onChange={(quotaSwitchPreviewModel) => onChange({ quotaSwitchPreviewModel })}
999-
/>
1000-
<ToggleRow
1001-
title={t('config_management.visual.sections.quota.antigravity_credits')}
1002-
description={t(
1003-
'config_management.visual.sections.quota.antigravity_credits_desc'
1004-
)}
1005-
checked={values.quotaAntigravityCredits}
1006-
disabled={disabled}
1007-
onChange={(quotaAntigravityCredits) => onChange({ quotaAntigravityCredits })}
1008-
/>
1009-
</SectionGrid>
992+
<SectionStack>
993+
<SectionGrid>
994+
<FieldShell
995+
label={t('config_management.visual.sections.quota.refresh_interval')}
996+
htmlFor={quotaRefreshIntervalInputId}
997+
hint={t('config_management.visual.sections.quota.refresh_interval_hint')}
998+
hintId={quotaRefreshIntervalHintId}
999+
error={quotaCacheRefreshIntervalError}
1000+
errorId={quotaRefreshIntervalErrorId}
1001+
>
1002+
<input
1003+
id={quotaRefreshIntervalInputId}
1004+
className="input"
1005+
type="number"
1006+
placeholder="3600"
1007+
value={values.quotaCacheRefreshInterval}
1008+
onChange={(e) => onChange({ quotaCacheRefreshInterval: e.target.value })}
1009+
disabled={disabled}
1010+
aria-describedby={
1011+
quotaCacheRefreshIntervalError
1012+
? `${quotaRefreshIntervalErrorId} ${quotaRefreshIntervalHintId}`
1013+
: quotaRefreshIntervalHintId
1014+
}
1015+
aria-invalid={quotaCacheRefreshIntervalError ? true : undefined}
1016+
/>
1017+
</FieldShell>
1018+
</SectionGrid>
1019+
1020+
<SectionGrid>
1021+
<ToggleRow
1022+
title={t('config_management.visual.sections.quota.switch_project')}
1023+
description={t('config_management.visual.sections.quota.switch_project_desc')}
1024+
checked={values.quotaSwitchProject}
1025+
disabled={disabled}
1026+
onChange={(quotaSwitchProject) => onChange({ quotaSwitchProject })}
1027+
/>
1028+
<ToggleRow
1029+
title={t('config_management.visual.sections.quota.switch_preview_model')}
1030+
description={t('config_management.visual.sections.quota.switch_preview_model_desc')}
1031+
checked={values.quotaSwitchPreviewModel}
1032+
disabled={disabled}
1033+
onChange={(quotaSwitchPreviewModel) => onChange({ quotaSwitchPreviewModel })}
1034+
/>
1035+
<ToggleRow
1036+
title={t('config_management.visual.sections.quota.antigravity_credits')}
1037+
description={t(
1038+
'config_management.visual.sections.quota.antigravity_credits_desc'
1039+
)}
1040+
checked={values.quotaAntigravityCredits}
1041+
disabled={disabled}
1042+
onChange={(quotaAntigravityCredits) => onChange({ quotaAntigravityCredits })}
1043+
/>
1044+
</SectionGrid>
1045+
</SectionStack>
10101046
</ConfigSection>
10111047

10121048
<ConfigSection

src/hooks/useVisualConfig.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ export function getVisualConfigValidationErrors(
184184
forwardRequestHeaders: getDuplicateHeaderKeyError(values.forwardRequestHeaders),
185185
maxRetryCredentials: getNonNegativeIntegerError(values.maxRetryCredentials),
186186
maxRetryInterval: getNonNegativeIntegerError(values.maxRetryInterval),
187+
quotaCacheRefreshInterval: getNonNegativeIntegerError(values.quotaCacheRefreshInterval),
187188
routingStickyTTL:
188189
values.routingStrategy === 'sticky-round-robin'
189190
? getNonNegativeIntegerError(values.routingStickyTTL)
@@ -715,6 +716,12 @@ function getNextDirtyFields(
715716
nextValues.maxRetryInterval === baselineValues.maxRetryInterval
716717
);
717718
}
719+
if (Object.prototype.hasOwnProperty.call(patch, 'quotaCacheRefreshInterval')) {
720+
updateDirty(
721+
'quotaCacheRefreshInterval',
722+
nextValues.quotaCacheRefreshInterval === baselineValues.quotaCacheRefreshInterval
723+
);
724+
}
718725
if (Object.prototype.hasOwnProperty.call(patch, 'wsAuth')) {
719726
updateDirty('wsAuth', nextValues.wsAuth === baselineValues.wsAuth);
720727
}
@@ -916,6 +923,7 @@ export function useVisualConfig() {
916923
forwardRequestHeaders: parseHeaderEntries(parsed['forward-request-headers']),
917924
maxRetryCredentials: String(parsed['max-retry-credentials'] ?? ''),
918925
maxRetryInterval: String(parsed['max-retry-interval'] ?? ''),
926+
quotaCacheRefreshInterval: String(parsed['quota-cache-refresh-interval'] ?? ''),
919927
routingStickyTTL: String(routing?.['sticky-ttl'] ?? ''),
920928
wsAuth: Boolean(parsed['ws-auth']),
921929

@@ -1024,6 +1032,11 @@ export function useVisualConfig() {
10241032
setIntFromStringInDoc(doc, ['request-retry'], values.requestRetry);
10251033
setIntFromStringInDoc(doc, ['max-retry-credentials'], values.maxRetryCredentials);
10261034
setIntFromStringInDoc(doc, ['max-retry-interval'], values.maxRetryInterval);
1035+
setIntFromStringInDoc(
1036+
doc,
1037+
['quota-cache-refresh-interval'],
1038+
values.quotaCacheRefreshInterval
1039+
);
10271040
setForwardRequestHeadersInDoc(doc, values.forwardRequestHeaders);
10281041
setBooleanInDoc(doc, ['ws-auth'], values.wsAuth);
10291042

src/i18n/locales/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,8 @@
12981298
"quota": {
12991299
"title": "Quota Fallback",
13001300
"description": "Fallback strategy when quota is exceeded",
1301+
"refresh_interval": "Quota Cache Refresh Interval (seconds)",
1302+
"refresh_interval_hint": "Set the quota cache refresh interval in seconds; leave empty to let the server use the default value of 3600 seconds.",
13011303
"switch_project": "Switch Project",
13021304
"switch_project_desc": "Automatically switch to another project when quota is exceeded",
13031305
"switch_preview_model": "Switch to Preview Model",

src/i18n/locales/ru.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,6 +1297,8 @@
12971297
"quota": {
12981298
"title": "Резерв по квоте",
12991299
"description": "Стратегия при превышении квоты",
1300+
"refresh_interval": "Интервал обновления кэша квоты (сек)",
1301+
"refresh_interval_hint": "Задаёт интервал обновления кэша квоты в секундах; оставьте поле пустым, чтобы сервер использовал значение по умолчанию 3600 секунд.",
13001302
"switch_project": "Переключить проект",
13011303
"switch_project_desc": "Автоматически переходить на другой проект при превышении квоты",
13021304
"switch_preview_model": "Переключить на preview-модель",

src/i18n/locales/zh-CN.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,8 @@
12981298
"quota": {
12991299
"title": "配额回退",
13001300
"description": "配额耗尽时的回退策略",
1301+
"refresh_interval": "配额缓存刷新间隔(秒)",
1302+
"refresh_interval_hint": "设置配额缓存的刷新间隔,单位为秒;留空时由服务端使用默认值 3600 秒。",
13011303
"switch_project": "切换项目",
13021304
"switch_project_desc": "配额耗尽时自动切换到其他项目",
13031305
"switch_preview_model": "切换预览模型",

src/types/visualConfig.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export type VisualConfigFieldPath =
1313
| 'forwardRequestHeaders'
1414
| 'maxRetryCredentials'
1515
| 'maxRetryInterval'
16+
| 'quotaCacheRefreshInterval'
1617
| 'routingStickyTTL'
1718
| 'streaming.keepaliveSeconds'
1819
| 'streaming.bootstrapRetries'
@@ -81,6 +82,7 @@ export type VisualConfigValues = {
8182
forwardRequestHeaders: HeaderEntry[];
8283
maxRetryCredentials: string;
8384
maxRetryInterval: string;
85+
quotaCacheRefreshInterval: string;
8486
routingStickyTTL: string;
8587
quotaSwitchProject: boolean;
8688
quotaSwitchPreviewModel: boolean;
@@ -123,6 +125,7 @@ export const DEFAULT_VISUAL_VALUES: VisualConfigValues = {
123125
forwardRequestHeaders: [],
124126
maxRetryCredentials: '',
125127
maxRetryInterval: '',
128+
quotaCacheRefreshInterval: '',
126129
routingStickyTTL: '',
127130
quotaSwitchProject: true,
128131
quotaSwitchPreviewModel: true,

0 commit comments

Comments
 (0)