feat(FN-669): complete Step 5 — manage model favorites in ModelSelectorTab

This commit is contained in:
gsxdsm
2026-04-01 22:24:23 -07:00
parent e8daccefdc
commit f7b85afb85

View File

@@ -69,6 +69,7 @@ function getSuccessToastMessage(target: "executor" | "validator", selection: Mod
export function ModelSelectorTab({ task, addToast }: ModelSelectorTabProps) { export function ModelSelectorTab({ task, addToast }: ModelSelectorTabProps) {
const [availableModels, setAvailableModels] = useState<ModelInfo[]>([]); const [availableModels, setAvailableModels] = useState<ModelInfo[]>([]);
const [favoriteProviders, setFavoriteProviders] = useState<string[]>([]); const [favoriteProviders, setFavoriteProviders] = useState<string[]>([]);
const [favoriteModels, setFavoriteModels] = useState<string[]>([]);
const [modelsLoading, setModelsLoading] = useState(false); const [modelsLoading, setModelsLoading] = useState(false);
const [modelsError, setModelsError] = useState<string | null>(null); const [modelsError, setModelsError] = useState<string | null>(null);
@@ -88,6 +89,7 @@ export function ModelSelectorTab({ task, addToast }: ModelSelectorTabProps) {
.then((response) => { .then((response) => {
setAvailableModels(response.models); setAvailableModels(response.models);
setFavoriteProviders(response.favoriteProviders); setFavoriteProviders(response.favoriteProviders);
setFavoriteModels(response.favoriteModels);
}) })
.catch((err) => { .catch((err) => {
setModelsError(err.message || "Failed to load models"); setModelsError(err.message || "Failed to load models");
@@ -108,13 +110,32 @@ export function ModelSelectorTab({ task, addToast }: ModelSelectorTabProps) {
setFavoriteProviders(newFavorites); setFavoriteProviders(newFavorites);
try { try {
await updateGlobalSettings({ favoriteProviders: newFavorites }); await updateGlobalSettings({ favoriteProviders: newFavorites, favoriteModels });
} catch (err) { } catch (err) {
// Revert on error // Revert on error
setFavoriteProviders(currentFavorites); setFavoriteProviders(currentFavorites);
addToast("Failed to update favorites", "error"); addToast("Failed to update favorites", "error");
} }
}, [favoriteProviders, addToast]); }, [favoriteProviders, favoriteModels, addToast]);
// Handle toggle model favorite
const handleToggleModelFavorite = useCallback(async (modelId: string) => {
const currentFavorites = favoriteModels;
const isFavorite = currentFavorites.includes(modelId);
const newFavorites = isFavorite
? currentFavorites.filter((m) => m !== modelId)
: [modelId, ...currentFavorites]; // Add to front
setFavoriteModels(newFavorites);
try {
await updateGlobalSettings({ favoriteProviders, favoriteModels: newFavorites });
} catch (err) {
// Revert on error
setFavoriteModels(currentFavorites);
addToast("Failed to update model favorites", "error");
}
}, [favoriteModels, favoriteProviders, addToast]);
useEffect(() => { useEffect(() => {
activeTaskIdRef.current = task.id; activeTaskIdRef.current = task.id;
@@ -249,6 +270,7 @@ export function ModelSelectorTab({ task, addToast }: ModelSelectorTabProps) {
.then((response) => { .then((response) => {
setAvailableModels(response.models); setAvailableModels(response.models);
setFavoriteProviders(response.favoriteProviders); setFavoriteProviders(response.favoriteProviders);
setFavoriteModels(response.favoriteModels);
}) })
.catch((err) => setModelsError(err.message)) .catch((err) => setModelsError(err.message))
.finally(() => setModelsLoading(false)); .finally(() => setModelsLoading(false));
@@ -286,6 +308,8 @@ export function ModelSelectorTab({ task, addToast }: ModelSelectorTabProps) {
placeholder="Select executor model…" placeholder="Select executor model…"
favoriteProviders={favoriteProviders} favoriteProviders={favoriteProviders}
onToggleFavorite={handleToggleFavorite} onToggleFavorite={handleToggleFavorite}
favoriteModels={favoriteModels}
onToggleModelFavorite={handleToggleModelFavorite}
/> />
<small>The AI model used to implement this task.</small> <small>The AI model used to implement this task.</small>
</div> </div>
@@ -312,6 +336,8 @@ export function ModelSelectorTab({ task, addToast }: ModelSelectorTabProps) {
placeholder="Select validator model…" placeholder="Select validator model…"
favoriteProviders={favoriteProviders} favoriteProviders={favoriteProviders}
onToggleFavorite={handleToggleFavorite} onToggleFavorite={handleToggleFavorite}
favoriteModels={favoriteModels}
onToggleModelFavorite={handleToggleModelFavorite}
/> />
<small>The AI model used to review code and plans for this task.</small> <small>The AI model used to review code and plans for this task.</small>
</div> </div>