import { NextResponse } from 'next/server'; import * as fs from 'fs'; import * as path from 'path'; const API_SECRET = process.env.API_SECRET || 'horus-mc-secret-2026'; function checkAuth(request: Request): boolean { const authHeader = request.headers.get('authorization'); return authHeader === `Bearer ${API_SECRET}`; } const MAIN_AGENTS = ["horus", "cleopatra", "amun"]; const AGENTS = [ { id: "horus", name: "Horus", icon: "👁️", color: "#3b82f6" }, { id: "cleopatra", name: "Cleopatra", icon: "👸", color: "#a855f7" }, { id: "amun", name: "Amun", icon: "👑", color: "#f59e0b" }, { 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" }, ]; interface AgentInfo { id: string; name: string; icon: string; color: string; } function getAgentInfo(agentName: string): AgentInfo { const lower = agentName.toLowerCase(); const found = AGENTS.find(a => lower.includes(a.id) || lower.includes(a.name.toLowerCase())); return found || { id: "unknown", name: agentName, icon: "🤖", color: "#64748b" }; } export async function GET(request: Request) { // Check auth if (!checkAuth(request)) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } try { const memoryDir = '/root/.openclaw/workspace/memory'; const briefsMorningDir = '/root/.openclaw/workspace/briefs/morning'; const briefsEodDir = '/root/.openclaw/workspace/briefs/eod'; const files = fs.readdirSync(memoryDir) .filter(f => f.endsWith('.md')) .filter(f => /^\d{4}-\d{2}-\d{2}$/.test(f.replace('.md', ''))); const days: any[] = []; const allTags: string[] = []; for (const file of files) { const date = file.replace('.md', ''); const filePath = path.join(memoryDir, file); const content = fs.readFileSync(filePath, 'utf8'); const entries: any[] = []; const lines = content.split('\n'); let currentEntry: any = null; for (const line of lines) { const agentMatch = line.match(/^##\s*(\w+)\s*[-–]\s*(\d{2}:\d{2})/); if (agentMatch) { if (currentEntry?.content?.trim()) { entries.push(currentEntry); } const agentInfo = getAgentInfo(agentMatch[1]); currentEntry = { agent: agentInfo.name, agentIcon: agentInfo.icon, agentColor: agentInfo.color, time: agentMatch[2], content: '', tags: [], isMainAgent: MAIN_AGENTS.includes(agentInfo.id), }; } else if (currentEntry) { const trimmed = line.trim(); if (!trimmed) continue; const standaloneTagsMatch = trimmed.match(/^\[Tags:\s*(.+?)\]$/); if (standaloneTagsMatch) { const tags = standaloneTagsMatch[1] .split(',') .map((t: string) => t.trim().replace(/^#/, '').trim()) .filter(Boolean); currentEntry.tags = [...new Set([...currentEntry.tags, ...tags])]; tags.forEach((t: string) => { if (!allTags.includes(t)) allTags.push(t); }); } else { const inlineTagsMatch = trimmed.match(/\[Tags:\s*(.+?)\]/); if (inlineTagsMatch) { const tags = inlineTagsMatch[1] .split(',') .map((t: string) => t.trim().replace(/^#/, '').trim()) .filter(Boolean); currentEntry.tags = [...new Set([...currentEntry.tags, ...tags])]; tags.forEach((t: string) => { if (!allTags.includes(t)) allTags.push(t); }); } const cleanLine = trimmed.replace(/\[Tags:.*?\]/g, '').trim(); if (cleanLine) { currentEntry.content += (currentEntry.content ? '\n' : '') + cleanLine; } } } } if (currentEntry?.content?.trim()) { entries.push(currentEntry); } const hasMorning = fs.existsSync(path.join(briefsMorningDir, `${date}.md`)); const hasEod = fs.existsSync(path.join(briefsEodDir, `${date}.md`)); days.push({ date, entries, hasBriefs: { morning: hasMorning, eod: hasEod }, }); } days.sort((a, b) => b.date.localeCompare(a.date)); return NextResponse.json({ days, allTags, totalDays: days.length, }); } catch (error) { console.error('Memory list error:', error); return NextResponse.json({ days: [], allTags: [], error: 'Failed to load memory' }, { status: 500 }); } }