fix: improve LlmSettings types, accessibility, debounce, and defaults

This commit is contained in:
2026-05-16 20:55:03 +02:00
parent 5dca683b88
commit c04f35a1b9
+26 -12
View File
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react"; import { useState, useEffect, useRef } from "react";
interface LlmSettingsProps { interface LlmSettingsProps {
settings: Record<string, any>; settings: Record<string, any>;
@@ -6,6 +6,10 @@ interface LlmSettingsProps {
saveError: string | null; saveError: string | null;
} }
const DEFAULT_MODEL = "openai/gpt-oss-120b:free";
const DEFAULT_TEMPERATURE = 0.7;
const DEFAULT_MAX_DEBATE_ROUNDS = 3;
const AVAILABLE_MODELS = [ const AVAILABLE_MODELS = [
"openai/gpt-oss-120b:free", "openai/gpt-oss-120b:free",
"openrouter/free", "openrouter/free",
@@ -14,14 +18,18 @@ const AVAILABLE_MODELS = [
]; ];
export default function LlmSettings({ settings, onSave, saveError }: LlmSettingsProps) { export default function LlmSettings({ settings, onSave, saveError }: LlmSettingsProps) {
const [model, setModel] = useState(settings["llm.model"] ?? "openai/gpt-oss-120b:free"); const [model, setModel] = useState(settings["llm.model"] ?? DEFAULT_MODEL);
const [temperature, setTemperature] = useState(settings["llm.temperature"] ?? 0.7); const [temperature, setTemperature] = useState(settings["llm.temperature"] ?? DEFAULT_TEMPERATURE);
const [maxDebateRounds, setMaxDebateRounds] = useState(settings["llm.maxDebateRounds"] ?? 3); const [maxDebateRounds, setMaxDebateRounds] = useState(settings["llm.maxDebateRounds"] ?? DEFAULT_MAX_DEBATE_ROUNDS);
const tempTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
useEffect(() => { useEffect(() => {
setModel(settings["llm.model"] ?? "openai/gpt-oss-120b:free"); setModel(settings["llm.model"] ?? DEFAULT_MODEL);
setTemperature(settings["llm.temperature"] ?? 0.7); setTemperature(settings["llm.temperature"] ?? DEFAULT_TEMPERATURE);
setMaxDebateRounds(settings["llm.maxDebateRounds"] ?? 3); setMaxDebateRounds(settings["llm.maxDebateRounds"] ?? DEFAULT_MAX_DEBATE_ROUNDS);
return () => {
if (tempTimerRef.current) clearTimeout(tempTimerRef.current);
};
}, [settings]); }, [settings]);
const saveModel = async (value: string) => { const saveModel = async (value: string) => {
@@ -31,7 +39,10 @@ export default function LlmSettings({ settings, onSave, saveError }: LlmSettings
const saveTemperature = async (value: number) => { const saveTemperature = async (value: number) => {
setTemperature(value); setTemperature(value);
await onSave("llm.temperature", value); if (tempTimerRef.current) clearTimeout(tempTimerRef.current);
tempTimerRef.current = setTimeout(() => {
onSave("llm.temperature", value);
}, 300);
}; };
const saveMaxDebateRounds = async (value: number) => { const saveMaxDebateRounds = async (value: number) => {
@@ -53,8 +64,9 @@ export default function LlmSettings({ settings, onSave, saveError }: LlmSettings
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1">Model</label> <label htmlFor="llm-model" className="block text-sm font-medium text-gray-700 mb-1">Model</label>
<select <select
id="llm-model"
value={model} value={model}
onChange={(e) => saveModel(e.target.value)} onChange={(e) => saveModel(e.target.value)}
className="w-full border border-gray-300 rounded-lg px-4 py-2.5 text-gray-900 focus:ring-2 focus:ring-blue-500 focus:border-blue-500" className="w-full border border-gray-300 rounded-lg px-4 py-2.5 text-gray-900 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
@@ -66,10 +78,11 @@ export default function LlmSettings({ settings, onSave, saveError }: LlmSettings
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1"> <label htmlFor="llm-temperature" className="block text-sm font-medium text-gray-700 mb-1">
Temperature: {temperature.toFixed(1)} Temperature: {temperature.toFixed(1)}
</label> </label>
<input <input
id="llm-temperature"
type="range" type="range"
min="0" min="0"
max="2" max="2"
@@ -85,13 +98,14 @@ export default function LlmSettings({ settings, onSave, saveError }: LlmSettings
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 mb-1">Max Debate Rounds</label> <label htmlFor="llm-max-debate-rounds" className="block text-sm font-medium text-gray-700 mb-1">Max Debate Rounds</label>
<input <input
id="llm-max-debate-rounds"
type="number" type="number"
min="1" min="1"
max="10" max="10"
value={maxDebateRounds} value={maxDebateRounds}
onChange={(e) => saveMaxDebateRounds(parseInt(e.target.value) || 1)} onChange={(e) => saveMaxDebateRounds(Math.max(1, parseInt(e.target.value) || 1))}
className="w-32 border border-gray-300 rounded-lg px-4 py-2.5 text-gray-900 focus:ring-2 focus:ring-blue-500" className="w-32 border border-gray-300 rounded-lg px-4 py-2.5 text-gray-900 focus:ring-2 focus:ring-blue-500"
/> />
</div> </div>