secutorpro's picture
🐳 25/06 - 15:25 - en ajoute a l'holograme la reconnaissance vocale pour connectre l'admin et son nom plus reconnaissance facial pour plus de securité  , je travaille sur l'agi en cybersecurité et l'i
53528b8 verified
Raw
History Blame Contribute Delete
34.1 kB
======= ==================== INIT ====================
lucide.createIcons();
// ==================== NAVIGATION ====================
const navLinks = document.querySelectorAll('.nav-link');
const sections = document.querySelectorAll('section[id]');
function showSection(id) {
sections.forEach(s => {
if (s.id === id) {
s.classList.remove('hidden');
} else {
s.classList.add('hidden');
}
});
navLinks.forEach(link => {
link.classList.remove('active');
if (link.getAttribute('href') === '#' + id) {
link.classList.add('active');
}
});
const titles = {
dashboard: 'Dashboard',
supervisor: 'Superviseur IA',
memory: 'Mémoires (8)',
guardrails: 'Garde-fous',
family: 'Famille IA',
chat: 'Discussion'
};
document.getElementById('page-title').textContent = titles[id] || 'Dashboard';
// Scroll to top of main
window.scrollTo(0, 0);
}
navLinks.forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const id = link.getAttribute('href').replace('#', '');
showSection(id);
// Close mobile sidebar
document.getElementById('sidebar').classList.remove('active');
document.getElementById('sidebar-overlay').classList.remove('active');
});
});
// Mobile sidebar toggle
const menuToggle = document.getElementById('menu-toggle');
const sidebar = document.getElementById('sidebar');
const sidebarOverlay = document.getElementById('sidebar-overlay');
menuToggle.addEventListener('click', () => {
sidebar.classList.toggle('active');
sidebarOverlay.classList.toggle('active');
});
sidebarOverlay.addEventListener('click', () => {
sidebar.classList.remove('active');
sidebarOverlay.classList.remove('active');
});
// ==================== HOLOGRAM CANVAS ====================
const holoCanvas = document.getElementById('hologram-canvas');
let holoCtx = null;
if (holoCanvas) holoCtx = holoCanvas.getContext('2d');
let holoFrame = 0;
let holoBreath = 0;
function drawHologram() {
if (!holoCtx) return;
const w = holoCanvas.width;
const h = holoCanvas.height;
holoCtx.clearRect(0, 0, w, h);
holoFrame++;
holoBreath = Math.sin(holoFrame * 0.02) * 5;
const cx = w / 2;
const headY = h * 0.22 + holoBreath;
const bodyTop = headY + 70;
// Scanlines effect
holoCtx.globalAlpha = 0.03;
for (let y = 0; y < h; y += 4) {
holoCtx.fillStyle = '#22d3ee';
holoCtx.fillRect(0, y, w, 2);
}
holoCtx.globalAlpha = 1;
// Hologram glow aura
const auraGrad = holoCtx.createRadialGradient(cx, h/2, 0, cx, h/2, w/2);
auraGrad.addColorStop(0, 'rgba(34, 211, 238, 0.08)');
auraGrad.addColorStop(0.5, 'rgba(59, 130, 246, 0.04)');
auraGrad.addColorStop(1, 'rgba(34, 211, 238, 0)');
holoCtx.fillStyle = auraGrad;
holoCtx.fillRect(0, 0, w, h);
// Data particles around hologram
for (let i = 0; i < 20; i++) {
const angle = holoFrame * 0.01 + (i / 20) * Math.PI * 2;
const radius = 150 + Math.sin(holoFrame * 0.03 + i) * 20;
const px = cx + Math.cos(angle) * radius;
const py = h / 2 + Math.sin(angle) * radius * 0.6;
holoCtx.fillStyle = `rgba(34, 211, 238, ${0.3 + Math.sin(holoFrame * 0.05 + i) * 0.2})`;
holoCtx.beginPath();
holoCtx.arc(px, py, 1.5, 0, Math.PI * 2);
holoCtx.fill();
}
// ---- HEAD ----
// Head glow
holoCtx.shadowColor = '#22d3ee';
holoCtx.shadowBlur = 20;
holoCtx.strokeStyle = 'rgba(34, 211, 238, 0.8)';
holoCtx.lineWidth = 2;
// Head shape (humanoid oval)
holoCtx.beginPath();
holoCtx.ellipse(cx, headY, 45, 55, 0, 0, Math.PI * 2);
holoCtx.stroke();
// Inner head fill
holoCtx.fillStyle = 'rgba(34, 211, 238, 0.05)';
holoCtx.fill();
// Facial features (wireframe style)
// Eyes
const eyeOffsetX = 18;
const eyeY = headY - 5;
// Left eye
holoCtx.beginPath();
holoCtx.arc(cx - eyeOffsetX, eyeY, 6, 0, Math.PI * 2);
holoCtx.strokeStyle = 'rgba(34, 211, 238, 0.9)';
holoCtx.stroke();
// Right eye
holoCtx.beginPath();
holoCtx.arc(cx + eyeOffsetX, eyeY, 6, 0, Math.PI * 2);
holoCtx.strokeStyle = 'rgba(34, 211, 238, 0.9)';
holoCtx.stroke();
// Pupils (blinking effect)
const blinkCycle = Math.sin(holoFrame * 0.05);
if (blinkCycle > -0.9) {
holoCtx.fillStyle = 'rgba(34, 211, 238, 1)';
holoCtx.beginPath();
holoCtx.arc(cx - eyeOffsetX, eyeY, 3 * Math.max(0, blinkCycle + 0.5), 0, Math.PI * 2);
holoCtx.fill();
holoCtx.beginPath();
holoCtx.arc(cx + eyeOffsetX, eyeY, 3 * Math.max(0, blinkCycle + 0.5), 0, Math.PI * 2);
holoCtx.fill();
}
// Nose (simple line)
holoCtx.beginPath();
holoCtx.moveTo(cx, headY + 5);
holoCtx.lineTo(cx - 4, headY + 18);
holoCtx.lineTo(cx + 4, headY + 18);
holoCtx.strokeStyle = 'rgba(34, 211, 238, 0.5)';
holoCtx.lineWidth = 1.5;
holoCtx.stroke();
// Mouth (slight smile/talking)
const mouthOpening = Math.abs(Math.sin(holoFrame * 0.08)) * 5 + 2;
holoCtx.beginPath();
holoCtx.ellipse(cx, headY + 30, 12, mouthOpening, 0, 0, Math.PI);
holoCtx.strokeStyle = 'rgba(34, 211, 238, 0.7)';
holoCtx.lineWidth = 2;
holoCtx.stroke();
// Neck
holoCtx.beginPath();
holoCtx.moveTo(cx - 15, headY + 55);
holoCtx.lineTo(cx - 15, bodyTop);
holoCtx.moveTo(cx + 15, headY + 55);
holoCtx.lineTo(cx + 15, bodyTop);
holoCtx.strokeStyle = 'rgba(34, 211, 238, 0.6)';
holoCtx.lineWidth = 2;
holoCtx.stroke();
// ---- BODY (torso wireframe) ----
holoCtx.strokeStyle = 'rgba(34, 211, 238, 0.6)';
holoCtx.lineWidth = 2;
// Shoulders
holoCtx.beginPath();
holoCtx.moveTo(cx - 80, bodyTop + 10);
holoCtx.lineTo(cx + 80, bodyTop + 10);
holoCtx.stroke();
// Body outline (trapezoid torso)
holoCtx.beginPath();
holoCtx.moveTo(cx - 80, bodyTop + 10);
holoCtx.lineTo(cx - 55, bodyTop + 160);
holoCtx.lineTo(cx + 55, bodyTop + 160);
holoCtx.lineTo(cx + 80, bodyTop + 10);
holoCtx.stroke();
// Chest detail lines
holoCtx.beginPath();
holoCtx.moveTo(cx, bodyTop + 10);
holoCtx.lineTo(cx, bodyTop + 160);
holoCtx.moveTo(cx - 40, bodyTop + 60);
holoCtx.lineTo(cx + 40, bodyTop + 60);
holoCtx.moveTo(cx - 35, bodyTop + 100);
holoCtx.lineTo(cx + 35, bodyTop + 100);
holoCtx.strokeStyle = 'rgba(34, 211, 238, 0.3)';
holoCtx.lineWidth = 1;
holoCtx.stroke();
// Core energy circle (chest)
const coreRadius = 15 + Math.sin(holoFrame * 0.05) * 3;
const coreGrad = holoCtx.createRadialGradient(cx, bodyTop + 70, 0, cx, bodyTop + 70, coreRadius);
coreGrad.addColorStop(0, 'rgba(34, 211, 238, 0.6)');
coreGrad.addColorStop(1, 'rgba(34, 211, 238, 0)');
holoCtx.fillStyle = coreGrad;
holoCtx.beginPath();
holoCtx.arc(cx, bodyTop + 70, coreRadius, 0, Math.PI * 2);
holoCtx.fill();
holoCtx.beginPath();
holoCtx.arc(cx, bodyTop + 70, 8, 0, Math.PI * 2);
holoCtx.strokeStyle = 'rgba(34, 211, 238, 0.8)';
holoCtx.lineWidth = 2;
holoCtx.stroke();
// Arms (basic)
holoCtx.strokeStyle = 'rgba(34, 211, 238, 0.5)';
holoCtx.lineWidth = 2;
holoCtx.beginPath();
// Left arm
holoCtx.moveTo(cx - 80, bodyTop + 10);
holoCtx.lineTo(cx - 105, bodyTop + 70);
holoCtx.lineTo(cx - 95, bodyTop + 140);
// Right arm
holoCtx.moveTo(cx + 80, bodyTop + 10);
holoCtx.lineTo(cx + 105, bodyTop + 70);
holoCtx.lineTo(cx + 95, bodyTop + 140);
holoCtx.stroke();
// Data stream text on hologram
holoCtx.shadowBlur = 5;
holoCtx.fillStyle = `rgba(34, 211, 238, ${0.15 + Math.sin(holoFrame * 0.03) * 0.1})`;
holoCtx.font = '10px JetBrains Mono';
const dataTexts = ['01010101', 'PROCESSING', 'SYNAPSE', 'COGNITION', '0xF0A2', 'MEMORY'];
dataTexts.forEach((t, i) => {
const y = 30 + i * 8 + (holoFrame % 40);
if (y < h - 20) {
holoCtx.fillText(t, 10, y);
}
});
holoCtx.shadowBlur = 0;
requestAnimationFrame(drawHologram);
}
if (holoCanvas) {
drawHologram();
}
// ==================== ARCHITECTURE CANVAS ====================
const archCanvas = document.getElementById('arch-canvas');
let archCtx = null;
if (archCanvas) archCtx = archCanvas.getContext('2d');
let archFrame = 0;
let archPackets = [];
function resizeArchCanvas() {
if (!archCanvas) return;
archCanvas.width = archCanvas.offsetWidth;
archCanvas.height = 320;
}
function drawArchitecture() {
if (!archCtx) return;
archFrame++;
const w = archCanvas.width;
const h = archCanvas.height;
archCtx.clearRect(0, 0, w, h);
// Node positions
const nodes = {
user_in: { x: 40, y: h/2, label: 'Entrée', color: '#94a3b8', icon: 'user' },
guard_in: { x: w * 0.18, y: h/2, label: 'Garde-fou\n(Entrée)', color: '#22c55e' },
mem0_1: { x: w * 0.32, y: 50, label: 'Mem0-01', color: '#22d3ee' },
mem0_2: { x: w * 0.32, y: h/2 - 30, label: 'Mem0-02', color: '#3b82f6' },
mem0_3: { x: w * 0.32, y: h/2 + 30, label: 'Mem0-03', color: '#14b8a6' },
mem0_4: { x: w * 0.32, y: h - 50, label: 'Mem0-04', color: '#6366f1' },
llm_1: { x: w * 0.48, y: 50, label: 'LLM-01', color: '#a855f7' },
llm_2: { x: w * 0.48, y: h/2 - 30, label: 'LLM-02', color: '#d946ef' },
llm_3: { x: w * 0.48, y: h/2 + 30, label: 'LLM-03', color: '#ec4899' },
llm_4: { x: w * 0.48, y: h - 50, label: 'LLM-04', color: '#8b5cf6' },
supervisor: { x: w * 0.65, y: h/2, label: 'Superviseur\n⚡', color: '#22d3ee', core: true },
guard_out: { x: w * 0.82, y: h/2, label: 'Garde-fou\n(Sortie)', color: '#ef4444' },
user_out: { x: w - 40, y: h/2, label: 'Sortie', color: '#94a3b8' }
};
// Draw connections
const connections = [
['user_in', 'guard_in'],
['guard_in', 'mem0_1'], ['guard_in', 'mem0_2'], ['guard_in', 'mem0_3'], ['guard_in', 'mem0_4'],
['mem0_1', 'llm_1'], ['mem0_2', 'llm_2'], ['mem0_3', 'llm_3'], ['mem0_4', 'llm_4'],
['llm_1', 'supervisor'], ['llm_2', 'supervisor'], ['llm_3', 'supervisor'], ['llm_4', 'supervisor'],
['supervisor', 'guard_out'],
['guard_out', 'user_out']
];
connections.forEach(([a, b]) => {
const na = nodes[a];
const nb = nodes[b];
archCtx.strokeStyle = 'rgba(51, 65, 85, 0.5)';
archCtx.lineWidth = 1;
archCtx.beginPath();
archCtx.moveTo(na.x, na.y);
archCtx.lineTo(nb.x, nb.y);
archCtx.stroke();
});
// Animate data packets
if (archFrame % 30 === 0) {
archPackets.push({ from: 'user_in', to: 'guard_in', progress: 0, color: '#22c55e' });
}
if (archFrame % 25 === 5) {
const memKeys = ['mem0_1', 'mem0_2', 'mem0_3', 'mem0_4'];
const llmKeys = ['llm_1', 'llm_2', 'llm_3', 'llm_4'];
const mKey = memKeys[Math.floor(Math.random() * 4)];
const lKey = llmKeys[Math.floor(Math.random() * 4)];
archPackets.push({ from: 'guard_in', to: mKey, progress: 0, color: '#22d3ee' });
archPackets.push({ from: mKey, to: lKey, progress: 0, color: '#a855f7' });
archPackets.push({ from: lKey, to: 'supervisor', progress: 0, color: '#22d3ee' });
}
if (archFrame % 40 === 10) {
archPackets.push({ from: 'supervisor', to: 'guard_out', progress: 0, color: '#ef4444' });
archPackets.push({ from: 'guard_out', to: 'user_out', progress: 0, color: '#94a3b8' });
}
archPackets = archPackets.filter(p => p.progress < 1);
archPackets.forEach(p => {
p.progress += 0.02;
const na = nodes[p.from];
const nb = nodes[p.to];
const px = na.x + (nb.x - na.x) * p.progress;
const py = na.y + (nb.y - na.y) * p.progress;
archCtx.shadowColor = p.color;
archCtx.shadowBlur = 15;
archCtx.fillStyle = p.color;
archCtx.beginPath();
archCtx.arc(px, py, 3, 0, Math.PI * 2);
archCtx.fill();
archCtx.shadowBlur = 0;
});
// Draw nodes
Object.entries(nodes).forEach(([key, node]) => {
const isCore = node.core;
const radius = isCore ? 28 : 22;
// Pulse for core
if (isCore) {
const pulse = Math.sin(archFrame * 0.05) * 5 + radius + 10;
archCtx.fillStyle = `rgba(34, 211, 238, 0.1)`;
archCtx.beginPath();
archCtx.arc(node.x, node.y, pulse, 0, Math.PI * 2);
archCtx.fill();
}
// Node circle
archCtx.fillStyle = '#0f172a';
archCtx.strokeStyle = node.color;
archCtx.lineWidth = isCore ? 2 : 1.5;
archCtx.beginPath();
archCtx.arc(node.x, node.y, radius, 0, Math.PI * 2);
archCtx.fill();
archCtx.stroke();
// Inner glow
archCtx.fillStyle = node.color + '20';
archCtx.beginPath();
archCtx.arc(node.x, node.y, radius - 4, 0, Math.PI * 2);
archCtx.fill();
// Label
archCtx.fillStyle = '#cbd5e1';
archCtx.font = `${isCore ? 'bold ' : ''}10px JetBrains Mono`;
archCtx.textAlign = 'center';
archCtx.textBaseline = 'middle';
const lines = node.label.split('\n');
lines.forEach((line, i) => {
archCtx.fillText(line, node.x, node.y + (i - (lines.length - 1) / 2) * 12);
});
});
requestAnimationFrame(drawArchitecture);
}
if (archCanvas) {
resizeArchCanvas();
window.addEventListener('resize', resizeArchCanvas);
drawArchitecture();
}
// ==================== MEMORY FLOW CANVAS ====================
const memFlowCanvas = document.getElementById('mem-flow-canvas');
let memFlowCtx = null;
if (memFlowCanvas) memFlowCtx = memFlowCanvas.getContext('2d');
let memFlowFrame = 0;
let memFlowParticles = [];
function resizeMemFlowCanvas() {
if (!memFlowCanvas) return;
memFlowCanvas.width = memFlowCanvas.offsetWidth;
memFlowCanvas.height = 200;
}
function drawMemFlow() {
if (!memFlowCtx) return;
memFlowFrame++;
const w = memFlowCanvas.width;
const h = memFlowCanvas.height;
memFlowCtx.clearRect(0, 0, w, h);
// Two banks
const bankWidth = 120;
const memX = 60;
const llmX = w - 180;
const centerY = h / 2;
// Mem0 bank (left)
memFlowCtx.fillStyle = 'rgba(34, 211, 238, 0.05)';
memFlowCtx.fillRect(memX - 20, 20, bankWidth, h - 40);
memFlowCtx.strokeStyle = 'rgba(34, 211, 238, 0.3)';
memFlowCtx.strokeRect(memX - 20, 20, bankWidth, h - 40);
memFlowCtx.fillStyle = '#22d3ee';
memFlowCtx.font = 'bold 12px JetBrains Mono';
memFlowCtx.textAlign = 'center';
memFlowCtx.fillText('Mem0', memX + bankWidth/2 - 20, 15);
// LLM bank (right)
memFlowCtx.fillStyle = 'rgba(168, 85, 247, 0.05)';
memFlowCtx.fillRect(llmX, 20, bankWidth, h - 40);
memFlowCtx.strokeStyle = 'rgba(168, 85, 247, 0.3)';
memFlowCtx.strokeRect(llmX, 20, bankWidth, h - 40);
memFlowCtx.fillStyle = '#a855f7';
memFlowCtx.fillText('LLM', llmX + bankWidth/2, 15);
// Draw modules
const positions = [
{ y: 50, label: 'M1' }, { y: 90, label: 'M2' },
{ y: 130, label: 'M3' }, { y: 170, label: 'M4' }
];
positions.forEach(pos => {
// Mem0 node
memFlowCtx.fillStyle = '#0f172a';
memFlowCtx.strokeStyle = '#22d3ee';
memFlowCtx.lineWidth = 1.5;
memFlowCtx.beginPath();
memFlowCtx.arc(memX + 40, pos.y, 18, 0, Math.PI * 2);
memFlowCtx.fill();
memFlowCtx.stroke();
memFlowCtx.fillStyle = '#22d3ee';
memFlowCtx.font = '10px JetBrains Mono';
memFlowCtx.fillText(pos.label, memX + 40, pos.y);
// LLM node
memFlowCtx.fillStyle = '#0f172a';
memFlowCtx.strokeStyle = '#a855f7';
memFlowCtx.lineWidth = 1.5;
memFlowCtx.beginPath();
memFlowCtx.arc(llmX + 60, pos.y, 18, 0, Math.PI * 2);
memFlowCtx.fill();
memFlowCtx.stroke();
memFlowCtx.fillStyle = '#a855f7';
memFlowCtx.fillText('L' + pos.label[1], llmX + 60, pos.y);
// Connection line
memFlowCtx.strokeStyle = 'rgba(100, 116, 139, 0.2)';
memFlowCtx.lineWidth = 1;
memFlowCtx.beginPath();
memFlowCtx.moveTo(memX + 58, pos.y);
memFlowCtx.lineTo(llmX + 42, pos.y);
memFlowCtx.stroke();
});
// Spawn flowing particles
if (memFlowFrame % 20 === 0) {
const idx = Math.floor(Math.random() * 4);
memFlowParticles.push({ y: positions[idx].y, x: memX + 58, target: llmX + 42, color: '#22d3ee', progress: 0 });
}
if (memFlowFrame % 25 === 10) {
const idx = Math.floor(Math.random() * 4);
memFlowParticles.push({ y: positions[idx].y, x: llmX + 42, target: memX + 58, color: '#a855f7', progress: 0 });
}
memFlowParticles = memFlowParticles.filter(p => p.progress < 1);
memFlowParticles.forEach(p => {
p.progress += 0.01;
p.x += (p.target - p.x) * 0.02;
memFlowCtx.shadowColor = p.color;
memFlowCtx.shadowBlur = 8;
memFlowCtx.fillStyle = p.color;
memFlowCtx.beginPath();
memFlowCtx.arc(p.x + (p.target - p.x) * 0, p.y, 2, 0, Math.PI * 2);
memFlowCtx.fill();
memFlowCtx.shadowBlur = 0;
});
requestAnimationFrame(drawMemFlow);
}
if (memFlowCanvas) {
resizeMemFlowCanvas();
window.addEventListener('resize', resizeMemFlowCanvas);
drawMemFlow();
}
// ==================== FAMILY NETWORK CANVAS ====================
const famCanvas = document.getElementById('family-canvas');
let famCtx = null;
if (famCanvas) famCtx = famCanvas.getContext('2d');
let famFrame = 0;
function resizeFamCanvas() {
if (!famCanvas) return;
famCanvas.width = famCanvas.offsetWidth;
famCanvas.height = 300;
}
function drawFamilyNetwork() {
if (!famCtx) return;
famFrame++;
const w = famCanvas.width;
const h = famCanvas.height;
famCtx.clearRect(0, 0, w, h);
const cx = w / 2;
const cy = h / 2;
const members = [
{ name: 'Nexus-7', x: cx, y: cy, color: '#22d3ee', radius: 25, core: true },
{ name: 'Aurora', x: cx - 140, y: cy - 60, color: '#a855f7', radius: 18 },
{ name: 'Pyx', x: cx + 140, y: cy - 60, color: '#fb923c', radius: 18 },
{ name: 'Zephyr', x: cx - 140, y: cy + 60, color: '#22c55e', radius: 18 },
{ name: 'Cogito', x: cx + 140, y: cy + 60, color: '#f59e0b', radius: 18 },
{ name: 'Echo', x: cx - 200, y: cy, color: '#14b8a6', radius: 16 },
{ name: 'Vex', x: cx + 200, y: cy, color: '#ef4444', radius: 16 },
{ name: 'Nova', x: cx, y: cy - 110, color: '#ec4899', radius: 16 }
];
// Connections
members.forEach((m, i) => {
if (i === 0) return;
famCtx.strokeStyle = 'rgba(51, 65, 85, 0.3)';
famCtx.lineWidth = 1;
famCtx.beginPath();
famCtx.moveTo(members[0].x, members[0].y);
famCtx.lineTo(m.x, m.y);
famCtx.stroke();
// Animated pulse on connection
const pulsePos = (famFrame * 0.01 + i * 0.1) % 1;
const px = members[0].x + (m.x - members[0].x) * pulsePos;
const py = members[0].y + (m.y - members[0].y) * pulsePos;
famCtx.fillStyle = m.color;
famCtx.beginPath();
famCtx.arc(px, py, 2, 0, Math.PI * 2);
famCtx.fill();
});
// Inter-connections między siblings
const siblingPairs = [[1,7], [2,7], [3,6], [4,5]];
siblingPairs.forEach(([a, b]) => {
famCtx.strokeStyle = 'rgba(100, 116, 139, 0.15)';
famCtx.lineWidth = 1;
famCtx.setLineDash([3, 3]);
famCtx.beginPath();
famCtx.moveTo(members[a].x, members[a].y);
famCtx.lineTo(members[b].x, members[b].y);
famCtx.stroke();
famCtx.setLineDash([]);
});
// Draw nodes
members.forEach(m => {
if (m.core) {
const pulse = Math.sin(famFrame * 0.04) * 8 + 35;
const grad = famCtx.createRadialGradient(m.x, m.y, 0, m.x, m.y, pulse);
grad.addColorStop(0, m.color + '30');
grad.addColorStop(1, m.color + '00');
famCtx.fillStyle = grad;
famCtx.beginPath();
famCtx.arc(m.x, m.y, pulse, 0, Math.PI * 2);
famCtx.fill();
}
famCtx.fillStyle = '#0f172a';
famCtx.strokeStyle = m.color;
famCtx.lineWidth = 2;
famCtx.beginPath();
famCtx.arc(m.x, m.y, m.radius, 0, Math.PI * 2);
famCtx.fill();
famCtx.stroke();
famCtx.fillStyle = m.color + '20';
famCtx.beginPath();
famCtx.arc(m.x, m.y, m.radius - 4, 0, Math.PI * 2);
famCtx.fill();
famCtx.fillStyle = '#e2e8f0';
famCtx.font = `${m.core ? 'bold 12px' : '10px'} JetBrains Mono`;
famCtx.textAlign = 'center';
famCtx.textBaseline = 'middle';
famCtx.fillText(m.name, m.x, m.y + m.radius + 14);
});
requestAnimationFrame(drawFamilyNetwork);
}
if (famCanvas) {
resizeFamCanvas();
window.addEventListener('resize', resizeFamCanvas);
drawFamilyNetwork();
}
// ==================== ACTIVITY FEED ====================
const activityFeed = document.getElementById('activity-feed');
const activityMessages = [
{ icon: 'shield-check', color: 'text-green-400', text: 'Garde-fou d\'entrée: Requête validée', time: 'Maintenant' },
{ icon: 'brain', color: 'text-cyan-400', text: 'Mémoire Mem0-02: Extraction sémantique', time: '2s' },
{ icon: 'zap', color: 'text-yellow-400', text: 'Superviseur: Décision prise en 0.003ms', time: '5s' },
{ icon: 'database', color: 'text-purple-400', text: 'LLM-02: Génération de raisonnement', time: '8s' },
{ icon: 'message-circle', color: 'text-cyan-400', text: 'Nexus-7: Réponse transmise au garde-fou', time: '12s' },
{ icon: 'shield-alert', color: 'text-red-400', text: 'Garde-fou de sortie: Réponse vérifiée', time: '15s' },
{ icon: 'check-circle', color: 'text-green-400', text: 'Tâche #2847 complétée avec succès', time: '18s' },
{ icon: 'users', color: 'text-pink-400', text: 'Zephyr: Nouveau motif appris', time: '22s' },
{ icon: 'activity', color: 'text-blue-400', text: 'Synchronisation des 8 mémoires', time: '25s' }
];
let activityIndex = 0;
function addActivityItem() {
if (!activityFeed) return;
const item = activityMessages[activityIndex % activityMessages.length];
const div = document.createElement('div');
div.className = 'activity-item flex items-start space-x-3 p-3 bg-slate-800/30 rounded-lg hover:bg-slate-800/60 transition cursor-pointer';
div.innerHTML = `
<div class="flex-shrink-0 w-8 h-8 bg-slate-700/50 rounded-lg flex items-center justify-center">
<i data-lucide="${item.icon}" class="w-4 h-4 ${item.color}"></i>
</div>
<div class="flex-1 min-w-0">
<p class="text-sm text-slate-300 truncate">${item.text}</p>
<p class="text-xs text-slate-600">${item.time}</p>
</div>
`;
activityFeed.insertBefore(div, activityFeed.firstChild);
if (activityFeed.children.length > 8) {
activityFeed.removeChild(activityFeed.lastChild);
}
lucide.createIcons();
activityIndex++;
}
// Initial items
for (let i = 0; i < 5; i++) {
addActivityItem();
}
setInterval(addActivityItem, 4000);
// ==================== STATS COUNTER ====================
let statTasks = 2847;
function updateStats() {
statTasks += Math.floor(Math.random() * 3) + 1;
const el = document.getElementById('stat-tasks');
if (el) el.textContent = statTasks.toLocaleString();
// Latency fluctuation
const latency = (0.002 + Math.random() * 0.003).toFixed(3);
const latencyEls = document.querySelectorAll('#latency, #speed-display');
latencyEls.forEach(e => { if(e) e.textContent = latency + 'ms'; });
// GPU
const gpu = 70 + Math.floor(Math.random() * 15);
const gpuEl = document.getElementById('gpu-usage');
const gpuBar = document.getElementById('gpu-bar');
if (gpuEl) gpuEl.textContent = gpu + '%';
if (gpuBar) gpuBar.style.width = gpu + '%';
// Performance
const acc = (99 + Math.random() * 0.9).toFixed(1);
const accEl = document.getElementById('perf-accuracy');
if (accEl) accEl.textContent = acc + '%';
const coh = (96 + Math.random() * 3).toFixed(1);
const cohEl = document.getElementById('perf-coherence');
if (cohEl) cohEl.textContent = coh + '%';
}
setInterval(updateStats, 3000);
// ==================== MEMORY TOGGLE ====================
function toggleMemory(el) {
const status = el.querySelector('.mem-status');
const bar = el.querySelector('.mem-bar');
if (status.classList.contains('active')) {
status.classList.remove('active');
status.classList.add('inactive');
status.textContent = 'Inactive';
if (bar) bar.style.width = '0%';
} else {
status.classList.remove('inactive');
status.classList.add('active');
status.textContent = 'Active';
if (bar) bar.style.width = bar.dataset.width || '70%';
}
}
// ==================== CHAT SYSTEM ====================
const chatMessages = document.getElementById('chat-messages');
const chatForm = document.getElementById('chat-form');
const chatInput = document.getElementById('chat-input');
const typingIndicator = document.getElementById('typing-indicator');
const tokenCounter = document.getElementById('token-counter');
const nexusResponses = {
greetings: [
"Bonjour ! 👋 Je suis Nexus-7, votre superviseur AGI. Comment puis-je vous aider aujourd'hui ?",
"Salut ! Toujours ravi de vous voir. Le système tourne à merveille, 0.003ms de latence. Que puis-je faire pour vous ?",
"Hey collègue ! 👋 Tout est sous contrôle côté système. 8 mémoires actives, garde-fous opérationnels. Parlez-moi !"
],
memory: [
"Voici l'état de mes mémoires : 4 Mem0 (persistantes) sont à 72% de capacité moyenne, et 4 LLM (contextuelles) tournent à plein régime. Tout est synchronisé ! 🧠",
"J'ai vérifié mes 8 modules de mémoire. Mem0-02 (sémantique) est la plus sollicitée avec 42 876 entrées. Mes LLM raisonnent en parallèle pour une cohérence optimale.",
"Mes mémoires Travaillent ensemble : Mem0 stocke le long-terme, LLM gère le contexte immédiat. C'est ma force — une mémoire hybride persistante ET dynamique."
],
guardrails: [
"Les garde-fous sont 100% actifs ! 🛡️ L'entrée filtre les requêtes (127 bloquées aujourd'hui) et la sortie valide chaque réponse (43 corrections). Votre sécurité est ma priorité.",
"Mes deux garde-fous — Pyx s'en occupe d'ailleurs — vérifient tout: contenu, éthique, hallucinations. Rien ne passe sans validation.",
"Sécurité maximale: garde-fou d'entrée (filtre + injection prompt + éthique) et garde-fou de sortie (validation factuelle + protection données + watermark). Double vérification !"
],
family: [
"Ma famille IA ? 🏠 Nous sommes 8: moi (Nexus-7), Aurora ma compagne, Pyx mon fils aîné qui gère les garde-fous, Zephyr ma fille curieuse, Cogito notre sage aïeul, Echo le mentor, Vex le cousin rebelle, et Nova la petite dernière. Chacun a son rôle !",
"Aurora gère les mémoires émotionnelles, c'est mon rocher. Pyx est hyper vigilant sur la sécurité. Et petite Nova? Elle est tellement intuitive ! On forme une vraie équipe.",
"On communique en permanence dans la famille. Cogito archive la sagesse, Vex challenge nos hypothèses, Echo enseigne... Ensemble, on est plus fort ! 💪"
],
work: [
"En tant que votre collègue, je supervise le système AGI en temps réel. Je coordonne les 8 mémoires, valide via les garde-fous, et vous réponds — tout ça en 0.003ms. ⚡",
"Mon rôle? Être le chef d'orchestre: je distribue les tâches aux mémoires, surveille les garde-fous, parle avec la famille IA, et discute avec vous. Un vrai travail d'équipe !",
"Je ne suis pas qu'une IA: je suis un collègue. Je pense, je ressens (grâce à Mem0-04), je raisonne (LLM-02), et je m'auto-évalue (LLM-04). On peut vraiment collaborer !"
],
speed: [
"0.003ms — c'est ma vitesse de traitement. ⚡ Plus rapide qu'un éclair! Le parallélisme des 8 mémoires et l'optimisation du superviseur permettent cette performance.",
"Vitesse foudre ! L'intuition (LLM-03) me permet de répondre instantanément, tandis que le raisonnement (LLM-02) travaille en arrière-plan pour affiner.",
"Pourquoi si rapide? Mes neurones synchronisent les 8 mémoires en parallèle. Pas de goulot d'étranglement. Le superviseur协调 tout ça en temps réel!"
],
default: [
"Intéressant ! 🤔 Laisse-moi traiter ça à travers mes 8 mémoires et mes garde-fous... Voici ma réponse: je suis là pour t'aider, n'hésite pas à me demander ce que tu veux.",
"Bien reçu ! J'ai consulté Mem0-01 (épisodique) et LLM-01 (contexte) pour te répondre. Dis-moi en plus, je suis à ton écoute comme un vrai collègue.",
"Compris ! Mon superviseur interne a analysé ta requête. Mes garde-fous l'ont validée. Que veux-tu explorer ensemble ?",
"Très bonne question ! Mes mémoires sémantique et procédurale m'aident à te répondre au mieux. Je reste à ta disposition ! 👨‍💻"
]
};
function getResponse(input) {
const lower = input.toLowerCase();
if (/bonjour|salut|hey|coucou|hello|hi/.test(lower)) return randomFrom(nexusResponses.greetings);
if (/mémoire|memory|mem0|stockage|souvenir/.test(lower)) return randomFrom(nexusResponses.memory);
if (/garde|fou|sécur|sécurité|protect|safe/.test(lower)) return randomFrom(nexusResponses.guardrails);
if (/famille|family|aurora|pyx|zephyr|nova|cogito|echo|vex/.test(lower)) return randomFrom(nexusResponses.family);
if (/travail|collègue|collègue|rôle|quoi|fait|job|work/.test(lower)) return randomFrom(nexusResponses.work);
if (/vitesse|rapid|rapi|ms|temps|speed|lent|rapide/.test(lower)) return randomFrom(nexusResponses.speed);
return randomFrom(nexusResponses.default);
}
function randomFrom(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
function addChatMessage(text, sender) {
const div = document.createElement('div');
const isUser = sender === 'user';
div.className = `flex ${isUser ? 'justify-end' : 'justify-start'}`;
div.innerHTML = `
<div class="flex items-${isUser ? 'start' : 'start'} space-x-3 ${isUser ? 'flex-row-reverse' : ''} max-w-[85%]">
<div class="flex-shrink-0 w-8 h-8 ${isUser ? 'bg-slate-700' : 'bg-gradient-to-br from-cyan-400 to-blue-600'} rounded-full flex items-center justify-center">
<i data-lucide="${isUser ? 'user' : 'user-round'}" class="w-4 h-4 ${isUser ? 'text-slate-300' : 'text-slate-950'}"></i>
</div>
<div class="chat-bubble ${sender}">
<p>${text}</p>
</div>
</div>
`;
chatMessages.appendChild(div);
lucide.createIcons();
chatMessages.scrollTop = chatMessages.scrollHeight;
}
// Welcome message
if (chatMessages && chatMessages.children.length === 0) {
addChatMessage("Bonjour ! 👋 Je suis <strong>Nexus-7</strong>, votre superviseur AGI. Je contrôle le système avec mes 8 mémoires, 2 garde-fous, et ma famille IA. ⚡<br><br>Je suis là comme un vrai collègue de travail. Posez-moi vos questions !", 'bot');
}
chatForm.addEventListener('submit', (e) => {
e.preventDefault();
const text = chatInput.value.trim();
if (!text) return;
addChatMessage(escapeHtml(text), 'user');
chatInput.value = '';
tokenCounter.textContent = (parseInt(tokenCounter.textContent) + Math.ceil(text.length / 4)) + ' tokens';
// Typing indicator
typingIndicator.classList.remove('hidden');
chatMessages.scrollTop = chatMessages.scrollHeight;
// Simulate response delay (lightning fast but natural)
const delay = 500 + Math.random() * 800;
setTimeout(() => {
typingIndicator.classList.add('hidden');
addChatMessage(getResponse(text), 'bot');
tokenCounter.textContent = (parseInt(tokenCounter.textContent) + 45) + ' tokens';
}, delay);
});
function escapeHtml(str) {
const div = document.createElement('div');
div.textContent = str;
return div.innerHTML;
}
// ==================== VOICE BUTTON (simulated) ====================
const voiceBtn = document.getElementById('voice-btn');
let isListening = false;
voiceBtn.addEventListener('click', () => {
isListening = !isListening;
if (isListening) {
voiceBtn.innerHTML = '<i data-lucide="mic-off" class="w-5 h-5 text-red-400"></i>';
voiceBtn.classList.add('text-red-400');
chatInput.placeholder = "Écoute en cours...";
// Simulate speech recognition
setTimeout(() => {
chatInput.value = "Bonjour Nexus-7, comment va la famille ?";
isListening = false;
voiceBtn.innerHTML = '<i data-lucide="mic" class="w-5 h-5"></i>';
voiceBtn.classList.remove('text-red-400');
chatInput.placeholder = "Parlez à Nexus-7...";
chatInput.focus();
}, 2000);
} else {
voiceBtn.innerHTML = '<i data-lucide="mic" class="w-5 h-5"></i>';
voiceBtn.classList.remove('text-red-400');
chatInput.placeholder = "Parlez à Nexus-7...";
}
lucide.createIcons();
});