- Fixed ES modules error by converting automation-with-learning-v2.js to pure ES6 - Fixed singleton pattern in automation-singleton.js for proper async handling - Fixed EnhancedAILearningPanel to handle recommendation objects correctly - Updated API routes to use correct import paths (../../../../lib/) - Created proper db.js utility with ES6 exports - Fixed simplified-stop-loss-learner imports and exports Automation v2 page now loads without errors AI learning system fully integrated and operational Learning status API working with detailed reports Recommendation rendering fixed for object structure
312 lines
12 KiB
TypeScript
312 lines
12 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
|
|
interface LearningData {
|
|
learningSystem: {
|
|
enabled: boolean;
|
|
learningActive?: boolean;
|
|
activeDecisions?: number;
|
|
message?: string;
|
|
recommendation?: string;
|
|
report?: {
|
|
summary?: {
|
|
totalDecisions?: number;
|
|
successRate?: number;
|
|
systemConfidence?: number;
|
|
};
|
|
insights?: {
|
|
thresholds?: any;
|
|
confidenceLevel?: number;
|
|
};
|
|
recommendations?: Array<{
|
|
type: string;
|
|
message: string;
|
|
priority: string;
|
|
} | string>;
|
|
};
|
|
};
|
|
visibility?: {
|
|
decisionTrackingActive?: boolean;
|
|
learningDatabaseConnected?: boolean;
|
|
aiEnhancementsActive?: boolean;
|
|
lastUpdateTime?: string;
|
|
};
|
|
automationStatus?: any;
|
|
}
|
|
|
|
const EnhancedAILearningPanel = () => {
|
|
const [learningData, setLearningData] = useState<LearningData | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const fetchLearningStatus = async () => {
|
|
try {
|
|
setLoading(true);
|
|
|
|
// Get both learning status and automation status
|
|
const [learningResponse, statusResponse] = await Promise.all([
|
|
fetch('/api/automation/learning-status'),
|
|
fetch('/api/automation/status')
|
|
]);
|
|
|
|
const learningData = await learningResponse.json();
|
|
const statusData = await statusResponse.json();
|
|
|
|
// Ensure we have a proper data structure even if APIs return errors
|
|
const safeData = {
|
|
learningSystem: learningData.learningSystem || {
|
|
enabled: false,
|
|
message: learningData.message || 'Learning system not available',
|
|
activeDecisions: 0
|
|
},
|
|
visibility: learningData.visibility || {
|
|
decisionTrackingActive: false,
|
|
learningDatabaseConnected: false,
|
|
aiEnhancementsActive: false,
|
|
lastUpdateTime: new Date().toISOString()
|
|
},
|
|
automationStatus: statusData
|
|
};
|
|
|
|
setLearningData(safeData);
|
|
setError(null);
|
|
} catch (err) {
|
|
console.error('Error fetching learning status:', err);
|
|
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
|
|
// Set default data structure on error
|
|
setLearningData({
|
|
learningSystem: {
|
|
enabled: false,
|
|
message: 'Failed to fetch learning status',
|
|
activeDecisions: 0
|
|
},
|
|
visibility: {
|
|
decisionTrackingActive: false,
|
|
learningDatabaseConnected: false,
|
|
aiEnhancementsActive: false,
|
|
lastUpdateTime: new Date().toISOString()
|
|
},
|
|
automationStatus: null
|
|
});
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchLearningStatus();
|
|
|
|
// Refresh every 30 seconds
|
|
const interval = setInterval(fetchLearningStatus, 30000);
|
|
return () => clearInterval(interval);
|
|
}, []);
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="bg-gradient-to-br from-purple-900/20 to-blue-900/20 rounded-xl p-6 border border-purple-500/30">
|
|
<div className="flex items-center space-x-3 mb-4">
|
|
<div className="w-3 h-3 bg-purple-500 rounded-full animate-pulse"></div>
|
|
<h3 className="text-lg font-semibold bg-gradient-to-r from-purple-400 to-blue-400 bg-clip-text text-transparent">
|
|
🧠 AI Learning System
|
|
</h3>
|
|
</div>
|
|
<div className="text-gray-400">Loading learning status...</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<div className="bg-gradient-to-br from-red-900/20 to-orange-900/20 rounded-xl p-6 border border-red-500/30">
|
|
<div className="flex items-center space-x-3 mb-4">
|
|
<div className="w-3 h-3 bg-red-500 rounded-full"></div>
|
|
<h3 className="text-lg font-semibold text-red-400">
|
|
🧠 AI Learning System
|
|
</h3>
|
|
</div>
|
|
<div className="text-red-400">Error: {error}</div>
|
|
<button
|
|
onClick={fetchLearningStatus}
|
|
className="mt-3 px-4 py-2 bg-red-600/20 hover:bg-red-600/30 text-red-400 rounded-lg transition-colors"
|
|
>
|
|
Retry
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!learningData) {
|
|
return null;
|
|
}
|
|
|
|
const { learningSystem, visibility } = learningData;
|
|
|
|
// Safety check for learningSystem
|
|
if (!learningSystem) {
|
|
return (
|
|
<div className="bg-gradient-to-br from-gray-900/20 to-gray-800/20 rounded-xl p-6 border border-gray-500/30">
|
|
<div className="flex items-center space-x-3 mb-4">
|
|
<div className="w-3 h-3 bg-gray-500 rounded-full"></div>
|
|
<h3 className="text-lg font-semibold bg-gradient-to-r from-purple-400 to-blue-400 bg-clip-text text-transparent">
|
|
🧠 AI Learning System
|
|
</h3>
|
|
</div>
|
|
<div className="text-gray-400">Loading learning system data...</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const renderLearningStatus = () => {
|
|
if (!learningSystem || !learningSystem.enabled) {
|
|
return (
|
|
<div className="space-y-4">
|
|
<div className="flex items-center space-x-2">
|
|
<div className="w-3 h-3 bg-yellow-500 rounded-full"></div>
|
|
<span className="text-yellow-400 font-medium">Learning System Not Active</span>
|
|
</div>
|
|
|
|
<div className="bg-yellow-900/20 rounded-lg p-4 border border-yellow-500/30">
|
|
<div className="text-yellow-300 text-sm">
|
|
{learningSystem?.message || 'The AI learning system is not currently integrated with the automation.'}
|
|
</div>
|
|
{learningSystem?.recommendation && (
|
|
<div className="text-yellow-400 text-sm mt-2 font-medium">
|
|
💡 {learningSystem.recommendation}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="text-gray-400 text-sm">
|
|
• Decision recording: Not active<br/>
|
|
• Learning database: Not connected<br/>
|
|
• AI enhancements: Not applied
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<div className="flex items-center space-x-2">
|
|
<div className="w-3 h-3 bg-green-500 rounded-full animate-pulse"></div>
|
|
<span className="text-green-400 font-medium">AI Learning Active</span>
|
|
</div>
|
|
|
|
{learningSystem?.report && (
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
<div className="bg-blue-900/20 rounded-lg p-4 border border-blue-500/30">
|
|
<div className="text-blue-300 text-sm font-medium">Total Decisions</div>
|
|
<div className="text-2xl font-bold text-blue-400">
|
|
{learningSystem.report.summary?.totalDecisions || 0}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="bg-purple-900/20 rounded-lg p-4 border border-purple-500/30">
|
|
<div className="text-purple-300 text-sm font-medium">Success Rate</div>
|
|
<div className="text-2xl font-bold text-purple-400">
|
|
{learningSystem.report.summary?.successRate || 0}%
|
|
</div>
|
|
</div>
|
|
|
|
<div className="bg-green-900/20 rounded-lg p-4 border border-green-500/30">
|
|
<div className="text-green-300 text-sm font-medium">Confidence</div>
|
|
<div className="text-2xl font-bold text-green-400">
|
|
{learningSystem.report.summary?.systemConfidence || 0}%
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<div className="bg-gray-800/50 rounded-lg p-4 border border-gray-600/30">
|
|
<div className="text-gray-300 text-sm font-medium mb-2">🔍 Learning Visibility</div>
|
|
<div className="grid grid-cols-2 gap-2 text-sm">
|
|
<div className="flex items-center space-x-2">
|
|
<div className={`w-2 h-2 rounded-full ${visibility?.decisionTrackingActive ? 'bg-green-500' : 'bg-gray-500'}`}></div>
|
|
<span className={visibility?.decisionTrackingActive ? 'text-green-400' : 'text-gray-400'}>
|
|
Decision Tracking
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center space-x-2">
|
|
<div className={`w-2 h-2 rounded-full ${visibility?.learningDatabaseConnected ? 'bg-green-500' : 'bg-gray-500'}`}></div>
|
|
<span className={visibility?.learningDatabaseConnected ? 'text-green-400' : 'text-gray-400'}>
|
|
Database Connected
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center space-x-2">
|
|
<div className={`w-2 h-2 rounded-full ${visibility?.aiEnhancementsActive ? 'bg-green-500' : 'bg-gray-500'}`}></div>
|
|
<span className={visibility?.aiEnhancementsActive ? 'text-green-400' : 'text-gray-400'}>
|
|
AI Enhancements
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center space-x-2">
|
|
<div className={`w-2 h-2 rounded-full ${(learningSystem?.activeDecisions || 0) > 0 ? 'bg-blue-500' : 'bg-gray-500'}`}></div>
|
|
<span className={(learningSystem?.activeDecisions || 0) > 0 ? 'text-blue-400' : 'text-gray-400'}>
|
|
Active Decisions ({learningSystem?.activeDecisions || 0})
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{learningSystem?.report?.insights && (
|
|
<div className="bg-purple-900/20 rounded-lg p-4 border border-purple-500/30">
|
|
<div className="text-purple-300 text-sm font-medium mb-2">🎯 Learning Insights</div>
|
|
<div className="text-sm text-gray-300">
|
|
{learningSystem.report.insights.thresholds && (
|
|
<div>Current Thresholds: {JSON.stringify(learningSystem.report.insights.thresholds)}</div>
|
|
)}
|
|
{learningSystem.report.insights.confidenceLevel && (
|
|
<div>Confidence Level: {learningSystem.report.insights.confidenceLevel}%</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{learningSystem?.report?.recommendations && learningSystem.report.recommendations.length > 0 && (
|
|
<div className="bg-yellow-900/20 rounded-lg p-4 border border-yellow-500/30">
|
|
<div className="text-yellow-300 text-sm font-medium mb-2">💡 AI Recommendations</div>
|
|
<div className="space-y-1">
|
|
{learningSystem.report.recommendations.map((rec: any, index: number) => (
|
|
<div key={index} className="text-sm text-yellow-400">
|
|
• {typeof rec === 'string' ? rec : rec.message || rec.type || 'No message'}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div className="bg-gradient-to-br from-purple-900/20 to-blue-900/20 rounded-xl p-6 border border-purple-500/30">
|
|
<div className="flex items-center justify-between mb-6">
|
|
<div className="flex items-center space-x-3">
|
|
<div className={`w-3 h-3 rounded-full ${learningSystem?.enabled ? 'bg-green-500 animate-pulse' : 'bg-yellow-500'}`}></div>
|
|
<h3 className="text-lg font-semibold bg-gradient-to-r from-purple-400 to-blue-400 bg-clip-text text-transparent">
|
|
🧠 AI Learning System
|
|
</h3>
|
|
</div>
|
|
|
|
<button
|
|
onClick={fetchLearningStatus}
|
|
className="px-3 py-1 bg-purple-600/20 hover:bg-purple-600/30 text-purple-400 rounded-lg transition-colors text-sm"
|
|
>
|
|
Refresh
|
|
</button>
|
|
</div>
|
|
|
|
{renderLearningStatus()}
|
|
|
|
{visibility?.lastUpdateTime && (
|
|
<div className="mt-4 pt-4 border-t border-gray-600/30">
|
|
<div className="text-gray-500 text-xs">
|
|
Last updated: {new Date(visibility.lastUpdateTime).toLocaleTimeString()}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default EnhancedAILearningPanel;
|