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
313 lines (312 loc) • 12 kB
JavaScript
import { z } from 'zod';
import { execSync } from 'child_process';
import * as fs from 'fs/promises';
export const patternDetectorTool = {
name: 'sis_patterns',
description: 'Detect patterns across workspace using quantum correlation',
parameters: z.object({
type: z.enum(['structural', 'behavioral', 'evolutionary', 'all']).default('all'),
threshold: z.number().min(0).max(1).default(0.7),
depth: z.number().min(1).max(5).default(3),
save: z.boolean().default(true)
}),
execute: async (args) => {
const patterns = {
structural: [],
behavioral: [],
evolutionary: []
};
// Structural patterns
if (args.type === 'structural' || args.type === 'all') {
patterns.structural = await detectStructuralPatterns(args.depth);
}
// Behavioral patterns
if (args.type === 'behavioral' || args.type === 'all') {
patterns.behavioral = await detectBehavioralPatterns(args.threshold);
}
// Evolutionary patterns
if (args.type === 'evolutionary' || args.type === 'all') {
patterns.evolutionary = await detectEvolutionaryPatterns();
}
// Filter by threshold
const filtered = filterPatternsByThreshold(patterns, args.threshold);
// Save to SIS patterns directory
if (args.save && Object.values(filtered).flat().length > 0) {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const patternFile = `./.sis/patterns/detected-${timestamp}.json`;
await fs.mkdir('./.sis/patterns', { recursive: true });
await fs.writeFile(patternFile, JSON.stringify(filtered, null, 2));
// Update PATTERNS.md if significant patterns found
const significantPatterns = Object.values(filtered).flat()
.filter((p) => p.confidence >= 0.9);
if (significantPatterns.length > 0) {
await updatePatternsDocument(significantPatterns);
}
}
return {
patterns: filtered,
total_detected: Object.values(filtered).flat().length,
high_confidence: Object.values(filtered).flat()
.filter((p) => p.confidence >= 0.9).length,
pattern_locations: args.save ? `./.sis/patterns/` : null
};
}
};
async function detectStructuralPatterns(depth) {
const patterns = [];
// Directory structure patterns
const dirTree = execSync(`find . -type d -maxdepth ${depth} | grep -v -E '^\\./(\\.|node_modules|venv)'`, {
encoding: 'utf-8'
}).split('\n').filter(Boolean);
// Analyze directory naming patterns
const dirPatterns = new Map();
for (const dir of dirTree) {
const parts = dir.split('/');
const lastPart = parts[parts.length - 1];
// Common patterns
if (lastPart.match(/^(src|lib|test|tests|spec|docs|scripts|utils|helpers|models|views|controllers)$/i)) {
dirPatterns.set('standard-structure', (dirPatterns.get('standard-structure') || 0) + 1);
}
if (lastPart.match(/^v\d+|version-?\d+/i)) {
dirPatterns.set('versioned-directories', (dirPatterns.get('versioned-directories') || 0) + 1);
}
}
// File naming patterns
const files = execSync('find . -type f -name "*.md" -o -name "*.py" -o -name "*.ts" -o -name "*.js" | head -100', {
encoding: 'utf-8'
}).split('\n').filter(Boolean);
const filePatterns = analyzeFilePatterns(files);
// Convert to pattern objects
for (const [pattern, count] of dirPatterns) {
if (count >= 3) {
patterns.push({
type: 'structural',
pattern: pattern,
occurrences: count,
confidence: Math.min(count / 10, 1),
description: `Directory structure pattern: ${pattern}`,
locations: dirTree.filter(d => d.match(getPatternRegex(pattern))).slice(0, 5)
});
}
}
patterns.push(...filePatterns);
return patterns;
}
async function detectBehavioralPatterns(threshold) {
const patterns = [];
// Git commit patterns
try {
const commits = execSync('git log --format="%s" -100', { encoding: 'utf-8' })
.split('\n').filter(Boolean);
const commitPatterns = new Map();
for (const commit of commits) {
// Conventional commits
const match = commit.match(/^(feat|fix|docs|style|refactor|test|chore|build|ci)(\(.+\))?:/);
if (match) {
commitPatterns.set('conventional-commits', (commitPatterns.get('conventional-commits') || 0) + 1);
}
// Version bumps
if (commit.match(/^(v?\d+\.\d+\.\d+|bump version|release)/i)) {
commitPatterns.set('version-releases', (commitPatterns.get('version-releases') || 0) + 1);
}
// Merge patterns
if (commit.match(/^Merge/)) {
commitPatterns.set('merge-commits', (commitPatterns.get('merge-commits') || 0) + 1);
}
}
for (const [pattern, count] of commitPatterns) {
const confidence = count / commits.length;
if (confidence >= threshold) {
patterns.push({
type: 'behavioral',
pattern: pattern,
occurrences: count,
confidence: confidence,
description: `Git commit pattern: ${pattern}`,
recommendation: getPatternRecommendation(pattern)
});
}
}
}
catch {
// Git not available
}
// File change patterns
const streamData = await readLatestStreamData();
if (streamData.length > 10) {
const changePatterns = analyzeChangePatterns(streamData);
patterns.push(...changePatterns.filter(p => p.confidence >= threshold));
}
return patterns;
}
async function detectEvolutionaryPatterns() {
const patterns = [];
// Growth patterns
try {
const fileCounts = execSync('git log --format="%at" --name-only --since="6 months ago" | grep -v "^$" | sort -u | wc -l', {
encoding: 'utf-8'
});
const currentFiles = execSync('find . -type f | wc -l', { encoding: 'utf-8' });
patterns.push({
type: 'evolutionary',
pattern: 'repository-growth',
current_size: parseInt(currentFiles),
growth_rate: 'calculated',
confidence: 0.8,
description: 'Repository growth pattern detected'
});
}
catch {
// Fallback for non-git repos
}
// Technology evolution
const techEvolution = await analyzeTechnologyEvolution();
patterns.push(...techEvolution);
return patterns;
}
function analyzeFilePatterns(files) {
const patterns = [];
const namingConventions = new Map();
for (const file of files) {
const basename = file.split('/').pop() || '';
// snake_case
if (basename.match(/^[a-z]+(_[a-z]+)+\./)) {
namingConventions.set('snake_case', (namingConventions.get('snake_case') || 0) + 1);
}
// kebab-case
if (basename.match(/^[a-z]+(-[a-z]+)+\./)) {
namingConventions.set('kebab-case', (namingConventions.get('kebab-case') || 0) + 1);
}
// CamelCase
if (basename.match(/^[A-Z][a-z]+([A-Z][a-z]+)+\./)) {
namingConventions.set('CamelCase', (namingConventions.get('CamelCase') || 0) + 1);
}
}
for (const [convention, count] of namingConventions) {
if (count >= 5) {
patterns.push({
type: 'structural',
pattern: `naming-convention-${convention}`,
occurrences: count,
confidence: Math.min(count / files.length, 1),
description: `File naming convention: ${convention}`
});
}
}
return patterns;
}
function getPatternRegex(pattern) {
switch (pattern) {
case 'standard-structure':
return /(src|lib|test|docs)/;
case 'versioned-directories':
return /v\d+|version-?\d+/;
default:
return new RegExp(pattern);
}
}
function getPatternRecommendation(pattern) {
switch (pattern) {
case 'conventional-commits':
return 'Continue using conventional commits for consistency';
case 'version-releases':
return 'Consider semantic versioning for releases';
case 'merge-commits':
return 'Consider squash merging for cleaner history';
default:
return 'Pattern detected - maintain consistency';
}
}
async function readLatestStreamData() {
try {
const streamPath = './.sis/intelligence/stream.jsonl';
const content = await fs.readFile(streamPath, 'utf-8');
const lines = content.trim().split('\n').slice(-100); // Last 100 entries
return lines.map(line => {
try {
return JSON.parse(line);
}
catch {
return null;
}
}).filter(Boolean);
}
catch {
return [];
}
}
function analyzeChangePatterns(streamData) {
const patterns = [];
// Time-based patterns
const hourlyActivity = new Map();
for (const entry of streamData) {
const hour = new Date(entry.t * 1000).getHours();
hourlyActivity.set(hour, (hourlyActivity.get(hour) || 0) + 1);
}
// Find peak hours
const peakHours = Array.from(hourlyActivity.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, 3);
if (peakHours.length > 0 && peakHours[0][1] > streamData.length * 0.2) {
patterns.push({
type: 'behavioral',
pattern: 'peak-activity-hours',
peak_hours: peakHours.map(([h]) => h),
confidence: peakHours[0][1] / streamData.length,
description: `Peak development activity during hours: ${peakHours.map(([h]) => h).join(', ')}`
});
}
return patterns;
}
async function analyzeTechnologyEvolution() {
const patterns = [];
// Check for framework migrations
try {
const packageJson = await fs.readFile('./package.json', 'utf-8');
const packages = JSON.parse(packageJson);
if (packages.dependencies || packages.devDependencies) {
patterns.push({
type: 'evolutionary',
pattern: 'technology-stack',
stack: 'node.js',
maturity: 'established',
confidence: 0.9,
description: 'Node.js ecosystem detected'
});
}
}
catch {
// Not a Node project
}
return patterns;
}
function filterPatternsByThreshold(patterns, threshold) {
const filtered = {};
for (const [type, typePatterns] of Object.entries(patterns)) {
filtered[type] = typePatterns.filter(p => p.confidence >= threshold);
}
return filtered;
}
async function updatePatternsDocument(patterns) {
try {
const patternsPath = './PATTERNS.md';
let content = await fs.readFile(patternsPath, 'utf-8');
// Add new patterns section
const newSection = `
## Automatically Detected Patterns (${new Date().toISOString().split('T')[0]})
${patterns.map(p => `### ${p.pattern}
- **Type**: ${p.type}
- **Confidence**: ${(p.confidence * 100).toFixed(1)}%
- **Description**: ${p.description}
${p.recommendation ? `- **Recommendation**: ${p.recommendation}` : ''}
`).join('\n')}
`;
// Append to file
content += newSection;
await fs.writeFile(patternsPath, content);
}
catch {
// PATTERNS.md doesn't exist or not writable
}
}
//# sourceMappingURL=pattern-detector.js.map