task-engine-ai-core
Version:
Revolutionary AI-driven task management system with complete transformation trilogy: Frontend v0.1.0, Backend v0.2.0, CLI v0.3.0 - Enterprise-grade performance with 95% improvements
378 lines (335 loc) • 12.6 kB
JavaScript
/**
* Active Agent Detection and Routing System
*
* This module detects when an active AI agent is present in the MCP session
* and routes task operations accordingly, eliminating redundant AI generation loops.
*/
import { logger } from '../utils/logger-utils.js';
/**
* Active Agent Detection Results
*/
export const AGENT_DETECTION_RESULTS = {
ACTIVE_AGENT_PRESENT: 'active_agent_present',
NO_AGENT_DETECTED: 'no_agent_detected',
DETECTION_ERROR: 'detection_error'
};
/**
* Routing Strategies
*/
export const ROUTING_STRATEGIES = {
ACTIVE_AGENT: 'active_agent',
MANUAL_CREATION: 'manual_creation',
EXTERNAL_AI: 'external_ai',
FALLBACK: 'fallback'
};
/**
* Active Agent Detector Class
*
* Handles detection of active AI agents in MCP sessions and determines
* the appropriate routing strategy for task operations.
*/
export class ActiveAgentDetector {
constructor(options = {}) {
this.options = {
enableLogging: options.enableLogging ?? true,
fallbackStrategy: options.fallbackStrategy ?? ROUTING_STRATEGIES.MANUAL_CREATION,
detectionTimeout: options.detectionTimeout ?? 5000,
...options
};
this.detectionCache = new Map();
this.sessionState = new Map();
}
/**
* Detect if an active AI agent is present in the session
* @param {Object} session - MCP session object
* @param {Object} context - Additional context information
* @returns {Promise<Object>} Detection result with routing strategy
*/
async detectActiveAgent(session, context = {}) {
try {
if (this.options.enableLogging) {
logger.info('Starting active agent detection', {
sessionId: session?.id,
contextKeys: Object.keys(context)
});
}
// Check cache first for performance
const cacheKey = this.generateCacheKey(session, context);
if (this.detectionCache.has(cacheKey)) {
const cached = this.detectionCache.get(cacheKey);
if (this.options.enableLogging) {
logger.debug('Using cached detection result', { cacheKey, result: cached.result });
}
return cached;
}
// Perform detection
const detectionResult = await this.performDetection(session, context);
// Cache the result
this.detectionCache.set(cacheKey, detectionResult);
// Update session state
this.updateSessionState(session, detectionResult);
if (this.options.enableLogging) {
logger.info('Active agent detection completed', {
result: detectionResult.result,
strategy: detectionResult.strategy,
confidence: detectionResult.confidence
});
}
return detectionResult;
} catch (error) {
logger.error('Error during active agent detection', { error: error.message });
return this.createErrorResult(error);
}
}
/**
* Perform the actual detection logic
* @param {Object} session - MCP session object
* @param {Object} context - Additional context information
* @returns {Promise<Object>} Detection result
*/
async performDetection(session, context) {
const detectionChecks = [
this.checkMCPSessionCapabilities(session),
this.checkClientCapabilities(session),
this.checkSamplingCapabilities(session),
this.checkContextualIndicators(context)
];
const results = await Promise.all(detectionChecks);
const confidence = this.calculateConfidence(results);
// Determine if active agent is present based on checks
const hasActiveAgent = results.some(result => result.hasAgent) && confidence > 0.7;
if (hasActiveAgent) {
return this.createSuccessResult(
AGENT_DETECTION_RESULTS.ACTIVE_AGENT_PRESENT,
ROUTING_STRATEGIES.ACTIVE_AGENT,
confidence,
{ checks: results }
);
} else {
return this.createSuccessResult(
AGENT_DETECTION_RESULTS.NO_AGENT_DETECTED,
this.options.fallbackStrategy,
confidence,
{ checks: results }
);
}
}
/**
* Check MCP session capabilities for active agent indicators
* @param {Object} session - MCP session object
* @returns {Object} Check result
*/
checkMCPSessionCapabilities(session) {
try {
const hasSession = !!session;
const hasCapabilities = !!(session?.capabilities);
const hasClientInfo = !!(session?.clientInfo);
return {
name: 'mcp_session',
hasAgent: hasSession && hasCapabilities,
confidence: hasSession ? (hasCapabilities ? 0.8 : 0.4) : 0.0,
details: { hasSession, hasCapabilities, hasClientInfo }
};
} catch (error) {
return { name: 'mcp_session', hasAgent: false, confidence: 0.0, error: error.message };
}
}
/**
* Check client capabilities for sampling/AI features
* @param {Object} session - MCP session object
* @returns {Object} Check result
*/
checkClientCapabilities(session) {
try {
const clientCapabilities = session?.clientCapabilities;
const hasSampling = !!(clientCapabilities?.sampling);
const hasRoots = !!(clientCapabilities?.roots);
return {
name: 'client_capabilities',
hasAgent: hasSampling,
confidence: hasSampling ? 0.9 : (hasRoots ? 0.3 : 0.0),
details: { hasSampling, hasRoots, capabilities: clientCapabilities }
};
} catch (error) {
return { name: 'client_capabilities', hasAgent: false, confidence: 0.0, error: error.message };
}
}
/**
* Check for sampling capabilities (strong indicator of AI agent)
* @param {Object} session - MCP session object
* @returns {Object} Check result
*/
checkSamplingCapabilities(session) {
try {
const sampling = session?.clientCapabilities?.sampling;
const hasSampling = !!sampling;
return {
name: 'sampling_capabilities',
hasAgent: hasSampling,
confidence: hasSampling ? 1.0 : 0.0,
details: { sampling }
};
} catch (error) {
return { name: 'sampling_capabilities', hasAgent: false, confidence: 0.0, error: error.message };
}
}
/**
* Check contextual indicators for active agent presence
* @param {Object} context - Additional context information
* @returns {Object} Check result
*/
checkContextualIndicators(context) {
try {
const hasAIContext = !!(context.aiContext || context.agentContext);
const hasIntelligentRequest = this.isIntelligentRequest(context);
return {
name: 'contextual_indicators',
hasAgent: hasAIContext || hasIntelligentRequest,
confidence: hasAIContext ? 0.7 : (hasIntelligentRequest ? 0.5 : 0.0),
details: { hasAIContext, hasIntelligentRequest }
};
} catch (error) {
return { name: 'contextual_indicators', hasAgent: false, confidence: 0.0, error: error.message };
}
}
/**
* Determine if the request shows signs of intelligent processing
* @param {Object} context - Request context
* @returns {boolean} True if request appears to be from an AI agent
*/
isIntelligentRequest(context) {
const intelligentPatterns = [
/create.*task.*that.*demonstrates/i,
/implement.*comprehensive/i,
/analyze.*and.*generate/i,
/design.*system.*for/i
];
const requestText = context.prompt || context.description || '';
return intelligentPatterns.some(pattern => pattern.test(requestText));
}
/**
* Calculate overall confidence score from detection checks
* @param {Array} results - Array of check results
* @returns {number} Confidence score between 0 and 1
*/
calculateConfidence(results) {
if (!results.length) return 0.0;
const validResults = results.filter(r => typeof r.confidence === 'number');
if (!validResults.length) return 0.0;
// Weighted average with higher weight for more reliable checks
const weights = {
'sampling_capabilities': 0.4,
'client_capabilities': 0.3,
'mcp_session': 0.2,
'contextual_indicators': 0.1
};
let totalWeight = 0;
let weightedSum = 0;
validResults.forEach(result => {
const weight = weights[result.name] || 0.1;
weightedSum += result.confidence * weight;
totalWeight += weight;
});
return totalWeight > 0 ? weightedSum / totalWeight : 0.0;
}
/**
* Generate cache key for detection results
* @param {Object} session - MCP session object
* @param {Object} context - Additional context
* @returns {string} Cache key
*/
generateCacheKey(session, context) {
const sessionId = session?.id || 'no-session';
const contextHash = this.hashObject(context);
return `${sessionId}-${contextHash}`;
}
/**
* Simple hash function for objects
* @param {Object} obj - Object to hash
* @returns {string} Hash string
*/
hashObject(obj) {
return JSON.stringify(obj).split('').reduce((a, b) => {
a = ((a << 5) - a) + b.charCodeAt(0);
return a & a;
}, 0).toString(36);
}
/**
* Update session state with detection results
* @param {Object} session - MCP session object
* @param {Object} result - Detection result
*/
updateSessionState(session, result) {
if (session?.id) {
this.sessionState.set(session.id, {
lastDetection: Date.now(),
result: result.result,
strategy: result.strategy,
confidence: result.confidence
});
}
}
/**
* Create success result object
* @param {string} result - Detection result
* @param {string} strategy - Routing strategy
* @param {number} confidence - Confidence score
* @param {Object} metadata - Additional metadata
* @returns {Object} Success result
*/
createSuccessResult(result, strategy, confidence, metadata = {}) {
return {
success: true,
result,
strategy,
confidence,
timestamp: Date.now(),
metadata
};
}
/**
* Create error result object
* @param {Error} error - Error that occurred
* @returns {Object} Error result
*/
createErrorResult(error) {
return {
success: false,
result: AGENT_DETECTION_RESULTS.DETECTION_ERROR,
strategy: this.options.fallbackStrategy,
confidence: 0.0,
error: error.message,
timestamp: Date.now()
};
}
/**
* Clear detection cache
*/
clearCache() {
this.detectionCache.clear();
if (this.options.enableLogging) {
logger.debug('Active agent detection cache cleared');
}
}
/**
* Get session state for debugging
* @param {string} sessionId - Session ID
* @returns {Object|null} Session state
*/
getSessionState(sessionId) {
return this.sessionState.get(sessionId) || null;
}
}
/**
* Default instance for easy importing
*/
export const activeAgentDetector = new ActiveAgentDetector();
/**
* Convenience function for quick detection
* @param {Object} session - MCP session object
* @param {Object} context - Additional context
* @returns {Promise<Object>} Detection result
*/
export async function detectActiveAgent(session, context = {}) {
return activeAgentDetector.detectActiveAgent(session, context);
}