"use client"; import { useState, useEffect } from "react"; // Only 3 main agents show as dots const MAIN_AGENTS = [ { id: "horus", name: "Horus", icon: "👁️", color: "#3b82f6" }, { id: "cleopatra", name: "Cleopatra", icon: "👸", color: "#a855f7" }, { id: "amun", name: "Amun", icon: "👑", color: "#f59e0b" }, ]; // All agents for tag detection const ALL_AGENTS = [ ...MAIN_AGENTS, { id: "anubis", name: "Anubis", icon: "🐕", color: "#22c55e" }, { id: "thoth", name: "Thoth", icon: "📚", color: "#06b6d4" }, { id: "ptah", name: "Ptah", icon: "🎨", color: "#f97316" }, { id: "seshat", name: "Seshat", icon: "📝", color: "#ec4899" }, { id: "hathor", name: "Hathor", icon: "💕", color: "#ef4444" }, { id: "sekhmet", name: "Sekhmet", icon: "⚔️", color: "#94a3b8" }, { id: "maat", name: "Maat", icon: "⚖️", color: "#64748b" }, ]; const INACTIVE_COLOR = "#4b5563"; interface DayEntry { agent: string; agentIcon: string; agentColor: string; time: string; content: string; tags: string[]; isMainAgent: boolean; } interface MemoryDay { date: string; entries: DayEntry[]; hasBriefs: { morning: boolean; eod: boolean }; } interface CalendarDay { date: string; day: number; isCurrentMonth: boolean; isToday: boolean; activeMainAgents: string[]; entries: DayEntry[]; hasBriefs: { morning: boolean; eod: boolean }; } export default function MemoryPage() { const [memoryDays, setMemoryDays] = useState([]); const [selectedDay, setSelectedDay] = useState(null); const [currentMonth, setCurrentMonth] = useState(new Date()); const [loading, setLoading] = useState(true); const [filterAgent, setFilterAgent] = useState(null); const [filterTag, setFilterTag] = useState(null); const [allTags, setAllTags] = useState([]); const [searchQuery, setSearchQuery] = useState(""); const [editingEntry, setEditingEntry] = useState(null); const [editTags, setEditTags] = useState(""); useEffect(() => { fetchMemory(); }, []); const fetchMemory = async () => { setLoading(true); try { const res = await fetch("/api/memory/list", { headers: { 'Authorization': 'Bearer horus-mc-secret-2026' } }); const data = await res.json(); setMemoryDays(data.days || []); setAllTags(data.allTags || []); } catch (e) { console.error("Failed to fetch memory:", e); } setLoading(false); }; const getAgentInfo = (agentName: string) => { const lower = agentName.toLowerCase(); const agent = ALL_AGENTS.find(a => lower.includes(a.id) || lower.includes(a.name.toLowerCase())); return agent || { name: agentName, icon: "🤖", color: INACTIVE_COLOR }; }; const isMainAgent = (agentName: string) => { const lower = agentName.toLowerCase(); return MAIN_AGENTS.some(a => lower.includes(a.id) || lower.includes(a.name.toLowerCase())); }; const getCalendarDays = (): CalendarDay[] => { const year = currentMonth.getFullYear(); const month = currentMonth.getMonth(); const firstDay = new Date(year, month, 1); const lastDay = new Date(year, month + 1, 0); const startPad = firstDay.getDay(); const days: CalendarDay[] = []; const today = new Date().toISOString().split("T")[0]; const monthDays = memoryDays.filter((d) => d.date.startsWith(`${year}-${String(month + 1).padStart(2, "0")}`)); for (let i = startPad - 1; i >= 0; i--) { const d = new Date(year, month, -i); days.push({ date: d.toISOString().split("T")[0], day: d.getDate(), isCurrentMonth: false, isToday: false, activeMainAgents: [], entries: [], hasBriefs: { morning: false, eod: false }, }); } for (let i = 1; i <= lastDay.getDate(); i++) { const date = `${year}-${String(month + 1).padStart(2, "0")}-${String(i).padStart(2, "0")}`; const memDay = monthDays.find((d) => d.date === date); const mainAgents = memDay?.entries .filter((e) => e.isMainAgent) .map((e) => e.agent.toLowerCase()) || []; days.push({ date, day: i, isCurrentMonth: true, isToday: date === today, activeMainAgents: [...new Set(mainAgents)], entries: memDay?.entries || [], hasBriefs: memDay?.hasBriefs || { morning: false, eod: false }, }); } const remaining = 42 - days.length; for (let i = 1; i <= remaining; i++) { const d = new Date(year, month + 1, i); days.push({ date: d.toISOString().split("T")[0], day: d.getDate(), isCurrentMonth: false, isToday: false, activeMainAgents: [], entries: [], hasBriefs: { morning: false, eod: false }, }); } return days; }; const getFilteredEntries = () => { if (!selectedDay) return []; let entries = selectedDay.entries; if (filterAgent) { entries = entries.filter((e) => e.agent.toLowerCase() === filterAgent.toLowerCase()); } if (filterTag) { entries = entries.filter((e) => e.tags.includes(filterTag)); } if (searchQuery) { entries = entries.filter((e) => e.content.toLowerCase().includes(searchQuery.toLowerCase()) ); } return entries; }; const calendarDays = getCalendarDays(); const filteredEntries = getFilteredEntries(); const getMainAgentDots = (activeMainAgents: string[]) => { return MAIN_AGENTS.map((agent) => ({ agent, active: activeMainAgents.some((a) => a.includes(agent.id) || a.includes(agent.name.toLowerCase())), })); }; const handleEditTags = (entry: DayEntry) => { setEditingEntry(entry); setEditTags(entry.tags.join(", ")); }; const saveTags = async () => { if (!editingEntry || !selectedDay) return; // In a real app, this would POST to an API to update the file // For now, just update the local state const newTags = editTags.split(",").map((t) => t.trim().replace(/^#/, "")).filter(Boolean); setSelectedDay({ ...selectedDay, entries: selectedDay.entries.map((e) => e === editingEntry ? { ...e, tags: newTags } : e ), }); setEditingEntry(null); setEditTags(""); // TODO: POST to /api/memory/tags to save }; return (
{/* Main Content */}
{/* Header */}

📅 Memory Calendar

Our unified memory system

{/* Calendar */}
{/* Month Navigation */}

{currentMonth.toLocaleDateString("en-US", { month: "long", year: "numeric" })}

{/* Day Headers */}
{["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].map((d) => (
{d}
))}
{/* Calendar Grid */}
{calendarDays.map((day, idx) => { const dots = getMainAgentDots(day.activeMainAgents); const isSelected = selectedDay?.date === day.date; const hasEntries = day.entries.length > 0; return ( ); })}
{/* Legend */}

Dots = Active Agents

{MAIN_AGENTS.map((agent) => (
{agent.icon} {agent.name}
))}
Inactive
📝 = Has entries (other agents)
{/* Right Sidebar - Day Detail */}
{selectedDay ? ( <> {/* Day Header */}

{new Date(selectedDay.date).toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric", })}

{selectedDay.hasBriefs.morning && ( ☀️ Morning Brief )} {selectedDay.hasBriefs.eod && ( 🌙 EOD Brief )}
{/* Filters */}
setSearchQuery(e.target.value)} className="w-full px-3 py-2 bg-slate-800 border border-slate-700 rounded text-white text-sm placeholder-slate-500" />
{MAIN_AGENTS.map((agent) => ( ))}
{allTags.length > 0 && (
{allTags.slice(0, 8).map((tag) => ( ))}
)}
{/* Entries */}
{loading ? (
Loading...
) : filteredEntries.length === 0 ? (
No entries for this day
) : ( filteredEntries.map((entry, idx) => (
{entry.agentIcon} {entry.agent} {entry.time}
                      {entry.content.length > 250
                        ? entry.content.slice(0, 250) + "..."
                        : entry.content}
                    
{/* Tags */}
{entry.tags.map((tag) => ( #{tag} ))}
)) )}
) : (
📅

Select a day to view entries

)} {/* Who's Active */}

Today

{MAIN_AGENTS.map((agent) => { const isActive = memoryDays[0]?.entries.some((e) => e.agent.toLowerCase().includes(agent.id) ); return (
{agent.icon}
); })}
{/* Edit Tags Modal */} {editingEntry && (

Edit Tags

{editingEntry.agentIcon} {editingEntry.agent}
setEditTags(e.target.value)} placeholder="tag1, tag2, tag3" className="w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded text-white text-sm placeholder-slate-400 mb-4" />
)}
); }