"use client"; import { useQuery } from "@tanstack/react-query"; import { useAtomValue } from "jotai"; import { useEffect, useState } from "react"; import { toast } from "sonner"; import { updateSearchSpaceMutationAtom } from "@/atoms/search-spaces/search-space-mutation.atoms"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import { Spinner } from "@/components/ui/spinner"; import { Textarea } from "@/components/ui/textarea"; 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 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 > 20_000) return "text-orange-500"; if (charCount > 15_000) return "text-yellow-500"; return "text-muted-foreground"; }; if (loading) { return (
This is the shared memory document for this search space. The AI assistant reads it at the start of every conversation and uses it for team-wide context. You can edit it directly or let the assistant update it during conversations.