mirror of
https://github.com/vxcontrol/pentagi.git
synced 2026-07-08 21:10:48 +00:00
fix(frontend): reasoning robustness — custom-model reset, max/xhigh→adaptive, range refines (refs #288)
Three QA-found edge cases in the provider form: - Choosing "Use <x> 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 <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
||||
type FieldValues,
|
||||
useController,
|
||||
useForm,
|
||||
type UseFormSetValue,
|
||||
useFormState,
|
||||
useWatch,
|
||||
} from 'react-hook-form';
|
||||
@@ -459,6 +460,7 @@ function FormModelComboboxItem<T extends FieldValues = FieldValues>({
|
||||
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<FormInput>;
|
||||
isLoading: boolean;
|
||||
models: ModelOption[];
|
||||
setValue: UseFormSetValue<FormInput>;
|
||||
}) {
|
||||
const selectedModel = useWatch({ control, name: `agents.${agentKey}.model` });
|
||||
const capability = models.find((model) => model.name === selectedModel)?.reasoning ?? null;
|
||||
@@ -697,7 +709,22 @@ function ReasoningFields({
|
||||
<FormLabel>Reasoning Effort</FormLabel>
|
||||
<Select
|
||||
disabled={isLoading}
|
||||
onValueChange={(value) => field.onChange(value !== 'none' ? value : null)}
|
||||
onValueChange={(value) => {
|
||||
const next = value !== 'none' ? value : null;
|
||||
field.onChange(next);
|
||||
|
||||
// max/xhigh are adaptive-thinking effort levels; selecting one
|
||||
// implies adaptive mode so the backend doesn't drop the reasoning.
|
||||
if (
|
||||
supportsAdaptive &&
|
||||
(next === ReasoningEffort.Xhigh || next === ReasoningEffort.Max)
|
||||
) {
|
||||
setValue(
|
||||
`agents.${agentKey}.reasoning.mode` as const,
|
||||
ReasoningMode.Adaptive,
|
||||
);
|
||||
}
|
||||
}}
|
||||
value={field.value ?? 'none'}
|
||||
>
|
||||
<FormControl>
|
||||
@@ -1671,6 +1698,7 @@ function SettingsProvider() {
|
||||
control={control}
|
||||
isLoading={isLoading}
|
||||
models={availableModels}
|
||||
setValue={setValue}
|
||||
/>
|
||||
|
||||
{/* Price Configuration */}
|
||||
|
||||
Reference in New Issue
Block a user