From 8d671cb7826cb40b0f425e1282f61ebfb8670eea Mon Sep 17 00:00:00 2001 From: Brixyy <123451340+Brixyy@users.noreply.github.com> Date: Sun, 15 Mar 2026 12:30:46 +0100 Subject: [PATCH] fix: scope memory health diagnostics to allowed prefixes (#367) When memoryAllowedPrefixes is configured, scan only those subdirectories instead of the entire MEMORY_PATH. Falls back to full scan if no prefixes are set.\n\nCloses #366 --- src/app/api/memory/health/route.ts | 42 ++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/app/api/memory/health/route.ts b/src/app/api/memory/health/route.ts index e9937f3..5fb5545 100644 --- a/src/app/api/memory/health/route.ts +++ b/src/app/api/memory/health/route.ts @@ -1,4 +1,6 @@ import { NextRequest, NextResponse } from 'next/server' +import { existsSync } from 'fs' +import { join } from 'path' import { config } from '@/lib/config' import { requireRole } from '@/lib/auth' import { readLimiter } from '@/lib/rate-limit' @@ -6,6 +8,35 @@ import { runHealthDiagnostics } from '@/lib/memory-utils' import { logger } from '@/lib/logger' const MEMORY_PATH = config.memoryDir +const MEMORY_ALLOWED_PREFIXES = (config.memoryAllowedPrefixes || []).map((p) => p.replace(/\\/g, '/')) + +function mergeReports(reports: Awaited>[]) { + const allCategories = reports.flatMap((report) => report.categories) + const mergedCategories = Array.from(new Set(allCategories.map((category) => category.name))).map((name) => { + const group = allCategories.filter((category) => category.name === name) + const score = Math.round(group.reduce((sum, category) => sum + category.score, 0) / group.length) + const status = score >= 80 ? 'healthy' : score >= 50 ? 'warning' : 'critical' + return { + name, + status, + score, + issues: group.flatMap((category) => category.issues).slice(0, 10), + suggestions: Array.from(new Set(group.flatMap((category) => category.suggestions))), + } + }) + + const overallScore = mergedCategories.length > 0 + ? Math.round(mergedCategories.reduce((sum, category) => sum + category.score, 0) / mergedCategories.length) + : 100 + const overall = overallScore >= 70 ? 'healthy' : overallScore >= 40 ? 'warning' : 'critical' + + return { + overall, + overallScore, + categories: mergedCategories, + generatedAt: Date.now(), + } +} export async function GET(request: NextRequest) { const auth = requireRole(request, 'viewer') @@ -19,6 +50,17 @@ export async function GET(request: NextRequest) { } try { + if (MEMORY_ALLOWED_PREFIXES.length) { + const reports = [] + for (const prefix of MEMORY_ALLOWED_PREFIXES) { + const folder = prefix.replace(/\/$/, '') + const fullPath = join(MEMORY_PATH, folder) + if (!existsSync(fullPath)) continue + reports.push(await runHealthDiagnostics(fullPath)) + } + return NextResponse.json(reports.length > 0 ? mergeReports(reports) : await runHealthDiagnostics(MEMORY_PATH)) + } + const report = await runHealthDiagnostics(MEMORY_PATH) return NextResponse.json(report) } catch (err) {