"use client"; import { useActionState } from "react"; import type { SettingsView } from "@/lib/settings"; type Result = { ok?: boolean; error?: string } | null; export function SettingsForm({ action, view, step, account, after }: { action: (state: Result, fd: FormData) => Promise; view: SettingsView; step?: string; account?: boolean; after?: string; }) { const [state, formAction, pending] = useActionState(action, null); const F = (name: string, label: string, value: string, help: string, type = "text") => (
{help}
); const Group = ({ title, children }: { title: string; children: React.ReactNode }) => (
{title}{children}
); return
{after && } {step &&

{step}

} {F("analyst_base_url", "Base URL", view.analyst_base_url, "e.g. https://api.openai.com/v1")} {F("analyst_key", "API key", "", view.has_analyst ? `Saved ${view.analyst_key_masked} — leave blank to keep it` : "Encrypted with APP_SECRET before it hits disk")} {F("analyst_model", "Model name", view.analyst_model, "e.g. gpt-4o-mini, llama-3.3-70b")} {F("analyst_extra", "Extra params (JSON)", view.analyst_extra, 'Merged into the request body, e.g. {"temperature":0.2}. Reasoning models stream thinking, not the answer: ' + 'vLLM/Qwen needs {"chat_template_kwargs":{"enable_thinking":false}} or the report arrives empty.')} {F("jev_key", "TypeSafe API key", "", view.has_jev ? `Saved ${view.jev_key_masked} — leave blank to keep it` : "console.typesafe.ai/keys")} {F("jev_model", "Jev model", view.jev_model, "jev-latest unless you know better")} {account && {F("email", "Email", "", "Used to sign in", "email")} {F("password", "New password", "", "Leave blank to keep the current one", "password")} } {state && !state.ok &&

{state.error}

} {state?.ok &&

Saved.

}
; }