From 3fc57ff7b752bdafb74b0a226d2e808ab2a00a30 Mon Sep 17 00:00:00 2001 From: Sergey Kozyrenko Date: Sun, 21 Jun 2026 16:46:22 +0700 Subject: [PATCH] =?UTF-8?q?fix(frontend):=20reasoning=20robustness=20?= =?UTF-8?q?=E2=80=94=20custom-model=20reset,=20max/xhigh=E2=86=92adaptive,?= =?UTF-8?q?=20range=20refines=20(refs=20#288)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three QA-found edge cases in the provider form: - Choosing "Use as custom" set the model without running onOptionSelect, so reasoning/price stayed stale for the typed model. Fire onOptionSelect with the synthetic option so they reset like a dropdown pick. - Selecting effort max/xhigh on an adaptive-capable model with mode unset left the backend with no way to route the reasoning (it dropped it). Auto-set mode to Adaptive, since max/xhigh are adaptive-thinking effort levels. - Add zod cross-field refines (minLength<=maxLength, reasoning.maxTokens<=32000) that native HTML5 validation can't express, mirroring the new backend checks. Co-Authored-By: Claude Opus 4.8 --- .../src/pages/settings/settings-provider.tsx | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/frontend/src/pages/settings/settings-provider.tsx b/frontend/src/pages/settings/settings-provider.tsx index d956817..3109af8 100644 --- a/frontend/src/pages/settings/settings-provider.tsx +++ b/frontend/src/pages/settings/settings-provider.tsx @@ -21,6 +21,7 @@ import { type FieldValues, useController, useForm, + type UseFormSetValue, useFormState, useWatch, } from 'react-hook-form'; @@ -459,6 +460,7 @@ function FormModelComboboxItem({ className="mt-2" onClick={() => { field.onChange(search); + onOptionSelect?.({ name: search }); setIsOpen(false); setSearch(''); }} @@ -553,6 +555,14 @@ const agentConfigSchema = z topK: optionalNumber, topP: optionalNumber, }) + .refine((data) => data.minLength == null || data.maxLength == null || data.minLength <= data.maxLength, { + message: 'Min length must not exceed max length', + path: ['minLength'], + }) + .refine((data) => data.reasoning?.maxTokens == null || data.reasoning.maxTokens <= 32000, { + message: 'Maximum 32000 tokens', + path: ['reasoning', 'maxTokens'], + }) .optional(); const formSchema = z.object({ @@ -635,11 +645,13 @@ function ReasoningFields({ control, isLoading, models, + setValue, }: { agentKey: string; control: Control; isLoading: boolean; models: ModelOption[]; + setValue: UseFormSetValue; }) { const selectedModel = useWatch({ control, name: `agents.${agentKey}.model` }); const capability = models.find((model) => model.name === selectedModel)?.reasoning ?? null; @@ -697,7 +709,22 @@ function ReasoningFields({ Reasoning Effort