import React, { useState } from 'react';
import {
Database,
Search,
Trash2,
Clock,
Layers,
Archive,
Share2,
AlertCircle,
} from 'lucide-react';
import { Card, CardHeader, CardContent } from '@/components/ui/Card';
import { Button } from '@/components/ui/Button';
import { Badge } from '@/components/ui/Badge';
import { Input } from '@/components/ui/Input';
import {
useMemory,
useClearMemory,
useQueryMemory,
getMemoryLayerBadge,
formatMemorySize,
} from '@/hooks/useMemory';
import { useCurrentEpisode } from '@/hooks/useEpisode';
import { formatTimestamp, truncateText } from '@/utils/helpers';
import type { MemoryEntry, MemoryLayer } from '@/types';
interface MemoryPanelProps {
className?: string;
}
const MEMORY_TABS: { key: MemoryLayer; label: string; icon: React.ReactNode }[] = [
{ key: 'short_term', label: 'Short-Term', icon: },
{ key: 'working', label: 'Working', icon: },
{ key: 'long_term', label: 'Long-Term', icon: },
{ key: 'shared', label: 'Shared', icon: },
];
const MemoryEntryCard: React.FC<{ entry: MemoryEntry }> = ({ entry }) => {
const [isExpanded, setIsExpanded] = useState(false);
return (
setIsExpanded(!isExpanded)}
>
{isExpanded ? entry.content : truncateText(entry.content, 80)}
{formatTimestamp(entry.timestamp)}
{isExpanded && entry.metadata && Object.keys(entry.metadata).length > 0 && (
{JSON.stringify(entry.metadata, null, 2)}
)}
);
};
export const MemoryPanel: React.FC = ({ className }) => {
const { data: episode } = useCurrentEpisode();
const { data: memory, isLoading } = useMemory(episode?.id);
const clearMemoryMutation = useClearMemory(episode?.id);
const queryMemoryMutation = useQueryMemory(episode?.id);
const [activeTab, setActiveTab] = useState('working');
const [searchQuery, setSearchQuery] = useState('');
const handleSearch = () => {
if (searchQuery.trim() && episode?.id) {
queryMemoryMutation.mutate({
query: searchQuery,
layer: activeTab,
limit: 10,
});
}
};
const handleClear = () => {
if (episode?.id && confirm(`Clear all ${activeTab.replace('_', ' ')} memory?`)) {
clearMemoryMutation.mutate(activeTab);
}
};
const getEntriesForTab = (): MemoryEntry[] => {
if (!memory) return [];
switch (activeTab) {
case 'short_term':
return memory.shortTerm;
case 'working':
return memory.working;
case 'long_term':
return memory.longTerm;
case 'shared':
return memory.shared;
default:
return [];
}
};
const entries = queryMemoryMutation.data ?? getEntriesForTab();
return (
}
action={
memory && (
{formatMemorySize(memory.memoryUsage)}
)
}
/>
{/* Tabs */}
{MEMORY_TABS.map((tab) => (
))}
{/* Search */}
setSearchQuery(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
leftIcon={}
className="flex-1"
/>
}
/>
{/* Memory Entries */}
{isLoading ? (
) : entries.length === 0 ? (
No {activeTab.replace('_', ' ')} memory entries
) : (
entries.map((entry) => (
))
)}
{/* Memory Stats */}
{memory && (
{MEMORY_TABS.map((tab) => {
const count =
tab.key === 'short_term'
? memory.shortTerm.length
: tab.key === 'working'
? memory.working.length
: tab.key === 'long_term'
? memory.longTerm.length
: memory.shared.length;
return (
);
})}
)}
);
};
export default MemoryPanel;