snow-flow
Version:
Snow-Flow v3.2.0: Complete ServiceNow Enterprise Suite with 180+ MCP Tools. ATF Testing, Knowledge Management, Service Catalog, Change Management with CAB scheduling, Virtual Agent chatbots with NLU, Performance Analytics KPIs, Flow Designer automation, A
333 lines • 16.4 kB
JavaScript
;
/**
* Intelligent Gap Analysis Engine - The core orchestrator
*
* This is the main engine that orchestrates all components to analyze objectives,
* detect missing ServiceNow configurations beyond MCP tools, and attempt automated
* resolution with fallback to detailed manual instructions.
*
* This fulfills the user's vision: "alle mogelijke soorten handelingen die nodig
* zouden zijn om een objective te bereiken die vallen buiten de standaard mcps"
*
* Usage:
* const engine = new GapAnalysisEngine(mcpTools, logger, autoPermissions);
* const result = await engine.analyzeAndResolve("create incident widget with charts");
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.GapAnalysisEngine = void 0;
exports.analyzeGaps = analyzeGaps;
exports.quickAnalyze = quickAnalyze;
const requirements_analyzer_1 = require("./requirements-analyzer");
const mcp_coverage_analyzer_1 = require("./mcp-coverage-analyzer");
const auto_resolution_engine_1 = require("./auto-resolution-engine");
const manual_instructions_generator_1 = require("./manual-instructions-generator");
class GapAnalysisEngine {
constructor(mcpTools, logger, autoPermissions = false) {
this.mcpTools = mcpTools;
this.logger = logger;
this.autoResolutionEngine = new auto_resolution_engine_1.AutoResolutionEngine(mcpTools, logger, autoPermissions);
}
/**
* Main entry point - analyze objective and resolve all gaps
*/
async analyzeAndResolve(objective, options = {}) {
const startTime = Date.now();
const analysisId = `gap_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
this.logger.info(`🧠 Starting Intelligent Gap Analysis for: "${objective}"`);
this.logger.info(`📊 Analysis ID: ${analysisId}`);
try {
// Step 1: Analyze requirements from natural language objective
this.logger.info('🔍 Step 1: Analyzing requirements...');
const requirementsAnalysis = requirements_analyzer_1.RequirementsAnalyzer.analyzeObjective(objective);
if (requirementsAnalysis.requirements.length === 0) {
this.logger.warn('⚠️ No specific ServiceNow requirements detected');
return this.createEmptyResult(objective, analysisId, startTime);
}
this.logger.info(`📋 Detected ${requirementsAnalysis.requirements.length} requirements`);
// Step 2: Analyze MCP coverage vs gaps
this.logger.info('🎯 Step 2: Analyzing MCP coverage...');
const mcpCoverage = mcp_coverage_analyzer_1.McpCoverageAnalyzer.analyzeCoverage(requirementsAnalysis.requirements);
this.logger.info(`✅ MCP Coverage: ${mcpCoverage.coveragePercentage}% (${mcpCoverage.covered.length}/${requirementsAnalysis.requirements.length})`);
this.logger.info(`❌ Gaps requiring attention: ${mcpCoverage.gaps.length}`);
this.logger.info(`⚠️ Partial coverage items: ${mcpCoverage.partialCoverage.length}`);
// Step 3: Attempt automated resolution for gaps
let automationResults;
if (options.enableAutomation !== false && !options.dryRun) {
this.logger.info('🤖 Step 3: Attempting automated resolution...');
automationResults = await this.autoResolutionEngine.resolveBulk(mcpCoverage.gaps);
this.logger.info(`🚀 Automation complete: ${automationResults.successRate}% success rate`);
this.logger.info(`✅ Automated: ${automationResults.successful.length}`);
this.logger.info(`❌ Failed: ${automationResults.failed.length}`);
this.logger.info(`📋 Manual: ${automationResults.manual.length}`);
}
else {
// Dry run or automation disabled
automationResults = {
successful: [],
failed: [],
manual: mcpCoverage.gaps.map(req => ({
requirement: req,
status: 'manual_required',
manualSteps: ['Automation disabled - manual configuration required']
})),
totalTime: 0,
successRate: 0,
recommendations: ['Enable automation to attempt automatic resolution']
};
}
// Step 4: Generate manual guides for remaining gaps
let manualGuides = null;
const manualRequirements = [
...automationResults.failed.map(r => r.requirement),
...automationResults.manual.map(r => r.requirement)
];
if (manualRequirements.length > 0 && options.includeManualGuides !== false) {
this.logger.info(`📚 Step 4: Generating manual guides for ${manualRequirements.length} items...`);
manualGuides = manual_instructions_generator_1.ManualInstructionsGenerator.generateBulkInstructions(manualRequirements);
}
// Step 5: Build comprehensive result
const totalTime = Date.now() - startTime;
const result = this.buildGapAnalysisResult(objective, analysisId, startTime, requirementsAnalysis, mcpCoverage, automationResults, manualGuides, totalTime);
this.logger.info(`🎉 Gap Analysis complete in ${totalTime}ms`);
this.logger.info(`📊 Final Summary:`);
this.logger.info(` • Total Requirements: ${result.totalRequirements}`);
this.logger.info(` • MCP Coverage: ${result.mcpCoverage.coveragePercentage}%`);
this.logger.info(` • Automation Rate: ${result.summary.automationRate}%`);
this.logger.info(` • Manual Work Required: ${result.summary.requiresManualWork} items`);
return result;
}
catch (error) {
this.logger.error('❌ Gap Analysis failed:', error);
throw new Error(`Gap Analysis failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
/**
* Quick _analysis without resolution - useful for planning
*/
async analyzeOnly(objective) {
this.logger.info(`🔍 Quick _analysis for: "${objective}"`);
const _analysis = requirements_analyzer_1.RequirementsAnalyzer.analyzeObjective(objective);
const coverage = mcp_coverage_analyzer_1.McpCoverageAnalyzer.analyzeCoverage(_analysis.requirements);
let canAutomate = coverage.covered.length;
let requiresManual = coverage.gaps.length;
// Check automation capabilities for gaps
for (const gap of coverage.gaps) {
if (this.autoResolutionEngine.canAutoResolve(gap)) {
canAutomate++;
requiresManual--;
}
}
const estimatedTime = this.estimateTotalTime(_analysis.requirements, canAutomate, requiresManual);
return {
requirements: _analysis.requirements,
coverage,
canAutomate,
requiresManual,
estimatedTime
};
}
/**
* Get detailed _analysis for a specific requirement type
*/
analyzeRequirementType(requirementType) {
const mcpTools = mcp_coverage_analyzer_1.McpCoverageAnalyzer.getAvailableTools(requirementType);
const automationStrategies = this.autoResolutionEngine.getResolutionStrategies(requirementType);
return {
mcpTools: mcpTools.map(tool => tool.tool),
automationStrategies: automationStrategies.map(strategy => strategy.automationMethod),
manualSteps: automationStrategies.flatMap(strategy => strategy.fallbackInstructions),
riskLevel: automationStrategies[0]?.riskLevel || 'medium'
};
}
// Private helper methods
createEmptyResult(objective, analysisId, startTime) {
return {
objective,
analysisId,
timestamp: startTime,
requirements: [],
totalRequirements: 0,
mcpCoverage: {
covered: [],
gaps: [],
partialCoverage: [],
coveragePercentage: 100,
recommendations: ['No specific ServiceNow requirements detected in objective']
},
automationResults: {
successful: [],
failed: [],
manual: [],
totalTime: 0,
successRate: 100,
recommendations: ['Consider more specific ServiceNow requirements']
},
manualGuides: null,
summary: {
totalTime: Date.now() - startTime,
automationRate: 100,
successfulAutomation: 0,
requiresManualWork: 0,
completionPercentage: 100
},
nextSteps: {
automated: [],
manual: ['Refine objective with specific ServiceNow requirements'],
recommendations: ['Use more specific ServiceNow terminology in objective'],
risks: []
},
executionPlan: []
};
}
buildGapAnalysisResult(objective, analysisId, startTime, requirementsAnalysis, mcpCoverage, automationResults, manualGuides, totalTime) {
const totalRequirements = requirementsAnalysis.requirements.length;
const automationRate = totalRequirements > 0
? Math.round(((automationResults.successful.length) / totalRequirements) * 100)
: 100;
const completionPercentage = totalRequirements > 0
? Math.round(((mcpCoverage.covered.length + automationResults.successful.length) / totalRequirements) * 100)
: 100;
return {
objective,
analysisId,
timestamp: startTime,
requirements: requirementsAnalysis.requirements,
totalRequirements,
mcpCoverage,
automationResults,
manualGuides,
summary: {
totalTime,
automationRate,
successfulAutomation: automationResults.successful.length,
requiresManualWork: automationResults.failed.length + automationResults.manual.length,
completionPercentage
},
nextSteps: this.generateNextSteps(mcpCoverage, automationResults, manualGuides),
executionPlan: this.generateExecutionPlan(mcpCoverage, automationResults, manualGuides)
};
}
generateNextSteps(mcpCoverage, automationResults, manualGuides) {
const automated = [];
const manual = [];
const recommendations = [];
const risks = [];
// MCP-covered items
if (mcpCoverage.covered.length > 0) {
automated.push(`✅ ${mcpCoverage.covered.length} items fully covered by MCP tools`);
}
// Successfully automated items
if (automationResults.successful.length > 0) {
automated.push(`🤖 ${automationResults.successful.length} gaps automatically resolved`);
}
// Failed automation items
if (automationResults.failed.length > 0) {
manual.push(`❌ ${automationResults.failed.length} automation attempts failed - manual setup required`);
recommendations.push('Review failed automation attempts and adjust permissions or configurations');
}
// Manual-only items
if (automationResults.manual.length > 0) {
manual.push(`📋 ${automationResults.manual.length} items require manual configuration`);
}
// Manual guides available
if (manualGuides) {
manual.push(`📚 Detailed manual guides available for ${manualGuides.guides.length} configurations`);
}
// Recommendations from sub-systems
recommendations.push(...mcpCoverage.recommendations);
recommendations.push(...automationResults.recommendations);
// Risk identification
if (manualGuides?.overallRisks) {
risks.push(...manualGuides.overallRisks);
}
// Add strategic recommendations
const automationRate = automationResults.successful.length /
(automationResults.successful.length + automationResults.failed.length + automationResults.manual.length);
if (automationRate < 0.5) {
recommendations.push('💡 Consider enabling auto-permissions to increase automation success rate');
}
if (manual.length > automated.length) {
recommendations.push('🔧 Significant manual work required - consider phased implementation approach');
}
return { automated, manual, recommendations, risks };
}
generateExecutionPlan(mcpCoverage, automationResults, manualGuides) {
const plan = [];
// Phase 1: MCP Tool Deployment
if (mcpCoverage.covered.length > 0) {
plan.push({
phase: 'Phase 1: MCP Tool Deployment',
description: 'Deploy artifacts using standard MCP tools',
estimatedTime: `${mcpCoverage.covered.length * 3} minutes`,
status: 'pending',
actions: mcpCoverage.covered.map(req => `Deploy ${req.type}: ${req.name}`)
});
}
// Phase 2: Automated Gap Resolution
if (automationResults.successful.length > 0) {
plan.push({
phase: 'Phase 2: Automated Gap Resolution',
description: 'Automatically resolve configuration gaps',
estimatedTime: `${automationResults.totalTime}ms`,
status: 'completed',
actions: automationResults.successful.map(res => `✅ Automated: ${res.requirement.type} - ${res.requirement.name}`)
});
}
// Phase 3: Manual Configuration
const manualItems = automationResults.failed.length + automationResults.manual.length;
if (manualItems > 0) {
plan.push({
phase: 'Phase 3: Manual Configuration',
description: 'Complete remaining configurations manually',
estimatedTime: manualGuides?.executionOrder.reduce((total, phase) => total + parseInt(phase.estimatedTime.match(/\d+/)?.[0] || '10'), 0) + ' minutes' || `${manualItems * 15} minutes`,
status: 'manual_required',
actions: [
...automationResults.failed.map(res => `❌ Manual fix needed: ${res.requirement.name}`),
...automationResults.manual.map(res => `📋 Manual setup: ${res.requirement.name}`)
]
});
}
return plan;
}
estimateTotalTime(requirements, canAutomate, requiresManual) {
const automationTime = canAutomate * 2; // 2 minutes per automated item
const manualTime = requiresManual * 15; // 15 minutes per manual item
const totalMinutes = automationTime + manualTime;
if (totalMinutes < 60) {
return `${totalMinutes} minutes`;
}
else {
const hours = Math.floor(totalMinutes / 60);
const minutes = totalMinutes % 60;
return `${hours}h ${minutes}m`;
}
}
}
exports.GapAnalysisEngine = GapAnalysisEngine;
/**
* Convenience function for quick gap analysis
*/
async function analyzeGaps(objective, mcpTools, logger, options = {}) {
const engine = new GapAnalysisEngine(mcpTools, logger, options.autoPermissions);
return engine.analyzeAndResolve(objective, options);
}
/**
* Quick _analysis without resolution
*/
function quickAnalyze(objective) {
const _analysis = requirements_analyzer_1.RequirementsAnalyzer.analyzeObjective(objective);
const coverage = mcp_coverage_analyzer_1.McpCoverageAnalyzer.analyzeCoverage(_analysis.requirements);
let estimatedComplexity = 'simple';
if (_analysis.requirements.length > 10 || coverage.coveragePercentage < 50) {
estimatedComplexity = 'complex';
}
else if (_analysis.requirements.length > 5 || coverage.coveragePercentage < 80) {
estimatedComplexity = 'moderate';
}
return {
requirements: _analysis.requirements,
coverage,
estimatedComplexity
};
}
//# sourceMappingURL=gap-analysis-engine.js.map