/* * ParamsPanel.tsx * Zyquo Cloud Web * * Author: Simon-Pierre Boucher * Mail: contact@spboucher.ai * * Per-conversation parameter editor. Only shows controls the active model's * ParameterSupport allows; every control is gated by an enable checkbox — * unchecked means "provider default" and the key is omitted from requests * entirely (native behavior). */ import { findModel } from '../features/catalogHelpers' import { useStore } from '../state/store' import type { ChatParameters, Conversation } from '../types' export default function ParamsPanel({ conversation, onClose, }: { conversation: Conversation onClose: () => void }) { const updateConversation = useStore((s) => s.updateConversation) const model = findModel(conversation.provider, conversation.modelID) const support = model?.parameterSupport const params = conversation.parameters const patch = (p: Partial) => { const merged = { ...params, ...p } for (const key of Object.keys(merged) as (keyof ChatParameters)[]) { if (merged[key] === undefined) delete merged[key] } updateConversation(conversation.id, { parameters: merged }) } const slider = ( label: string, key: 'temperature' | 'topP' | 'frequencyPenalty' | 'presencePenalty', min: number, max: number, step: number, fallback: number ) => (
{params[key] !== undefined ? ( <> patch({ [key]: Number(e.target.value) })} /> {params[key]?.toFixed(2)} ) : ( default )}
) return (
e.target === e.currentTarget && onClose()}>

Parameters — {model?.displayName ?? conversation.modelID}

{support?.temperature && slider('Temperature', 'temperature', 0, 2, 0.05, 1)} {support?.topP && slider('Top P', 'topP', 0, 1, 0.01, 1)} {support?.frequencyPenalty && slider('Frequency penalty', 'frequencyPenalty', -2, 2, 0.1, 0)} {support?.presencePenalty && slider('Presence penalty', 'presencePenalty', -2, 2, 0.1, 0)}
Max tokens patch({ maxTokens: e.target.value === '' ? undefined : Number(e.target.value) }) } />
{support?.reasoningEffort && (
Reasoning effort
)} {support?.thinkingToggle && (
)}
) }