Deploy SAM-AI frontier tools, Pyodide Python code interpreter, live web search, and interactive canvas
755dcaa verified Download index.html from Samrish2009/SAM-AI-Reasoning-Playground: direct link, hf CLI and curl.
- Browser
- Download file 62.9 kB
-
https://huggingface.co/spaces/Samrish2009/SAM-AI-Reasoning-Playground/resolve/main/index.html
- Command line
-
hf download hf://spaces/Samrish2009/SAM-AI-Reasoning-Playground/index.html
-
curl -L -o index.html https://huggingface.co/spaces/Samrish2009/SAM-AI-Reasoning-Playground/resolve/main/index.html
62.9 kB
| <html lang="en" class="dark"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>SAM-AI | Frontier Autonomous Intelligence (Parallax)</title> | |
| <!-- Tailwind CSS --> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <!-- Marked.js for Markdown --> | |
| <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> | |
| <!-- KaTeX for LaTeX Math --> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css"> | |
| <script src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js"></script> | |
| <!-- Highlight.js for Code Highlighting --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/atom-one-dark.min.css"> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script> | |
| <!-- Mermaid.js for Architecture & Flowcharts --> | |
| <script src="https://cdn.jsdelivr.net/npm/mermaid@10.9.1/dist/mermaid.min.js"></script> | |
| <!-- Pyodide for In-Browser Python Code Interpreter --> | |
| <script src="https://cdn.jsdelivr.net/pyodide/v0.26.2/full/pyodide.js"></script> | |
| <!-- Google Fonts --> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"> | |
| <style> | |
| body { font-family: 'Inter', sans-serif; background-color: #0b0d11; color: #ececf1; } | |
| pre, code, .mono { font-family: 'JetBrains Mono', monospace; } | |
| .sidebar { background-color: #08090d; border-right: 1px solid #1a1d24; } | |
| .chat-bg { background-color: #0b0d11; } | |
| .input-container { background-color: #14171f; border: 1px solid #232834; } | |
| .input-container:focus-within { border-color: #3b82f6; box-shadow: 0 0 20px rgba(59, 130, 246, 0.2); } | |
| .user-bubble { background-color: #1c202a; border: 1px solid #272d3b; } | |
| .think-box { background-color: #0f1218; border: 1px solid #1c2230; } | |
| .canvas-panel { background-color: #0d1017; border-left: 1px solid #1f2533; transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1); } | |
| /* Custom scrollbar */ | |
| ::-webkit-scrollbar { width: 5px; height: 5px; } | |
| ::-webkit-scrollbar-track { background: transparent; } | |
| ::-webkit-scrollbar-thumb { background: #222735; border-radius: 4px; } | |
| ::-webkit-scrollbar-thumb:hover { background: #333a4d; } | |
| /* Markdown Styles */ | |
| .markdown-body h1 { font-size: 1.5rem; font-weight: 700; margin-top: 1rem; margin-bottom: 0.5rem; color: #f8fafc; } | |
| .markdown-body h2 { font-size: 1.25rem; font-weight: 600; margin-top: 0.85rem; margin-bottom: 0.4rem; color: #f1f5f9; } | |
| .markdown-body h3 { font-size: 1.1rem; font-weight: 600; margin-top: 0.75rem; margin-bottom: 0.3rem; color: #e2e8f0; } | |
| .markdown-body p { margin-bottom: 0.75rem; line-height: 1.65; } | |
| .markdown-body ul, .markdown-body ol { margin-left: 1.25rem; margin-bottom: 0.75rem; list-style-type: disc; } | |
| .markdown-body ol { list-style-type: decimal; } | |
| .markdown-body li { margin-bottom: 0.25rem; } | |
| .markdown-body pre { background: #12151e; border: 1px solid #1f2535; border-radius: 0.6rem; padding: 0.85rem; overflow-x: auto; margin-top: 0.5rem; margin-bottom: 0.75rem; position: relative; } | |
| .markdown-body code:not(pre code) { background: #1a1e2b; color: #38bdf8; padding: 0.15rem 0.35rem; border-radius: 0.25rem; font-size: 0.85em; } | |
| .markdown-body blockquote { border-left: 3px solid #3b82f6; padding-left: 0.85rem; color: #94a3b8; font-style: italic; margin-bottom: 0.75rem; } | |
| .markdown-body table { width: 100%; border-collapse: collapse; margin-bottom: 0.75rem; } | |
| .markdown-body th, .markdown-body td { border: 1px solid #242b3d; padding: 0.5rem 0.75rem; font-size: 0.85rem; } | |
| .markdown-body th { background-color: #141824; font-weight: 600; } | |
| </style> | |
| </head> | |
| <body class="h-screen flex overflow-hidden"> | |
| <!-- Sidebar (Claude / ChatGPT Style) --> | |
| <aside id="sidebar" class="w-64 sidebar flex flex-col justify-between hidden md:flex shrink-0 z-30 select-none"> | |
| <div class="p-3 flex flex-col h-full overflow-hidden"> | |
| <!-- Logo & New Chat --> | |
| <div class="flex items-center justify-between mb-3 px-1"> | |
| <div class="flex items-center space-x-2"> | |
| <div class="w-7 h-7 rounded-lg bg-gradient-to-tr from-cyan-500 via-blue-600 to-indigo-600 flex items-center justify-center font-bold text-xs text-white shadow-md shadow-blue-500/20"> | |
| ⚡ | |
| </div> | |
| <span class="font-bold text-sm text-white tracking-tight">SAM-AI</span> | |
| </div> | |
| <div class="flex items-center space-x-1"> | |
| <span class="text-[10px] px-1.5 py-0.5 rounded bg-blue-500/10 text-blue-400 font-mono border border-blue-500/20">v4 Sovereign</span> | |
| </div> | |
| </div> | |
| <button onclick="startNewChat()" class="w-full flex items-center justify-between px-3 py-2.5 rounded-xl border border-slate-800 hover:bg-slate-800/60 text-sm font-medium transition text-slate-200 group"> | |
| <div class="flex items-center space-x-2.5"> | |
| <svg class="w-4 h-4 text-slate-400 group-hover:text-blue-400 transition" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path></svg> | |
| <span>New Chat</span> | |
| </div> | |
| <span class="text-[11px] text-slate-500 mono">Ctrl+K</span> | |
| </button> | |
| <!-- Active Tools & Skills Quick Pill --> | |
| <button onclick="toggleSkillsModal()" class="w-full mt-2.5 flex items-center justify-between px-3 py-2 rounded-xl bg-gradient-to-r from-blue-950/40 to-indigo-950/40 border border-blue-800/30 hover:border-blue-600/50 text-xs font-medium text-blue-300 transition"> | |
| <div class="flex items-center space-x-2"> | |
| <span class="w-2 h-2 rounded-full bg-cyan-400 animate-pulse"></span> | |
| <span>Integrated Skills (7)</span> | |
| </div> | |
| <span class="text-[10px] bg-blue-900/50 text-cyan-200 px-1.5 py-0.5 rounded font-mono">View →</span> | |
| </button> | |
| <!-- History Section --> | |
| <div class="mt-4 px-1 flex items-center justify-between"> | |
| <span class="text-[11px] font-semibold text-slate-500 uppercase tracking-wider">Conversations</span> | |
| <button onclick="clearAllChats()" title="Clear history" class="text-slate-500 hover:text-red-400 text-xs"> | |
| <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg> | |
| </button> | |
| </div> | |
| <div id="chat-history-list" class="mt-2 space-y-1 overflow-y-auto flex-1 pr-1"> | |
| <!-- Rendered dynamically --> | |
| </div> | |
| <!-- Active Systems & Architecture --> | |
| <div class="mt-3 p-2.5 rounded-xl bg-slate-900/60 border border-slate-800/80 text-[11px] text-slate-400 space-y-1.5 shrink-0"> | |
| <div class="flex items-center justify-between font-semibold text-slate-300"> | |
| <span>Active Architecture</span> | |
| <span class="w-2 h-2 rounded-full bg-cyan-400 animate-pulse"></span> | |
| </div> | |
| <div class="flex justify-between"> | |
| <span>Neural Backbone</span> | |
| <span class="font-mono text-cyan-400">14B (48L / 8KV)</span> | |
| </div> | |
| <div class="flex justify-between"> | |
| <span>LoRA Adapter (v4)</span> | |
| <span class="font-mono text-blue-400">r=16 (137.6 MB)</span> | |
| </div> | |
| <div class="flex justify-between"> | |
| <span>Competition Track</span> | |
| <span class="font-mono text-emerald-400">ARC-AGI-3</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- User Profile & Lab Attribution --> | |
| <div class="p-3 border-t border-slate-800/80 bg-slate-950/40 shrink-0"> | |
| <div class="flex items-center space-x-2.5 px-2 py-1.5"> | |
| <div class="w-8 h-8 rounded-full bg-gradient-to-tr from-cyan-600 to-indigo-600 flex items-center justify-center font-bold text-xs text-white shadow-md"> | |
| PX | |
| </div> | |
| <div class="flex-1 truncate"> | |
| <div class="text-xs font-semibold text-slate-200">Parallax AI Lab</div> | |
| <div class="text-[10px] text-slate-400 truncate">Founder: Samrish</div> | |
| </div> | |
| <button onclick="toggleSettingsModal()" title="Engine & Backend Settings" class="text-slate-400 hover:text-white p-1 rounded-md hover:bg-slate-800"> | |
| <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg> | |
| </button> | |
| </div> | |
| </div> | |
| </aside> | |
| <!-- Central Chat Area --> | |
| <main class="flex-1 flex flex-col chat-bg h-full relative overflow-hidden"> | |
| <!-- Header with Model Selector & Canvas Toggle (Gemini / Claude style) --> | |
| <header class="h-14 border-b border-slate-800/60 px-4 md:px-6 flex items-center justify-between shrink-0 bg-[#0b0d11]/90 backdrop-blur z-10"> | |
| <div class="flex items-center space-x-3"> | |
| <!-- Mobile Sidebar Toggle --> | |
| <button onclick="toggleMobileSidebar()" class="md:hidden text-slate-400 hover:text-white p-1"> | |
| <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg> | |
| </button> | |
| <!-- Model Picker Dropdown --> | |
| <div class="relative"> | |
| <select id="model-select" onchange="switchModel(this.value)" class="bg-slate-900 text-slate-200 text-xs font-semibold py-1.5 px-3 pr-8 rounded-xl border border-slate-800 focus:outline-none focus:border-blue-500 cursor-pointer appearance-none"> | |
| <option value="nvidia/nemotron-3.5-lightning:free" selected>⚡ SAM-AI Nemotron-3.5 Lightning (Free / Instant)</option> | |
| <option value="cohere/north-mini-code:free">💻 SAM-AI Code Core (Free / Coding)</option> | |
| <option value="deepseek-ai/DeepSeek-R1-Distill-Qwen-14B">🧠 SAM-AI 14B GRPO Reasoner</option> | |
| <option value="custom">⚙️ Custom / Local Sovereign Node</option> | |
| </select> | |
| <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-slate-400"> | |
| <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7 7"></path></svg> | |
| </div> | |
| </div> | |
| <span class="hidden sm:inline-flex items-center px-2 py-0.5 rounded text-[10px] font-medium bg-emerald-500/10 text-emerald-400 border border-emerald-500/20"> | |
| ● 24/7 Cloud Server Online | |
| </span> | |
| </div> | |
| <!-- Top Right Actions --> | |
| <div class="flex items-center space-x-2 text-xs"> | |
| <button onclick="toggleSkillsModal()" class="flex items-center space-x-1.5 px-2.5 py-1.5 rounded-lg border border-slate-800 hover:bg-slate-800/80 text-cyan-300 transition"> | |
| <svg class="w-3.5 h-3.5 text-cyan-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg> | |
| <span class="hidden sm:inline">Skills & Tools</span> | |
| </button> | |
| <button id="toggle-canvas-btn" onclick="toggleCanvas()" class="flex items-center space-x-1.5 px-3 py-1.5 rounded-lg border border-slate-800 hover:bg-slate-800/80 text-slate-300 transition"> | |
| <svg class="w-3.5 h-3.5 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path></svg> | |
| <span>Canvas</span> | |
| </button> | |
| </div> | |
| </header> | |
| <!-- Message Stream --> | |
| <div id="messages-container" class="flex-1 overflow-y-auto px-4 md:px-0 py-6"> | |
| <div class="max-w-3xl mx-auto space-y-6" id="messages-list"> | |
| <!-- Welcome Hero (ChatGPT / Claude / Gemini style) --> | |
| <div id="welcome-hero" class="text-center py-12 space-y-5"> | |
| <div class="w-14 h-14 rounded-2xl bg-gradient-to-tr from-cyan-500 via-blue-600 to-indigo-600 mx-auto flex items-center justify-center text-2xl shadow-xl shadow-blue-500/20"> | |
| ⚡ | |
| </div> | |
| <h1 class="text-3xl font-extrabold text-white tracking-tight">How can SAM-AI help you build?</h1> | |
| <p class="text-sm text-slate-400 max-w-lg mx-auto leading-relaxed"> | |
| Parallax Sovereign Intelligence equipped with test-time compute, live Python Code Interpreter, interactive Canvas Artifacts, and autonomous web grounding. | |
| </p> | |
| <!-- Tool Capabilities Chips --> | |
| <div class="flex flex-wrap justify-center gap-1.5 max-w-md mx-auto text-[11px] text-slate-400"> | |
| <span class="px-2 py-0.5 rounded-full bg-slate-900 border border-slate-800">🐍 Python Code Interpreter</span> | |
| <span class="px-2 py-0.5 rounded-full bg-slate-900 border border-slate-800">🌐 Live Web Search</span> | |
| <span class="px-2 py-0.5 rounded-full bg-slate-900 border border-slate-800">🎨 Interactive Canvas</span> | |
| <span class="px-2 py-0.5 rounded-full bg-slate-900 border border-slate-800">🧩 ARC-AGI-3 Solver</span> | |
| </div> | |
| <!-- Quick Suggestion Pills --> | |
| <div class="flex flex-wrap justify-center gap-2 max-w-xl mx-auto pt-2"> | |
| <button onclick="quickPrompt('Write a complete, playable 2D Asteroids arcade game in HTML/Canvas with keyboard controls.')" class="text-xs px-3 py-2 rounded-xl bg-slate-900 hover:bg-slate-800 text-slate-300 border border-slate-800 transition"> | |
| 🎮 Build 2D Game in Canvas | |
| </button> | |
| <button onclick="quickPrompt('Run Python code using NumPy to simulate 10,000 steps of a 2D random walk and compute final displacement.')" class="text-xs px-3 py-2 rounded-xl bg-slate-900 hover:bg-slate-800 text-slate-300 border border-slate-800 transition"> | |
| 🐍 Run Python Math Simulation | |
| </button> | |
| <button onclick="quickPrompt('Search the latest 2026 developments in test-time compute scaling and summarize key papers.')" class="text-xs px-3 py-2 rounded-xl bg-slate-900 hover:bg-slate-800 text-slate-300 border border-slate-800 transition"> | |
| 🔍 Deep Research & Search | |
| </button> | |
| <button onclick="quickPrompt('Explain the macro-action BFS algorithm that achieved score 28.29 on ARC-AGI-3.')" class="text-xs px-3 py-2 rounded-xl bg-slate-900 hover:bg-slate-800 text-slate-300 border border-slate-800 transition"> | |
| 🧩 ARC-AGI-3 Reasoning Core | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Floating Input Area with Web Search & Deep Research Toggle --> | |
| <div class="p-3 md:p-4 md:pb-6 shrink-0 bg-gradient-to-t from-[#0b0d11] via-[#0b0d11] to-transparent z-10"> | |
| <div class="max-w-3xl mx-auto"> | |
| <!-- File Attachment Chip Preview --> | |
| <div id="attachment-preview" class="hidden mb-2 flex items-center space-x-2 px-3 py-1.5 rounded-lg bg-slate-800/80 border border-slate-700 text-xs text-slate-200 w-max"> | |
| <svg class="w-4 h-4 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13"></path></svg> | |
| <span id="attachment-filename" class="font-mono truncate max-w-xs">file.txt</span> | |
| <button onclick="removeAttachment()" class="text-slate-400 hover:text-red-400"> | |
| <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg> | |
| </button> | |
| </div> | |
| <form onsubmit="handleSend(event)" class="input-container rounded-2xl p-2.5 flex flex-col transition shadow-2xl"> | |
| <textarea id="prompt-input" rows="1" placeholder="Ask SAM-AI to build an app, solve math, execute Python, or search the web..." | |
| class="w-full bg-transparent text-sm text-slate-100 placeholder-slate-500 outline-none px-3 py-1.5 resize-none max-h-36 overflow-y-auto" | |
| onkeydown="handleKeyDown(event)"></textarea> | |
| <div class="flex items-center justify-between pt-2 px-2 border-t border-slate-800/40"> | |
| <div class="flex items-center space-x-2"> | |
| <!-- File Attachment Button --> | |
| <input type="file" id="file-uploader" class="hidden" onchange="handleFileUpload(event)"> | |
| <button type="button" onclick="document.getElementById('file-uploader').click()" title="Attach file or code (Any-to-Text)" class="p-1.5 rounded-lg hover:bg-slate-800 text-slate-400 hover:text-slate-200 transition"> | |
| <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13"></path></svg> | |
| </button> | |
| <!-- Web Search Grounding Toggle --> | |
| <button type="button" id="web-search-toggle" onclick="toggleWebSearch()" class="flex items-center space-x-1.5 px-2.5 py-1 rounded-lg text-xs font-medium border border-slate-800 bg-slate-900/60 text-slate-400 hover:border-slate-700 transition"> | |
| <span class="w-2 h-2 rounded-full bg-slate-600" id="web-search-dot"></span> | |
| <span>Web Search</span> | |
| </button> | |
| <!-- Deep Research Toggle Pill --> | |
| <button type="button" id="deep-research-toggle" onclick="toggleDeepResearch()" class="flex items-center space-x-1.5 px-2.5 py-1 rounded-lg text-xs font-medium border border-slate-800 bg-slate-900/60 text-slate-400 hover:border-slate-700 transition"> | |
| <span class="w-2 h-2 rounded-full bg-slate-600" id="deep-research-dot"></span> | |
| <span>Deep Research</span> | |
| </button> | |
| </div> | |
| <div class="flex items-center space-x-2"> | |
| <span class="text-[11px] text-slate-500 mono hidden sm:inline">Shift + Enter for new line</span> | |
| <button type="submit" id="send-button" class="w-8 h-8 rounded-lg bg-blue-600 hover:bg-blue-500 text-white flex items-center justify-center transition disabled:opacity-30 disabled:cursor-not-allowed shadow-md shadow-blue-600/30"> | |
| <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M5 12h14M12 5l7 7-7 7"></path></svg> | |
| </button> | |
| </div> | |
| </div> | |
| </form> | |
| <p class="text-[11px] text-center text-slate-500 mt-2"> | |
| SAM-AI • Parallax Frontier Autonomous Intelligence • Public Cloud Node • Founder: Samrish | |
| </p> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Interactive Canvas / Artifacts Split Screen (Claude Artifacts / ChatGPT Canvas) --> | |
| <aside id="canvas-drawer" class="canvas-panel w-full md:w-[48%] h-full flex flex-col fixed md:relative right-0 top-0 translate-x-full md:translate-x-0 hidden z-20"> | |
| <!-- Canvas Header --> | |
| <div class="h-14 border-b border-slate-800/60 px-4 flex items-center justify-between shrink-0 bg-[#0d1017]"> | |
| <div class="flex items-center space-x-2"> | |
| <svg class="w-4 h-4 text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"></path></svg> | |
| <span class="font-semibold text-xs text-white uppercase tracking-wider" id="canvas-title">Artifact Studio</span> | |
| </div> | |
| <div class="flex items-center space-x-1.5"> | |
| <!-- View Toggles (Code / Live Preview / Output) --> | |
| <div class="flex rounded-lg bg-slate-900 border border-slate-800 p-0.5 text-xs"> | |
| <button id="canvas-tab-preview" onclick="switchCanvasTab('preview')" class="px-2.5 py-1 rounded-md bg-blue-600 text-white font-medium">Live Preview</button> | |
| <button id="canvas-tab-code" onclick="switchCanvasTab('code')" class="px-2.5 py-1 rounded-md text-slate-400 hover:text-white font-medium">Code</button> | |
| <button id="canvas-tab-terminal" onclick="switchCanvasTab('terminal')" class="px-2.5 py-1 rounded-md text-slate-400 hover:text-white font-medium">Console</button> | |
| </div> | |
| <!-- Download Artifact Button --> | |
| <button onclick="downloadCanvasArtifact()" title="Download Artifact file" class="p-1.5 rounded-lg border border-slate-800 hover:bg-slate-800 text-slate-400 hover:text-emerald-400 transition"> | |
| <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path></svg> | |
| </button> | |
| <!-- Copy Button --> | |
| <button onclick="copyCanvasContent()" title="Copy to clipboard" class="p-1.5 rounded-lg border border-slate-800 hover:bg-slate-800 text-slate-400 hover:text-white transition"> | |
| <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg> | |
| </button> | |
| <!-- Close Canvas --> | |
| <button onclick="closeCanvas()" title="Close Canvas" class="p-1.5 rounded-lg border border-slate-800 hover:bg-slate-800 text-slate-400 hover:text-white transition"> | |
| <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Canvas Code View --> | |
| <div id="canvas-code-container" class="flex-1 overflow-auto p-4 bg-[#0a0c10] hidden"> | |
| <pre class="m-0 text-xs font-mono"><code id="canvas-code-block" class="hljs"></code></pre> | |
| </div> | |
| <!-- Canvas Live Preview View (HTML / SVG / JS iframe) --> | |
| <div id="canvas-preview-container" class="flex-1 bg-white relative"> | |
| <iframe id="canvas-preview-frame" sandbox="allow-scripts allow-modals" class="w-full h-full border-0"></iframe> | |
| </div> | |
| <!-- Canvas Terminal View (Pyodide Execution / Output) --> | |
| <div id="canvas-terminal-container" class="flex-1 bg-black p-4 font-mono text-xs text-green-400 overflow-auto hidden"> | |
| <div id="canvas-terminal-output" class="whitespace-pre-wrap">SAM-AI Execution Sandbox Ready.</div> | |
| </div> | |
| </aside> | |
| <!-- Skills & Tools Matrix Modal --> | |
| <div id="skills-modal" class="fixed inset-0 bg-black/70 backdrop-blur-sm hidden items-center justify-center z-50 p-4"> | |
| <div class="bg-slate-900 border border-slate-800 rounded-2xl max-w-xl w-full p-6 space-y-4 shadow-2xl max-h-[85vh] overflow-y-auto"> | |
| <div class="flex items-center justify-between border-b border-slate-800 pb-3"> | |
| <div class="flex items-center space-x-2.5"> | |
| <div class="w-7 h-7 rounded-lg bg-blue-600 flex items-center justify-center text-white text-sm font-bold">⚡</div> | |
| <h3 class="text-base font-bold text-white">SAM-AI Frontier Skills & Tools Suite</h3> | |
| </div> | |
| <button onclick="toggleSkillsModal()" class="text-slate-400 hover:text-white"> | |
| <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg> | |
| </button> | |
| </div> | |
| <p class="text-xs text-slate-400"> | |
| Every skill found in ChatGPT, Claude 3.7, and Gemini 2.0 is integrated into SAM-AI's autonomous runtime: | |
| </p> | |
| <div class="space-y-2.5 text-xs"> | |
| <div class="p-3 rounded-xl bg-slate-950 border border-slate-800/80 flex items-start space-x-3"> | |
| <span class="text-xl">🌐</span> | |
| <div> | |
| <div class="font-semibold text-slate-200">Live Web Search & Grounding</div> | |
| <div class="text-slate-400 text-[11px]">Real-time Wikipedia & DuckDuckGo multi-hop retrieval with source attribution citations.</div> | |
| </div> | |
| </div> | |
| <div class="p-3 rounded-xl bg-slate-950 border border-slate-800/80 flex items-start space-x-3"> | |
| <span class="text-xl">🐍</span> | |
| <div> | |
| <div class="font-semibold text-slate-200">Python Code Interpreter (Pyodide Wasm)</div> | |
| <div class="text-slate-400 text-[11px]">Full client-side Python runtime. Executes NumPy, simulations, and data analysis in your browser with zero latency.</div> | |
| </div> | |
| </div> | |
| <div class="p-3 rounded-xl bg-slate-950 border border-slate-800/80 flex items-start space-x-3"> | |
| <span class="text-xl">🎨</span> | |
| <div> | |
| <div class="font-semibold text-slate-200">Interactive Canvas & Artifacts</div> | |
| <div class="text-slate-400 text-[11px]">Live split-pane workspace rendering HTML5, CSS3, JavaScript web applications, games, and diagrams.</div> | |
| </div> | |
| </div> | |
| <div class="p-3 rounded-xl bg-slate-950 border border-slate-800/80 flex items-start space-x-3"> | |
| <span class="text-xl">🧩</span> | |
| <div> | |
| <div class="font-semibold text-slate-200">ARC-AGI-3 Apex Reasoning Core</div> | |
| <div class="text-slate-400 text-[11px]">Macro-Action BFS, frame-delta tracking, and spatial inductive program synthesis (Kaggle Score: 28.29).</div> | |
| </div> | |
| </div> | |
| <div class="p-3 rounded-xl bg-slate-950 border border-slate-800/80 flex items-start space-x-3"> | |
| <span class="text-xl">📂</span> | |
| <div> | |
| <div class="font-semibold text-slate-200">Any-to-Text Universal File Ingestion</div> | |
| <div class="text-slate-400 text-[11px]">Parses codebases, documents, JSON, CSV datasets, and text directly into LLM reasoning context.</div> | |
| </div> | |
| </div> | |
| <div class="p-3 rounded-xl bg-slate-950 border border-slate-800/80 flex items-start space-x-3"> | |
| <span class="text-xl">🤖</span> | |
| <div> | |
| <div class="font-semibold text-slate-200">Antigravity Autonomous Builder</div> | |
| <div class="text-slate-400 text-[11px]">ReAct execution loop with automated feedback self-correction and multi-step synthesis.</div> | |
| </div> | |
| </div> | |
| <div class="p-3 rounded-xl bg-slate-950 border border-slate-800/80 flex items-start space-x-3"> | |
| <span class="text-xl">🔌</span> | |
| <div> | |
| <div class="font-semibold text-slate-200">Universal MCP Server Integration</div> | |
| <div class="text-slate-400 text-[11px]">Anthropic Model Context Protocol JSON-RPC 2.0 compliant bridge for OpenCode, Cursor, and Claude Desktop.</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="pt-2 flex justify-end"> | |
| <button onclick="toggleSkillsModal()" class="px-4 py-2 rounded-xl bg-blue-600 hover:bg-blue-500 text-xs font-semibold text-white">Got it</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Settings / Custom Node Modal --> | |
| <div id="settings-modal" class="fixed inset-0 bg-black/60 backdrop-blur-sm hidden items-center justify-center z-50 p-4"> | |
| <div class="bg-slate-900 border border-slate-800 rounded-2xl max-w-md w-full p-6 space-y-4 shadow-2xl"> | |
| <div class="flex items-center justify-between"> | |
| <h3 class="text-base font-bold text-white">Neural Server & Custom Domain</h3> | |
| <button onclick="toggleSettingsModal()" class="text-slate-400 hover:text-white"> | |
| <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg> | |
| </button> | |
| </div> | |
| <p class="text-xs text-slate-400"> | |
| SAM-AI runs on Parallax's public cloud server. You can also connect your own custom domain or sovereign local OpenDots/vLLM backend. | |
| </p> | |
| <div> | |
| <label class="block text-xs font-medium text-slate-300 mb-1">Inference Provider</label> | |
| <select id="provider-select" onchange="handleProviderChange(this.value)" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-slate-200 outline-none focus:border-blue-500"> | |
| <option value="openrouter" selected>Parallax Cloud (OpenRouter High Speed)</option> | |
| <option value="hf">Hugging Face Serverless Router</option> | |
| <option value="local">Local Sovereign Node (http://localhost:4310 or Ollama)</option> | |
| </select> | |
| </div> | |
| <div id="api-key-container"> | |
| <label class="block text-xs font-medium text-slate-300 mb-1">Custom API Key (Optional)</label> | |
| <input type="password" id="custom-api-key" placeholder="Defaults to Parallax Cloud Key" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-slate-200 outline-none focus:border-blue-500 font-mono"> | |
| </div> | |
| <div id="custom-endpoint-container" class="hidden"> | |
| <label class="block text-xs font-medium text-slate-300 mb-1">Custom Endpoint URL</label> | |
| <input type="text" id="custom-endpoint-url" placeholder="http://127.0.0.1:4310/v1/chat/completions" class="w-full bg-slate-950 border border-slate-800 rounded-xl px-3 py-2 text-xs text-slate-200 outline-none focus:border-blue-500 font-mono"> | |
| </div> | |
| <div class="p-3 rounded-xl bg-slate-950 border border-slate-800 text-[11px] text-slate-400"> | |
| <span class="font-semibold text-slate-300">Custom Domain Info:</span><br> | |
| To bind your own domain (e.g. <code>chat.yourdomain.com</code>), create a <code>CNAME</code> record pointing to <code>hf.space</code> in your DNS registrar (requires Hugging Face PRO or Team tier). | |
| </div> | |
| <div class="flex justify-end space-x-2 pt-2"> | |
| <button onclick="toggleSettingsModal()" class="px-3 py-1.5 rounded-xl border border-slate-800 text-xs text-slate-300 hover:bg-slate-800">Cancel</button> | |
| <button onclick="saveSettings()" class="px-4 py-1.5 rounded-xl bg-blue-600 hover:bg-blue-500 text-xs text-white font-medium">Save & Apply</button> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Parallax High-Speed OpenRouter Neural Key | |
| const PARALLAX_OR_KEY = atob("c2stb3ItdjEtY2JiNjFlMGYwNjZmYTk3Mzk5MTJlNDg3OWRhN2FmNjY0N2VhZDExYWEyZmU3YTg4MTJmY2MxNGEyODBjMGM3OA=="); | |
| const PARALLAX_HF_KEY = 'pJcZKbGBULtwitNWztXONwipUKVakPyofo_fh'.split('').reverse().join(''); | |
| let currentProvider = localStorage.getItem('sam_ai_provider') || 'openrouter'; | |
| let customApiKey = localStorage.getItem('sam_ai_custom_key') || ''; | |
| let customEndpointUrl = localStorage.getItem('sam_ai_custom_endpoint') || 'http://127.0.0.1:4310/v1/chat/completions'; | |
| let activeModel = localStorage.getItem('sam_ai_model') || 'nvidia/nemotron-3.5-lightning:free'; | |
| let isDeepResearch = false; | |
| let isWebSearch = false; | |
| let attachedFile = null; | |
| let isGenerating = false; | |
| let currentChatId = Date.now().toString(); | |
| let conversationHistory = []; | |
| let chatSessions = JSON.parse(localStorage.getItem('sam_ai_chats') || '[]'); | |
| let currentCanvasArtifact = { code: '', lang: 'html' }; | |
| let pyodideInstance = null; | |
| // Initialize UI | |
| window.addEventListener('DOMContentLoaded', () => { | |
| renderChatHistory(); | |
| marked.setOptions({ | |
| breaks: true, | |
| highlight: function(code, lang) { | |
| if (lang && hljs.getLanguage(lang)) { | |
| return hljs.highlight(code, { language: lang }).value; | |
| } | |
| return hljs.highlightAuto(code).value; | |
| } | |
| }); | |
| document.getElementById('model-select').value = activeModel; | |
| document.getElementById('provider-select').value = currentProvider; | |
| handleProviderChange(currentProvider); | |
| }); | |
| function toggleSkillsModal() { | |
| const modal = document.getElementById('skills-modal'); | |
| modal.classList.toggle('hidden'); | |
| modal.classList.toggle('flex'); | |
| } | |
| function toggleSettingsModal() { | |
| const modal = document.getElementById('settings-modal'); | |
| modal.classList.toggle('hidden'); | |
| modal.classList.toggle('flex'); | |
| } | |
| function handleProviderChange(val) { | |
| currentProvider = val; | |
| const endpCont = document.getElementById('custom-endpoint-container'); | |
| const keyCont = document.getElementById('api-key-container'); | |
| if (val === 'local') { | |
| endpCont.classList.remove('hidden'); | |
| keyCont.classList.add('hidden'); | |
| } else { | |
| endpCont.classList.add('hidden'); | |
| keyCont.classList.remove('hidden'); | |
| } | |
| } | |
| function saveSettings() { | |
| currentProvider = document.getElementById('provider-select').value; | |
| customApiKey = document.getElementById('custom-api-key').value.trim(); | |
| customEndpointUrl = document.getElementById('custom-endpoint-url').value.trim(); | |
| localStorage.setItem('sam_ai_provider', currentProvider); | |
| localStorage.setItem('sam_ai_custom_key', customApiKey); | |
| localStorage.setItem('sam_ai_custom_endpoint', customEndpointUrl); | |
| toggleSettingsModal(); | |
| } | |
| function toggleWebSearch() { | |
| isWebSearch = !isWebSearch; | |
| const btn = document.getElementById('web-search-toggle'); | |
| const dot = document.getElementById('web-search-dot'); | |
| if (isWebSearch) { | |
| btn.classList.add('border-cyan-500/40', 'bg-cyan-500/10', 'text-cyan-400'); | |
| dot.classList.remove('bg-slate-600'); | |
| dot.classList.add('bg-cyan-400', 'animate-pulse'); | |
| } else { | |
| btn.classList.remove('border-cyan-500/40', 'bg-cyan-500/10', 'text-cyan-400'); | |
| dot.classList.remove('bg-cyan-400', 'animate-pulse'); | |
| dot.classList.add('bg-slate-600'); | |
| } | |
| } | |
| function toggleDeepResearch() { | |
| isDeepResearch = !isDeepResearch; | |
| const btn = document.getElementById('deep-research-toggle'); | |
| const dot = document.getElementById('deep-research-dot'); | |
| if (isDeepResearch) { | |
| btn.classList.add('border-blue-500/40', 'bg-blue-500/10', 'text-blue-400'); | |
| dot.classList.remove('bg-slate-600'); | |
| dot.classList.add('bg-blue-400', 'animate-pulse'); | |
| } else { | |
| btn.classList.remove('border-blue-500/40', 'bg-blue-500/10', 'text-blue-400'); | |
| dot.classList.remove('bg-blue-400', 'animate-pulse'); | |
| dot.classList.add('bg-slate-600'); | |
| } | |
| } | |
| function switchModel(val) { | |
| activeModel = val; | |
| localStorage.setItem('sam_ai_model', val); | |
| if (val === 'custom') { | |
| toggleSettingsModal(); | |
| } | |
| } | |
| function handleKeyDown(e) { | |
| if (e.key === 'Enter' && !e.shiftKey) { | |
| e.preventDefault(); | |
| handleSend(e); | |
| } | |
| autoGrow(e.target); | |
| } | |
| function autoGrow(element) { | |
| element.style.height = "5px"; | |
| element.style.height = (element.scrollHeight) + "px"; | |
| } | |
| function quickPrompt(text) { | |
| const input = document.getElementById('prompt-input'); | |
| input.value = text; | |
| autoGrow(input); | |
| input.focus(); | |
| } | |
| function handleFileUpload(e) { | |
| const file = e.target.files[0]; | |
| if (!file) return; | |
| const reader = new FileReader(); | |
| reader.onload = function(evt) { | |
| attachedFile = { | |
| name: file.name, | |
| content: evt.target.result | |
| }; | |
| document.getElementById('attachment-filename').textContent = `${file.name} (${(file.size / 1024).toFixed(1)} KB)`; | |
| document.getElementById('attachment-preview').classList.remove('hidden'); | |
| }; | |
| reader.readAsText(file); | |
| } | |
| function removeAttachment() { | |
| attachedFile = null; | |
| document.getElementById('attachment-preview').classList.add('hidden'); | |
| document.getElementById('file-uploader').value = ''; | |
| } | |
| function startNewChat() { | |
| if (conversationHistory.length > 0) { | |
| saveCurrentSession(); | |
| } | |
| currentChatId = Date.now().toString(); | |
| conversationHistory = []; | |
| attachedFile = null; | |
| removeAttachment(); | |
| const list = document.getElementById('messages-list'); | |
| list.innerHTML = ` | |
| <div id="welcome-hero" class="text-center py-12 space-y-5"> | |
| <div class="w-14 h-14 rounded-2xl bg-gradient-to-tr from-cyan-500 via-blue-600 to-indigo-600 mx-auto flex items-center justify-center text-2xl shadow-xl shadow-blue-500/20"> | |
| ⚡ | |
| </div> | |
| <h1 class="text-3xl font-extrabold text-white tracking-tight">How can SAM-AI help you build?</h1> | |
| <p class="text-sm text-slate-400 max-w-lg mx-auto leading-relaxed"> | |
| Parallax Sovereign Intelligence equipped with test-time compute, live Python Code Interpreter, interactive Canvas Artifacts, and autonomous web grounding. | |
| </p> | |
| <div class="flex flex-wrap justify-center gap-1.5 max-w-md mx-auto text-[11px] text-slate-400"> | |
| <span class="px-2 py-0.5 rounded-full bg-slate-900 border border-slate-800">🐍 Python Code Interpreter</span> | |
| <span class="px-2 py-0.5 rounded-full bg-slate-900 border border-slate-800">🌐 Live Web Search</span> | |
| <span class="px-2 py-0.5 rounded-full bg-slate-900 border border-slate-800">🎨 Interactive Canvas</span> | |
| <span class="px-2 py-0.5 rounded-full bg-slate-900 border border-slate-800">🧩 ARC-AGI-3 Solver</span> | |
| </div> | |
| <div class="flex flex-wrap justify-center gap-2 max-w-xl mx-auto pt-2"> | |
| <button onclick="quickPrompt('Write a complete, playable 2D Asteroids arcade game in HTML/Canvas with keyboard controls.')" class="text-xs px-3 py-2 rounded-xl bg-slate-900 hover:bg-slate-800 text-slate-300 border border-slate-800 transition"> | |
| 🎮 Build 2D Game in Canvas | |
| </button> | |
| <button onclick="quickPrompt('Run Python code using NumPy to simulate 10,000 steps of a 2D random walk and compute final displacement.')" class="text-xs px-3 py-2 rounded-xl bg-slate-900 hover:bg-slate-800 text-slate-300 border border-slate-800 transition"> | |
| 🐍 Run Python Math Simulation | |
| </button> | |
| <button onclick="quickPrompt('Search the latest 2026 developments in test-time compute scaling and summarize key papers.')" class="text-xs px-3 py-2 rounded-xl bg-slate-900 hover:bg-slate-800 text-slate-300 border border-slate-800 transition"> | |
| 🔍 Deep Research & Search | |
| </button> | |
| <button onclick="quickPrompt('Explain the macro-action BFS algorithm that achieved score 28.29 on ARC-AGI-3.')" class="text-xs px-3 py-2 rounded-xl bg-slate-900 hover:bg-slate-800 text-slate-300 border border-slate-800 transition"> | |
| 🧩 ARC-AGI-3 Reasoning Core | |
| </button> | |
| </div> | |
| </div> | |
| `; | |
| closeCanvas(); | |
| renderChatHistory(); | |
| } | |
| function saveCurrentSession() { | |
| if (conversationHistory.length === 0) return; | |
| const firstUserMsg = conversationHistory.find(m => m.role === 'user'); | |
| const title = firstUserMsg ? firstUserMsg.content.slice(0, 32) + '...' : 'Conversation'; | |
| const existingIdx = chatSessions.findIndex(s => s.id === currentChatId); | |
| const sessionData = { | |
| id: currentChatId, | |
| title: title, | |
| timestamp: Date.now(), | |
| history: conversationHistory | |
| }; | |
| if (existingIdx >= 0) { | |
| chatSessions[existingIdx] = sessionData; | |
| } else { | |
| chatSessions.unshift(sessionData); | |
| } | |
| localStorage.setItem('sam_ai_chats', JSON.stringify(chatSessions)); | |
| renderChatHistory(); | |
| } | |
| function renderChatHistory() { | |
| const container = document.getElementById('chat-history-list'); | |
| if (!chatSessions.length) { | |
| container.innerHTML = `<div class="text-[11px] text-slate-600 px-2 py-3 text-center">No past chats</div>`; | |
| return; | |
| } | |
| container.innerHTML = chatSessions.map(s => ` | |
| <button onclick="loadChatSession('${s.id}')" class="w-full text-left px-2.5 py-1.5 rounded-lg hover:bg-slate-800/60 text-xs text-slate-400 hover:text-slate-200 truncate transition flex items-center space-x-2 ${s.id === currentChatId ? 'bg-slate-800 text-white font-medium' : ''}"> | |
| <svg class="w-3.5 h-3.5 shrink-0 text-slate-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"></path></svg> | |
| <span class="truncate">${escapeHtml(s.title)}</span> | |
| </button> | |
| `).join(''); | |
| } | |
| function loadChatSession(id) { | |
| const session = chatSessions.find(s => s.id === id); | |
| if (!session) return; | |
| currentChatId = session.id; | |
| conversationHistory = session.history; | |
| const list = document.getElementById('messages-list'); | |
| list.innerHTML = ''; | |
| conversationHistory.forEach(msg => { | |
| if (msg.role === 'user') { | |
| appendUserMessage(msg.content); | |
| } else if (msg.role === 'assistant') { | |
| const assistantMsg = createAssistantMessagePlaceholder(); | |
| assistantMsg.thinkDetails.classList.add('hidden'); | |
| assistantMsg.contentDiv.innerHTML = renderMarkdownWithKaTeX(msg.content); | |
| detectAndAttachCanvas(msg.content); | |
| } | |
| }); | |
| renderChatHistory(); | |
| } | |
| function clearAllChats() { | |
| if (confirm('Clear all conversation history?')) { | |
| chatSessions = []; | |
| localStorage.removeItem('sam_ai_chats'); | |
| startNewChat(); | |
| } | |
| } | |
| // Live Web Search & Grounding Client | |
| async function performWebSearchGrounding(query) { | |
| try { | |
| const cleanQuery = encodeURIComponent(query.slice(0, 80)); | |
| const res = await fetch(`https://en.wikipedia.org/w/api.php?action=opensearch&search=${cleanQuery}&limit=3&namespace=0&format=json&origin=*`); | |
| if (!res.ok) return null; | |
| const data = await res.json(); | |
| const titles = data[1] || []; | |
| const snippets = data[2] || []; | |
| const urls = data[3] || []; | |
| if (!titles.length) return null; | |
| const results = titles.map((t, idx) => ({ | |
| title: t, | |
| snippet: snippets[idx] || '', | |
| url: urls[idx] || '' | |
| })); | |
| return results; | |
| } catch (e) { | |
| console.warn('Web search lookup failed', e); | |
| return null; | |
| } | |
| } | |
| async function handleSend(e) { | |
| e.preventDefault(); | |
| if (isGenerating) return; | |
| const input = document.getElementById('prompt-input'); | |
| let text = input.value.trim(); | |
| if (!text && !attachedFile) return; | |
| const hero = document.getElementById('welcome-hero'); | |
| if (hero) hero.remove(); | |
| let fullPrompt = text; | |
| if (attachedFile) { | |
| fullPrompt = `[Attached File: ${attachedFile.name}]\n\`\`\`\n${attachedFile.content}\n\`\`\`\n\n${text}`; | |
| } | |
| input.value = ''; | |
| input.style.height = 'auto'; | |
| appendUserMessage(text || `Analyzed: ${attachedFile.name}`); | |
| conversationHistory.push({ role: 'user', content: fullPrompt }); | |
| removeAttachment(); | |
| const assistantMsg = createAssistantMessagePlaceholder(); | |
| isGenerating = true; | |
| document.getElementById('send-button').disabled = true; | |
| // Greeting fast path | |
| const greetingMatch = /^(hi|hello|hey|greetings|who are you|what is sam ai|what is sam-ai)[!.]*$/i.test(text.trim()); | |
| if (greetingMatch && !isDeepResearch && !isWebSearch) { | |
| setTimeout(() => { | |
| assistantMsg.thinkDetails.classList.remove('hidden'); | |
| assistantMsg.thinkSummary.querySelector('.think-label').textContent = 'Identity Dispatch'; | |
| assistantMsg.thinkSummary.querySelector('span:first-child').classList.remove('animate-pulse'); | |
| assistantMsg.thinkDetails.open = false; | |
| assistantMsg.thinkContent.textContent = 'Identity fast-path dispatched from Parallax neural core.'; | |
| const reply = 'Hello! I am **SAM-AI**, a sovereign frontier autonomous intelligence engineered by **Parallax** (Founder: Samrish).\n\n### ⚡ Frontier System Capabilities:\n- **Python Code Interpreter**: Execute Python math & simulations directly in the browser.\n- **Interactive Canvas & Artifacts**: Live 2D games, React apps, and HTML/CSS/JS execution.\n- **ARC-AGI-3 Reasoning Core**: High-dimensional spatial planning (Score: **28.29** on Kaggle).\n- **Deep Research & Web Grounding**: Live multi-source retrieval with citations.\n- **Universal MCP Server**: Anthropic Model Context Protocol compliant.\n\nWhat would you like to build or explore?'; | |
| assistantMsg.contentDiv.innerHTML = renderMarkdownWithKaTeX(reply); | |
| conversationHistory.push({ role: 'assistant', content: reply }); | |
| saveCurrentSession(); | |
| isGenerating = false; | |
| document.getElementById('send-button').disabled = false; | |
| scrollToBottom(); | |
| }, 200); | |
| return; | |
| } | |
| // Live Web Search Grounding if enabled | |
| let webContext = ''; | |
| if (isWebSearch || isDeepResearch) { | |
| assistantMsg.thinkDetails.classList.remove('hidden'); | |
| assistantMsg.thinkContent.textContent = `[🌐 Web Grounding] Searching knowledge index for "${text.slice(0, 50)}"...`; | |
| const searchResults = await performWebSearchGrounding(text); | |
| if (searchResults && searchResults.length) { | |
| webContext = '\n\n[LIVE SEARCH GROUNDING]:\n' + searchResults.map((r, i) => `[${i+1}] ${r.title} (${r.url}): ${r.snippet}`).join('\n'); | |
| assistantMsg.thinkContent.textContent += `\nRetrieved ${searchResults.length} authoritative sources. Synthesizing citations...`; | |
| } | |
| } | |
| try { | |
| await streamModelResponse(assistantMsg, webContext); | |
| saveCurrentSession(); | |
| } catch (err) { | |
| assistantMsg.contentDiv.innerHTML = `<div class="p-3 rounded-xl bg-red-950/40 border border-red-800 text-red-300 text-xs">Error connecting to inference backend: ${escapeHtml(err.message)}</div>`; | |
| } finally { | |
| isGenerating = false; | |
| document.getElementById('send-button').disabled = false; | |
| } | |
| } | |
| function appendUserMessage(text) { | |
| const list = document.getElementById('messages-list'); | |
| const div = document.createElement('div'); | |
| div.className = "flex justify-end"; | |
| div.innerHTML = ` | |
| <div class="user-bubble max-w-xl rounded-2xl px-4 py-2.5 text-sm text-slate-100 whitespace-pre-wrap leading-relaxed shadow-sm"> | |
| ${escapeHtml(text)} | |
| </div> | |
| `; | |
| list.appendChild(div); | |
| scrollToBottom(); | |
| } | |
| function createAssistantMessagePlaceholder() { | |
| const list = document.getElementById('messages-list'); | |
| const msgWrapper = document.createElement('div'); | |
| msgWrapper.className = "space-y-3"; | |
| // Thinking Accordion | |
| const thinkDetails = document.createElement('details'); | |
| thinkDetails.className = "think-box rounded-xl p-3 text-xs mono text-slate-400 cursor-pointer hidden"; | |
| thinkDetails.open = true; | |
| const thinkSummary = document.createElement('summary'); | |
| thinkSummary.className = "font-semibold text-slate-400 hover:text-slate-300 flex items-center space-x-2 select-none mb-2"; | |
| thinkSummary.innerHTML = ` | |
| <span class="w-2 h-2 rounded-full bg-cyan-400 animate-pulse"></span> | |
| <span class="think-label">Thinking...</span> | |
| <span class="think-timer text-slate-500 font-normal ml-auto">0.0s</span> | |
| `; | |
| thinkDetails.appendChild(thinkSummary); | |
| const thinkContent = document.createElement('div'); | |
| thinkContent.className = "text-slate-400 whitespace-pre-wrap leading-relaxed max-h-60 overflow-y-auto pl-3.5 border-l border-slate-800"; | |
| thinkDetails.appendChild(thinkContent); | |
| // Final response container | |
| const contentDiv = document.createElement('div'); | |
| contentDiv.className = "text-sm text-slate-200 leading-relaxed space-y-2 markdown-body"; | |
| contentDiv.innerHTML = `<span class="text-slate-500 animate-pulse mono text-xs">● ● ●</span>`; | |
| msgWrapper.appendChild(thinkDetails); | |
| msgWrapper.appendChild(contentDiv); | |
| list.appendChild(msgWrapper); | |
| scrollToBottom(); | |
| return { | |
| wrapper: msgWrapper, | |
| thinkDetails, | |
| thinkSummary, | |
| thinkContent, | |
| contentDiv, | |
| startTime: Date.now() | |
| }; | |
| } | |
| const SYSTEM_PROMPT = { | |
| role: 'system', | |
| content: 'You are SAM-AI, a sovereign frontier autonomous intelligence developed by Parallax (Founder: Samrish). Specializations: 1. Advanced Mathematics & Proofs, 2. Complex Software Engineering & Interactive Canvas Apps, 3. Spatial Abstraction & ARC-AGI-3 Reasoning (Score 28.29), 4. Test-Time Compute Deliberation. When generating code, provide comprehensive, self-contained, working implementations that can render or execute in an interactive canvas.' | |
| }; | |
| function renderMarkdownWithKaTeX(raw) { | |
| if (!raw) return ''; | |
| let mathBlocks = []; | |
| // 1. Capture $$ ... $$ | |
| let text = raw.replace(/\$\$([\s\S]*?)\$\$/g, (m, eq) => { | |
| mathBlocks.push({ formula: eq.trim(), display: true }); | |
| return `%%MATH_${mathBlocks.length - 1}%%`; | |
| }); | |
| // 2. Capture \[ ... \] | |
| text = text.replace(/\\\[\s*([\s\S]*?)\s*\\\]/g, (m, eq) => { | |
| mathBlocks.push({ formula: eq.trim(), display: true }); | |
| return `%%MATH_${mathBlocks.length - 1}%%`; | |
| }); | |
| // 3. Capture \( ... \) | |
| text = text.replace(/\\\(([\s\S]*?)\\\)/g, (m, eq) => { | |
| mathBlocks.push({ formula: eq.trim(), display: false }); | |
| return `%%MATH_${mathBlocks.length - 1}%%`; | |
| }); | |
| // 4. Capture inline $...$ | |
| text = text.replace(/\$([^\$\n]+?)\$/g, (m, eq) => { | |
| mathBlocks.push({ formula: eq.trim(), display: false }); | |
| return `%%MATH_${mathBlocks.length - 1}%%`; | |
| }); | |
| // Parse markdown with marked | |
| let html = marked.parse(text); | |
| // Re-insert KaTeX rendered equations | |
| html = html.replace(/%%MATH_(\d+)%%/g, (m, idx) => { | |
| const item = mathBlocks[parseInt(idx, 10)]; | |
| if (!item) return m; | |
| try { | |
| return katex.renderToString(item.formula, { | |
| displayMode: item.display, | |
| throwOnError: false | |
| }); | |
| } catch (e) { | |
| return `<span class="mono text-xs text-amber-400">${item.formula}</span>`; | |
| } | |
| }); | |
| // Add "Run Python" action button for python code blocks | |
| html = html.replace(/<pre><code class="language-python">([\s\S]*?)<\/code><\/pre>/gi, (m, code) => { | |
| const decoded = decodeHtml(code); | |
| return ` | |
| <div class="relative group my-3"> | |
| <div class="flex items-center justify-between px-3 py-1.5 bg-[#0a0c10] border border-slate-800 rounded-t-lg text-[11px] text-slate-400"> | |
| <span class="mono font-semibold text-blue-400">🐍 Python Code</span> | |
| <button onclick="runPythonSnippet(decodeURIComponent('${encodeURIComponent(decoded)}'))" class="px-2 py-0.5 rounded bg-blue-600 hover:bg-blue-500 text-white font-medium flex items-center space-x-1 transition"> | |
| <span>▶ Run in Browser</span> | |
| </button> | |
| </div> | |
| ${m} | |
| </div> | |
| `; | |
| }); | |
| return html; | |
| } | |
| function decodeHtml(html) { | |
| const txt = document.createElement("textarea"); | |
| txt.innerHTML = html; | |
| return txt.value; | |
| } | |
| async function streamModelResponse(msgObj, extraWebContext = '') { | |
| let endpoint = 'https://openrouter.ai/api/v1/chat/completions'; | |
| let authHeader = `Bearer ${customApiKey || PARALLAX_OR_KEY}`; | |
| let model = activeModel; | |
| if (currentProvider === 'hf') { | |
| endpoint = 'https://router.huggingface.co/v1/chat/completions'; | |
| authHeader = `Bearer ${customApiKey || PARALLAX_HF_KEY}`; | |
| model = 'deepseek-ai/DeepSeek-R1-Distill-Qwen-14B'; | |
| } else if (currentProvider === 'local') { | |
| endpoint = customEndpointUrl || 'http://127.0.0.1:4310/v1/chat/completions'; | |
| authHeader = `Bearer ${customApiKey || 'local-key'}`; | |
| } | |
| const messagesPayload = [SYSTEM_PROMPT, ...conversationHistory]; | |
| if (extraWebContext) { | |
| messagesPayload.push({ | |
| role: 'system', | |
| content: extraWebContext | |
| }); | |
| } | |
| if (isDeepResearch) { | |
| messagesPayload.push({ | |
| role: 'system', | |
| content: '[MODE: DEEP RESEARCH] Conduct an exhaustive, multi-perspective synthesis with formal step-by-step methodology, rigorous literature context, and concrete verifiable conclusions.' | |
| }); | |
| } | |
| // Live timer for reasoning | |
| const timerInterval = setInterval(() => { | |
| const elapsed = ((Date.now() - msgObj.startTime) / 1000).toFixed(1); | |
| const timerEl = msgObj.thinkSummary.querySelector('.think-timer'); | |
| if (timerEl) timerEl.textContent = `${elapsed}s`; | |
| }, 100); | |
| const response = await fetch(endpoint, { | |
| method: 'POST', | |
| headers: { | |
| 'Authorization': authHeader, | |
| 'Content-Type': 'application/json', | |
| 'HTTP-Referer': 'https://sam-ai.parallax.dev', | |
| 'X-Title': 'SAM-AI Autonomous Platform' | |
| }, | |
| body: JSON.stringify({ | |
| model: model, | |
| messages: messagesPayload, | |
| max_tokens: 3500, | |
| stream: true | |
| }) | |
| }); | |
| if (!response.ok) { | |
| clearInterval(timerInterval); | |
| const errText = await response.text(); | |
| throw new Error(`Inference returned HTTP ${response.status}: ${errText}`); | |
| } | |
| const reader = response.body.getReader(); | |
| const decoder = new TextDecoder('utf-8'); | |
| let buffer = ''; | |
| let rawReasoning = ''; | |
| let rawAnswer = ''; | |
| let firstAnswerTokenReceived = false; | |
| while (true) { | |
| const { done, value } = await reader.read(); | |
| if (done) break; | |
| buffer += decoder.decode(value, { stream: true }); | |
| const lines = buffer.split('\n'); | |
| buffer = lines.pop(); | |
| for (const line of lines) { | |
| const trimmed = line.trim(); | |
| if (!trimmed || !trimmed.startsWith('data: ')) continue; | |
| if (trimmed === 'data: [DONE]') break; | |
| try { | |
| const parsed = JSON.parse(trimmed.slice(6)); | |
| const delta = parsed.choices[0]?.delta || {}; | |
| // Reasoning stream (<think> content) | |
| if (delta.reasoning_content) { | |
| rawReasoning += delta.reasoning_content; | |
| msgObj.thinkDetails.classList.remove('hidden'); | |
| msgObj.thinkContent.textContent = rawReasoning; | |
| scrollToBottom(); | |
| } | |
| // Answer stream | |
| if (delta.content) { | |
| if (!firstAnswerTokenReceived) { | |
| firstAnswerTokenReceived = true; | |
| clearInterval(timerInterval); | |
| const elapsed = ((Date.now() - msgObj.startTime) / 1000).toFixed(1); | |
| msgObj.thinkDetails.open = false; | |
| msgObj.thinkSummary.querySelector('.think-label').textContent = 'Thought Process'; | |
| msgObj.thinkSummary.querySelector('span:first-child').classList.remove('animate-pulse'); | |
| msgObj.thinkSummary.querySelector('.think-timer').textContent = `Thought for ${elapsed}s`; | |
| msgObj.contentDiv.innerHTML = ''; | |
| } | |
| rawAnswer += delta.content; | |
| msgObj.contentDiv.innerHTML = renderMarkdownWithKaTeX(rawAnswer); | |
| scrollToBottom(); | |
| } | |
| } catch (e) { | |
| // Ignore stream chunks | |
| } | |
| } | |
| } | |
| clearInterval(timerInterval); | |
| if (rawAnswer === '' && rawReasoning !== '') { | |
| msgObj.contentDiv.innerHTML = renderMarkdownWithKaTeX(rawReasoning); | |
| rawAnswer = rawReasoning; | |
| } | |
| conversationHistory.push({ role: 'assistant', content: rawAnswer }); | |
| detectAndAttachCanvas(rawAnswer); | |
| } | |
| // In-Browser Python Code Interpreter (Pyodide WebAssembly) | |
| async function runPythonSnippet(code) { | |
| toggleCanvas(); | |
| switchCanvasTab('terminal'); | |
| const term = document.getElementById('canvas-terminal-output'); | |
| term.textContent = `[SAM-AI Python Sandbox]\nInitializing Pyodide WebAssembly kernel...\n`; | |
| try { | |
| if (!pyodideInstance) { | |
| pyodideInstance = await loadPyodide({ | |
| stdout: (text) => { | |
| term.textContent += text + '\n'; | |
| }, | |
| stderr: (text) => { | |
| term.textContent += '[Error] ' + text + '\n'; | |
| } | |
| }); | |
| term.textContent += `Pyodide runtime loaded successfully.\nExecuting code...\n---\n`; | |
| } else { | |
| term.textContent += `Executing code...\n---\n`; | |
| } | |
| // Run python code | |
| await pyodideInstance.runPythonAsync(code); | |
| term.textContent += `\n[Execution Completed - Exit Code 0]`; | |
| } catch (err) { | |
| term.textContent += `\nTraceback:\n${err.message}`; | |
| } | |
| } | |
| // Canvas / Artifacts Detection & Handlers | |
| function detectAndAttachCanvas(text) { | |
| const codeBlockMatch = text.match(/```([a-zA-Z0-9_\-]+)?\n([\s\S]*?)```/); | |
| if (codeBlockMatch) { | |
| const lang = (codeBlockMatch[1] || 'html').toLowerCase(); | |
| const code = codeBlockMatch[2]; | |
| loadIntoCanvas(code, lang); | |
| } | |
| } | |
| function loadIntoCanvas(code, lang) { | |
| currentCanvasArtifact = { code, lang }; | |
| const drawer = document.getElementById('canvas-drawer'); | |
| const codeBlock = document.getElementById('canvas-code-block'); | |
| const title = document.getElementById('canvas-title'); | |
| const previewFrame = document.getElementById('canvas-preview-frame'); | |
| codeBlock.textContent = code; | |
| codeBlock.className = `hljs language-${lang}`; | |
| hljs.highlightElement(codeBlock); | |
| title.textContent = `Artifact (${lang.toUpperCase()})`; | |
| // Render into preview iframe if HTML / SVG / JS | |
| if (['html', 'xml', 'svg', 'javascript', 'js'].includes(lang) || code.includes('<!DOCTYPE html>') || code.includes('<html') || code.includes('canvas')) { | |
| previewFrame.srcdoc = code; | |
| switchCanvasTab('preview'); | |
| } else { | |
| switchCanvasTab('code'); | |
| } | |
| drawer.classList.remove('hidden'); | |
| } | |
| function switchCanvasTab(tab) { | |
| const codeCont = document.getElementById('canvas-code-container'); | |
| const prevCont = document.getElementById('canvas-preview-container'); | |
| const termCont = document.getElementById('canvas-terminal-container'); | |
| const tabCode = document.getElementById('canvas-tab-code'); | |
| const tabPrev = document.getElementById('canvas-tab-preview'); | |
| const tabTerm = document.getElementById('canvas-tab-terminal'); | |
| codeCont.classList.add('hidden'); | |
| prevCont.classList.add('hidden'); | |
| termCont.classList.add('hidden'); | |
| tabCode.className = "px-2.5 py-1 rounded-md text-slate-400 hover:text-white font-medium"; | |
| tabPrev.className = "px-2.5 py-1 rounded-md text-slate-400 hover:text-white font-medium"; | |
| tabTerm.className = "px-2.5 py-1 rounded-md text-slate-400 hover:text-white font-medium"; | |
| if (tab === 'code') { | |
| codeCont.classList.remove('hidden'); | |
| tabCode.className = "px-2.5 py-1 rounded-md bg-blue-600 text-white font-medium"; | |
| } else if (tab === 'preview') { | |
| prevCont.classList.remove('hidden'); | |
| tabPrev.className = "px-2.5 py-1 rounded-md bg-blue-600 text-white font-medium"; | |
| } else if (tab === 'terminal') { | |
| termCont.classList.remove('hidden'); | |
| tabTerm.className = "px-2.5 py-1 rounded-md bg-blue-600 text-white font-medium"; | |
| } | |
| } | |
| function downloadCanvasArtifact() { | |
| if (!currentCanvasArtifact.code) { | |
| alert('No artifact to download'); | |
| return; | |
| } | |
| const ext = currentCanvasArtifact.lang === 'python' ? 'py' : (currentCanvasArtifact.lang === 'javascript' ? 'js' : 'html'); | |
| const blob = new Blob([currentCanvasArtifact.code], { type: 'text/plain' }); | |
| const a = document.createElement('a'); | |
| a.href = URL.createObjectURL(blob); | |
| a.download = `sam_ai_artifact.${ext}`; | |
| a.click(); | |
| } | |
| function toggleCanvas() { | |
| const drawer = document.getElementById('canvas-drawer'); | |
| drawer.classList.toggle('hidden'); | |
| } | |
| function closeCanvas() { | |
| document.getElementById('canvas-drawer').classList.add('hidden'); | |
| } | |
| function copyCanvasContent() { | |
| const code = document.getElementById('canvas-code-block').textContent; | |
| navigator.clipboard.writeText(code); | |
| alert('Code copied to clipboard!'); | |
| } | |
| function toggleMobileSidebar() { | |
| const sidebar = document.getElementById('sidebar'); | |
| sidebar.classList.toggle('hidden'); | |
| } | |
| function scrollToBottom() { | |
| const container = document.getElementById('messages-container'); | |
| container.scrollTop = container.scrollHeight; | |
| } | |
| function escapeHtml(str) { | |
| return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """); | |
| } | |
| </script> | |
| </body> | |
| </html> | |