| const canvas = document.getElementById("field"); |
| const ctx = canvas.getContext("2d"); |
| const prefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches; |
|
|
| let width = 0; |
| let height = 0; |
| let particles = []; |
|
|
| function resize() { |
| const dpr = Math.min(window.devicePixelRatio || 1, 2); |
| width = window.innerWidth; |
| height = window.innerHeight; |
| canvas.width = Math.floor(width * dpr); |
| canvas.height = Math.floor(height * dpr); |
| canvas.style.width = `${width}px`; |
| canvas.style.height = `${height}px`; |
| ctx.setTransform(dpr, 0, 0, dpr, 0, 0); |
| const count = Math.max(48, Math.min(120, Math.floor(width / 13))); |
| particles = Array.from({ length: count }, () => ({ |
| x: Math.random() * width, |
| y: Math.random() * height, |
| z: Math.random() * 1 + 0.35, |
| vx: (Math.random() - 0.5) * 0.28, |
| vy: (Math.random() - 0.5) * 0.18, |
| })); |
| } |
|
|
| function draw() { |
| ctx.clearRect(0, 0, width, height); |
| ctx.fillStyle = "rgba(2,4,5,0.22)"; |
| ctx.fillRect(0, 0, width, height); |
|
|
| for (const p of particles) { |
| if (!prefersReduced) { |
| p.x += p.vx * p.z; |
| p.y += p.vy * p.z; |
| if (p.x < -20) p.x = width + 20; |
| if (p.x > width + 20) p.x = -20; |
| if (p.y < -20) p.y = height + 20; |
| if (p.y > height + 20) p.y = -20; |
| } |
|
|
| ctx.beginPath(); |
| ctx.fillStyle = `rgba(37,247,196,${0.10 + p.z * 0.18})`; |
| ctx.arc(p.x, p.y, 1.2 * p.z, 0, Math.PI * 2); |
| ctx.fill(); |
| } |
|
|
| for (let i = 0; i < particles.length; i++) { |
| for (let j = i + 1; j < particles.length; j++) { |
| const a = particles[i]; |
| const b = particles[j]; |
| const dx = a.x - b.x; |
| const dy = a.y - b.y; |
| const dist = Math.sqrt(dx * dx + dy * dy); |
| if (dist < 120) { |
| ctx.strokeStyle = `rgba(91,211,255,${(1 - dist / 120) * 0.11})`; |
| ctx.lineWidth = 1; |
| ctx.beginPath(); |
| ctx.moveTo(a.x, a.y); |
| ctx.lineTo(b.x, b.y); |
| ctx.stroke(); |
| } |
| } |
| } |
|
|
| requestAnimationFrame(draw); |
| } |
|
|
| const lines = [ |
| "$ ollama run hf.co/AdvancedDataIntelligence/adi-qwen3.5-4b-glm5.2-general-GGUF:Q4_K_M", |
| "loading gguf shards...", |
| "teacher imprint: glm-5.2", |
| "context window: long", |
| "mode: local-first", |
| "ready: ask ADI anything" |
| ]; |
|
|
| const typeout = document.getElementById("typeout"); |
| let char = 0; |
| let text = ""; |
|
|
| function typeLoop() { |
| const full = lines.join("\n"); |
| text = full.slice(0, char); |
| typeout.textContent = text + (char % 2 ? "█" : ""); |
| char = char >= full.length ? 0 : char + 1; |
| setTimeout(typeLoop, char === 0 ? 900 : 32); |
| } |
|
|
| const models = { |
| qwen35: { |
| kind: "general assistant", |
| name: "adi-qwen3.5-4b-glm5.2-general", |
| body: "The smallest flagship ADI general model: distilled from glm-5.2 for practical local reasoning, explanation, and tool-aware chat.", |
| command: "ollama run hf.co/AdvancedDataIntelligence/adi-qwen3.5-4b-glm5.2-general-GGUF:Q4_K_M", |
| link: "https://huggingface.co/AdvancedDataIntelligence/adi-qwen3.5-4b-glm5.2-general-GGUF" |
| }, |
| qwen359: { |
| kind: "general assistant", |
| name: "adi-qwen3.5-9b-glm5.2-general", |
| body: "A larger Qwen3.5 general student with more reasoning headroom while keeping the ADI local-first distillation style.", |
| command: "hf.co/AdvancedDataIntelligence/adi-qwen3.5-9b-glm5.2-general-GGUF", |
| link: "https://huggingface.co/AdvancedDataIntelligence/adi-qwen3.5-9b-glm5.2-general-GGUF" |
| }, |
| qwen3: { |
| kind: "general assistant", |
| name: "adi-qwen3-8b-glm5.2-general", |
| body: "More headroom for general reasoning while staying within a practical single-machine local inference envelope.", |
| command: "ollama run hf.co/AdvancedDataIntelligence/adi-qwen3-8b-glm5.2-general-GGUF:Q4_K_M", |
| link: "https://huggingface.co/AdvancedDataIntelligence/adi-qwen3-8b-glm5.2-general-GGUF" |
| }, |
| coder: { |
| kind: "coding assistant", |
| name: "adi-qwen2.5-coder-7b-kimi2.7-code", |
| body: "A local coding model distilled from a frontier code teacher for generation, debugging, refactoring, and explanation.", |
| command: "ollama run hf.co/AdvancedDataIntelligence/adi-qwen2.5-coder-7b-kimi2.7-code-GGUF:Q4_K_M", |
| link: "https://huggingface.co/AdvancedDataIntelligence/adi-qwen2.5-coder-7b-kimi2.7-code-GGUF" |
| }, |
| wake: { |
| kind: "voice interface", |
| name: "hey-adi-wakeword", |
| body: "A wakeword model for hands-free ADI loops, pairing local intelligence with ambient interaction.", |
| command: "hf.co/AdvancedDataIntelligence/hey-adi-wakeword", |
| link: "https://huggingface.co/AdvancedDataIntelligence/hey-adi-wakeword" |
| } |
| }; |
|
|
| const kind = document.getElementById("model-kind"); |
| const name = document.getElementById("model-name"); |
| const body = document.getElementById("model-body"); |
| const command = document.getElementById("model-command"); |
| const link = document.getElementById("model-link"); |
| const toast = document.getElementById("toast"); |
|
|
| document.querySelectorAll(".tab").forEach((tab) => { |
| tab.addEventListener("click", () => { |
| document.querySelectorAll(".tab").forEach((item) => item.classList.toggle("active", item === tab)); |
| const model = models[tab.dataset.model]; |
| kind.textContent = model.kind; |
| name.textContent = model.name; |
| body.textContent = model.body; |
| command.textContent = model.command; |
| link.href = model.link; |
| }); |
| }); |
|
|
| document.getElementById("copy-command").addEventListener("click", async () => { |
| await navigator.clipboard.writeText(command.textContent); |
| toast.classList.add("show"); |
| clearTimeout(window.toastTimer); |
| window.toastTimer = setTimeout(() => toast.classList.remove("show"), 1500); |
| }); |
|
|
| const connectPrompt = document.getElementById("connect-prompt"); |
| const connectAudio = document.getElementById("connect-audio"); |
| const connectContinue = document.getElementById("connect-continue"); |
| const connectClose = document.getElementById("connect-close"); |
| const connectStay = document.getElementById("connect-stay"); |
|
|
| document.querySelectorAll(".connect-link").forEach((link) => { |
| link.addEventListener("click", async (event) => { |
| event.preventDefault(); |
| connectContinue.href = link.href; |
| connectPrompt.hidden = false; |
| connectAudio.currentTime = 0; |
| try { |
| await connectAudio.play(); |
| } catch { |
| toast.textContent = "Tap Open link when ready"; |
| toast.classList.add("show"); |
| clearTimeout(window.toastTimer); |
| window.toastTimer = setTimeout(() => toast.classList.remove("show"), 1500); |
| } |
| }); |
| }); |
|
|
| function closeConnectPrompt() { |
| connectPrompt.hidden = true; |
| connectAudio.pause(); |
| connectAudio.currentTime = 0; |
| } |
|
|
| connectClose.addEventListener("click", closeConnectPrompt); |
| connectStay.addEventListener("click", closeConnectPrompt); |
| connectPrompt.addEventListener("click", (event) => { |
| if (event.target === connectPrompt) closeConnectPrompt(); |
| }); |
|
|
| window.addEventListener("resize", resize); |
| resize(); |
| draw(); |
| typeLoop(); |
|
|