"use client"; import { useQuery } from "@tanstack/react-query"; import { useAtomValue } from "jotai"; import { Info } from "lucide-react"; import { useCallback, useEffect, useState } from "react"; import { toast } from "sonner"; import { updateSearchSpaceMutationAtom } from "@/atoms/search-spaces/search-space-mutation.atoms"; import { PlateEditor } from "@/components/editor/plate-editor"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Button } from "@/components/ui/button"; import { Spinner } from "@/components/ui/spinner"; import { searchSpacesApiService } from "@/lib/apis/search-spaces-api.service"; import { cacheKeys } from "@/lib/query-client/cache-keys"; const MEMORY_HARD_LIMIT = 25_000; interface TeamMemoryManagerProps { searchSpaceId: number; } export function TeamMemoryManager({ searchSpaceId }: TeamMemoryManagerProps) { const { data: searchSpace, isLoading: loading } = useQuery({ queryKey: cacheKeys.searchSpaces.detail(searchSpaceId.toString()), queryFn: () => searchSpacesApiService.getSearchSpace({ id: searchSpaceId }), enabled: !!searchSpaceId, }); const { mutateAsync: updateSearchSpace } = useAtomValue(updateSearchSpaceMutationAtom); const [memory, setMemory] = useState(""); const [saving, setSaving] = useState(false); useEffect(() => { if (searchSpace) { setMemory(searchSpace.shared_memory_md || ""); } }, [searchSpace?.shared_memory_md]); const handleMarkdownChange = useCallback((md: string) => { const trimmed = md.trim(); setMemory(trimmed); }, []); const hasChanges = !!searchSpace && (searchSpace.shared_memory_md || "") !== memory; const handleSave = async () => { try { setSaving(true); await updateSearchSpace({ id: searchSpaceId, data: { shared_memory_md: memory }, }); toast.success("Team memory saved"); } catch { toast.error("Failed to save team memory"); } finally { setSaving(false); } }; const handleClear = async () => { try { setSaving(true); await updateSearchSpace({ id: searchSpaceId, data: { shared_memory_md: "" }, }); setMemory(""); toast.success("Team memory cleared"); } catch { toast.error("Failed to clear team memory"); } finally { setSaving(false); } }; const charCount = memory.length; const isOverLimit = charCount > MEMORY_HARD_LIMIT; const getCounterColor = () => { if (charCount > MEMORY_HARD_LIMIT) return "text-red-500"; if (charCount > 15_000) return "text-orange-500"; if (charCount > 10_000) return "text-yellow-500"; return "text-muted-foreground"; }; if (loading) { return (
SurfSense uses this shared memory to provide team-wide context across all conversations in this search space. Supports Markdown formatting.