"use client"; import { useRouter } from "next/navigation"; import { useState, useTransition } from "react"; import { resetAssistantName, resetAssistantSystemPrompt, setAssistantEnabled, setAssistantName, setAssistantModelRoute, setAssistantSystemPrompt, } from "@/app/settings/assistant-actions"; import { DEFAULT_ASSISTANT_NAME, MAX_ASSISTANT_NAME_LENGTH } from "@/lib/assistant-config"; import type { AssistantModelRoute } from "@/lib/llm/models"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Switch } from "@/components/ui/switch"; type Props = { enabled: boolean; name: string; modelRoute: string | null; systemPrompt: string | null; defaultSystemPrompt: string; }; function normalizeAssistantModelRoute(value: string | null): AssistantModelRoute { return value === "uncensored" ? "uncensored" : "auto"; } export function AssistantSettings({ enabled, name, modelRoute, systemPrompt, defaultSystemPrompt, }: Props) { const [isPending, startTransition] = useTransition(); const router = useRouter(); const effectivePrompt = systemPrompt ?? defaultSystemPrompt; const [selectedRoute, setSelectedRoute] = useState(() => normalizeAssistantModelRoute(modelRoute), ); const [savedName, setSavedName] = useState(name); const [draftName, setDraftName] = useState(name); const [savedPrompt, setSavedPrompt] = useState(systemPrompt); const [draftPrompt, setDraftPrompt] = useState(effectivePrompt); const nameDirty = draftName.trim() !== savedName; const promptDirty = savedPrompt === null ? draftPrompt.trim() !== defaultSystemPrompt.trim() : draftPrompt.trim() !== savedPrompt.trim(); const usingDefaultPrompt = savedPrompt === null; function toggle(next: boolean) { startTransition(async () => { await setAssistantEnabled(next); router.refresh(); }); } function changeModelRoute(nextRoute: string) { const route = normalizeAssistantModelRoute(nextRoute); setSelectedRoute(route); startTransition(async () => { await setAssistantModelRoute(route); router.refresh(); }); } function saveName() { const next = draftName.trim(); if (!next) return; startTransition(async () => { await setAssistantName(next); setSavedName(next); setDraftName(next); router.refresh(); }); } function savePrompt() { const next = draftPrompt.trim(); if (!next) return; startTransition(async () => { const isDefault = next === defaultSystemPrompt.trim(); await setAssistantSystemPrompt(isDefault ? null : next); setSavedPrompt(isDefault ? null : next); setDraftPrompt(next); router.refresh(); }); } function handleResetName() { startTransition(async () => { await resetAssistantName(); setSavedName(DEFAULT_ASSISTANT_NAME); setDraftName(DEFAULT_ASSISTANT_NAME); router.refresh(); }); } function handleResetPrompt() { startTransition(async () => { await resetAssistantSystemPrompt(); setSavedPrompt(null); setDraftPrompt(defaultSystemPrompt); router.refresh(); }); } return (

Choose the default router family for your assistant. Individual models can still be picked from the chat panel.

Shown in the chat bubble and message labels.

setDraftName(event.target.value)} aria-label="Assistant name" />

Instructions sent to the model before each conversation. Customize tone, priorities, or household context.