Spaces:
Paused
Paused
| <html lang="da"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>WidgeTDC | Omni-Link v5.0 (Sentience)</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet"> | |
| <style> | |
| :root { | |
| --bg-void: #020203; | |
| --panel-glass: rgba(15, 23, 42, 0.9); | |
| --neon-cyan: #22d3ee; | |
| --neon-purple: #c084fc; | |
| --neon-amber: #fbbf24; | |
| --neon-red: #f43f5e; | |
| --font-display: 'Orbitron', sans-serif; | |
| --font-code: 'JetBrains Mono', monospace; | |
| } | |
| body { | |
| background-color: var(--bg-void); | |
| color: #e2e8f0; | |
| font-family: var(--font-code); | |
| overflow: hidden; | |
| margin: 0; | |
| } | |
| .font-display { font-family: var(--font-display); } | |
| /* Canvas & Layers */ | |
| #neural-canvas { position: absolute; inset: 0; z-index: 0; } | |
| .ui-layer { position: absolute; inset: 0; pointer-events: none; z-index: 10; display: flex; flex-direction: column; } | |
| .pointer-auto { pointer-events: auto; } | |
| /* Glass Panels */ | |
| .glass-panel { | |
| background: var(--panel-glass); | |
| border: 1px solid rgba(255,255,255,0.1); | |
| backdrop-filter: blur(12px); | |
| box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5); | |
| } | |
| /* Status Indicators */ | |
| .status-dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; } | |
| .status-dot.saving { background-color: var(--neon-amber); animation: pulse-fast 0.5s infinite; } | |
| .status-dot.saved { background-color: var(--neon-cyan); } | |
| .status-dot.error { background-color: var(--neon-red); } | |
| @keyframes pulse-fast { 0% { opacity: 1; } 50% { opacity: 0.3; } 100% { opacity: 1; } } | |
| /* Inspector Slide */ | |
| .inspector-panel { transform: translateX(110%); transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1); } | |
| .inspector-panel.active { transform: translateX(0); } | |
| /* Chat Stream */ | |
| .chat-msg { margin-bottom: 4px; padding: 4px 8px; border-left: 2px solid transparent; font-size: 11px; opacity: 0; animation: slideIn 0.2s forwards; } | |
| .chat-msg.sys { border-color: var(--neon-cyan); background: rgba(34,211,238,0.05); } | |
| .chat-msg.exec { border-color: var(--neon-purple); background: rgba(192,132,252,0.1); color: #e9d5ff; font-weight: bold; } | |
| .chat-msg.security { border-color: var(--neon-red); background: rgba(244,63,94,0.1); color: #fda4af; } | |
| @keyframes slideIn { from { opacity: 0; transform: translateX(-5px); } to { opacity: 1; transform: translateX(0); } } | |
| /* Scanlines */ | |
| .scanlines { | |
| position: fixed; inset: 0; pointer-events: none; z-index: 50; opacity: 0.08; | |
| background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06)); | |
| background-size: 100% 2px, 3px 100%; | |
| } | |
| .omni-input { background: transparent; border: none; outline: none; width: 100%; color: white; font-family: var(--font-code); } | |
| </style> | |
| <!-- CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. --> | |
| </head> | |
| <body> | |
| <div class="scanlines"></div> | |
| <canvas id="neural-canvas"></canvas> | |
| <!-- UI LAYER --> | |
| <div class="ui-layer p-4"> | |
| <!-- HEADER --> | |
| <header class="flex justify-between items-start pointer-auto mb-4"> | |
| <div> | |
| <h1 class="font-display text-xl text-white tracking-widest drop-shadow-[0_0_15px_rgba(192,132,252,0.5)]"> | |
| OMNI-LINK <span class="text-purple-400 text-xs align-top font-bold">v5.0 SENTIENCE</span> | |
| </h1> | |
| <div class="flex items-center gap-2 mt-1 text-[9px] text-gray-500 font-mono tracking-widest"> | |
| <span id="save-indicator" class="status-dot saved"></span> | |
| <span id="save-status">PLASTICITY ACTIVE (LOCAL)</span> | |
| </div> | |
| </div> | |
| <div class="glass-panel px-3 py-2 rounded text-[10px] font-mono text-gray-400"> | |
| <div class="flex gap-4"> | |
| <div>NODES: <span id="stat-nodes" class="text-white">0</span></div> | |
| <div>LINKS: <span id="stat-links" class="text-white">0</span></div> | |
| </div> | |
| <div class="mt-1 text-right text-xs text-purple-400 font-bold" id="action-feed">IDLE</div> | |
| </div> | |
| </header> | |
| <div class="flex-1 flex gap-4 overflow-hidden relative"> | |
| <!-- STREAM --> | |
| <div class="w-80 glass-panel rounded-lg flex flex-col pointer-auto z-20 mb-20"> | |
| <div class="p-2 border-b border-gray-700 bg-black/40 flex justify-between"> | |
| <span class="font-display text-[10px] text-cyan-400">CORTEX LOG</span> | |
| <button onclick="clearMemory()" class="text-[9px] text-red-500 hover:text-red-300">RESET MEMORY</button> | |
| </div> | |
| <div id="chat-stream" class="flex-1 overflow-y-auto p-2 scrollbar-hide"></div> | |
| </div> | |
| <!-- INSPECTOR --> | |
| <div id="inspector" class="absolute right-0 top-0 bottom-20 w-96 glass-panel rounded-lg inspector-panel flex flex-col pointer-auto z-30 border-l-2 border-l-purple-500"> | |
| <div class="p-4 border-b border-gray-700 bg-black/40 flex justify-between items-center"> | |
| <h2 class="font-display text-sm text-purple-400">NODE INTERFACE</h2> | |
| <button onclick="closeInspector()" class="text-gray-400 hover:text-white">×</button> | |
| </div> | |
| <div class="p-4 text-center border-b border-gray-800 relative group"> | |
| <div class="absolute inset-0 bg-purple-900/10 opacity-0 group-hover:opacity-100 transition-opacity"></div> | |
| <h1 id="inspect-label" class="text-2xl font-bold text-white relative z-10">Node</h1> | |
| <span id="inspect-type" class="text-xs text-cyan-500 font-mono border border-cyan-900/50 px-2 py-0.5 rounded bg-cyan-900/10 mt-2 inline-block">TYPE</span> | |
| <!-- ACTION BUTTON --> | |
| <button id="btn-action" class="w-full mt-4 py-3 rounded bg-purple-900/30 border border-purple-500/50 text-purple-300 font-display font-bold text-sm hover:bg-purple-500 hover:text-white transition-all shadow-[0_0_15px_rgba(168,85,247,0.2)]"> | |
| ⚡ EXECUTE PROTOCOL | |
| </button> | |
| <div id="action-desc" class="text-[9px] text-gray-500 mt-2 font-mono">Triggers associated functional payload</div> | |
| </div> | |
| <div class="flex-1 overflow-y-auto p-4 space-y-3 font-mono"> | |
| <div class="text-[10px] text-gray-500 uppercase">Payload Data</div> | |
| <pre id="inspect-json" class="bg-black/60 rounded p-3 border border-gray-800 text-[10px] overflow-x-auto text-green-400"></pre> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- OMNI BAR --> | |
| <footer class="fixed bottom-6 left-4 right-4 md:left-20 md:right-20 pointer-auto z-40"> | |
| <div class="glass-panel rounded-full px-4 py-3 flex items-center gap-3 border border-gray-700 shadow-xl"> | |
| <span class="text-purple-500 font-bold animate-pulse">></span> | |
| <input id="omni-input" type="text" class="omni-input" placeholder="Commands: /inject, /exec, /reset..." autocomplete="off"> | |
| </div> | |
| </footer> | |
| </div> | |
| <script> | |
| // --- 1. CONFIG --- | |
| const config = { | |
| colors: { bg: '#020203', node: '#3b82f6', link: '#1e293b', active: '#c084fc', error: '#f43f5e' }, | |
| physics: { friction: 0.92, spring: 0.04, repulsion: 250 } | |
| }; | |
| // --- 2. STATE & MEMORY (PLASTICITY) --- | |
| let state = { | |
| nodes: [], | |
| links: [], | |
| camera: { x: 0, y: 0, zoom: 1 }, | |
| selection: null, | |
| drag: { active: false, node: null } | |
| }; | |
| // LOAD FROM LOCAL STORAGE (Plasticity) | |
| function loadMemory() { | |
| const mem = localStorage.getItem('widgetdc_graph_v5'); | |
| if (mem) { | |
| try { | |
| const parsed = JSON.parse(mem); | |
| state.nodes = parsed.nodes; | |
| // Reconstruct link references (stored as IDs) | |
| state.links = parsed.links.map(l => ({ | |
| source: state.nodes.find(n => n.id === l.sourceId), | |
| target: state.nodes.find(n => n.id === l.targetId) | |
| })).filter(l => l.source && l.target); | |
| log("Cortex", "Long-term memory restored. Graph plasticity active.", "sys"); | |
| updateStats(); | |
| return true; | |
| } catch (e) { | |
| console.error("Memory corruption", e); | |
| return false; | |
| } | |
| } | |
| return false; | |
| } | |
| function saveMemory() { | |
| const indicator = document.getElementById('save-indicator'); | |
| indicator.className = "status-dot saving"; | |
| // Serialize links as IDs to avoid circular refs | |
| const serializableLinks = state.links.map(l => ({ sourceId: l.source.id, targetId: l.target.id })); | |
| const data = { | |
| nodes: state.nodes.map(n => ({...n, vx:0, vy:0})), // Reset velocity on save | |
| links: serializableLinks | |
| }; | |
| localStorage.setItem('widgetdc_graph_v5', JSON.stringify(data)); | |
| setTimeout(() => { | |
| indicator.className = "status-dot saved"; | |
| }, 500); | |
| } | |
| function clearMemory() { | |
| if(confirm("CRITICAL WARNING: This will wipe the cortex memory. Continue?")) { | |
| localStorage.removeItem('widgetdc_graph_v5'); | |
| location.reload(); | |
| } | |
| } | |
| // --- 3. SECURITY (BLOOD-BRAIN BARRIER) --- | |
| const securityProtocols = { | |
| "Agent": (data) => true, // Trusted | |
| "System": (data) => true, // Trusted | |
| "Injected": (data) => { | |
| // Sanity Check: Prevent huge payloads or malicious keys | |
| if (JSON.stringify(data).length > 1000) return false; | |
| if (data.label && data.label.includes("<script>")) return false; | |
| return true; | |
| } | |
| }; | |
| function validateInjection(node) { | |
| const protocol = securityProtocols[node.type] || securityProtocols["Injected"]; | |
| if (protocol(node.data)) { | |
| return true; | |
| } else { | |
| log("Security", `Injection blocked: Payload validation failed for ${node.label}`, "security"); | |
| return false; | |
| } | |
| } | |
| // --- 4. REFLEXES (ACTION BINDINGS) --- | |
| function executeNode(node) { | |
| // Nudge Physics | |
| const angle = Math.random() * Math.PI * 2; | |
| node.vx += Math.cos(angle) * 30; | |
| node.vy += Math.sin(angle) * 30; | |
| // Functional Logic based on Type | |
| const feed = document.getElementById('action-feed'); | |
| if (node.type === "Agent") { | |
| log("EXEC", `Establishing Neural Bridge to [${node.label}]...`, "exec"); | |
| feed.innerText = "CALLING AGENT..."; | |
| // Mock Async Call | |
| setTimeout(() => { | |
| log("Agent", `Message received. WidgeTDC protocol active.`, "sys"); | |
| feed.innerText = "IDLE"; | |
| }, 1000); | |
| } | |
| else if (node.type === "Deploy") { | |
| log("EXEC", "Initiating Deployment Sequence...", "exec"); | |
| feed.innerText = "DEPLOYING..."; | |
| setTimeout(() => { | |
| log("System", "Build v4.2.1 successful.", "sys"); | |
| feed.innerText = "IDLE"; | |
| }, 2000); | |
| } | |
| else if (node.type === "Memory") { | |
| log("EXEC", `Recalling vector [${node.id}]`, "exec"); | |
| alert(`Memory Content:\n${node.data.content || "No content"}`); | |
| } | |
| else { | |
| log("System", `Node [${node.label}] has no executable payload.`, "sys"); | |
| } | |
| saveMemory(); // Save state after interaction | |
| } | |
| // --- 5. CORE ENGINE --- | |
| function initGraph() { | |
| if (!loadMemory()) { | |
| // Default Seed if no memory | |
| const center = createNode("WidgeTDC Core", "System", 0, 0); | |
| const agent = createNode("Architect (Gemini)", "Agent", 150, -50); | |
| const deploy = createNode("Deploy Pipeline", "Deploy", -150, 50); | |
| state.nodes.push(center, agent, deploy); | |
| state.links.push({source: center, target: agent}, {source: center, target: deploy}); | |
| log("System", "New cortex initialized. Memory empty.", "sys"); | |
| saveMemory(); | |
| } | |
| render(); | |
| // Auto-save loop | |
| setInterval(saveMemory, 5000); | |
| } | |
| function createNode(label, type, x, y) { | |
| return { | |
| id: Math.random().toString(36).substr(2, 9), | |
| label, type, | |
| x: x || (Math.random()-0.5)*500, | |
| y: y || (Math.random()-0.5)*500, | |
| vx: 0, vy: 0, | |
| radius: type === 'System' ? 25 : (type === 'Agent' ? 20 : 10), | |
| data: { content: "Raw data payload...", created: Date.now() } | |
| }; | |
| } | |
| // Canvas & Physics | |
| const canvas = document.getElementById('neural-canvas'); | |
| const ctx = canvas.getContext('2d'); | |
| function resize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } | |
| window.addEventListener('resize', resize); resize(); | |
| function render() { | |
| // Physics | |
| state.nodes.forEach(n1 => { | |
| state.nodes.forEach(n2 => { | |
| if (n1 === n2) return; | |
| const dx = n1.x - n2.x, dy = n1.y - n2.y; | |
| const dist = Math.sqrt(dx*dx + dy*dy) || 1; | |
| if (dist < 300) { | |
| const f = config.physics.repulsion / (dist*dist); | |
| n1.vx += (dx/dist)*f; n1.vy += (dy/dist)*f; | |
| } | |
| }); | |
| n1.vx *= config.physics.friction; n1.vy *= config.physics.friction; | |
| n1.x += n1.vx; n1.y += n1.vy; | |
| }); | |
| state.links.forEach(l => { | |
| const dx = l.target.x - l.source.x, dy = l.target.y - l.source.y; | |
| const dist = Math.sqrt(dx*dx + dy*dy); | |
| const f = (dist - 100) * config.physics.spring; | |
| const fx = (dx/dist)*f, fy = (dy/dist)*f; | |
| l.source.vx += fx; l.source.vy += fy; | |
| l.target.vx -= fx; l.target.vy -= fy; | |
| }); | |
| // Draw | |
| ctx.fillStyle = config.colors.bg; | |
| ctx.fillRect(0, 0, canvas.width, canvas.height); | |
| // Camera transform | |
| const cx = canvas.width/2 + state.camera.x; | |
| const cy = canvas.height/2 + state.camera.y; | |
| const z = state.camera.zoom; | |
| ctx.lineWidth = 1; | |
| state.links.forEach(l => { | |
| ctx.beginPath(); | |
| ctx.moveTo(cx + l.source.x*z, cy + l.source.y*z); | |
| ctx.lineTo(cx + l.target.x*z, cy + l.target.y*z); | |
| ctx.strokeStyle = config.colors.link; | |
| ctx.stroke(); | |
| }); | |
| state.nodes.forEach(n => { | |
| const x = cx + n.x*z, y = cy + n.y*z, r = n.radius*z; | |
| ctx.beginPath(); | |
| ctx.arc(x, y, r, 0, Math.PI*2); | |
| ctx.fillStyle = n.type === 'Agent' ? '#c084fc' : (n.type === 'System' ? '#fff' : '#3b82f6'); | |
| if (state.selection === n) { ctx.fillStyle = '#22d3ee'; ctx.shadowBlur = 10; ctx.shadowColor = '#22d3ee'; } | |
| else { ctx.shadowBlur = 0; } | |
| ctx.fill(); | |
| // Label | |
| if (z > 0.8 || state.selection === n) { | |
| ctx.fillStyle = "#fff"; | |
| ctx.font = "10px monospace"; | |
| ctx.fillText(n.label, x + r + 5, y + 4); | |
| } | |
| }); | |
| requestAnimationFrame(render); | |
| } | |
| // --- 6. INTERACTION --- | |
| canvas.addEventListener('mousedown', e => { | |
| const z = state.camera.zoom; | |
| const mx = (e.clientX - canvas.width/2 - state.camera.x)/z; | |
| const my = (e.clientY - canvas.height/2 - state.camera.y)/z; | |
| const hit = state.nodes.find(n => { | |
| const dx = n.x - mx, dy = n.y - my; | |
| return Math.sqrt(dx*dx + dy*dy) < n.radius + 10; | |
| }); | |
| if (hit) { | |
| state.selection = hit; | |
| state.drag = { active: true, node: hit }; | |
| openInspector(hit); | |
| } else { | |
| closeInspector(); | |
| } | |
| }); | |
| canvas.addEventListener('mousemove', e => { | |
| if (state.drag.active) { | |
| const z = state.camera.zoom; | |
| state.drag.node.x = (e.clientX - canvas.width/2 - state.camera.x)/z; | |
| state.drag.node.y = (e.clientY - canvas.height/2 - state.camera.y)/z; | |
| state.drag.node.vx = 0; state.drag.node.vy = 0; | |
| } | |
| }); | |
| canvas.addEventListener('mouseup', () => { state.drag.active = false; saveMemory(); }); | |
| // Inspector Logic | |
| function openInspector(node) { | |
| document.getElementById('inspector').classList.add('active'); | |
| document.getElementById('inspect-label').innerText = node.label; | |
| document.getElementById('inspect-type').innerText = node.type.toUpperCase(); | |
| document.getElementById('inspect-json').innerText = JSON.stringify(node.data, null, 2); | |
| // Re-bind Action Button | |
| const btn = document.getElementById('btn-action'); | |
| const newBtn = btn.cloneNode(true); | |
| btn.parentNode.replaceChild(newBtn, btn); | |
| newBtn.addEventListener('click', () => executeNode(node)); | |
| } | |
| function closeInspector() { document.getElementById('inspector').classList.remove('active'); state.selection = null; } | |
| // Omni Bar | |
| document.getElementById('omni-input').addEventListener('keydown', e => { | |
| if(e.key === 'Enter') { | |
| const cmd = e.target.value.trim(); | |
| e.target.value = ""; | |
| processCommand(cmd); | |
| } | |
| }); | |
| function processCommand(cmd) { | |
| log("User", cmd, "sys"); | |
| if (cmd.startsWith("/inject")) { | |
| const parts = cmd.split(" "); | |
| const label = parts.slice(1).join(" ") || "Injected Node"; | |
| const newNode = createNode(label, "Injected"); | |
| if (validateInjection(newNode)) { | |
| state.nodes.push(newNode); | |
| state.links.push({source: state.nodes[0], target: newNode}); | |
| log("System", `Node injected: ${label}`, "sys"); | |
| saveMemory(); | |
| } | |
| } else if (cmd === "/reset") { | |
| clearMemory(); | |
| } | |
| } | |
| function log(src, msg, type) { | |
| const div = document.createElement('div'); | |
| div.className = `chat-msg ${type}`; | |
| div.innerHTML = `<span class="opacity-75 font-bold">${src}:</span> ${msg}`; | |
| document.getElementById('chat-stream').appendChild(div); | |
| } | |
| function updateStats() { | |
| document.getElementById('stat-nodes').innerText = state.nodes.length; | |
| document.getElementById('stat-links').innerText = state.links.length; | |
| } | |
| // START | |
| initGraph(); | |
| </script> | |
| </body> | |
| </html> | |