/* Copyright (C) 2023-2026 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import { useEffect, useMemo, useRef } from 'react' import * as z from 'zod' import { useForm } from 'react-hook-form' import { zodResolver } from '@hookform/resolvers/zod' import { useTranslation } from 'react-i18next' import { toast } from 'sonner' import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from '@/components/ui/form' import { Input } from '@/components/ui/input' import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { Switch } from '@/components/ui/switch' import { SettingsForm, SettingsSwitchContent, SettingsSwitchItem, } from '../components/settings-form-layout' import { SettingsPageFormActions } from '../components/settings-page-context' import { SettingsSection } from '../components/settings-section' import { useResetForm } from '../hooks/use-reset-form' import { useUpdateOption } from '../hooks/use-update-option' import { safeNumberFieldProps } from '../utils/numeric-field' const numericString = z.string().refine((value) => { const trimmed = value.trim() if (!trimmed) return true return !Number.isNaN(Number(trimmed)) && Number(trimmed) >= 0 }, 'Enter a non-negative number or leave empty') const monitoringSchema = z.object({ QuotaRemindThreshold: numericString, perf_metrics_setting: z.object({ enabled: z.boolean(), flush_interval: z.coerce.number().min(1), bucket_time: z.enum(['minute', '5min', 'hour']), retention_days: z.coerce.number().min(0), }), }) type MonitoringFormInput = z.input type MonitoringFormValues = z.output type FlatMonitoringDefaults = { QuotaRemindThreshold: string 'perf_metrics_setting.enabled': boolean 'perf_metrics_setting.flush_interval': number 'perf_metrics_setting.bucket_time': 'minute' | '5min' | 'hour' 'perf_metrics_setting.retention_days': number } type MonitoringSettingsSectionProps = { defaultValues: FlatMonitoringDefaults } const buildFormDefaults = ( defaults: MonitoringSettingsSectionProps['defaultValues'] ): MonitoringFormInput => ({ QuotaRemindThreshold: defaults.QuotaRemindThreshold ?? '', perf_metrics_setting: { enabled: defaults['perf_metrics_setting.enabled'], flush_interval: defaults['perf_metrics_setting.flush_interval'], bucket_time: defaults['perf_metrics_setting.bucket_time'], retention_days: defaults['perf_metrics_setting.retention_days'], }, }) const normalizeDefaults = ( defaults: MonitoringSettingsSectionProps['defaultValues'] ): FlatMonitoringDefaults => ({ QuotaRemindThreshold: (defaults.QuotaRemindThreshold ?? '').trim(), 'perf_metrics_setting.enabled': defaults['perf_metrics_setting.enabled'], 'perf_metrics_setting.flush_interval': defaults['perf_metrics_setting.flush_interval'], 'perf_metrics_setting.bucket_time': defaults['perf_metrics_setting.bucket_time'], 'perf_metrics_setting.retention_days': defaults['perf_metrics_setting.retention_days'], }) const normalizeFormValues = ( values: MonitoringFormValues ): FlatMonitoringDefaults => ({ QuotaRemindThreshold: values.QuotaRemindThreshold.trim(), 'perf_metrics_setting.enabled': values.perf_metrics_setting.enabled, 'perf_metrics_setting.flush_interval': values.perf_metrics_setting.flush_interval, 'perf_metrics_setting.bucket_time': values.perf_metrics_setting.bucket_time, 'perf_metrics_setting.retention_days': values.perf_metrics_setting.retention_days, }) export function MonitoringSettingsSection({ defaultValues, }: MonitoringSettingsSectionProps) { const { t } = useTranslation() const updateOption = useUpdateOption() const baselineRef = useRef( normalizeDefaults(defaultValues) ) const baselineSerializedRef = useRef( JSON.stringify(normalizeDefaults(defaultValues)) ) const formDefaults = useMemo( () => buildFormDefaults(defaultValues), [defaultValues] ) const form = useForm({ resolver: zodResolver(monitoringSchema), defaultValues: formDefaults, }) useResetForm(form, formDefaults) useEffect(() => { const normalized = normalizeDefaults(defaultValues) const serialized = JSON.stringify(normalized) if (serialized === baselineSerializedRef.current) return baselineRef.current = normalized baselineSerializedRef.current = serialized }, [defaultValues]) const perfMetricsEnabled = form.watch('perf_metrics_setting.enabled') const onSubmit = async (values: MonitoringFormValues) => { const normalized = normalizeFormValues(values) const updates = ( Object.keys(normalized) as Array ).filter((key) => normalized[key] !== baselineRef.current[key]) if (updates.length === 0) { toast.info(t('No changes to save')) return } for (const key of updates) { await updateOption.mutateAsync({ key, value: normalized[key], }) } baselineRef.current = normalized baselineSerializedRef.current = JSON.stringify(normalized) } return (
( {t('Quota reminder (tokens)')} field.onChange(event.target.value)} /> {t('Send email alerts when a user falls below this quota')} )} />

{t('Model performance metrics')}

{t( 'Collect relay latency and success-rate metrics for the model square.' )}

( {t('Enable model performance metrics')} )} /> ( {t('Flush interval (minutes)')} )} /> ( {t('Aggregation bucket')} )} /> ( {t('Retention days')} {t('0 means data is kept permanently')} )} />
) }