"use client"; import { Icon } from "@iconify/react"; import { useEffect, useState } from "react"; import { getLighthouseModelIds, getTenantConfig, updateTenantConfig, } from "@/actions/lighthouse/lighthouse"; import { Button } from "@/components/shadcn"; import type { LighthouseProvider } from "@/types/lighthouse"; import { getProviderIdByType, refreshModelsInBackground, } from "./llm-provider-utils"; // Recommended models per provider const RECOMMENDED_MODELS: Record> = { openai: new Set(["gpt-5.2"]), bedrock: new Set([]), openai_compatible: new Set([]), }; interface SelectModelProps { provider: LighthouseProvider; mode?: string; onSelect: () => void; } interface Model { id: string; name: string; } export const SelectModel = ({ provider, mode = "create", onSelect, }: SelectModelProps) => { const [selectedModel, setSelectedModel] = useState(null); const [isLoading, setIsLoading] = useState(true); const [isSaving, setIsSaving] = useState(false); const [models, setModels] = useState([]); const [searchQuery, setSearchQuery] = useState(""); const [error, setError] = useState(null); const isEditMode = mode === "edit"; const isRecommended = (modelId: string) => { return RECOMMENDED_MODELS[provider]?.has(modelId) || false; }; const fetchModels = async (triggerRefresh: boolean = false) => { setIsLoading(true); setError(null); try { // If triggerRefresh is true, trigger background job to refetch models from LLM provider API if (triggerRefresh) { const providerId = await getProviderIdByType(provider); await refreshModelsInBackground(providerId); } // Fetch models from database const result = await getLighthouseModelIds(provider); if (result.errors) { throw new Error(result.errors[0]?.detail || "Failed to fetch models"); } const models = result.data || []; setModels(models); } catch (err) { setError(err instanceof Error ? err.message : String(err)); setModels([]); } finally { setIsLoading(false); } }; useEffect(() => { fetchModels(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const handleSelect = async () => { if (!selectedModel) return; setIsSaving(true); setError(null); try { const currentConfig = await getTenantConfig(); const existingDefaults = currentConfig?.data?.attributes?.default_models || {}; const existingDefaultProvider = currentConfig?.data?.attributes?.default_provider || ""; const mergedDefaults = { ...existingDefaults, [provider]: selectedModel, }; // Prepare update payload const updatePayload: { default_models: Record; default_provider?: LighthouseProvider; } = { default_models: mergedDefaults, }; // Set this provider as default if no default provider is currently set if (!existingDefaultProvider) { updatePayload.default_provider = provider; } const result = await updateTenantConfig(updatePayload); if (result.errors) { throw new Error( result.errors[0]?.detail || "Failed to save default model", ); } onSelect(); } catch (err) { setError(err instanceof Error ? err.message : String(err)); } finally { setIsSaving(false); } }; // Filter models based on search query and sort with recommended models first const filteredModels = models .filter( (model) => model.name.toLowerCase().includes(searchQuery.toLowerCase()) || model.id.toLowerCase().includes(searchQuery.toLowerCase()), ) .sort((a, b) => { const aRecommended = isRecommended(a.id); const bRecommended = isRecommended(b.id); // Recommended models first if (aRecommended && !bRecommended) return -1; if (!aRecommended && bRecommended) return 1; // Then alphabetically by name return a.name.localeCompare(b.name); }); return (

{isEditMode ? "Update Default Model" : "Select Default Model"}

{isEditMode ? "Update the default model to use with this provider." : "Choose the default model to use with this provider."}

{error && (

{error}

)} {!isLoading && models.length > 0 && (
setSearchQuery(e.target.value)} className="border-border-neutral-primary bg-bg-neutral-primary focus:border-button-primary focus:ring-button-primary w-full rounded-lg border py-2.5 pr-4 pl-11 text-sm focus:ring-1 focus:outline-none" />
)} {isLoading ? (
) : models.length === 0 ? (

No models available. Click refresh to fetch models.

) : filteredModels.length === 0 ? (

No models found matching "{searchQuery}"

) : (
{filteredModels.map((model) => ( ))}
)}
); };