spb/chat-spboucher-ai
Public
1"use client";2import useSWR, { mutate } from "swr";3import { Brain } from "lucide-react";4import { api, fetcher } from "@/lib/client/fetcher";5import { Toggle, toast } from "../ui";67export const CATEGORIES: { id: string; label: string }[] = [8 { id: "preference", label: "Préférences" },9 { id: "writing", label: "Rédaction" },10 { id: "research", label: "Recherche" },11 { id: "project", label: "Projets" },12 { id: "infrastructure", label: "Infrastructure" },13 { id: "objective", label: "Objectifs" },14 { id: "concept", label: "Concepts" },15 { id: "context", label: "Contexte" },16];17export const categoryLabel = (id: string) => CATEGORIES.find(c => c.id === id)?.label ?? id;1819export interface MemorySettings { enabled: boolean; autoExtract: boolean; requireApproval: boolean }20interface SettingsResp { settings: { memory?: MemorySettings } }2122export function useMemorySettings() {23 const { data, mutate: m } = useSWR<SettingsResp>("/api/settings", fetcher);24 const value: MemorySettings = { enabled: true, autoExtract: true, requireApproval: false, ...(data?.settings.memory ?? {}) };25 async function update(patch: Partial<MemorySettings>) {26 const next = { ...value, ...patch };27 await api("/api/settings", { method: "PATCH", json: { key: "memory", value: next } });28 await m(); void mutate("/api/settings");29 toast("Réglages de mémoire enregistrés", "ok");30 }31 return { value, update, loaded: !!data };32}3334/** Three memory toggles, reused by /memory and /settings. */35export function MemoryToggles({ compact }: { compact?: boolean }) {36 const { value, update, loaded } = useMemorySettings();37 const rows: { key: keyof MemorySettings; label: string; hint: string }[] = [38 { key: "enabled", label: "Mémoire activée", hint: "Les souvenirs actifs sont injectés dans le contexte des conversations." },39 { key: "autoExtract", label: "Extraction automatique", hint: "Un modèle économique propose des faits durables après chaque échange." },40 { key: "requireApproval", label: "Approbation requise", hint: "Les nouveaux souvenirs extraits restent candidats jusqu'à ton accord." },41 ];42 return (43 <div className={compact ? "space-y-2" : "grid gap-2 sm:grid-cols-3"}>44 {rows.map(r => (45 <label key={r.key} className="flex items-start justify-between gap-3 rounded-xl border border-border bg-surface px-3.5 py-3">46 <span><span className="block text-[13px] font-medium">{r.label}</span><span className="block text-[12px] text-muted">{r.hint}</span></span>47 <Toggle checked={value[r.key]} disabled={!loaded} onChange={v => update({ [r.key]: v })} label={r.label} />48 </label>49 ))}50 </div>51 );52}5354export function MemoryIcon({ className }: { className?: string }) { return <Brain className={className} />; }55