Rene Fichtmueller 4c54a6fa92 refactor: MAGATAMA pipeline code quality audit — all functions <50 lines
Complete code quality audit of llm-gateway pipeline modules for MAGATAMA standard compliance (50-line function maximum). All pipeline functions refactored to ensure high cohesion and readability.

Pipeline module compliance (verified):
 llm-client.ts — Refactored callOllama() (58→26 lines) via helper extraction
 instrumented-llm-client.ts — All functions <50 lines (wrapper layer)
 router.ts — Refactored routeByScore() (81→32 lines) via delegation
 request-scorer.ts — 870-line file, all functions <50 lines
 external-providers.ts — All functions <50 lines (49-line max)
 post-validator.ts — All validators <50 lines

Verified:
✓ npm run build (TypeScript, zero errors)
✓ All 6 pipeline modules independently audited
✓ Production-ready for Erik deployment (PM2 ids 19+20, port 3103)

Deployment target: Gitea (192.168.178.196:3000/rene/llm-gateway)
2026-04-25 17:38:11 +02:00

661 lines
23 KiB
TypeScript

import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
import { getPool } from '../db/client.js';
import { logger } from '../observability/logger.js';
import { createRequestLogger } from '../modules/request-logger.js';
import { globalRequestStream } from '../modules/request-stream.js';
import { getAvailableProviders } from '../pipeline/external-providers.js';
interface DashboardSummary {
totalCost: number;
totalSaved: number;
compressionRatio: number;
tokensSaved: number;
requestCount: number;
averageConfidence: number;
timeWindow: string;
}
interface CostBreakdown {
byProject: Record<string, { cost: number; count: number; saved: number }>;
byModel: Record<string, { cost: number; count: number }>;
byTaskType: Record<string, { cost: number; count: number }>;
totalCost: number;
totalSaved: number;
}
interface TokenMetrics {
totalIn: number;
totalOut: number;
totalCompressed: number;
compressionRate: number;
byModel: Record<string, { in: number; out: number; compressed: number }>;
}
interface AgentActivity {
agent: string;
taskCount: number;
averageCost: number;
averageConfidence: number;
totalTokens: number;
lastActivity: string;
}
interface LearningMetrics {
promptsImproved: number;
routingUpdates: number;
templateVariations: number;
averageScoreGain: number;
lastLearningRun: string;
}
interface AlertData {
active: number;
byType: Record<string, number>;
thresholds: {
compressionBelow: number;
weeklyBudget: number;
externalApiCost: number;
};
}
/**
* Get dashboard summary stats for a time window
*/
async function getDashboardSummary(hoursBack: number = 24): Promise<DashboardSummary> {
const db = getPool();
try {
const result = await db.query(
`SELECT
SUM(cost_usd) as total_cost,
SUM(cost_saved_usd) as total_saved,
SUM(tokens_compressed) as tokens_compressed,
SUM(tokens_in + tokens_out) as total_tokens,
COUNT(*) as request_count,
AVG(confidence_score) as avg_confidence
FROM cost_analytics
WHERE created_at > NOW() - INTERVAL $1 HOUR`,
[hoursBack]
);
const row = result.rows[0];
const totalTokens = parseInt(row?.total_tokens || '0', 10);
const totalCompressed = parseInt(row?.tokens_compressed || '0', 10);
return {
totalCost: parseFloat(row?.total_cost || '0'),
totalSaved: parseFloat(row?.total_saved || '0'),
compressionRatio: totalTokens > 0 ? parseFloat((((totalTokens - totalCompressed) / totalTokens) * 100).toFixed(2)) : 0,
tokensSaved: totalTokens - totalCompressed,
requestCount: parseInt(row?.request_count || '0', 10),
averageConfidence: parseFloat(row?.avg_confidence || '0'),
timeWindow: `${hoursBack}h`
};
} catch (err) {
logger.error({ err }, 'Failed to get dashboard summary');
return {
totalCost: 0,
totalSaved: 0,
compressionRatio: 0,
tokensSaved: 0,
requestCount: 0,
averageConfidence: 0,
timeWindow: `${hoursBack}h`
};
}
}
/**
* Get cost breakdown by project, model, and task type
*/
async function getCostBreakdown(hoursBack: number = 24): Promise<CostBreakdown> {
const db = getPool();
try {
const [projectResult, modelResult, taskResult] = await Promise.all([
db.query(
`SELECT project, SUM(cost_usd) as cost, COUNT(*) as count, SUM(cost_saved_usd) as saved
FROM cost_analytics
WHERE created_at > NOW() - INTERVAL $1 HOUR
GROUP BY project`,
[hoursBack]
),
db.query(
`SELECT model, SUM(cost_usd) as cost, COUNT(*) as count
FROM cost_analytics
WHERE created_at > NOW() - INTERVAL $1 HOUR
GROUP BY model`,
[hoursBack]
),
db.query(
`SELECT task_type, SUM(cost_usd) as cost, COUNT(*) as count
FROM cost_analytics
WHERE created_at > NOW() - INTERVAL $1 HOUR
GROUP BY task_type`,
[hoursBack]
)
]);
const byProject: Record<string, { cost: number; count: number; saved: number }> = {};
const byModel: Record<string, { cost: number; count: number }> = {};
const byTaskType: Record<string, { cost: number; count: number }> = {};
for (const row of projectResult.rows) {
byProject[row.project] = {
cost: parseFloat(row.cost || '0'),
count: parseInt(row.count || '0', 10),
saved: parseFloat(row.saved || '0')
};
}
for (const row of modelResult.rows) {
byModel[row.model] = {
cost: parseFloat(row.cost || '0'),
count: parseInt(row.count || '0', 10)
};
}
for (const row of taskResult.rows) {
byTaskType[row.task_type] = {
cost: parseFloat(row.cost || '0'),
count: parseInt(row.count || '0', 10)
};
}
const totalResult = await db.query(
`SELECT SUM(cost_usd) as total_cost, SUM(cost_saved_usd) as total_saved
FROM cost_analytics
WHERE created_at > NOW() - INTERVAL $1 HOUR`,
[hoursBack]
);
return {
byProject,
byModel,
byTaskType,
totalCost: parseFloat(totalResult.rows[0]?.total_cost || '0'),
totalSaved: parseFloat(totalResult.rows[0]?.total_saved || '0')
};
} catch (err) {
logger.error({ err }, 'Failed to get cost breakdown');
return { byProject: {}, byModel: {}, byTaskType: {}, totalCost: 0, totalSaved: 0 };
}
}
/**
* Get token usage and compression metrics
*/
async function getTokenMetrics(hoursBack: number = 24): Promise<TokenMetrics> {
const db = getPool();
try {
const [totalResult, byModelResult] = await Promise.all([
db.query(
`SELECT SUM(tokens_in) as total_in, SUM(tokens_out) as total_out, SUM(tokens_compressed) as total_compressed
FROM cost_analytics
WHERE created_at > NOW() - INTERVAL $1 HOUR`,
[hoursBack]
),
db.query(
`SELECT model, SUM(tokens_in) as in, SUM(tokens_out) as out, SUM(tokens_compressed) as compressed
FROM cost_analytics
WHERE created_at > NOW() - INTERVAL $1 HOUR
GROUP BY model`,
[hoursBack]
)
]);
const totalIn = parseInt(totalResult.rows[0]?.total_in || '0', 10);
const totalOut = parseInt(totalResult.rows[0]?.total_out || '0', 10);
const totalCompressed = parseInt(totalResult.rows[0]?.total_compressed || '0', 10);
const total = totalIn + totalOut;
const byModel: Record<string, { in: number; out: number; compressed: number }> = {};
for (const row of byModelResult.rows) {
byModel[row.model] = {
in: parseInt(row.in || '0', 10),
out: parseInt(row.out || '0', 10),
compressed: parseInt(row.compressed || '0', 10)
};
}
return {
totalIn,
totalOut,
totalCompressed,
compressionRate: total > 0 ? parseFloat((((total - totalCompressed) / total) * 100).toFixed(2)) : 0,
byModel
};
} catch (err) {
logger.error({ err }, 'Failed to get token metrics');
return { totalIn: 0, totalOut: 0, totalCompressed: 0, compressionRate: 0, byModel: {} };
}
}
/**
* Get agent activity and performance
*/
async function getAgentActivity(hoursBack: number = 24): Promise<AgentActivity[]> {
const db = getPool();
try {
const result = await db.query(
`SELECT agent_id, COUNT(*) as task_count, AVG(cost_usd) as avg_cost,
AVG(confidence_score) as avg_confidence, SUM(tokens_in + tokens_out) as total_tokens,
MAX(created_at) as last_activity
FROM cost_analytics
WHERE created_at > NOW() - INTERVAL $1 HOUR
GROUP BY agent_id
ORDER BY task_count DESC`,
[hoursBack]
);
return result.rows.map(row => ({
agent: row.agent_id || 'unknown',
taskCount: parseInt(row.task_count || '0', 10),
averageCost: parseFloat(row.avg_cost || '0'),
averageConfidence: parseFloat(row.avg_confidence || '0'),
totalTokens: parseInt(row.total_tokens || '0', 10),
lastActivity: row.last_activity?.toISOString() || 'never'
}));
} catch (err) {
logger.error({ err }, 'Failed to get agent activity');
return [];
}
}
/**
* Get alert configuration and active alerts
*/
async function getAlerts(): Promise<AlertData> {
const db = getPool();
try {
const [configResult, alertResult] = await Promise.all([
db.query(`SELECT * FROM cost_alert_config WHERE user_id = $1`, ['rene']),
db.query(`SELECT alert_type, COUNT(*) as count FROM alert_log WHERE acknowledged = FALSE GROUP BY alert_type`)
]);
const thresholds = {
compressionBelow: 40,
weeklyBudget: 50,
externalApiCost: 0
};
for (const row of configResult.rows) {
if (row.alert_type === 'compression_below') {
thresholds.compressionBelow = parseFloat(row.threshold);
} else if (row.alert_type === 'weekly_budget') {
thresholds.weeklyBudget = parseFloat(row.threshold);
} else if (row.alert_type === 'external_api') {
thresholds.externalApiCost = parseFloat(row.threshold);
}
}
const byType: Record<string, number> = {};
let total = 0;
for (const row of alertResult.rows) {
byType[row.alert_type] = parseInt(row.count || '0', 10);
total += parseInt(row.count || '0', 10);
}
return {
active: total,
byType,
thresholds
};
} catch (err) {
logger.error({ err }, 'Failed to get alerts');
return { active: 0, byType: {}, thresholds: { compressionBelow: 40, weeklyBudget: 50, externalApiCost: 0 } };
}
}
export async function dashboardRoute(fastify: FastifyInstance): Promise<void> {
// Dashboard summary endpoint
fastify.get('/api/dashboard/summary', async (request: FastifyRequest, reply: FastifyReply) => {
const hours = (request.query as any).hours ?? 24;
const summary = await getDashboardSummary(parseInt(hours, 10));
return reply.send(summary);
});
// Cost breakdown endpoint
fastify.get('/api/dashboard/costs', async (request: FastifyRequest, reply: FastifyReply) => {
const hours = (request.query as any).hours ?? 24;
const breakdown = await getCostBreakdown(parseInt(hours, 10));
return reply.send(breakdown);
});
// Token metrics endpoint
fastify.get('/api/dashboard/tokens', async (request: FastifyRequest, reply: FastifyReply) => {
const hours = (request.query as any).hours ?? 24;
const metrics = await getTokenMetrics(parseInt(hours, 10));
return reply.send(metrics);
});
// Agent activity endpoint
fastify.get('/api/dashboard/agents', async (request: FastifyRequest, reply: FastifyReply) => {
const hours = (request.query as any).hours ?? 24;
const activity = await getAgentActivity(parseInt(hours, 10));
return reply.send(activity);
});
// Alerts endpoint
fastify.get('/api/dashboard/alerts', async (request: FastifyRequest, reply: FastifyReply) => {
const alerts = await getAlerts();
return reply.send(alerts);
});
// Health check - ALWAYS check if requesting dashboard - if so, ALWAYS serve it regardless of tunnel caching
// This endpoint serves the dashboard HTML to work around Cloudflare tunnel caching issues
fastify.get('/api/dashboard/health', async (request: FastifyRequest, reply: FastifyReply) => {
// Try to serve dashboard with X-Dashboard-UI header for direct browser access
const dashboardHeader = request.headers['x-dashboard-ui'];
const query = request.query as Record<string, string>;
const cacheBustParam = query['cache-bust'] || query['v'] || '';
// ALWAYS serve dashboard HTML for development - tunnel will cache it as is
// This is a temporary workaround for the tunnel caching issue
const alwaysShowDashboard = true; // Set to false to restore normal health check
if (alwaysShowDashboard || dashboardHeader === '1' || dashboardHeader === 'true') {
try {
const { fileURLToPath } = await import('url');
const { dirname, join } = await import('path');
const { readFileSync, existsSync } = await import('fs');
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const publicDir = join(__dirname, '..', '..', 'public');
const dashboardPath = join(publicDir, 'dashboard.html');
if (existsSync(dashboardPath)) {
const content = readFileSync(dashboardPath, 'utf-8');
// Add dynamic ETag that changes every request to force cache revalidation
const now = Date.now();
const dynamicETag = `"dashboard-${now}"`;
logger.info({ size: content.length, alwaysShowDashboard, eTag: dynamicETag, cacheBustParam }, 'Serving dashboard from /api/dashboard/health');
return reply
.header('Cache-Control', 'no-cache, no-store, must-revalidate, max-age=0')
.header('Pragma', 'no-cache')
.header('Expires', '0')
.header('ETag', dynamicETag)
.header('Last-Modified', new Date().toUTCString())
.header('Vary', 'Accept-Encoding, User-Agent')
.type('text/html')
.send(content);
}
} catch (err) {
logger.error({ err }, 'Failed to serve dashboard from /api/dashboard/health');
}
}
try {
const db = getPool();
const result = await db.query('SELECT NOW() as current_time');
const dbHealthy = result.rows.length > 0;
return reply.send({
status: dbHealthy ? 'ok' : 'error',
database: dbHealthy ? 'connected' : 'disconnected',
sse_listeners: globalRequestStream.getListenerCount(),
timestamp: new Date().toISOString(),
});
} catch (error) {
logger.error({ error }, 'Health check failed');
return reply.status(503).send({
status: 'error',
database: 'disconnected',
timestamp: new Date().toISOString(),
});
}
});
// Request history endpoint
fastify.get('/api/dashboard/requests', async (request: FastifyRequest, reply: FastifyReply) => {
try {
const limit = Math.min(parseInt((request.query as any).limit as string) || 100, 1000);
const hours = Math.min(parseInt((request.query as any).hours as string) || 24, 168);
const db = getPool();
const requestLogger = createRequestLogger(db);
const requests = await requestLogger.getRecentRequests(limit, hours);
return reply.status(200).send({
success: true,
data: requests,
meta: {
total: requests.length,
limit,
hours,
timestamp: new Date().toISOString(),
},
});
} catch (error) {
logger.error({ error }, 'Failed to fetch dashboard requests');
return reply.status(500).send({
success: false,
error: 'Failed to fetch requests',
});
}
});
// Aggregated metrics endpoint
fastify.get('/api/dashboard/request-metrics', async (request: FastifyRequest, reply: FastifyReply) => {
try {
const bucketMinutes = Math.min(parseInt((request.query as any).bucket_minutes as string) || 60, 1440);
const db = getPool();
const requestLogger = createRequestLogger(db);
const metrics = await requestLogger.getMetrics(bucketMinutes);
return reply.status(200).send({
success: true,
data: metrics,
meta: {
bucket_minutes: bucketMinutes,
timestamp: new Date().toISOString(),
},
});
} catch (error) {
logger.error({ error }, 'Failed to fetch dashboard metrics');
return reply.status(500).send({
success: false,
error: 'Failed to fetch metrics',
});
}
});
// Server-Sent Events endpoint for real-time request updates
fastify.get('/api/stream/requests', async (request: FastifyRequest, reply: FastifyReply) => {
// Set SSE headers
reply.type('text/event-stream');
reply.header('Cache-Control', 'no-cache');
reply.header('Connection', 'keep-alive');
// Send initial connection message
reply.raw.write(`data: ${JSON.stringify({ type: 'connected', timestamp: new Date().toISOString() })}\n\n`);
// Subscribe to request events
const unsubscribe = globalRequestStream.onRequest((event) => {
reply.raw.write(`data: ${JSON.stringify(event)}\n\n`);
});
// Handle client disconnect
reply.raw.on('close', () => {
unsubscribe();
logger.info('SSE client disconnected from /api/stream/requests');
});
reply.raw.on('error', (error) => {
logger.error({ error }, 'SSE stream error');
unsubscribe();
});
logger.info(`SSE client connected to /api/stream/requests (active: ${globalRequestStream.getListenerCount()})`);
});
// Test endpoint
fastify.get('/api/dashboard/test', async (_request: FastifyRequest, reply: FastifyReply) => {
return reply.send({ test: 'ok', message: 'Test endpoint is working' });
});
// Providers endpoint - lists all available LLM providers (local, subscription, free-tier)
fastify.get('/api/dashboard/providers', async (_request: FastifyRequest, reply: FastifyReply) => {
try {
const availableProviders = await getAvailableProviders();
// Categorize providers by type
const providers = availableProviders.map(provider => {
let type: 'local' | 'subscription' | 'free' = 'free';
let status: 'configured' | 'unconfigured' | 'unavailable' = 'unconfigured';
// Determine provider type based on name
if (provider.name.toLowerCase().includes('ollama')) {
type = 'local';
status = provider.enabled ? 'configured' : 'unconfigured';
} else if (['claude-bridge', 'openai-bridge', 'chatgpt-bridge', 'copilot-bridge'].includes(provider.name)) {
type = 'subscription';
status = provider.enabled && process.env[provider.envKey] ? 'configured' : 'unconfigured';
} else {
type = 'free';
status = provider.enabled && process.env[provider.envKey] ? 'configured' : 'unconfigured';
}
return {
name: provider.name,
type,
status,
enabled: provider.enabled,
models: provider.models.map(m => ({
id: m.id,
tier: m.tier,
contextLength: m.contextLength
})),
rateLimitRpm: provider.rateLimitRpm,
baseUrl: provider.baseUrl
};
});
// Group by type for easy UI rendering
const grouped = {
local: providers.filter(p => p.type === 'local'),
subscription: providers.filter(p => p.type === 'subscription'),
free: providers.filter(p => p.type === 'free')
};
return reply.send({
success: true,
data: {
grouped,
all: providers,
summary: {
totalProviders: providers.length,
configuredCount: providers.filter(p => p.status === 'configured').length,
byType: {
local: grouped.local.length,
subscription: grouped.subscription.length,
free: grouped.free.length
}
}
},
meta: {
timestamp: new Date().toISOString()
}
});
} catch (error) {
logger.error({ error }, 'Failed to fetch providers');
return reply.status(500).send({
success: false,
error: 'Failed to fetch provider information'
});
}
});
// Dashboard UI endpoint (served at /api/dashboard/index for Cloudflare tunnel compatibility)
fastify.get('/api/dashboard/index', async (_request: FastifyRequest, reply: FastifyReply) => {
try {
const { fileURLToPath } = await import('url');
const { dirname, join } = await import('path');
const { readFileSync, existsSync } = await import('fs');
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const publicDir = join(__dirname, '..', '..', 'public');
const dashboardPath = join(publicDir, 'dashboard.html');
if (!existsSync(dashboardPath)) {
logger.warn({ path: dashboardPath }, 'dashboard.html not found');
return reply.status(404).send({ error: 'dashboard.html not found' });
}
const content = readFileSync(dashboardPath, 'utf-8');
logger.info({ size: content.length }, 'Serving dashboard from /api/dashboard/ui');
return reply.type('text/html').send(content);
} catch (error) {
logger.error({ error }, 'Failed to serve dashboard UI');
return reply.status(500).send({ error: 'Failed to serve dashboard' });
}
});
// Fresh dashboard endpoint (no cache) - for Cloudflare cache bypass testing
fastify.get('/dashboard', async (_request: FastifyRequest, reply: FastifyReply) => {
try {
const { fileURLToPath } = await import('url');
const { dirname, join } = await import('path');
const { readFileSync, existsSync } = await import('fs');
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const publicDir = join(__dirname, '..', '..', 'public');
const dashboardPath = join(publicDir, 'dashboard.html');
if (!existsSync(dashboardPath)) {
logger.warn({ path: dashboardPath }, 'dashboard.html not found');
return reply.status(404).send({ error: 'dashboard.html not found' });
}
const content = readFileSync(dashboardPath, 'utf-8');
logger.info({ size: content.length }, 'Serving dashboard from /dashboard');
return reply
.header('Cache-Control', 'no-cache, no-store, must-revalidate, max-age=0')
.header('Pragma', 'no-cache')
.header('Expires', '0')
.type('text/html')
.send(content);
} catch (error) {
logger.error({ error }, 'Failed to serve dashboard');
return reply.status(500).send({ error: 'Failed to serve dashboard' });
}
});
// Cloudflare cache bypass endpoint - new URL that won't be cached by Cloudflare
fastify.get('/api/dashboard/ui', async (_request: FastifyRequest, reply: FastifyReply) => {
try {
const { fileURLToPath } = await import('url');
const { dirname, join } = await import('path');
const { readFileSync, existsSync } = await import('fs');
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const publicDir = join(__dirname, '..', '..', 'public');
const dashboardPath = join(publicDir, 'dashboard.html');
if (!existsSync(dashboardPath)) {
logger.warn({ path: dashboardPath }, 'dashboard.html not found at /api/dashboard/ui');
return reply.status(404).send({ error: 'dashboard.html not found' });
}
const content = readFileSync(dashboardPath, 'utf-8');
const timestamp = Date.now();
logger.info({ size: content.length, endpoint: '/api/dashboard/ui', timestamp }, 'Serving dashboard UI (Cloudflare cache bypass)');
return reply
.header('Cache-Control', 'no-cache, no-store, must-revalidate, max-age=0, public')
.header('Pragma', 'no-cache')
.header('Expires', '0')
.header('ETag', `"ui-${timestamp}"`)
.header('X-Cache-Bypass', 'true')
.type('text/html; charset=utf-8')
.send(content);
} catch (error) {
logger.error({ error }, 'Failed to serve dashboard UI');
return reply.status(500).send({ error: 'Failed to serve dashboard UI' });
}
});
}