Aegis-Engine / index.html
PratamaSSS's picture
Update index.html
49e9a62 verified
Raw
History Blame Contribute Delete
10.3 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Aegis Engine | WebGPU AI</title>
<style>
:root {
--bg: #030712;
--surface: rgba(17, 24, 39, 0.7);
--accent: #00f6ff;
--text: #f3f4f6;
--text-dim: #9ca3af;
}
* { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Courier New', Courier, monospace; }
body { background-color: var(--bg); color: var(--text); min-height: 100vh; display: flex; justify-content: center; align-items: center; padding: 20px; overflow: hidden;}
.grid-overlay { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background-image: linear-gradient(rgba(0, 246, 255, 0.05) 1px, transparent 1px), linear-gradient(90deg, rgba(0, 246, 255, 0.05) 1px, transparent 1px); background-size: 30px 30px; z-index: -1; }
.terminal { background: var(--surface); backdrop-filter: blur(12px); border: 1px solid rgba(0, 246, 255, 0.2); border-radius: 12px; width: 100%; max-width: 800px; padding: 30px; box-shadow: 0 0 40px rgba(0, 246, 255, 0.1); }
.header { border-bottom: 1px solid rgba(0, 246, 255, 0.3); padding-bottom: 15px; margin-bottom: 25px; display: flex; justify-content: space-between; align-items: flex-end; }
.header h1 { font-size: 24px; text-transform: uppercase; letter-spacing: 3px; color: var(--accent); text-shadow: 0 0 10px rgba(0, 246, 255, 0.5); }
.badge { background: rgba(0, 246, 255, 0.1); color: var(--accent); padding: 4px 8px; border-radius: 4px; font-size: 12px; font-weight: bold; border: 1px solid var(--accent); }
/* --- PHASE 1: LOADING UI --- */
#bootSequence { display: flex; flex-direction: column; gap: 15px; }
.log-line { color: var(--text-dim); font-size: 14px; }
.progress-box { width: 100%; height: 20px; border: 1px solid var(--accent); border-radius: 4px; padding: 2px; position: relative; }
.progress-bar { height: 100%; background: var(--accent); width: 0%; box-shadow: 0 0 10px var(--accent); transition: width 0.2s; }
.progress-text { position: absolute; top: 0; left: 50%; transform: translateX(-50%); font-size: 12px; font-weight: bold; color: #000; line-height: 18px; mix-blend-mode: overlay;}
/* --- PHASE 2: GENERATION UI --- */
#inferenceUI { display: none; flex-direction: column; gap: 20px; }
.canvas-container { width: 100%; aspect-ratio: 1/1; background: #000; border-radius: 8px; border: 1px dashed var(--text-dim); display: flex; justify-content: center; align-items: center; overflow: hidden; position: relative;}
.canvas-container img { width: 100%; height: 100%; object-fit: cover; display: none; }
.status-pulse { color: var(--accent); font-size: 14px; letter-spacing: 2px; animation: pulse 1.5s infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
.input-group { display: flex; gap: 10px; }
input[type="text"] { flex: 1; background: rgba(0,0,0,0.5); border: 1px solid rgba(0, 246, 255, 0.3); color: var(--text); padding: 15px; border-radius: 6px; font-size: 16px; outline: none; transition: 0.3s; }
input[type="text"]:focus { border-color: var(--accent); box-shadow: 0 0 15px rgba(0, 246, 255, 0.2); }
button { background: var(--accent); color: #000; border: none; padding: 0 25px; font-weight: bold; font-size: 16px; letter-spacing: 1px; border-radius: 6px; cursor: pointer; transition: 0.2s; text-transform: uppercase; }
button:hover { background: #fff; box-shadow: 0 0 20px var(--accent); }
button:disabled { background: #333; color: #666; cursor: not-allowed; box-shadow: none; }
.error-state { color: #ff3366; background: rgba(255, 51, 102, 0.1); padding: 15px; border: 1px solid #ff3366; border-radius: 6px; display: none; margin-top: 15px;}
</style>
</head>
<body>
<div class="grid-overlay"></div>
<div class="terminal">
<div class="header">
<h1>Aegis Engine</h1>
<span class="badge" id="hardwareBadge">CHECKING WEBGPU...</span>
</div>
<div id="errorPanel" class="error-state"></div>
<div id="bootSequence">
<div class="log-line" id="logMsg">> Initializing Local Neural Runtime...</div>
<div class="log-line">> Target: SD-Turbo (WebGPU)</div>
<div class="log-line" style="color: #ffcc00; font-size: 12px;">⚠ Note: First-time boot requires ~1.5GB local cache allocation.</div>
<div class="progress-box">
<div class="progress-bar" id="progressBar"></div>
<div class="progress-text" id="progressText">0%</div>
</div>
<button id="btnBoot" style="padding: 12px; margin-top: 10px;">MOUNT NEURAL WEIGHTS</button>
</div>
<div id="inferenceUI">
<div class="canvas-container">
<div class="status-pulse" id="statusPulse" style="display: none;">COMPUTING LATENT MATRICES...</div>
<img id="outputImage" alt="Generated Output">
</div>
<div class="input-group">
<input type="text" id="promptInput" placeholder="Enter prompt (e.g., A cyberpunk samurai reading a neon book)..." autocomplete="off">
<button id="btnGenerate">RENDER</button>
</div>
<div class="log-line" id="renderStats" style="text-align: right; font-size: 11px;">Awaiting Input</div>
</div>
</div>
<script type="module">
import { client } from 'https://esm.sh/web-txt2img@latest';
const dom = {
bootSeq: document.getElementById('bootSequence'),
infUI: document.getElementById('inferenceUI'),
btnBoot: document.getElementById('btnBoot'),
btnGen: document.getElementById('btnGenerate'),
prompt: document.getElementById('promptInput'),
img: document.getElementById('outputImage'),
pulse: document.getElementById('statusPulse'),
progBar: document.getElementById('progressBar'),
progTxt: document.getElementById('progressText'),
log: document.getElementById('logMsg'),
badge: document.getElementById('hardwareBadge'),
err: document.getElementById('errorPanel'),
stats: document.getElementById('renderStats')
};
// 1. Hardware Check
if (!navigator.gpu) {
dom.badge.innerText = "WEBGPU NOT SUPPORTED";
dom.badge.style.color = "#ff3366";
dom.badge.style.borderColor = "#ff3366";
showError("Your browser does not support WebGPU. Please use a recent version of Chrome, Edge, or Brave on a desktop computer.");
dom.btnBoot.disabled = true;
} else {
dom.badge.innerText = "WEBGPU ACTIVE";
}
function showError(msg) {
dom.err.style.display = "block";
dom.err.innerText = msg;
}
// 2. Mount Model to VRAM
dom.btnBoot.addEventListener('click', async () => {
dom.btnBoot.disabled = true;
dom.btnBoot.innerText = "DOWNLOADING & COMPILING...";
dom.err.style.display = "none";
try {
// Initialize the SD-Turbo pipeline
await client.load('sd-turbo', { backendPreference: ['webgpu'] }, (msg) => {
// Update Progress UI
if(msg.progress !== undefined) {
const pct = Math.round(msg.progress * 100);
dom.progBar.style.width = pct + '%';
dom.progTxt.innerText = pct + '%';
}
dom.log.innerText = `> ${msg.text || msg.phase || 'Loading...'}`;
});
// Transition to Inference UI
dom.bootSeq.style.display = "none";
dom.infUI.style.display = "flex";
} catch (error) {
showError("Failed to mount model: " + error.message);
dom.btnBoot.disabled = false;
dom.btnBoot.innerText = "RETRY MOUNT";
}
});
// 3. Local Offline Generation
dom.btnGen.addEventListener('click', async () => {
const promptText = dom.prompt.value.trim();
if(!promptText) return;
// UI State Update
dom.btnGen.disabled = true;
dom.prompt.disabled = true;
dom.img.style.display = "none";
dom.pulse.style.display = "block";
dom.stats.innerText = "Processing through local GPU...";
dom.err.style.display = "none";
const startTime = performance.now();
try {
// Execute WebGPU Inference
const { promise } = client.generate({
prompt: promptText
});
const response = await promise;
// The library returns a Blob/Image data depending on internal handling
// We convert it to a renderable URL
const imageUrl = (response instanceof Blob) ? URL.createObjectURL(response) : response;
const endTime = performance.now();
const renderTime = ((endTime - startTime) / 1000).toFixed(2);
dom.img.src = imageUrl;
dom.img.style.display = "block";
dom.stats.innerText = `Rendered locally in ${renderTime} seconds.`;
} catch (error) {
showError("Generation Error: " + error.message);
dom.stats.innerText = "Render Failed.";
} finally {
dom.pulse.style.display = "none";
dom.btnGen.disabled = false;
dom.prompt.disabled = false;
dom.prompt.focus();
}
});
// Allow Enter key to trigger generation
dom.prompt.addEventListener('keypress', (e) => {
if(e.key === 'Enter') dom.btnGen.click();
});
</script>
</body>
</html>