UNPKG

semantic-prompt-mcp

Version:

MCP server for semantic prompt framework - NLP-inspired adaptive reasoning engine for LLM orchestration

292 lines 10.3 kB
/** * Unified Command Handler * Implements intelligent framework detection, parameter normalization, and routing * Core implementation of DRY, SSOT, KISS principles */ import { readFileSync, existsSync } from 'fs'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; import { ParameterNormalizer } from '../utils/parameterNormalizer.js'; // Get current directory for ES modules const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); export class UnifiedCommandHandler { bridge; // Use definite assignment assertion normalizer; cache; sessionDocuments; constructor() { this.normalizer = new ParameterNormalizer(); this.cache = new Map(); this.sessionDocuments = new Set(); this.loadBridgeConfiguration(); } /** * Loads the framework bridge configuration */ loadBridgeConfiguration() { const bridgePath = join(__dirname, '..', 'prompts', 'framework-bridge.json'); if (existsSync(bridgePath)) { const content = readFileSync(bridgePath, 'utf-8'); this.bridge = JSON.parse(content); } else { // Fallback configuration if bridge file doesn't exist this.bridge = this.getDefaultBridge(); } } /** * Provides default bridge configuration */ getDefaultBridge() { return { frameworks: { superclaude: { name: 'SuperClaude Framework', enabled: true, prefix: '/sc:', alternativePrefixes: [], paths: { commands: '~/.claude/commands/sc/' }, features: { chainOfThought: true, taskAgents: true } }, supergemini: { name: 'SuperGemini Framework', enabled: true, prefix: '/sg:', alternativePrefixes: ['/sgc:'], paths: { commands: '~/.claude/commands/sg/' }, features: { chainOfThought: true, waveOrchestration: true } } }, routing: { strategy: 'intelligent', default: 'supergemini', fallback: 'superclaude', detection: { enabled: true, rules: [] }, aliasMapping: {} }, parameterNormalization: { enabled: true, strategies: {}, errorHandling: {} }, interoperability: { sharedResources: { agents: [], mcpServers: [] }, crossFrameworkCalls: { enabled: true, allowedPaths: ['*'], parameterTranslation: true } } }; } /** * Detects which framework should handle the command */ detectFramework(command) { // First, check alias mapping if (this.bridge.routing.aliasMapping[command]) { command = this.bridge.routing.aliasMapping[command]; } // Check detection rules if (this.bridge.routing.detection.enabled) { const sortedRules = [...this.bridge.routing.detection.rules].sort((a, b) => a.priority - b.priority); for (const rule of sortedRules) { const regex = new RegExp(rule.pattern); if (regex.test(command)) { if (rule.framework === 'default') { return this.bridge.routing.default; } return rule.framework; } } } // Check framework prefixes for (const [key, framework] of Object.entries(this.bridge.frameworks)) { if (!framework.enabled) continue; if (command.startsWith(framework.prefix)) { return key; } for (const altPrefix of framework.alternativePrefixes || []) { if (command.startsWith(altPrefix)) { return key; } } } // Return default framework return this.bridge.routing.default; } /** * Normalizes parameters based on bridge configuration */ normalizeParameters(params, tool) { if (!this.bridge.parameterNormalization.enabled) { return params; } // Special handling for chain_of_thought tool if (tool === 'chain_of_thought' || tool === 'chainOfThought') { return this.normalizer.normalizeChainOfThoughtParams(params); } // General normalization const normalized = {}; for (const [key, value] of Object.entries(params || {})) { // Check if special normalization is needed const strategy = this.bridge.parameterNormalization.strategies[key]; if (strategy && strategy.normalize) { switch (key) { case 'commandSelection': normalized[key] = this.normalizer.normalizeCommandSelection(value); break; case 'agentSelection': normalized[key] = this.normalizer.normalizeAgentSelection(value); break; default: normalized[key] = this.normalizer.autoNormalize(value); } } else { // Apply general normalization normalized[key] = this.normalizer.autoNormalize(value); } } return normalized; } /** * Routes command to appropriate framework handler */ async route(command, params) { const framework = this.detectFramework(command); const normalizedParams = this.normalizeParameters(params); // Log routing decision if enabled if (this.bridge.configuration?.logging?.routingDecisions) { console.log(`[Router] Command: ${command} -> Framework: ${framework}`); } // Check cache const cacheKey = `${framework}:${command}:${JSON.stringify(normalizedParams)}`; if (this.cache.has(cacheKey)) { return this.cache.get(cacheKey); } // Route to framework handler const result = await this.handleFrameworkCommand(framework, command, normalizedParams); // Cache result if enabled if (this.bridge.configuration?.cacheEnabled) { this.cache.set(cacheKey, result); } return result; } /** * Handles command execution for specific framework */ async handleFrameworkCommand(framework, command, params) { const fw = this.bridge.frameworks[framework]; if (!fw || !fw.enabled) { // Fallback to default framework const fallback = this.bridge.routing.fallback; if (fallback && fallback !== framework) { return this.handleFrameworkCommand(fallback, command, params); } throw new Error(`Framework ${framework} is not available`); } // Here you would integrate with actual framework handlers // For now, return a structured response return { framework: fw.name, command, params, features: fw.features, status: 'ready', timestamp: new Date().toISOString() }; } /** * Validates cross-framework call permissions */ canCrossCall(from, to) { if (!this.bridge.interoperability.crossFrameworkCalls.enabled) { return false; } const allowedPaths = this.bridge.interoperability.crossFrameworkCalls.allowedPaths; // Check if wildcard is allowed if (allowedPaths.includes('*') || allowedPaths.includes(`${from} -> *`)) { return true; } // Check specific path return allowedPaths.includes(`${from} -> ${to}`); } /** * Gets available agents across frameworks */ getAvailableAgents() { return this.bridge.interoperability.sharedResources.agents || []; } /** * Gets available MCP servers across frameworks */ getAvailableMCPServers() { return this.bridge.interoperability.sharedResources.mcpServers || []; } /** * Handles parameter translation between frameworks */ translateParameters(params, fromFramework, toFramework) { if (!this.bridge.interoperability.crossFrameworkCalls.parameterTranslation) { return params; } // Normalize parameters first const normalized = this.normalizeParameters(params); // Apply framework-specific translations // This could be extended with framework-specific rules const translated = { ...normalized }; // Example: SuperClaude uses 'commandSelection', SuperGemini might use 'selectedCommand' // Add translation rules as needed return translated; } /** * Clears cache */ clearCache() { this.cache.clear(); } /** * Gets framework configuration */ getFrameworkConfig(framework) { return this.bridge.frameworks[framework]; } /** * Checks if a feature is available in a framework */ hasFeature(framework, feature) { const fw = this.bridge.frameworks[framework]; return fw?.features?.[feature] === true; } /** * Document tracking for session management */ trackDocument(document) { this.sessionDocuments.add(document); } /** * Check if document was already read in session */ isDocumentRead(document) { return this.sessionDocuments.has(document); } /** * Reset session state */ resetSession() { this.sessionDocuments.clear(); this.clearCache(); } } // Export singleton instance export const commandHandler = new UnifiedCommandHandler(); //# sourceMappingURL=commandHandler.js.map