import { NextResponse } from 'next/server'; import * as fs from 'fs'; import * as path from 'path'; const DATA_DIR = '/app/data'; // Types type CronJob = { name: string; enabled: boolean; status: string }; type Task = { id: string; title: string; created: string; priority: string; status: string; assignee: string }; type Memory = { id: string; title: string; date: string; preview: string }; // Helper to read files function readDir(dir: string, pattern: string = '.md'): string[] { if (!fs.existsSync(dir)) return []; return fs.readdirSync(dir).filter(f => f.endsWith(pattern)); } export async function GET(request: Request) { const { searchParams } = new URL(request.url); const type = searchParams.get('type') || 'tasks'; try { // TASKS if (type === 'tasks') { const tasksDir = path.join(DATA_DIR, 'shared-context/jelena-neo-tasks/archive'); const tasks: Task[] = []; if (fs.existsSync(tasksDir)) { for (const file of readDir(tasksDir).slice(0, 20)) { const content = fs.readFileSync(path.join(tasksDir, file), 'utf-8'); tasks.push({ id: file.replace('.md', ''), title: content.match(/^# Task: (.+)$/m)?.[1] || file, created: content.match(/Created: (.+)$/m)?.[1] || '', priority: content.match(/Priority: (.+)$/m)?.[1] || 'normal', status: 'done', assignee: 'neo' }); } } return NextResponse.json(tasks); } // CRONS - from shared-context if (type === 'crons') { // Try multiple paths for cron jobs const cronPaths = [ path.join(DATA_DIR, 'shared-context/.openclaw/cron/jobs.json'), path.join(DATA_DIR, 'workspace-neo/.openclaw/cron/jobs.json'), ]; for (const cronFile of cronPaths) { if (fs.existsSync(cronFile)) { const data = JSON.parse(fs.readFileSync(cronFile, 'utf-8')); const jobs: CronJob[] = (data.jobs || []).map((job: any) => ({ name: job.name, enabled: job.enabled, status: job.state?.lastStatus || 'unknown' })); return NextResponse.json(jobs); } } return NextResponse.json([]); } // MEMORY if (type === 'memory') { const memoryDir = path.join(DATA_DIR, 'memory'); const memories: Memory[] = []; if (fs.existsSync(memoryDir)) { for (const file of readDir(memoryDir).slice(0, 20)) { const content = fs.readFileSync(path.join(memoryDir, file), 'utf-8'); memories.push({ id: file.replace('.md', ''), title: content.match(/^# (.+)$/m)?.[1] || file, date: file.substring(0, 10), preview: content.substring(0, 150).replace(/[#*]/g, '') }); } } return NextResponse.json(memories); } // SERVER STATUS - basic data only if (type === 'server') { return NextResponse.json({ status: 'ok', note: 'Full stats coming soon' }); } // BACKUP STATUS if (type === 'backups') { const backups: any[] = []; // Git backup const gitBackupDir = path.join(DATA_DIR, 'workspace-neo/.git'); if (fs.existsSync(gitBackupDir)) { const stats = fs.statSync(gitBackupDir); backups.push({ name: 'Git Config', status: 'ok', lastRun: 'Today 10:49' }); } // Storage backup const storageDir = path.join(DATA_DIR, '../openclaw/jelena/backups/config'); if (fs.existsSync(storageDir)) { const files = fs.readdirSync(storageDir); if (files.length > 0) { const latest = files.sort().pop(); backups.push({ name: 'Storage Box', status: 'ok', lastRun: latest?.replace('.tar.gz', '') || 'unknown' }); } } return NextResponse.json(backups); } // AGENT STATUS if (type === 'agents') { return NextResponse.json([ { name: 'Jelena', role: 'Chief of Staff', status: 'online' }, { name: 'Neo', role: 'CTO / DevOps', status: 'online' } ]); } // WHATSAPP BACKUP if (type === 'whatsapp') { const waDir = path.join(DATA_DIR, '../openclaw/jelena/whatsapp-chats'); if (fs.existsSync(waDir)) { const chats = fs.readdirSync(waDir); return NextResponse.json({ status: 'ok', chats: chats.length, lastUpdate: 'Today' }); } return NextResponse.json({ status: 'not_configured', chats: 0, lastUpdate: 'Never' }); } return NextResponse.json({ error: 'Unknown type' }, { status: 400 }); } catch (e: any) { return NextResponse.json({ error: e.message }, { status: 500 }); } }