UNPKG

csvlod-ai-mcp-server

Version:

CSVLOD-AI MCP Server v3.0 with Quantum Context Intelligence - Revolutionary Context Intelligence Engine and Multimodal Processor for sovereign AI development

155 lines 5.54 kB
import { z } from 'zod'; import * as fs from 'fs/promises'; import { createReadStream } from 'fs'; import { createInterface } from 'readline'; export const streamReaderTool = { name: 'sis_stream', description: 'Read and analyze SIS intelligence stream with real-time filtering', parameters: z.object({ since: z.string().datetime().optional(), filter: z.array(z.string()).optional(), limit: z.number().max(1000).default(100), aggregate: z.boolean().default(false), live: z.boolean().default(false) }), execute: async (args) => { const streamPath = './.sis/intelligence/stream.jsonl'; // Check if stream exists try { await fs.access(streamPath); } catch { return { error: 'No intelligence stream found. Start with: sis stream 60 &' }; } const entries = []; const sinceTimestamp = args.since ? new Date(args.since).getTime() / 1000 : 0; // Read stream const fileStream = createReadStream(streamPath); const rl = createInterface({ input: fileStream, crlfDelay: Infinity }); for await (const line of rl) { try { const entry = JSON.parse(line); // Time filter if (entry.t < sinceTimestamp) continue; // Content filter if (args.filter && args.filter.length > 0) { const matches = args.filter.some((f) => JSON.stringify(entry).toLowerCase().includes(f.toLowerCase())); if (!matches) continue; } entries.push(entry); if (entries.length >= args.limit) break; } catch { // Skip malformed lines } } // Aggregate if requested if (args.aggregate && entries.length > 0) { const aggregated = aggregateEntries(entries); return { entries: entries.slice(-10), // Last 10 for context aggregation: aggregated, total_entries: entries.length, time_span: { start: new Date(entries[0].t * 1000).toISOString(), end: new Date(entries[entries.length - 1].t * 1000).toISOString() } }; } // Live streaming setup if (args.live) { return { message: 'Live streaming not available in this context', alternative: 'Use WebSocket connection to MCP server for live updates', stream_command: 'sis stream 5 &' }; } return { entries: entries.reverse(), // Most recent first total: entries.length, stream_health: analyzeStreamHealth(entries) }; } }; function aggregateEntries(entries) { const agg = { total_changes: 0, change_types: { minor: 0, major: 0, initial: 0 }, file_activity: new Map(), process_activity: new Map(), peak_activity_time: '', average_interval: 0 }; let lastTime = 0; let intervals = []; for (const entry of entries) { // Count changes if (entry.change) { agg.total_changes++; agg.change_types[entry.change]++; } // Parse pulse data if (entry.pulse) { const fileMatch = entry.pulse.match(/F\[(\d+)\]/); const procMatch = entry.pulse.match(/P\[(\d+)\]/); if (fileMatch) { const files = parseInt(fileMatch[1]); agg.file_activity.set(files, (agg.file_activity.get(files) || 0) + 1); } if (procMatch) { const procs = parseInt(procMatch[1]); agg.process_activity.set(procs, (agg.process_activity.get(procs) || 0) + 1); } } // Calculate intervals if (lastTime > 0) { intervals.push(entry.t - lastTime); } lastTime = entry.t; } // Find peak activity const hourCounts = new Map(); for (const entry of entries) { const hour = new Date(entry.t * 1000).toISOString().substring(0, 13); hourCounts.set(hour, (hourCounts.get(hour) || 0) + 1); } const peakHour = Array.from(hourCounts.entries()) .sort((a, b) => b[1] - a[1])[0]; if (peakHour) { agg.peak_activity_time = peakHour[0]; } // Average interval if (intervals.length > 0) { agg.average_interval = intervals.reduce((a, b) => a + b, 0) / intervals.length; } return { ...agg, file_activity: Object.fromEntries(agg.file_activity), process_activity: Object.fromEntries(agg.process_activity) }; } function analyzeStreamHealth(entries) { if (entries.length === 0) { return { status: 'no_data' }; } const lastEntry = entries[entries.length - 1]; const timeSinceLastEntry = Date.now() / 1000 - lastEntry.t; let status = 'healthy'; if (timeSinceLastEntry > 300) status = 'stale'; // 5 minutes if (timeSinceLastEntry > 3600) status = 'dead'; // 1 hour return { status, last_entry_age: Math.round(timeSinceLastEntry), entry_count: entries.length, stream_quality: entries.length > 10 ? 'good' : 'sparse' }; } //# sourceMappingURL=stream-reader.js.map