InklyAI / templates /agents.html
pravinai's picture
Upload folder using huggingface_hub
8eab354 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>InklyAI - Agent Management</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
overflow: hidden;
}
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 30px;
text-align: center;
}
.header h1 {
font-size: 2.5em;
margin-bottom: 10px;
font-weight: 300;
}
.nav {
background: #f8f9fa;
padding: 15px 30px;
border-bottom: 1px solid #dee2e6;
}
.nav a {
color: #667eea;
text-decoration: none;
margin-right: 20px;
padding: 8px 16px;
border-radius: 5px;
transition: background-color 0.3s;
}
.nav a:hover, .nav a.active {
background: #667eea;
color: white;
}
.main-content {
padding: 40px;
}
.section {
background: #f8f9fa;
border-radius: 15px;
padding: 30px;
margin-bottom: 30px;
}
.section h2 {
margin-bottom: 20px;
color: #333;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: 600;
color: #333;
}
.form-group input, .form-group select {
width: 100%;
padding: 12px;
border: 2px solid #ddd;
border-radius: 8px;
font-size: 1em;
}
.form-group input:focus, .form-group select:focus {
outline: none;
border-color: #667eea;
}
.btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 12px 30px;
border-radius: 25px;
cursor: pointer;
font-size: 1em;
transition: transform 0.2s ease;
}
.btn:hover {
transform: translateY(-2px);
}
.btn-danger {
background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
}
.btn-success {
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
}
.agents-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
margin-top: 20px;
}
.agent-card {
background: white;
border-radius: 15px;
padding: 20px;
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
border-left: 4px solid #667eea;
}
.agent-card.inactive {
border-left-color: #dc3545;
opacity: 0.7;
}
.agent-id {
font-size: 1.2em;
font-weight: bold;
color: #333;
margin-bottom: 10px;
}
.agent-status {
display: inline-block;
padding: 4px 12px;
border-radius: 20px;
font-size: 0.8em;
font-weight: bold;
margin-bottom: 15px;
}
.agent-status.active {
background: #d4edda;
color: #155724;
}
.agent-status.inactive {
background: #f8d7da;
color: #721c24;
}
.agent-stats {
margin-bottom: 15px;
}
.stat-item {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
font-size: 0.9em;
color: #666;
}
.agent-actions {
display: flex;
gap: 10px;
}
.agent-actions .btn {
padding: 8px 16px;
font-size: 0.9em;
}
.message {
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
display: none;
}
.message.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.message.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.loading {
text-align: center;
padding: 20px;
display: none;
}
.spinner {
border: 4px solid #f3f3f3;
border-top: 4px solid #667eea;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.file-upload {
border: 2px dashed #ddd;
border-radius: 10px;
padding: 20px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.file-upload:hover {
border-color: #667eea;
background: #f0f4ff;
}
.file-upload.dragover {
border-color: #667eea;
background: #e8f2ff;
}
.file-input {
display: none;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>InklyAI</h1>
<p>Agent Management System</p>
</div>
<div class="nav">
<a href="/">Signature Verification</a>
<a href="/agents" class="active">Agent Management</a>
</div>
<div class="main-content">
<!-- Messages -->
<div id="message" class="message"></div>
<!-- Register New Agent -->
<div class="section">
<h2>Register New Agent</h2>
<form id="registerForm">
<div class="form-group">
<label for="agentId">Agent ID:</label>
<input type="text" id="agentId" name="agent_id" required>
</div>
<div class="form-group">
<label for="signatureTemplate">Signature Template:</label>
<div class="file-upload" id="fileUpload">
<div>📝</div>
<div>Click to upload or drag and drop signature template</div>
<input type="file" id="signatureTemplate" class="file-input" accept="image/*" required>
</div>
</div>
<button type="submit" class="btn">Register Agent</button>
</form>
</div>
<!-- Agent List -->
<div class="section">
<h2>Registered Agents</h2>
<div class="loading" id="loading">
<div class="spinner"></div>
<div>Loading agents...</div>
</div>
<div class="agents-grid" id="agentsGrid">
<!-- Agents will be loaded here -->
</div>
</div>
</div>
</div>
<script>
// Load agents on page load
document.addEventListener('DOMContentLoaded', function() {
loadAgents();
setupFileUpload();
setupRegisterForm();
});
function setupFileUpload() {
const fileUpload = document.getElementById('fileUpload');
const fileInput = document.getElementById('signatureTemplate');
fileUpload.addEventListener('click', () => fileInput.click());
fileUpload.addEventListener('dragover', (e) => {
e.preventDefault();
fileUpload.classList.add('dragover');
});
fileUpload.addEventListener('dragleave', () => {
fileUpload.classList.remove('dragover');
});
fileUpload.addEventListener('drop', (e) => {
e.preventDefault();
fileUpload.classList.remove('dragover');
const files = e.dataTransfer.files;
if (files.length > 0) {
fileInput.files = files;
updateFileUploadDisplay(files[0]);
}
});
fileInput.addEventListener('change', (e) => {
if (e.target.files.length > 0) {
updateFileUploadDisplay(e.target.files[0]);
}
});
}
function updateFileUploadDisplay(file) {
const fileUpload = document.getElementById('fileUpload');
fileUpload.innerHTML = `
<div>✅</div>
<div>${file.name}</div>
<div style="font-size: 0.8em; color: #666;">${(file.size / 1024).toFixed(1)} KB</div>
`;
}
function setupRegisterForm() {
document.getElementById('registerForm').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData();
formData.append('agent_id', document.getElementById('agentId').value);
formData.append('signature_template', document.getElementById('signatureTemplate').files[0]);
try {
const response = await fetch('/api/register-agent', {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.success) {
showMessage('Agent registered successfully!', 'success');
document.getElementById('registerForm').reset();
document.getElementById('fileUpload').innerHTML = `
<div>📝</div>
<div>Click to upload or drag and drop signature template</div>
`;
loadAgents();
} else {
showMessage('Failed to register agent: ' + result.error, 'error');
}
} catch (error) {
showMessage('Error registering agent: ' + error.message, 'error');
}
});
}
async function loadAgents() {
const loading = document.getElementById('loading');
const agentsGrid = document.getElementById('agentsGrid');
loading.style.display = 'block';
agentsGrid.innerHTML = '';
try {
const response = await fetch('/api/agents');
const data = await response.json();
if (data.success) {
data.agents.forEach(agent => {
const agentCard = createAgentCard(agent);
agentsGrid.appendChild(agentCard);
});
} else {
showMessage('Failed to load agents: ' + data.error, 'error');
}
} catch (error) {
showMessage('Error loading agents: ' + error.message, 'error');
} finally {
loading.style.display = 'none';
}
}
function createAgentCard(agent) {
const card = document.createElement('div');
card.className = `agent-card ${agent.is_active ? '' : 'inactive'}`;
card.innerHTML = `
<div class="agent-id">${agent.agent_id}</div>
<div class="agent-status ${agent.is_active ? 'active' : 'inactive'}">
${agent.is_active ? 'Active' : 'Inactive'}
</div>
<div class="agent-stats">
<div class="stat-item">
<span>Verifications:</span>
<span>${agent.verification_count}</span>
</div>
<div class="stat-item">
<span>Created:</span>
<span>${new Date(agent.created_at).toLocaleDateString()}</span>
</div>
<div class="stat-item">
<span>Last Verified:</span>
<span>${agent.last_verified ? new Date(agent.last_verified).toLocaleDateString() : 'Never'}</span>
</div>
</div>
<div class="agent-actions">
${agent.is_active ?
`<button class="btn btn-danger" onclick="deactivateAgent('${agent.agent_id}')">Deactivate</button>` :
`<button class="btn btn-success" onclick="reactivateAgent('${agent.agent_id}')">Reactivate</button>`
}
<button class="btn" onclick="viewAgentStats('${agent.agent_id}')">Stats</button>
</div>
`;
return card;
}
async function deactivateAgent(agentId) {
try {
const response = await fetch(`/api/deactivate-agent/${agentId}`, {
method: 'POST'
});
const result = await response.json();
if (result.success) {
showMessage('Agent deactivated successfully!', 'success');
loadAgents();
} else {
showMessage('Failed to deactivate agent: ' + result.error, 'error');
}
} catch (error) {
showMessage('Error deactivating agent: ' + error.message, 'error');
}
}
async function reactivateAgent(agentId) {
try {
const response = await fetch(`/api/reactivate-agent/${agentId}`, {
method: 'POST'
});
const result = await response.json();
if (result.success) {
showMessage('Agent reactivated successfully!', 'success');
loadAgents();
} else {
showMessage('Failed to reactivate agent: ' + result.error, 'error');
}
} catch (error) {
showMessage('Error reactivating agent: ' + error.message, 'error');
}
}
async function viewAgentStats(agentId) {
try {
const response = await fetch(`/api/agent-stats/${agentId}`);
const result = await response.json();
if (result.success) {
const stats = result.stats;
const message = `
Agent: ${agentId}
Total Verifications: ${stats.total_verifications}
Success Rate: ${(stats.success_rate * 100).toFixed(1)}%
Average Similarity: ${stats.average_similarity.toFixed(3)}
Last Verification: ${stats.last_verification || 'Never'}
`;
alert(message);
} else {
showMessage('Failed to load agent stats: ' + result.error, 'error');
}
} catch (error) {
showMessage('Error loading agent stats: ' + error.message, 'error');
}
}
function showMessage(text, type) {
const messageDiv = document.getElementById('message');
messageDiv.textContent = text;
messageDiv.className = `message ${type}`;
messageDiv.style.display = 'block';
setTimeout(() => {
messageDiv.style.display = 'none';
}, 5000);
}
</script>
</body>
</html>