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
JavaScript
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