semantic-prompt-mcp
Version:
MCP server for semantic prompt framework - NLP-inspired adaptive reasoning engine for LLM orchestration
292 lines • 10.3 kB
JavaScript
/**
* 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