Rubibot🧠
Human-like Experimental AGI
🎤 Try RubiNet: Voice Assistant →Try RubiCoder →
How to use it?
1) Optional: Enter OpenRouter API key for premium models (GPT-5.6, Claude Opus 4.8, etc.)
2) Free mode: Leave API key empty to use DeepSeek-V4-Flash (no key needed)
3) Type a message or upload an image
4) Click Send
Pricing Contact & Partnership
For 3 days, free plan message limit has been increased to 50 🏆
preview
No image attached
No files attached
Stream (faster response)
Enable Internet Search
Planner off
Debug (show server debug blob)
Click mic to speak
Read reply aloud (TTS)
Identify music (Shazam)
Commands:
/coding on   /coding off
/engineering <topic>
/science <topic>
/3ddesign <topic> NEW
/datavisualization <query> NEW
/research <query> NEW
/imagegenerate <description> PLUS
/musicgenerate <description> PRO
/videogenerate <description> PRO
/internet <query>
Free mode: 50 messages per day with DeepSeek-V4-Flash (no API key)
Premium mode: Enter API key for GPT-5.6 etc. (billing to your key)
Upgrade RubiBot
Plus $7/mo — 50 msg/day, 20K coding tokens
Pro $30/mo — Unlimited messages, 32K coding tokens, 2x larger answer capability
View Plans
`; div.querySelector(".html-content").appendChild(iframe); chat.appendChild(div); } else { addBot(m.content); } } else { // Check if assistant content contains HTML (research, 3ddesign, etc.) const _hasHtml = m.content.includes("RubiBot:
`; const iframe = document.createElement("iframe"); iframe.style.cssText = "width:100%;height:800px;border:1px solid rgba(255,255,255,0.1);border-radius:10px;margin-top:8px;display:block;overflow:auto;"; iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms allow-modals allow-popups allow-downloads"); const _blob = new Blob([`${m.content}`], {type: "text/html"}); const _blobUrl = URL.createObjectURL(_blob); iframe.src = _blobUrl; iframe.onload = () => URL.revokeObjectURL(_blobUrl); div.querySelector(".html-content").appendChild(iframe); chat.appendChild(div); } else { addBot(m.content); } } } }); chat.scrollTop = chat.scrollHeight; } catch (err) { addErr("Failed to load messages: " + err.message); } } document.getElementById("newChatBtn").addEventListener("click", () => { currentConvId = null; chatLog = []; isSharedView = false; chat.innerHTML = ""; updateShareBtn(); renderConvList(); // Close sidebar on mobile after clicking new chat if (window.innerWidth <= 900) { convSidebar.classList.remove("show"); sidebarBackdrop.classList.remove("active"); } }); // Mobile new chat button document.addEventListener("DOMContentLoaded", () => { const mobileNewBtn = document.getElementById("mobileNewChatBtn"); if (mobileNewBtn) { mobileNewBtn.addEventListener("click", () => { currentConvId = null; chatLog = []; isSharedView = false; chat.innerHTML = ""; updateShareBtn(); renderConvList(); }); } }); // ── Mobile long-press delete popup ─────────────────────── let _mobileDelTargetId = null; const _mobileDelPopup = document.getElementById("mobileDelPopup"); const _mobileDelBtn = document.getElementById("mobileDelBtn"); function showMobileDelPopup(convId, x, y) { _mobileDelTargetId = convId; _mobileDelPopup.style.left = Math.min(x, window.innerWidth - 200) + "px"; _mobileDelPopup.style.top = Math.max(y - 60, 8) + "px"; _mobileDelPopup.classList.add("show"); } function hideMobileDelPopup() { _mobileDelPopup.classList.remove("show"); _mobileDelTargetId = null; } _mobileDelBtn.addEventListener("click", async () => { if (!_mobileDelTargetId) return; hideMobileDelPopup(); if (!confirm("Delete this conversation?")) return; try { await authApi(`/conversations/${_mobileDelTargetId}`, { method: "DELETE" }); if (currentConvId === _mobileDelTargetId) { currentConvId = null; chat.innerHTML = ""; } loadConversations(); } catch (err) { alert(err.message); } }); document.addEventListener("touchstart", (e) => { if (_mobileDelPopup.classList.contains("show") && !_mobileDelPopup.contains(e.target)) { hideMobileDelPopup(); } }, { passive: true }); document.addEventListener("click", (e) => { if (_mobileDelPopup.classList.contains("show") && !_mobileDelPopup.contains(e.target)) { hideMobileDelPopup(); } }); // Auto-create conversation on first message if logged in async function ensureConversation(firstMsgText) { if (isGuest || currentConvId) return; try { const title = firstMsgText.substring(0, 40) + (firstMsgText.length > 40 ? "..." : ""); const data = await authApi("/conversations", { method: "POST", body: JSON.stringify({ title }), }); currentConvId = data.conversation.id; loadConversations(); } catch (err) { console.error("Auto-create conversation failed:", err); } } // ========================================================= // SUBSCRIPTION / PLUS / PRO // ========================================================= const planBadge = document.getElementById("planBadge"); const planUsageText = document.getElementById("planUsageText"); const planUsageBar = document.getElementById("planUsageBar"); const upgradeBtn = document.getElementById("upgradeBtn"); const plusOverlay = document.getElementById("plusOverlay"); const plusCloseBtn = document.getElementById("plusCloseBtn"); const plusBuyBtn = document.getElementById("plusBuyBtn"); const proBuyBtn = document.getElementById("proBuyBtn"); const plusBanner = document.getElementById("plusBanner"); let currentPlan = "FREE"; async function loadSubscription() { if (isGuest || !currentUser) { planBadge.textContent = "FREE"; planBadge.className = "plan-badge free"; // Fetch session stats for guest users try { const response = await fetch(CORE_BASE + "/rate-limit/stats", { method: "GET", headers: { "X-Session-Id": sessionId } }); const sessionData = await response.json(); if (sessionData?.session) { const used = sessionData.session.used || 0; const limit = sessionData.session.limit || getCurrentFreeLimit(); planUsageText.textContent = `${used} / ${limit} messages`; planUsageBar.style.width = Math.min(100, (used / limit) * 100) + "%"; } else { planUsageText.textContent = `0 / ${getCurrentFreeLimit()} messages`; planUsageBar.style.width = "0%"; } } catch (err) { console.error("[SESSION] Failed to load session stats:", err); planUsageText.textContent = `0 / ${getCurrentFreeLimit()} messages`; planUsageBar.style.width = "0%"; } upgradeBtn.classList.remove("hidden"); plusBanner.classList.remove("hidden"); return; } try { const data = await authApi("/billing/subscription"); currentPlan = data.plan || "FREE"; const isPaid = (currentPlan === "PLUS" || currentPlan === "PRO") && data.is_active; const isPro = currentPlan === "PRO" && data.is_active; planBadge.textContent = isPro ? "PRO" : (isPaid ? "PLUS" : "FREE"); planBadge.className = isPro ? "plan-badge pro" : (isPaid ? "plan-badge plus" : "plan-badge free"); const dm = data.daily_messages || {}; const used = dm.used || 0; const limit = dm.limit || getCurrentFreeLimit(); const limitLabel = isPro ? "Unlimited" : `${limit}`; planUsageText.textContent = isPro ? `${used} messages today (Unlimited)` : `${used} / ${limit} messages today`; planUsageBar.style.width = isPro ? "0%" : Math.min(100, (used / limit) * 100) + "%"; if (isPro) { upgradeBtn.classList.add("hidden"); plusBanner.classList.add("hidden"); } else if (isPaid) { upgradeBtn.textContent = "Upgrade to Pro"; upgradeBtn.classList.remove("hidden"); plusBanner.classList.add("hidden"); } else { upgradeBtn.textContent = "Upgrade"; upgradeBtn.classList.remove("hidden"); plusBanner.classList.remove("hidden"); } if (data.upgrade_url_plus) plusBuyBtn.href = data.upgrade_url_plus; if (data.upgrade_url_pro) proBuyBtn.href = data.upgrade_url_pro; } catch (err) { console.error("[SUBSCRIPTION] Failed to load:", err); } } upgradeBtn.addEventListener("click", (e) => { e.preventDefault(); plusOverlay.classList.remove("hidden"); }); plusCloseBtn.addEventListener("click", () => { plusOverlay.classList.add("hidden"); }); plusOverlay.addEventListener("click", (e) => { if (e.target === plusOverlay) plusOverlay.classList.add("hidden"); }); // Plus/Pro purchase buttons — disabled (Coming soon) // plusBuyBtn and proBuyBtn are disabled in HTML, no click handler needed // Init auth check on page load checkAuth(); initGoogleSignIn(); window.addEventListener("load", initGoogleSignIn); function escapeHtml(s) { return String(s) .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); } function addSys(text) { chat.insertAdjacentHTML("beforeend", `
System: ${escapeHtml(text)}
`); chat.scrollTop = chat.scrollHeight; } function addErr(text) { chat.insertAdjacentHTML("beforeend", `
Error: ${escapeHtml(text)}
`); chat.scrollTop = chat.scrollHeight; } function updateShareBtn() { const shareBtn = document.getElementById("shareBtn"); if (shareBtn) shareBtn.style.display = (isSharedView || chatLog.length === 0) ? "none" : "flex"; } function addUser(text) { const label = isSharedView ? "User:" : "You:"; chat.insertAdjacentHTML("beforeend", `
${label} ${escapeHtml(text)}
`); chat.scrollTop = chat.scrollHeight; if (!isSharedView) { chatLog.push({ role: "user", text }); updateShareBtn(); } } function renderMath(el) { if (typeof renderMathInElement === "function") { try { renderMathInElement(el, { delimiters: [ { left: "$$", right: "$$", display: true }, { left: "\\[", right: "\\]", display: true }, { left: "\\(", right: "\\)", display: false } ], throwOnError: false }); } catch (e) { console.warn("[KaTeX]", e); } } } function addCodeDownloadButtons(messageDiv) { // Detect code blocks in the message and add download buttons const content = messageDiv.querySelector('.bot-content'); if (!content) return; const text = content.textContent || content.innerText; // Detect code blocks with file extensions // Pattern: ```language\ncode\n``` or filename.ext followed by code const codeBlockRegex = /```(\w+)?\n([\s\S]+?)```/g; const filenameRegex = /(?:^|\n)([\w\-\.]+\.(py|js|html|css|java|cpp|c|h|ts|tsx|jsx|json|xml|yaml|yml|md|txt|sh|bat|sql|go|rs|php|rb|swift|kt|scala|r|m|mat|ipynb))\s*\n/gi; let match; const codeBlocks = []; // Find code blocks with triple backticks while ((match = codeBlockRegex.exec(text)) !== null) { const language = match[1] || 'txt'; const code = match[2].trim(); const extension = getExtensionFromLanguage(language); codeBlocks.push({ code, extension, language }); } // Find code blocks with filename headers const lines = text.split('\n'); for (let i = 0; i < lines.length; i++) { const filenameMatch = lines[i].match(/^([\w\-\.]+\.(py|js|html|css|java|cpp|c|h|ts|tsx|jsx|json|xml|yaml|yml|md|txt|sh|bat|sql|go|rs|php|rb|swift|kt|scala|r|m|mat|ipynb))$/i); if (filenameMatch && i + 1 < lines.length) { const filename = filenameMatch[1]; const extension = filename.split('.').pop(); // Collect code until next filename or end let code = ''; for (let j = i + 1; j < lines.length; j++) { if (lines[j].match(/^[\w\-\.]+\.\w+$/)) break; code += lines[j] + '\n'; } if (code.trim()) { codeBlocks.push({ code: code.trim(), extension, filename }); } } } // Add download buttons for each code block if (codeBlocks.length > 0) { const buttonContainer = document.createElement('div'); buttonContainer.style.cssText = 'margin-top:12px;display:flex;gap:8px;flex-wrap:wrap;'; codeBlocks.forEach((block, index) => { const btn = document.createElement('button'); btn.textContent = `📥 Download ${block.filename || `code.${block.extension}`}`; btn.style.cssText = 'padding:6px 12px;background:linear-gradient(135deg,#22c55e,#16a34a);color:#fff;border:none;border-radius:8px;font-size:12px;font-weight:600;cursor:pointer;width:auto;margin:0;'; btn.onmouseover = () => btn.style.opacity = '0.85'; btn.onmouseout = () => btn.style.opacity = '1'; btn.onclick = () => downloadCode(block.code, block.filename || `code_${index + 1}.${block.extension}`); buttonContainer.appendChild(btn); }); messageDiv.appendChild(buttonContainer); } } function getExtensionFromLanguage(lang) { const langMap = { 'python': 'py', 'javascript': 'js', 'typescript': 'ts', 'html': 'html', 'css': 'css', 'java': 'java', 'cpp': 'cpp', 'c': 'c', 'csharp': 'cs', 'go': 'go', 'rust': 'rs', 'php': 'php', 'ruby': 'rb', 'swift': 'swift', 'kotlin': 'kt', 'scala': 'scala', 'r': 'r', 'matlab': 'm', 'sql': 'sql', 'bash': 'sh', 'shell': 'sh', 'json': 'json', 'xml': 'xml', 'yaml': 'yaml', 'markdown': 'md', 'text': 'txt' }; return langMap[lang.toLowerCase()] || 'txt'; } function downloadCode(code, filename) { const blob = new Blob([code], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); addSys(`✅ Downloaded: ${filename}`); } function addBot(text) { const div = document.createElement("div"); div.className = "msg bot"; // Debug: Log all bot responses console.log("[BOT RESPONSE DEBUG] Response length:", text.length); console.log("[BOT RESPONSE DEBUG] First 200 chars:", text.substring(0, 200)); // Check if response contains HTML (from /3ddesign or similar commands) const hasFullHtml = text.includes("") || text.includes(" 0) { // There's text before HTML - show it as description with markdown formatting const description = text.substring(0, htmlStart).trim(); htmlContent = text.substring(htmlStart); if (description) { // Convert markdown-style formatting to HTML let formattedDesc = description .replace(/\*\*([^*]+)\*\*/g, '$1') // **bold** .replace(/\*([^*]+)\*/g, '$1') // *italic* .replace(/\n/g, '
'); // newlines div.innerHTML = `RubiBot: ${formattedDesc}
`; } else { div.innerHTML = `RubiBot:
`; } } else { div.innerHTML = `RubiBot:
`; } chat.appendChild(div); const htmlContainer = div.querySelector(".html-content"); const iframe = document.createElement("iframe"); iframe.style.width = "100%"; iframe.style.height = "500px"; iframe.style.border = "1px solid #ddd"; iframe.style.borderRadius = "8px"; iframe.style.backgroundColor = "white"; iframe.style.marginTop = "10px"; htmlContainer.appendChild(iframe); // Write HTML content to iframe const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; iframeDoc.open(); iframeDoc.write(htmlContent); iframeDoc.close(); } else if (hasInlineHtml) { // Inline HTML (like 3D designs, visualizations) - render directly without markdown processing // This preserves HTML structure and prevents breaking tags console.log("[3D DESIGN DEBUG] Detected inline HTML response"); console.log("[3D DESIGN DEBUG] Response length:", text.length); console.log("[3D DESIGN DEBUG] Contains 'Trimesh':", text.includes("Trimesh")); console.log("[3D DESIGN DEBUG] Contains 'CADRender':", text.includes("CADRender")); console.log("[3D DESIGN DEBUG] Contains 'Three.js':", text.includes("Three.js")); console.log("[3D DESIGN DEBUG] Contains 'STL':", text.includes("STL")); console.log("[3D DESIGN DEBUG] Contains 'OBJ':", text.includes("OBJ")); console.log("[3D DESIGN DEBUG] Contains 'GLB':", text.includes("GLB")); console.log("[3D DESIGN DEBUG] Contains 'VTK':", text.includes("VTK")); console.log("[3D DESIGN DEBUG] Contains 'Parameters JSON':", text.includes("Parameters JSON")); console.log("[3D DESIGN DEBUG] Contains 'Quality Report':", text.includes("Quality Report")); console.log("[3D DESIGN DEBUG] Contains 'PASSED':", text.includes("PASSED")); console.log("[3D DESIGN DEBUG] Contains 'FAILED':", text.includes("FAILED")); // Check for actual CAD generation errors only if (text.includes("❌ **CAD Design Error**") || text.includes("Failed to generate CAD model")) { console.error("[3D DESIGN DEBUG] Response contains actual CAD error"); const errorMatch = text.match(/Failed to generate CAD model:\s*([^\n]+)/); if (errorMatch) { console.error("[3D DESIGN DEBUG] Error message:", errorMatch[1]); } } // Check which generator was used if (text.includes("Trimesh")) { console.log("[3D DESIGN DEBUG] ✅ Trimesh generator was used"); } else if (text.includes("CADRender") || text.includes("CAD-Render") || text.includes("OCCT")) { console.log("[3D DESIGN DEBUG] ✅ CAD-Render (OCCT) generator was used"); } else if (text.includes("CSS")) { console.log("[3D DESIGN DEBUG] ⚠️ CSS fallback was used"); } // Read debug data from data attributes const debugData = div.dataset.debug; if (debugData) { console.log("[DEBUG DATA]", debugData); } // Use iframe srcdoc so embedded