ai-debug-local-mcp
Version:
🎯 ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh
427 lines • 15.9 kB
JavaScript
/**
* Human Escalation Framework
* Implements Philip's concept of "knowing what it doesn't know" and bringing humans into the loop
*/
import { EventEmitter } from 'events';
/**
* Human Escalation Manager
* Intelligently determines when to escalate to humans and manages the escalation process
*/
export class HumanEscalationManager extends EventEmitter {
activeEscalations = new Map();
escalationHistory = [];
autoTimeouts = new Map();
// Learning system - tracks what types of escalations users typically approve/reject
userPreferences = new Map(); // escalation type -> approval rate
constructor() {
super();
}
/**
* Determine if a situation requires human escalation
* Core intelligence: "knowing what it doesn't know"
*/
shouldEscalate(context, attemptedActions = []) {
// Knowledge gap detection
if (this.detectKnowledgeGap(context, attemptedActions)) {
return {
type: 'knowledge_gap',
description: 'Insufficient information or expertise to proceed safely',
severity: 'medium',
autoResolvable: false
};
}
// Permission requirements
if (this.requiresPermission(context)) {
return {
type: 'permission_needed',
description: 'Action requires explicit user authorization',
severity: this.calculatePermissionSeverity(context),
autoResolvable: false
};
}
// Ambiguous context
if (this.hasAmbiguousContext(context)) {
return {
type: 'ambiguous_context',
description: 'Multiple valid approaches exist, user preference needed',
severity: 'low',
autoResolvable: true
};
}
// Critical decisions
if (this.isCriticalDecision(context)) {
return {
type: 'critical_decision',
description: 'Decision has significant impact and requires human judgment',
severity: 'high',
autoResolvable: false
};
}
// Error recovery
if (this.needsErrorRecoveryGuidance(context, attemptedActions)) {
return {
type: 'error_recovery',
description: 'Unable to recover from errors automatically',
severity: 'medium',
autoResolvable: true
};
}
// Resource access issues
if (this.lacksResourceAccess(context)) {
return {
type: 'resource_access',
description: 'Required resources or credentials are not available',
severity: 'medium',
autoResolvable: false
};
}
return null; // No escalation needed
}
/**
* Create an escalation request
*/
async createEscalation(reason, context, autoTimeoutMs) {
const escalationId = `escalation-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const suggestedActions = this.generateSuggestedActions(reason, context);
const escalationRequest = {
id: escalationId,
timestamp: new Date(),
reason,
context,
suggestedActions,
waitingForResponse: true,
autoTimeoutMs,
fallbackAction: this.determineFallbackAction(reason, context)
};
this.activeEscalations.set(escalationId, escalationRequest);
// Set up auto-timeout if specified
if (autoTimeoutMs) {
const timeout = setTimeout(() => {
this.handleAutoTimeout(escalationId);
}, autoTimeoutMs);
this.autoTimeouts.set(escalationId, timeout);
}
// Emit escalation event
this.emit('escalation_created', escalationRequest);
return escalationId;
}
/**
* Handle escalation response from human
*/
async handleEscalationResponse(response) {
const escalation = this.activeEscalations.get(response.escalationId);
if (!escalation) {
throw new Error(`Escalation ${response.escalationId} not found`);
}
// Clear auto-timeout
const timeout = this.autoTimeouts.get(response.escalationId);
if (timeout) {
clearTimeout(timeout);
this.autoTimeouts.delete(response.escalationId);
}
// Mark as resolved
escalation.waitingForResponse = false;
this.activeEscalations.delete(response.escalationId);
this.escalationHistory.push(escalation);
// Learn from user response
this.learnFromResponse(escalation, response);
// Emit response event
this.emit('escalation_resolved', { escalation, response });
}
/**
* Get pending escalations
*/
getPendingEscalations() {
return Array.from(this.activeEscalations.values());
}
/**
* Get escalation by ID
*/
getEscalation(escalationId) {
return this.activeEscalations.get(escalationId);
}
/**
* INTELLIGENCE: Detect knowledge gaps
*/
detectKnowledgeGap(context, attemptedActions) {
// Repeated failed attempts suggest knowledge gap
if (attemptedActions.length > 3 && context.errorHistory.length > 2) {
return true;
}
// Complex projects with beginner users often need guidance
if (context.projectComplexity === 'complex' && context.userExperience === 'beginner') {
return true;
}
// Multiple similar errors suggest systematic issue
const uniqueErrors = new Set(context.errorHistory);
if (context.errorHistory.length > 0 && uniqueErrors.size === 1) {
return true;
}
return false;
}
/**
* INTELLIGENCE: Determine if permission is required
*/
requiresPermission(context) {
// File modifications always require permission for beginners
if (context.userExperience === 'beginner' && context.toolName?.includes('file')) {
return true;
}
// System modifications require permission
if (context.toolName?.includes('system') || context.toolName?.includes('install')) {
return true;
}
// Network operations in production-like contexts
if (context.sessionId?.includes('prod') || context.sessionId?.includes('deploy')) {
return true;
}
return false;
}
/**
* INTELLIGENCE: Detect ambiguous context
*/
hasAmbiguousContext(context) {
// Multiple frameworks detected
if (context.lastActions.some(action => action.includes('framework')) &&
context.lastActions.length > 1) {
return true;
}
// Multiple possible solutions for the same problem
if (context.lastActions.filter(action => action.includes('suggest')).length > 2) {
return true;
}
return false;
}
/**
* INTELLIGENCE: Identify critical decisions
*/
isCriticalDecision(context) {
// Database operations
if (context.toolName?.includes('database') || context.toolName?.includes('migration')) {
return true;
}
// Production deployments
if (context.sessionId?.includes('production') || context.toolName?.includes('deploy')) {
return true;
}
// Security-related operations
if (context.toolName?.includes('security') || context.toolName?.includes('auth')) {
return true;
}
return false;
}
/**
* INTELLIGENCE: Determine if error recovery guidance is needed
*/
needsErrorRecoveryGuidance(context, attemptedActions) {
// Too many recovery attempts
if (attemptedActions.filter(action => action.includes('retry') || action.includes('recover')).length > 3) {
return true;
}
// Cascading errors
if (context.errorHistory.length > 3 &&
context.errorHistory[context.errorHistory.length - 1] !== context.errorHistory[0]) {
return true;
}
return false;
}
/**
* INTELLIGENCE: Check for resource access issues
*/
lacksResourceAccess(context) {
// Common access-related errors
const accessErrors = ['permission denied', 'unauthorized', 'not found', 'timeout', 'connection refused'];
return context.errorHistory.some(error => accessErrors.some(accessError => error.toLowerCase().includes(accessError)));
}
/**
* Calculate permission severity based on context
*/
calculatePermissionSeverity(context) {
if (context.toolName?.includes('delete') || context.toolName?.includes('remove')) {
return 'critical';
}
if (context.toolName?.includes('system') || context.toolName?.includes('install')) {
return 'high';
}
if (context.userExperience === 'beginner') {
return 'medium';
}
return 'low';
}
/**
* Generate suggested actions for human
*/
generateSuggestedActions(reason, context) {
const actions = [];
switch (reason.type) {
case 'knowledge_gap':
actions.push({
id: 'provide_context',
description: 'Provide additional context about the issue',
type: 'context_clarification',
riskLevel: 'low',
estimatedTime: '2-3 minutes'
});
actions.push({
id: 'suggest_approach',
description: 'Suggest a specific approach to take',
type: 'user_input',
riskLevel: 'low',
estimatedTime: '5 minutes'
});
break;
case 'permission_needed':
actions.push({
id: 'grant_permission',
description: `Allow ${context.toolName} to proceed`,
type: 'permission_grant',
riskLevel: this.mapSeverityToRisk(reason.severity),
estimatedTime: '30 seconds'
});
actions.push({
id: 'deny_permission',
description: 'Deny permission and suggest alternative',
type: 'tool_selection',
riskLevel: 'low',
estimatedTime: '1 minute'
});
break;
case 'ambiguous_context':
actions.push({
id: 'choose_approach',
description: 'Choose preferred approach from options',
type: 'user_input',
riskLevel: 'low',
estimatedTime: '1-2 minutes'
});
break;
case 'critical_decision':
actions.push({
id: 'review_and_approve',
description: 'Review the proposed action and approve if safe',
type: 'permission_grant',
riskLevel: 'high',
estimatedTime: '5-10 minutes'
});
actions.push({
id: 'manual_intervention',
description: 'Handle this manually to ensure safety',
type: 'manual_intervention',
riskLevel: 'low',
estimatedTime: '10-30 minutes'
});
break;
case 'error_recovery':
actions.push({
id: 'provide_credentials',
description: 'Provide missing credentials or access',
type: 'user_input',
riskLevel: 'medium',
estimatedTime: '2-5 minutes'
});
actions.push({
id: 'reset_environment',
description: 'Reset debugging environment and start fresh',
type: 'tool_selection',
riskLevel: 'medium',
estimatedTime: '5 minutes'
});
break;
case 'resource_access':
actions.push({
id: 'provide_access',
description: 'Provide required credentials or permissions',
type: 'user_input',
riskLevel: 'medium',
estimatedTime: '3-5 minutes'
});
break;
}
// Always provide a "continue autonomously" option for non-critical situations
if (reason.severity !== 'critical') {
actions.push({
id: 'continue_autonomous',
description: 'Continue without human intervention (use best judgment)',
type: 'permission_grant',
riskLevel: 'medium',
estimatedTime: 'immediate'
});
}
return actions;
}
/**
* Determine fallback action for auto-timeout
*/
determineFallbackAction(reason, context) {
if (reason.autoResolvable) {
return 'proceed_with_safe_default';
}
if (context.timeConstraint === 'urgent') {
return 'continue_with_minimal_risk_approach';
}
return 'pause_and_wait_for_human';
}
/**
* Handle auto-timeout
*/
handleAutoTimeout(escalationId) {
const escalation = this.activeEscalations.get(escalationId);
if (!escalation)
return;
// Execute fallback action
const fallbackResponse = {
escalationId,
customAction: escalation.fallbackAction,
continueAutonomously: true
};
this.emit('escalation_auto_resolved', { escalation, fallbackResponse });
this.handleEscalationResponse(fallbackResponse);
}
/**
* Learn from user responses to improve future escalation decisions
*/
learnFromResponse(escalation, response) {
const reasonType = escalation.reason.type;
const approved = response.continueAutonomously || response.selectedActionId === 'grant_permission';
const currentRate = this.userPreferences.get(reasonType) || 0.5;
const learningRate = 0.1;
const newRate = approved ?
currentRate + (1 - currentRate) * learningRate :
currentRate - currentRate * learningRate;
this.userPreferences.set(reasonType, newRate);
}
/**
* Get escalation statistics for learning insights
*/
getEscalationStats() {
const total = this.escalationHistory.length;
const byType = {};
let totalResponseTime = 0;
let autoResolved = 0;
for (const escalation of this.escalationHistory) {
const type = escalation.reason.type;
byType[type] = (byType[type] || 0) + 1;
if (escalation.autoTimeoutMs) {
autoResolved++;
}
}
return {
totalEscalations: total,
byType,
averageResponseTime: total > 0 ? totalResponseTime / total : 0,
autoResolvedRate: total > 0 ? autoResolved / total : 0
};
}
/**
* Map severity to risk level
*/
mapSeverityToRisk(severity) {
switch (severity) {
case 'critical':
case 'high': return 'high';
case 'medium': return 'medium';
default: return 'low';
}
}
}
//# sourceMappingURL=escalation-manager.js.map