Files
llm-automation-docs-and-rem…/frontend/src/App_Enhanced.jsx
LLM Automation System 1ba5ce851d Initial commit: LLM Automation Docs & Remediation Engine v2.0
Features:
- Automated datacenter documentation generation
- MCP integration for device connectivity
- Auto-remediation engine with safety checks
- Multi-factor reliability scoring (0-100%)
- Human feedback learning loop
- Pattern recognition and continuous improvement
- Agentic chat support with AI
- API for ticket resolution
- Frontend React with Material-UI
- CI/CD pipelines (GitLab + Gitea)
- Docker & Kubernetes deployment
- Complete documentation and guides

v2.0 Highlights:
- Auto-remediation with write operations (disabled by default)
- Reliability calculator with 4-factor scoring
- Human feedback system for continuous learning
- Pattern-based progressive automation
- Approval workflow for critical actions
- Full audit trail and rollback capability
2025-10-17 23:47:28 +00:00

669 lines
20 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import {
AppBar, Toolbar, Typography, Container, Box, Paper,
TextField, Button, List, ListItem, ListItemText,
CircularProgress, Chip, Grid, Card, CardContent,
Tabs, Tab, Divider, IconButton, Switch, FormControlLabel,
Alert, AlertTitle, Dialog, DialogTitle, DialogContent,
DialogActions, Rating, LinearProgress, Tooltip
} from '@mui/material';
import {
Send as SendIcon,
ThumbUp, ThumbDown, Warning as WarningIcon,
CheckCircle, Info, Shield, Speed, TrendingUp
} from '@mui/icons-material';
import axios from 'axios';
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000';
function App() {
const [activeTab, setActiveTab] = useState(0);
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static" sx={{ bgcolor: '#1976d2' }}>
<Toolbar>
<Shield sx={{ mr: 2 }} />
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Datacenter AI System - Auto-Remediation Enabled
</Typography>
<Chip label="AI Powered" color="secondary" size="small" sx={{ mr: 1 }} />
<Chip label="v2.0" color="success" size="small" />
</Toolbar>
</AppBar>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs value={activeTab} onChange={(e, v) => setActiveTab(v)}>
<Tab label="Submit Ticket" />
<Tab label="Ticket Status" />
<Tab label="Feedback Center" />
<Tab label="Analytics" />
</Tabs>
</Box>
<Container maxWidth="xl" sx={{ mt: 4, mb: 4 }}>
{activeTab === 0 && <TicketSubmitInterface />}
{activeTab === 1 && <TicketStatusInterface />}
{activeTab === 2 && <FeedbackCenter />}
{activeTab === 3 && <AnalyticsDashboard />}
</Container>
</Box>
);
}
// Ticket Submit Interface with Auto-Remediation Toggle
function TicketSubmitInterface() {
const [ticketData, setTicketData] = useState({
ticket_id: '',
title: '',
description: '',
priority: 'medium',
category: '',
enable_auto_remediation: false // DEFAULT: DISABLED
});
const [loading, setLoading] = useState(false);
const [result, setResult] = useState(null);
const [showWarning, setShowWarning] = useState(false);
const submitTicket = async () => {
setLoading(true);
try {
const response = await axios.post(`${API_URL}/api/v1/tickets`, ticketData);
setResult(response.data);
// Poll for updates
const ticketId = response.data.ticket_id;
const pollInterval = setInterval(async () => {
const statusResponse = await axios.get(`${API_URL}/api/v1/tickets/${ticketId}`);
setResult(statusResponse.data);
if (statusResponse.data.status === 'resolved' ||
statusResponse.data.status === 'failed') {
clearInterval(pollInterval);
setLoading(false);
}
}, 3000);
} catch (error) {
console.error('Error:', error);
setLoading(false);
}
};
return (
<Grid container spacing={3}>
<Grid item xs={12} md={6}>
<Paper sx={{ p: 3 }}>
<Typography variant="h6" gutterBottom>
Submit Ticket for AI Resolution
</Typography>
<TextField
fullWidth
label="Ticket ID"
value={ticketData.ticket_id}
onChange={(e) => setTicketData({...ticketData, ticket_id: e.target.value})}
margin="normal"
/>
<TextField
fullWidth
label="Title"
value={ticketData.title}
onChange={(e) => setTicketData({...ticketData, title: e.target.value})}
margin="normal"
/>
<TextField
fullWidth
multiline
rows={4}
label="Problem Description"
value={ticketData.description}
onChange={(e) => setTicketData({...ticketData, description: e.target.value})}
margin="normal"
/>
<TextField
fullWidth
select
label="Category"
value={ticketData.category}
onChange={(e) => setTicketData({...ticketData, category: e.target.value})}
margin="normal"
SelectProps={{ native: true }}
>
<option value="">Select...</option>
<option value="network">Network</option>
<option value="server">Server</option>
<option value="storage">Storage</option>
<option value="security">Security</option>
<option value="backup">Backup</option>
</TextField>
<Divider sx={{ my: 2 }} />
<Box sx={{ bgcolor: '#fff3e0', p: 2, borderRadius: 1, mb: 2 }}>
<Box sx={{ display: 'flex', alignItems: 'center', mb: 1 }}>
<WarningIcon color="warning" sx={{ mr: 1 }} />
<Typography variant="subtitle2" color="warning.dark">
Auto-Remediation Control
</Typography>
</Box>
<FormControlLabel
control={
<Switch
checked={ticketData.enable_auto_remediation}
onChange={(e) => {
setTicketData({
...ticketData,
enable_auto_remediation: e.target.checked
});
if (e.target.checked) setShowWarning(true);
}}
color="warning"
/>
}
label={
<Typography variant="body2">
Enable Auto-Remediation (Write Operations)
</Typography>
}
/>
<Typography variant="caption" display="block" color="text.secondary">
When enabled, AI can automatically execute fixes on your infrastructure.
Default: DISABLED for safety. Only enable if you trust AI decisions.
</Typography>
</Box>
<Button
fullWidth
variant="contained"
onClick={submitTicket}
disabled={loading}
sx={{ mt: 2 }}
>
{loading ? <CircularProgress size={24} /> : 'Submit Ticket'}
</Button>
</Paper>
</Grid>
<Grid item xs={12} md={6}>
{result && <TicketResultDisplay result={result} />}
</Grid>
{/* Warning Dialog */}
<Dialog open={showWarning} onClose={() => setShowWarning(false)}>
<DialogTitle>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<WarningIcon color="warning" sx={{ mr: 1 }} />
Auto-Remediation Warning
</Box>
</DialogTitle>
<DialogContent>
<Alert severity="warning" sx={{ mb: 2 }}>
You are enabling auto-remediation. This means:
</Alert>
<List dense>
<ListItem>
<ListItemText
primary="✓ AI can execute WRITE operations on your infrastructure"
secondary="Includes: restarting services, modifying configs, scaling resources"
/>
</ListItem>
<ListItem>
<ListItemText
primary="✓ Actions are based on reliability scores and learned patterns"
secondary="Only high-confidence actions with ≥85% reliability are auto-executed"
/>
</ListItem>
<ListItem>
<ListItemText
primary="✓ All actions are logged and can be rolled back"
secondary="Safety checks and pre/post validation included"
/>
</ListItem>
<ListItem>
<ListItemText
primary="⚠️ Critical actions require human approval"
secondary="Destructive operations always need manual confirmation"
/>
</ListItem>
</List>
</DialogContent>
<DialogActions>
<Button onClick={() => setShowWarning(false)}>
I Understand
</Button>
</DialogActions>
</Dialog>
</Grid>
);
}
// Enhanced Ticket Result Display
function TicketResultDisplay({ result }) {
const getConfidenceColor = (level) => {
const colors = {
'very_high': 'success',
'high': 'info',
'medium': 'warning',
'low': 'error'
};
return colors[level] || 'default';
};
return (
<Paper sx={{ p: 3 }}>
<Typography variant="h6" gutterBottom>
Resolution & Analysis
</Typography>
<Box sx={{ mb: 2 }}>
<Chip
label={result.status}
color={result.status === 'resolved' ? 'success' : 'warning'}
sx={{ mr: 1 }}
/>
{result.auto_remediation_enabled && (
<Chip
icon={<Shield />}
label="Auto-Remediation Enabled"
color="warning"
size="small"
/>
)}
</Box>
{/* Reliability Scores */}
<Box sx={{ mb: 3 }}>
<Typography variant="subtitle2" gutterBottom>
AI Confidence & Reliability
</Typography>
<Box sx={{ mb: 2 }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', mb: 0.5 }}>
<Typography variant="body2">AI Confidence</Typography>
<Typography variant="body2" fontWeight="bold">
{(result.confidence_score * 100).toFixed(0)}%
</Typography>
</Box>
<LinearProgress
variant="determinate"
value={result.confidence_score * 100}
color="primary"
/>
</Box>
{result.reliability_score && (
<Box sx={{ mb: 2 }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', mb: 0.5 }}>
<Typography variant="body2">Reliability Score</Typography>
<Chip
label={result.confidence_level || 'calculating'}
color={getConfidenceColor(result.confidence_level)}
size="small"
/>
</Box>
<LinearProgress
variant="determinate"
value={result.reliability_score}
color={result.reliability_score >= 85 ? 'success' : 'warning'}
/>
<Typography variant="caption" color="text.secondary">
Based on: AI confidence, historical success, feedback, patterns
</Typography>
</Box>
)}
</Box>
{/* Resolution */}
<Typography variant="subtitle2" gutterBottom>Resolution:</Typography>
<Typography variant="body1" paragraph>{result.resolution}</Typography>
{/* Suggested Actions */}
{result.suggested_actions?.length > 0 && (
<>
<Typography variant="subtitle2" gutterBottom>Suggested Actions:</Typography>
<List dense>
{result.suggested_actions.map((action, idx) => (
<ListItem key={idx}>
<ListItemText primary={`${idx + 1}. ${action.action || action}`} />
</ListItem>
))}
</List>
</>
)}
{/* Auto-Remediation Status */}
{result.auto_remediation_enabled && (
<Alert
severity={result.auto_remediation_executed ? 'success' : 'info'}
sx={{ mt: 2 }}
>
<AlertTitle>
{result.auto_remediation_executed ? 'Auto-Remediation Executed' : 'Auto-Remediation Status'}
</AlertTitle>
{result.remediation_decision && (
<Typography variant="body2">
{result.remediation_decision.allowed
? `✓ Actions approved for execution (${result.remediation_decision.action_type})`
: `✗ Actions require manual intervention: ${result.remediation_decision.reasoning.join(', ')}`
}
</Typography>
)}
</Alert>
)}
<Box sx={{ mt: 2 }}>
<Typography variant="caption">
Processing Time: {result.processing_time?.toFixed(2)}s
</Typography>
</Box>
</Paper>
);
}
// Ticket Status Interface
function TicketStatusInterface() {
const [ticketId, setTicketId] = useState('');
const [ticket, setTicket] = useState(null);
const [logs, setLogs] = useState([]);
const [loading, setLoading] = useState(false);
const fetchTicket = async () => {
setLoading(true);
try {
const response = await axios.get(`${API_URL}/api/v1/tickets/${ticketId}`);
setTicket(response.data);
// Fetch logs if auto-remediation was executed
if (response.data.auto_remediation_executed) {
const logsResponse = await axios.get(`${API_URL}/api/v1/tickets/${ticketId}/remediation-logs`);
setLogs(logsResponse.data.logs);
}
} catch (error) {
console.error('Error:', error);
}
setLoading(false);
};
return (
<Grid container spacing={3}>
<Grid item xs={12}>
<Paper sx={{ p: 2 }}>
<Box sx={{ display: 'flex', gap: 1 }}>
<TextField
fullWidth
value={ticketId}
onChange={(e) => setTicketId(e.target.value)}
placeholder="Enter Ticket ID"
/>
<Button variant="contained" onClick={fetchTicket} disabled={loading}>
Fetch
</Button>
</Box>
</Paper>
</Grid>
{ticket && (
<>
<Grid item xs={12} md={8}>
<TicketResultDisplay result={ticket} />
</Grid>
<Grid item xs={12} md={4}>
<FeedbackForm ticketId={ticketId} />
</Grid>
</>
)}
{logs.length > 0 && (
<Grid item xs={12}>
<RemediationLogsDisplay logs={logs} />
</Grid>
)}
</Grid>
);
}
// Feedback Form
function FeedbackForm({ ticketId }) {
const [feedback, setFeedback] = useState({
feedback_type: 'positive',
rating: 5,
was_helpful: true,
resolution_accurate: true,
actions_worked: true,
comment: ''
});
const [submitted, setSubmitted] = useState(false);
const submitFeedback = async () => {
try {
await axios.post(`${API_URL}/api/v1/feedback`, {
ticket_id: ticketId,
...feedback
});
setSubmitted(true);
} catch (error) {
console.error('Error:', error);
}
};
return (
<Paper sx={{ p: 3 }}>
<Typography variant="h6" gutterBottom>
<ThumbUp sx={{ mr: 1, verticalAlign: 'middle' }} />
Provide Feedback
</Typography>
{submitted ? (
<Alert severity="success">
<AlertTitle>Thank You!</AlertTitle>
Your feedback helps improve the AI system.
</Alert>
) : (
<>
<Typography variant="body2" gutterBottom>
Was this resolution helpful?
</Typography>
<Box sx={{ my: 2 }}>
<Rating
value={feedback.rating}
onChange={(e, value) => setFeedback({...feedback, rating: value})}
/>
</Box>
<FormControlLabel
control={
<Switch
checked={feedback.resolution_accurate}
onChange={(e) => setFeedback({
...feedback,
resolution_accurate: e.target.checked,
feedback_type: e.target.checked ? 'positive' : 'negative'
})}
/>
}
label="Resolution was accurate"
/>
<FormControlLabel
control={
<Switch
checked={feedback.actions_worked}
onChange={(e) => setFeedback({...feedback, actions_worked: e.target.checked})}
/>
}
label="Suggested actions worked"
/>
<TextField
fullWidth
multiline
rows={3}
label="Comments (optional)"
value={feedback.comment}
onChange={(e) => setFeedback({...feedback, comment: e.target.value})}
margin="normal"
/>
<Button
fullWidth
variant="contained"
onClick={submitFeedback}
sx={{ mt: 2 }}
>
Submit Feedback
</Button>
</>
)}
</Paper>
);
}
// Remediation Logs Display
function RemediationLogsDisplay({ logs }) {
return (
<Paper sx={{ p: 3 }}>
<Typography variant="h6" gutterBottom>
Auto-Remediation Execution Logs
</Typography>
<List>
{logs.map((log, idx) => (
<ListItem key={idx} divider>
<ListItemText
primary={
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
{log.success ?
<CheckCircle color="success" fontSize="small" /> :
<WarningIcon color="error" fontSize="small" />
}
<Typography variant="body2">{log.action}</Typography>
<Chip label={log.type} size="small" />
</Box>
}
secondary={
<>
<Typography variant="caption" display="block">
Target: {log.target_system} / {log.target_resource}
</Typography>
<Typography variant="caption" display="block">
Executed: {new Date(log.executed_at).toLocaleString()}
</Typography>
{log.error && (
<Typography variant="caption" color="error" display="block">
Error: {log.error}
</Typography>
)}
</>
}
/>
</ListItem>
))}
</List>
</Paper>
);
}
// Feedback Center
function FeedbackCenter() {
// Implementation for viewing all feedback and metrics
return (
<Paper sx={{ p: 3 }}>
<Typography variant="h6">Feedback Center</Typography>
<Typography variant="body2">
View all feedback, improve AI accuracy, and track pattern learning.
</Typography>
</Paper>
);
}
// Analytics Dashboard
function AnalyticsDashboard() {
const [stats, setStats] = useState(null);
const [autoRemStats, setAutoRemStats] = useState(null);
useEffect(() => {
fetchStats();
}, []);
const fetchStats = async () => {
try {
const [reliability, autoRem] = await Promise.all([
axios.get(`${API_URL}/api/v1/stats/reliability`),
axios.get(`${API_URL}/api/v1/stats/auto-remediation`)
]);
setStats(reliability.data);
setAutoRemStats(autoRem.data);
} catch (error) {
console.error('Error:', error);
}
};
return (
<Grid container spacing={3}>
<Grid item xs={12} md={3}>
<StatCard
title="Avg Reliability"
value={`${stats?.avg_reliability || 0}%`}
icon={<Speed />}
color="primary"
/>
</Grid>
<Grid item xs={12} md={3}>
<StatCard
title="Avg Confidence"
value={`${stats?.avg_confidence || 0}%`}
icon={<TrendingUp />}
color="success"
/>
</Grid>
<Grid item xs={12} md={3}>
<StatCard
title="Resolution Rate"
value={`${stats?.resolution_rate || 0}%`}
icon={<CheckCircle />}
color="info"
/>
</Grid>
<Grid item xs={12} md={3}>
<StatCard
title="Auto-Rem Success"
value={`${autoRemStats?.success_rate || 0}%`}
icon={<Shield />}
color="warning"
/>
</Grid>
</Grid>
);
}
function StatCard({ title, value, icon, color }) {
return (
<Card>
<CardContent>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<Box>
<Typography color="text.secondary" gutterBottom variant="body2">
{title}
</Typography>
<Typography variant="h4">
{value}
</Typography>
</Box>
<Box sx={{ color: `${color}.main` }}>
{icon}
</Box>
</Box>
</CardContent>
</Card>
);
}
export default App;