Spaces:
Running
Running
Vedika commited on
Update index.html
Browse files- index.html +121 -70
index.html
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
<!DOCTYPE html>
|
| 2 |
<html lang="en">
|
| 3 |
<head>
|
|
@@ -6,10 +7,12 @@
|
|
| 6 |
<title>CODE VED | Engineered by Divy Patel</title>
|
| 7 |
<meta name="description" content="CODE VED - 202 Billion Parameter Enterprise AI System">
|
| 8 |
|
|
|
|
| 9 |
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 10 |
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 11 |
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
| 12 |
|
|
|
|
| 13 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css">
|
| 14 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
|
| 15 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.6.0/mammoth.browser.min.js"></script>
|
|
@@ -23,20 +26,15 @@
|
|
| 23 |
--bg-sidebar: #f9f9f9;
|
| 24 |
--bg-input: #f4f4f4;
|
| 25 |
--bg-hover: #ebebeb;
|
| 26 |
-
|
| 27 |
--text-primary: #0f0f0f;
|
| 28 |
--text-secondary: #606060;
|
| 29 |
--text-tertiary: #8e8e8e;
|
| 30 |
-
|
| 31 |
--border-light: #e5e5e5;
|
| 32 |
--border-focus: #d0d0d0;
|
| 33 |
-
|
| 34 |
--brand-color: #1a1a1a;
|
| 35 |
--brand-accent: #0066cc; /* Tool Calling Color */
|
| 36 |
-
|
| 37 |
--font-ui: 'Inter', sans-serif;
|
| 38 |
--font-code: 'JetBrains Mono', monospace;
|
| 39 |
-
|
| 40 |
--radius-sm: 8px;
|
| 41 |
--radius-md: 12px;
|
| 42 |
--radius-lg: 24px;
|
|
@@ -44,6 +42,7 @@
|
|
| 44 |
|
| 45 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 46 |
|
|
|
|
| 47 |
html, body {
|
| 48 |
height: 100%; height: 100dvh; width: 100vw;
|
| 49 |
font-family: var(--font-ui); background-color: var(--bg-main); color: var(--text-primary);
|
|
@@ -59,11 +58,11 @@
|
|
| 59 |
::-webkit-scrollbar-thumb { background: #d4d4d4; border-radius: 10px; }
|
| 60 |
::-webkit-scrollbar-thumb:hover { background: #a0a0a0; }
|
| 61 |
|
| 62 |
-
/* --- SIDEBAR --- */
|
| 63 |
.sidebar {
|
| 64 |
width: 260px; background-color: var(--bg-sidebar); border-right: 1px solid var(--border-light);
|
| 65 |
display: flex; flex-direction: column; transition: transform 0.3s ease, width 0.3s ease; z-index: 100;
|
| 66 |
-
height: 100%;
|
| 67 |
}
|
| 68 |
.sidebar.collapsed { margin-left: -260px; }
|
| 69 |
|
|
@@ -76,11 +75,10 @@
|
|
| 76 |
.btn-new-chat:hover { background: var(--bg-hover); color: #000; border-color: #ccc; }
|
| 77 |
|
| 78 |
.sidebar-history { flex: 1; overflow-y: auto; padding: 10px; }
|
|
|
|
|
|
|
| 79 |
|
| 80 |
-
.sidebar-footer {
|
| 81 |
-
padding: 16px; border-top: 1px solid var(--border-light); display: flex; align-items: center; gap: 12px;
|
| 82 |
-
transition: background 0.2s;
|
| 83 |
-
}
|
| 84 |
.user-avatar { width: 34px; height: 34px; border-radius: 50%; background: var(--brand-color); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 15px; font-weight: 600; flex-shrink: 0; }
|
| 85 |
.user-info-box { flex: 1; overflow: hidden; }
|
| 86 |
.user-name { font-size: 14px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text-primary); }
|
|
@@ -88,11 +86,11 @@
|
|
| 88 |
|
| 89 |
.btn-power {
|
| 90 |
width: 32px; height: 32px; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center;
|
| 91 |
-
color: var(--text-secondary); transition: 0.2s; cursor: pointer; border: 1px solid transparent;
|
| 92 |
}
|
| 93 |
.btn-power:hover { background: #ffe6e6; color: #cc0000; border-color: #ffcccc; }
|
| 94 |
|
| 95 |
-
/* --- MAIN WORKSPACE --- */
|
| 96 |
.main-area { flex: 1; display: flex; flex-direction: column; position: relative; background: var(--bg-main); transition: 0.3s; height: 100%; overflow: hidden; }
|
| 97 |
|
| 98 |
.top-bar { padding: 12px 20px; display: flex; align-items: center; justify-content: space-between; background: var(--bg-main); z-index: 10; flex-shrink: 0; border-bottom: 1px solid transparent; transition: border 0.3s; }
|
|
@@ -103,9 +101,10 @@
|
|
| 103 |
|
| 104 |
.model-selector { font-size: 14px; font-weight: 600; color: var(--text-secondary); display: flex; align-items: center; gap: 6px; }
|
| 105 |
|
| 106 |
-
/* --- CHAT CONTAINER --- */
|
| 107 |
.chat-container { flex: 1; overflow-y: auto; padding: 20px 20px 40px; display: flex; flex-direction: column; align-items: center; scroll-behavior: smooth; }
|
| 108 |
|
|
|
|
| 109 |
.welcome-center { margin: auto; text-align: center; display: flex; flex-direction: column; align-items: center; animation: fadeIn 0.5s ease; }
|
| 110 |
.welcome-center img { width: 70px; height: 70px; border-radius: 18px; margin-bottom: 24px; box-shadow: 0 4px 12px rgba(0,0,0,0.05); }
|
| 111 |
.welcome-center h1 { font-size: 26px; font-weight: 500; color: var(--text-primary); margin-bottom: 8px; letter-spacing: -0.5px; }
|
|
@@ -130,26 +129,16 @@
|
|
| 130 |
.chat-attachment { display: inline-flex; align-items: center; gap: 8px; background: #fff; border: 1px solid var(--border-light); padding: 6px 12px; border-radius: var(--radius-md); font-size: 13px; font-weight: 500; margin-bottom: 10px; box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
|
| 131 |
.chat-img-preview { max-width: 250px; border-radius: var(--radius-md); border: 1px solid var(--border-light); margin-bottom: 10px; }
|
| 132 |
|
| 133 |
-
/* --- GOOGLE SEARCH TOOL
|
| 134 |
-
.tool-indicator {
|
| 135 |
-
|
| 136 |
-
color: var(--brand-accent); background: rgba(0, 102, 204, 0.05); padding: 8px 14px;
|
| 137 |
-
border-radius: var(--radius-sm); margin-bottom: 16px; border: 1px solid rgba(0, 102, 204, 0.2);
|
| 138 |
-
transition: 0.3s;
|
| 139 |
-
}
|
| 140 |
-
.tool-indicator.active {
|
| 141 |
-
animation: pulseGlow 2s infinite alternate;
|
| 142 |
-
}
|
| 143 |
.tool-indicator svg { width: 16px; height: 16px; }
|
| 144 |
.tool-indicator.active svg { animation: spin 2s linear infinite; }
|
| 145 |
|
| 146 |
-
@keyframes pulseGlow {
|
| 147 |
-
0% { box-shadow: 0 0 0 rgba(0, 102, 204, 0); border-color: rgba(0, 102, 204, 0.2); }
|
| 148 |
-
100% { box-shadow: 0 0 12px rgba(0, 102, 204, 0.3); border-color: rgba(0, 102, 204, 0.5); }
|
| 149 |
-
}
|
| 150 |
@keyframes spin { 100% { transform: rotate(360deg); } }
|
| 151 |
|
| 152 |
-
/* --- INPUT DOCK --- */
|
| 153 |
.input-dock { flex-shrink: 0; padding: 15px 20px 25px; background: var(--bg-main); border-top: 1px solid transparent; display: flex; justify-content: center; z-index: 20; width: 100%; transition: border 0.3s; }
|
| 154 |
.input-dock.scrolled { border-top: 1px solid var(--border-light); }
|
| 155 |
|
|
@@ -183,7 +172,7 @@
|
|
| 183 |
.dropdown-item { padding: 10px 12px; border-radius: var(--radius-sm); font-size: 13px; font-weight: 500; display: flex; align-items: center; gap: 10px; cursor: pointer; transition: 0.2s; }
|
| 184 |
.dropdown-item:hover { background: var(--bg-hover); }
|
| 185 |
|
| 186 |
-
/* --- SECURE AUTHENTICATION MODAL --- */
|
| 187 |
.auth-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.4); backdrop-filter: blur(5px); display: none; align-items: center; justify-content: center; z-index: 2000; }
|
| 188 |
.auth-modal { background: #fff; width: 90%; max-width: 400px; border-radius: var(--radius-md); padding: 32px; box-shadow: 0 20px 40px rgba(0,0,0,0.1); position: relative; }
|
| 189 |
.auth-close { position: absolute; top: 16px; right: 16px; color: var(--text-secondary); width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: 0.2s; }
|
|
@@ -207,37 +196,31 @@
|
|
| 207 |
.auth-phase.active { display: flex; flex-direction: column; }
|
| 208 |
.auth-message { font-size: 12px; color: #cc0000; text-align: center; margin-top: 10px; min-height: 18px; }
|
| 209 |
|
| 210 |
-
/* --- WORKSPACE RIGHT PANEL --- */
|
| 211 |
.workspace-panel { width: 0; background: #fff; border-left: 1px solid var(--border-light); display: flex; flex-direction: column; transition: width 0.3s ease; overflow: hidden; box-shadow: -5px 0 20px rgba(0,0,0,0.02); z-index: 90; }
|
| 212 |
.workspace-panel.active { width: 50%; }
|
| 213 |
-
|
| 214 |
.ws-header { padding: 12px 20px; border-bottom: 1px solid var(--border-light); display: flex; justify-content: space-between; align-items: center; background: #fafafa; }
|
| 215 |
.ws-tabs { display: flex; gap: 4px; background: #ebebeb; padding: 4px; border-radius: var(--radius-sm); }
|
| 216 |
.ws-tab { padding: 6px 16px; font-size: 13px; font-weight: 500; border-radius: 6px; cursor: pointer; color: var(--text-secondary); transition: 0.2s; }
|
| 217 |
.ws-tab.active { background: #fff; color: var(--text-primary); box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
|
| 218 |
-
|
| 219 |
.ws-actions { display: flex; gap: 8px; }
|
| 220 |
.ws-btn { padding: 6px; border-radius: var(--radius-sm); color: var(--text-secondary); transition: 0.2s; }
|
| 221 |
.ws-btn:hover { background: #ebebeb; color: var(--text-primary); }
|
| 222 |
-
|
| 223 |
.ws-content { flex: 1; overflow: hidden; position: relative; }
|
| 224 |
.ws-code { height: 100%; overflow: auto; padding: 20px; background: #fbfbfb; }
|
| 225 |
.ws-code pre { margin: 0; font-family: var(--font-code); font-size: 14px; }
|
| 226 |
.ws-preview { display: none; height: 100%; width: 100%; flex-direction: column; background: #fff; }
|
| 227 |
.ws-console { background: #1a1a1a; color: #fff; font-family: var(--font-code); padding: 20px; font-size: 13px; flex: 1; overflow: auto; white-space: pre-wrap; }
|
| 228 |
-
|
| 229 |
.btn-launch-ws { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; background: var(--bg-main); border: 1px solid var(--border-light); border-radius: var(--radius-sm); font-size: 12px; font-weight: 500; cursor: pointer; margin-top: 10px; transition: 0.2s; }
|
| 230 |
.btn-launch-ws:hover { background: #f0f0f0; }
|
| 231 |
|
| 232 |
/* Utilities */
|
| 233 |
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
| 234 |
-
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
|
| 235 |
.typing-indicator { display: flex; gap: 4px; padding: 10px 0; }
|
| 236 |
.typing-dot { width: 6px; height: 6px; background: var(--text-tertiary); border-radius: 50%; animation: typeBounce 1.4s infinite ease-in-out both; }
|
| 237 |
.typing-dot:nth-child(1) { animation-delay: -0.32s; } .typing-dot:nth-child(2) { animation-delay: -0.16s; }
|
| 238 |
@keyframes typeBounce { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1); } }
|
| 239 |
svg { width: 100%; height: 100%; }
|
| 240 |
-
.sys-msg { padding: 40px; text-align: center; color: var(--text-secondary); font-size: 14px; }
|
| 241 |
|
| 242 |
@media (max-width: 900px) {
|
| 243 |
.sidebar { position: absolute; left: 0; height: 100%; box-shadow: 5px 0 20px rgba(0,0,0,0.05); }
|
|
@@ -249,6 +232,7 @@
|
|
| 249 |
</head>
|
| 250 |
<body>
|
| 251 |
|
|
|
|
| 252 |
<aside class="sidebar collapsed" id="sidebar">
|
| 253 |
<div class="sidebar-header">
|
| 254 |
<button class="btn-icon" onclick="UI.toggleSidebar()" title="Close Sidebar">
|
|
@@ -263,34 +247,40 @@
|
|
| 263 |
</button>
|
| 264 |
</div>
|
| 265 |
|
|
|
|
| 266 |
<div class="sidebar-history" id="chatHistory">
|
| 267 |
-
<
|
|
|
|
| 268 |
|
|
|
|
| 269 |
<div class="sidebar-footer" id="profileArea">
|
| 270 |
<div class="user-avatar" id="uAv">G</div>
|
| 271 |
<div class="user-info-box">
|
| 272 |
<div class="user-name" id="uName">Guest Session</div>
|
| 273 |
<div class="user-sub" id="uSub" onclick="Auth.openModal()" style="cursor:pointer; color:var(--brand-accent);">Login Required</div>
|
| 274 |
</div>
|
|
|
|
| 275 |
<button class="btn-power" id="btnLogout" onclick="Auth.handleLogout()" title="Logout" style="display:none;">
|
| 276 |
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18.36 6.64a9 9 0 1 1-12.73 0"></path><line x1="12" y1="2" x2="12" y2="12"></line></svg>
|
| 277 |
</button>
|
| 278 |
</div>
|
| 279 |
</aside>
|
| 280 |
|
|
|
|
| 281 |
<main class="main-area">
|
| 282 |
<header class="top-bar" id="topBar">
|
| 283 |
<button class="btn-icon" onclick="UI.toggleSidebar()" title="Open Menu" id="btnMenuOpen">
|
| 284 |
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>
|
| 285 |
</button>
|
| 286 |
<div class="model-selector">CODE VED 202B</div>
|
| 287 |
-
<div style="width: 32px;"></div> <
|
|
|
|
| 288 |
|
| 289 |
<div class="chat-container" id="chatContainer">
|
| 290 |
<div class="welcome-center" id="welcomeScreen">
|
| 291 |
<img src="https://i.ibb.co/MyYStcGP/TIRANGA-20260613-131924-0000.png" alt="CODE VED Logo">
|
| 292 |
<h1>What's your focus today?</h1>
|
| 293 |
-
<p id="welcomeGreeting">Hi
|
| 294 |
</div>
|
| 295 |
</div>
|
| 296 |
|
|
@@ -335,6 +325,7 @@
|
|
| 335 |
</div>
|
| 336 |
</main>
|
| 337 |
|
|
|
|
| 338 |
<aside class="workspace-panel" id="workspacePanel">
|
| 339 |
<div class="ws-header">
|
| 340 |
<div class="ws-tabs">
|
|
@@ -356,6 +347,7 @@
|
|
| 356 |
</div>
|
| 357 |
</aside>
|
| 358 |
|
|
|
|
| 359 |
<div class="auth-overlay" id="authModal">
|
| 360 |
<div class="auth-modal">
|
| 361 |
<button class="auth-close" onclick="Auth.closeModal()"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg></button>
|
|
@@ -366,6 +358,7 @@
|
|
| 366 |
<div class="auth-tab" id="tabRegister" onclick="Auth.switchTab('register')">Register</div>
|
| 367 |
</div>
|
| 368 |
|
|
|
|
| 369 |
<div id="flowLogin">
|
| 370 |
<div class="auth-phase active" id="loginPhase1">
|
| 371 |
<div class="auth-input-group">
|
|
@@ -382,6 +375,7 @@
|
|
| 382 |
</div>
|
| 383 |
</div>
|
| 384 |
|
|
|
|
| 385 |
<div id="flowRegister" style="display:none;">
|
| 386 |
<div class="auth-phase active" id="regPhase1">
|
| 387 |
<div class="auth-input-group">
|
|
@@ -407,7 +401,7 @@
|
|
| 407 |
// --- 1. CONFIG & STATE ---
|
| 408 |
const Config = {
|
| 409 |
GAS_URL: "https://script.google.com/macros/s/AKfycbz5vrlB4GrfkfBVYdQ52IQweIXC1cNDwKuTUorxdAiOdSSIrH55mzJlaz9kq1Y94ot5/exec",
|
| 410 |
-
API_ENDPOINT: "/api/chat",
|
| 411 |
LOGO: "https://i.ibb.co/MyYStcGP/TIRANGA-20260613-131924-0000.png"
|
| 412 |
};
|
| 413 |
|
|
@@ -461,7 +455,7 @@
|
|
| 461 |
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); Chat.handleSend(); }
|
| 462 |
});
|
| 463 |
|
| 464 |
-
// --- 3. AUTHENTICATION & HISTORY DB (RESTORED) ---
|
| 465 |
const Auth = {
|
| 466 |
init: () => {
|
| 467 |
const uAv = document.getElementById('uAv');
|
|
@@ -488,7 +482,7 @@
|
|
| 488 |
uSub.innerText = `Queries: ${State.guestCount}/10`;
|
| 489 |
uSub.style.color = "var(--text-tertiary)";
|
| 490 |
btnLogout.style.display = 'none';
|
| 491 |
-
greeting.innerText = `Hi
|
| 492 |
}
|
| 493 |
},
|
| 494 |
handleLogout: () => {
|
|
@@ -564,8 +558,13 @@
|
|
| 564 |
if(data.status === 'success' && data.historyJSON !== "[]") {
|
| 565 |
State.history = JSON.parse(data.historyJSON);
|
| 566 |
document.getElementById('welcomeScreen').style.display = 'none';
|
| 567 |
-
State.history.forEach(msg => {
|
| 568 |
-
if(msg.role === 'user')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 569 |
else {
|
| 570 |
const botNode = Chat.renderBot();
|
| 571 |
botNode.innerHTML = marked.parse(msg.content.replace(/<think>[\s\S]*?<\/think>/gi, ''));
|
|
@@ -583,14 +582,13 @@
|
|
| 583 |
},
|
| 584 |
clearHistory: async () => {
|
| 585 |
if(State.user) {
|
| 586 |
-
document.getElementById('chatContainer').innerHTML = '<div class="sys-msg">Clearing Memory Workspace...</div>';
|
| 587 |
try { await fetch(Config.GAS_URL, { method: 'POST', body: JSON.stringify({action: "delete_history", email: State.user}) }); } catch(e){}
|
| 588 |
}
|
| 589 |
location.reload();
|
| 590 |
}
|
| 591 |
};
|
| 592 |
|
| 593 |
-
// --- 4. FILE HANDLING ---
|
| 594 |
const FileSys = {
|
| 595 |
process: async (input, type) => {
|
| 596 |
document.getElementById('attachMenu').classList.remove('active');
|
|
@@ -634,7 +632,9 @@
|
|
| 634 |
} else {
|
| 635 |
r.onload = (e) => {
|
| 636 |
let data = e.target.result;
|
| 637 |
-
if(file.name.endsWith('.html')) {
|
|
|
|
|
|
|
| 638 |
State.attachment = { type: 'text', data: data, name: file.name };
|
| 639 |
};
|
| 640 |
r.readAsText(file);
|
|
@@ -660,54 +660,93 @@
|
|
| 660 |
Speech.rec.onstart = () => { Speech.isRec = true; document.getElementById('btnStt').classList.add('recording'); };
|
| 661 |
Speech.rec.onresult = (e) => {
|
| 662 |
let trans = '';
|
| 663 |
-
for (let i = e.resultIndex; i < e.results.length; ++i) {
|
| 664 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 665 |
};
|
| 666 |
Speech.rec.onerror = () => Speech.stop();
|
| 667 |
Speech.rec.onend = () => Speech.stop();
|
| 668 |
},
|
| 669 |
-
toggle: () => {
|
| 670 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 671 |
};
|
| 672 |
|
| 673 |
// --- 6. WORKSPACE PRO MAX ---
|
| 674 |
const Workspace = {
|
| 675 |
open: (id) => {
|
| 676 |
-
State.currentWs = id;
|
| 677 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 678 |
document.getElementById('workspacePanel').classList.add('active');
|
| 679 |
if(window.innerWidth <= 900) { document.getElementById('sidebar').classList.add('collapsed'); }
|
| 680 |
Workspace.switchTab('code');
|
| 681 |
},
|
| 682 |
close: () => document.getElementById('workspacePanel').classList.remove('active'),
|
| 683 |
switchTab: (tab) => {
|
| 684 |
-
document.getElementById('tabCode').classList.remove('active');
|
|
|
|
| 685 |
if(tab === 'code') {
|
| 686 |
-
document.getElementById('tabCode').classList.add('active');
|
|
|
|
|
|
|
| 687 |
} else {
|
| 688 |
-
document.getElementById('tabPreview').classList.add('active');
|
|
|
|
|
|
|
| 689 |
Workspace.run();
|
| 690 |
}
|
| 691 |
},
|
| 692 |
-
copy: () => {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 693 |
run: async () => {
|
| 694 |
if (State.currentWs === null) return;
|
| 695 |
-
const d = State.workspaces[State.currentWs];
|
|
|
|
|
|
|
| 696 |
|
| 697 |
if (['html', 'xml', 'javascript', 'js', 'css'].includes(lang)) {
|
| 698 |
let html = d.code;
|
| 699 |
if(lang === 'javascript' || lang === 'js') html = `<script>${d.code}<\/script>`;
|
| 700 |
if(lang === 'css') html = `<style>${d.code}</style><div style="padding:20px;font-family:sans-serif;">CSS Applied. Add HTML to test.</div>`;
|
| 701 |
-
|
| 702 |
-
|
|
|
|
|
|
|
|
|
|
| 703 |
return;
|
| 704 |
}
|
|
|
|
| 705 |
view.innerHTML = '<div class="ws-console" style="color:var(--brand-accent);">Compiling code...</div>';
|
| 706 |
-
const pMap = {'python':'python', 'py':'python', 'c':'c', 'cpp':'c++', 'java':'java'};
|
|
|
|
|
|
|
| 707 |
if(!rLang) { view.innerHTML = `<div class="ws-console" style="color:#cc0000;">Live Preview not supported for ${lang}.</div>`; return; }
|
| 708 |
|
| 709 |
try {
|
| 710 |
-
const res = await fetch('https://emkc.org/api/v2/piston/execute', {
|
|
|
|
|
|
|
|
|
|
| 711 |
const data = await res.json();
|
| 712 |
let out = (data.compile?.output || "") + "\n" + (data.run?.output || "") + "\n" + (data.run?.stderr || "");
|
| 713 |
view.innerHTML = `<div class="ws-console">${UI.escape(out.trim() || "[Execution Finished]")}</div>`;
|
|
@@ -717,7 +756,8 @@
|
|
| 717 |
|
| 718 |
const MDRenderer = new marked.Renderer();
|
| 719 |
MDRenderer.code = function(code, lang) {
|
| 720 |
-
const id = State.workspaces.length;
|
|
|
|
| 721 |
const highlighted = hljs.highlightAuto(code).value;
|
| 722 |
return `
|
| 723 |
<div style="margin: 16px 0;">
|
|
@@ -732,7 +772,7 @@
|
|
| 732 |
};
|
| 733 |
marked.use({ renderer: MDRenderer });
|
| 734 |
|
| 735 |
-
// --- 7. CHAT ENGINE (WITH
|
| 736 |
const Chat = {
|
| 737 |
renderUser: (txt, attachUI) => {
|
| 738 |
const c = document.getElementById('chatContainer');
|
|
@@ -766,7 +806,7 @@
|
|
| 766 |
const text = input.value.trim();
|
| 767 |
if(!text && !State.attachment) return;
|
| 768 |
|
| 769 |
-
// Guest Validation
|
| 770 |
if(!State.user) {
|
| 771 |
if(State.guestCount >= 10) { Auth.openModal(); UI.showAuthMsg("Guest limit reached. Secure Login required.", true); return; }
|
| 772 |
State.guestCount++; localStorage.setItem('codeved_guest', State.guestCount);
|
|
@@ -779,7 +819,11 @@
|
|
| 779 |
let payloadStr = text;
|
| 780 |
let attachUI = '';
|
| 781 |
let mediaArray = [];
|
| 782 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 783 |
|
| 784 |
if(State.attachment) {
|
| 785 |
if(State.attachment.type === 'text') {
|
|
@@ -792,6 +836,11 @@
|
|
| 792 |
}
|
| 793 |
|
| 794 |
Chat.renderUser(text || '[Attached Media]', attachUI);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 795 |
State.history.push({ role: 'user', content: payloadStr });
|
| 796 |
FileSys.discard();
|
| 797 |
|
|
@@ -803,11 +852,13 @@
|
|
| 803 |
}
|
| 804 |
|
| 805 |
try {
|
|
|
|
| 806 |
const res = await fetch(Config.API_ENDPOINT, {
|
| 807 |
method: 'POST', headers: {'Content-Type': 'application/json'},
|
| 808 |
body: JSON.stringify({
|
| 809 |
-
message: payloadStr,
|
| 810 |
-
|
|
|
|
| 811 |
history: State.history
|
| 812 |
})
|
| 813 |
});
|
|
@@ -867,4 +918,4 @@
|
|
| 867 |
|
| 868 |
</script>
|
| 869 |
</body>
|
| 870 |
-
</html>
|
|
|
|
| 1 |
+
|
| 2 |
<!DOCTYPE html>
|
| 3 |
<html lang="en">
|
| 4 |
<head>
|
|
|
|
| 7 |
<title>CODE VED | Engineered by Divy Patel</title>
|
| 8 |
<meta name="description" content="CODE VED - 202 Billion Parameter Enterprise AI System">
|
| 9 |
|
| 10 |
+
<!-- Premium Fonts -->
|
| 11 |
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 12 |
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 13 |
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
| 14 |
|
| 15 |
+
<!-- Syntax Highlighting & Parsers -->
|
| 16 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css">
|
| 17 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
|
| 18 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.6.0/mammoth.browser.min.js"></script>
|
|
|
|
| 26 |
--bg-sidebar: #f9f9f9;
|
| 27 |
--bg-input: #f4f4f4;
|
| 28 |
--bg-hover: #ebebeb;
|
|
|
|
| 29 |
--text-primary: #0f0f0f;
|
| 30 |
--text-secondary: #606060;
|
| 31 |
--text-tertiary: #8e8e8e;
|
|
|
|
| 32 |
--border-light: #e5e5e5;
|
| 33 |
--border-focus: #d0d0d0;
|
|
|
|
| 34 |
--brand-color: #1a1a1a;
|
| 35 |
--brand-accent: #0066cc; /* Tool Calling Color */
|
|
|
|
| 36 |
--font-ui: 'Inter', sans-serif;
|
| 37 |
--font-code: 'JetBrains Mono', monospace;
|
|
|
|
| 38 |
--radius-sm: 8px;
|
| 39 |
--radius-md: 12px;
|
| 40 |
--radius-lg: 24px;
|
|
|
|
| 42 |
|
| 43 |
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 44 |
|
| 45 |
+
/* 📱 MOBILE BUG FIX: Using 100dvh to prevent input dock from hiding behind browser URL bar */
|
| 46 |
html, body {
|
| 47 |
height: 100%; height: 100dvh; width: 100vw;
|
| 48 |
font-family: var(--font-ui); background-color: var(--bg-main); color: var(--text-primary);
|
|
|
|
| 58 |
::-webkit-scrollbar-thumb { background: #d4d4d4; border-radius: 10px; }
|
| 59 |
::-webkit-scrollbar-thumb:hover { background: #a0a0a0; }
|
| 60 |
|
| 61 |
+
/* --- 1. SIDEBAR (Restored History & Power Button) --- */
|
| 62 |
.sidebar {
|
| 63 |
width: 260px; background-color: var(--bg-sidebar); border-right: 1px solid var(--border-light);
|
| 64 |
display: flex; flex-direction: column; transition: transform 0.3s ease, width 0.3s ease; z-index: 100;
|
| 65 |
+
height: 100%; flex-shrink: 0;
|
| 66 |
}
|
| 67 |
.sidebar.collapsed { margin-left: -260px; }
|
| 68 |
|
|
|
|
| 75 |
.btn-new-chat:hover { background: var(--bg-hover); color: #000; border-color: #ccc; }
|
| 76 |
|
| 77 |
.sidebar-history { flex: 1; overflow-y: auto; padding: 10px; }
|
| 78 |
+
.history-item { padding: 10px; border-radius: var(--radius-sm); font-size: 13px; color: var(--text-secondary); cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 4px; transition: 0.2s;}
|
| 79 |
+
.history-item:hover { background: var(--border-light); color: var(--text-primary); }
|
| 80 |
|
| 81 |
+
.sidebar-footer { padding: 16px; border-top: 1px solid var(--border-light); display: flex; align-items: center; gap: 12px; transition: background 0.2s; }
|
|
|
|
|
|
|
|
|
|
| 82 |
.user-avatar { width: 34px; height: 34px; border-radius: 50%; background: var(--brand-color); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 15px; font-weight: 600; flex-shrink: 0; }
|
| 83 |
.user-info-box { flex: 1; overflow: hidden; }
|
| 84 |
.user-name { font-size: 14px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text-primary); }
|
|
|
|
| 86 |
|
| 87 |
.btn-power {
|
| 88 |
width: 32px; height: 32px; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center;
|
| 89 |
+
color: var(--text-secondary); transition: 0.2s; cursor: pointer; border: 1px solid transparent; flex-shrink: 0;
|
| 90 |
}
|
| 91 |
.btn-power:hover { background: #ffe6e6; color: #cc0000; border-color: #ffcccc; }
|
| 92 |
|
| 93 |
+
/* --- 2. MAIN WORKSPACE AREA --- */
|
| 94 |
.main-area { flex: 1; display: flex; flex-direction: column; position: relative; background: var(--bg-main); transition: 0.3s; height: 100%; overflow: hidden; }
|
| 95 |
|
| 96 |
.top-bar { padding: 12px 20px; display: flex; align-items: center; justify-content: space-between; background: var(--bg-main); z-index: 10; flex-shrink: 0; border-bottom: 1px solid transparent; transition: border 0.3s; }
|
|
|
|
| 101 |
|
| 102 |
.model-selector { font-size: 14px; font-weight: 600; color: var(--text-secondary); display: flex; align-items: center; gap: 6px; }
|
| 103 |
|
| 104 |
+
/* --- 3. CHAT CONTAINER --- */
|
| 105 |
.chat-container { flex: 1; overflow-y: auto; padding: 20px 20px 40px; display: flex; flex-direction: column; align-items: center; scroll-behavior: smooth; }
|
| 106 |
|
| 107 |
+
/* Restored Welcome Screen */
|
| 108 |
.welcome-center { margin: auto; text-align: center; display: flex; flex-direction: column; align-items: center; animation: fadeIn 0.5s ease; }
|
| 109 |
.welcome-center img { width: 70px; height: 70px; border-radius: 18px; margin-bottom: 24px; box-shadow: 0 4px 12px rgba(0,0,0,0.05); }
|
| 110 |
.welcome-center h1 { font-size: 26px; font-weight: 500; color: var(--text-primary); margin-bottom: 8px; letter-spacing: -0.5px; }
|
|
|
|
| 129 |
.chat-attachment { display: inline-flex; align-items: center; gap: 8px; background: #fff; border: 1px solid var(--border-light); padding: 6px 12px; border-radius: var(--radius-md); font-size: 13px; font-weight: 500; margin-bottom: 10px; box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
|
| 130 |
.chat-img-preview { max-width: 250px; border-radius: var(--radius-md); border: 1px solid var(--border-light); margin-bottom: 10px; }
|
| 131 |
|
| 132 |
+
/* --- 4. GOOGLE SEARCH TOOL UI --- */
|
| 133 |
+
.tool-indicator { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 500; color: var(--brand-accent); background: rgba(0, 102, 204, 0.05); padding: 8px 14px; border-radius: var(--radius-sm); margin-bottom: 16px; border: 1px solid rgba(0, 102, 204, 0.2); transition: 0.3s; }
|
| 134 |
+
.tool-indicator.active { animation: pulseGlow 2s infinite alternate; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
.tool-indicator svg { width: 16px; height: 16px; }
|
| 136 |
.tool-indicator.active svg { animation: spin 2s linear infinite; }
|
| 137 |
|
| 138 |
+
@keyframes pulseGlow { 0% { box-shadow: 0 0 0 rgba(0, 102, 204, 0); border-color: rgba(0, 102, 204, 0.2); } 100% { box-shadow: 0 0 12px rgba(0, 102, 204, 0.3); border-color: rgba(0, 102, 204, 0.5); } }
|
|
|
|
|
|
|
|
|
|
| 139 |
@keyframes spin { 100% { transform: rotate(360deg); } }
|
| 140 |
|
| 141 |
+
/* --- 5. FIXED INPUT DOCK (MOBILE SAFE) --- */
|
| 142 |
.input-dock { flex-shrink: 0; padding: 15px 20px 25px; background: var(--bg-main); border-top: 1px solid transparent; display: flex; justify-content: center; z-index: 20; width: 100%; transition: border 0.3s; }
|
| 143 |
.input-dock.scrolled { border-top: 1px solid var(--border-light); }
|
| 144 |
|
|
|
|
| 172 |
.dropdown-item { padding: 10px 12px; border-radius: var(--radius-sm); font-size: 13px; font-weight: 500; display: flex; align-items: center; gap: 10px; cursor: pointer; transition: 0.2s; }
|
| 173 |
.dropdown-item:hover { background: var(--bg-hover); }
|
| 174 |
|
| 175 |
+
/* --- 6. SECURE AUTHENTICATION MODAL --- */
|
| 176 |
.auth-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.4); backdrop-filter: blur(5px); display: none; align-items: center; justify-content: center; z-index: 2000; }
|
| 177 |
.auth-modal { background: #fff; width: 90%; max-width: 400px; border-radius: var(--radius-md); padding: 32px; box-shadow: 0 20px 40px rgba(0,0,0,0.1); position: relative; }
|
| 178 |
.auth-close { position: absolute; top: 16px; right: 16px; color: var(--text-secondary); width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: 0.2s; }
|
|
|
|
| 196 |
.auth-phase.active { display: flex; flex-direction: column; }
|
| 197 |
.auth-message { font-size: 12px; color: #cc0000; text-align: center; margin-top: 10px; min-height: 18px; }
|
| 198 |
|
| 199 |
+
/* --- 7. WORKSPACE RIGHT PANEL --- */
|
| 200 |
.workspace-panel { width: 0; background: #fff; border-left: 1px solid var(--border-light); display: flex; flex-direction: column; transition: width 0.3s ease; overflow: hidden; box-shadow: -5px 0 20px rgba(0,0,0,0.02); z-index: 90; }
|
| 201 |
.workspace-panel.active { width: 50%; }
|
|
|
|
| 202 |
.ws-header { padding: 12px 20px; border-bottom: 1px solid var(--border-light); display: flex; justify-content: space-between; align-items: center; background: #fafafa; }
|
| 203 |
.ws-tabs { display: flex; gap: 4px; background: #ebebeb; padding: 4px; border-radius: var(--radius-sm); }
|
| 204 |
.ws-tab { padding: 6px 16px; font-size: 13px; font-weight: 500; border-radius: 6px; cursor: pointer; color: var(--text-secondary); transition: 0.2s; }
|
| 205 |
.ws-tab.active { background: #fff; color: var(--text-primary); box-shadow: 0 1px 3px rgba(0,0,0,0.05); }
|
|
|
|
| 206 |
.ws-actions { display: flex; gap: 8px; }
|
| 207 |
.ws-btn { padding: 6px; border-radius: var(--radius-sm); color: var(--text-secondary); transition: 0.2s; }
|
| 208 |
.ws-btn:hover { background: #ebebeb; color: var(--text-primary); }
|
|
|
|
| 209 |
.ws-content { flex: 1; overflow: hidden; position: relative; }
|
| 210 |
.ws-code { height: 100%; overflow: auto; padding: 20px; background: #fbfbfb; }
|
| 211 |
.ws-code pre { margin: 0; font-family: var(--font-code); font-size: 14px; }
|
| 212 |
.ws-preview { display: none; height: 100%; width: 100%; flex-direction: column; background: #fff; }
|
| 213 |
.ws-console { background: #1a1a1a; color: #fff; font-family: var(--font-code); padding: 20px; font-size: 13px; flex: 1; overflow: auto; white-space: pre-wrap; }
|
|
|
|
| 214 |
.btn-launch-ws { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; background: var(--bg-main); border: 1px solid var(--border-light); border-radius: var(--radius-sm); font-size: 12px; font-weight: 500; cursor: pointer; margin-top: 10px; transition: 0.2s; }
|
| 215 |
.btn-launch-ws:hover { background: #f0f0f0; }
|
| 216 |
|
| 217 |
/* Utilities */
|
| 218 |
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
|
|
|
| 219 |
.typing-indicator { display: flex; gap: 4px; padding: 10px 0; }
|
| 220 |
.typing-dot { width: 6px; height: 6px; background: var(--text-tertiary); border-radius: 50%; animation: typeBounce 1.4s infinite ease-in-out both; }
|
| 221 |
.typing-dot:nth-child(1) { animation-delay: -0.32s; } .typing-dot:nth-child(2) { animation-delay: -0.16s; }
|
| 222 |
@keyframes typeBounce { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1); } }
|
| 223 |
svg { width: 100%; height: 100%; }
|
|
|
|
| 224 |
|
| 225 |
@media (max-width: 900px) {
|
| 226 |
.sidebar { position: absolute; left: 0; height: 100%; box-shadow: 5px 0 20px rgba(0,0,0,0.05); }
|
|
|
|
| 232 |
</head>
|
| 233 |
<body>
|
| 234 |
|
| 235 |
+
<!-- SIDEBAR -->
|
| 236 |
<aside class="sidebar collapsed" id="sidebar">
|
| 237 |
<div class="sidebar-header">
|
| 238 |
<button class="btn-icon" onclick="UI.toggleSidebar()" title="Close Sidebar">
|
|
|
|
| 247 |
</button>
|
| 248 |
</div>
|
| 249 |
|
| 250 |
+
<!-- RESTORED: Chat History Section -->
|
| 251 |
<div class="sidebar-history" id="chatHistory">
|
| 252 |
+
<!-- Dynamic History populated here -->
|
| 253 |
+
</div>
|
| 254 |
|
| 255 |
+
<!-- User Profile Area -->
|
| 256 |
<div class="sidebar-footer" id="profileArea">
|
| 257 |
<div class="user-avatar" id="uAv">G</div>
|
| 258 |
<div class="user-info-box">
|
| 259 |
<div class="user-name" id="uName">Guest Session</div>
|
| 260 |
<div class="user-sub" id="uSub" onclick="Auth.openModal()" style="cursor:pointer; color:var(--brand-accent);">Login Required</div>
|
| 261 |
</div>
|
| 262 |
+
<!-- RESTORED: Power Button (Logout) -->
|
| 263 |
<button class="btn-power" id="btnLogout" onclick="Auth.handleLogout()" title="Logout" style="display:none;">
|
| 264 |
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18.36 6.64a9 9 0 1 1-12.73 0"></path><line x1="12" y1="2" x2="12" y2="12"></line></svg>
|
| 265 |
</button>
|
| 266 |
</div>
|
| 267 |
</aside>
|
| 268 |
|
| 269 |
+
<!-- MAIN AREA -->
|
| 270 |
<main class="main-area">
|
| 271 |
<header class="top-bar" id="topBar">
|
| 272 |
<button class="btn-icon" onclick="UI.toggleSidebar()" title="Open Menu" id="btnMenuOpen">
|
| 273 |
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>
|
| 274 |
</button>
|
| 275 |
<div class="model-selector">CODE VED 202B</div>
|
| 276 |
+
<div style="width: 32px;"></div> <!-- Spacer -->
|
| 277 |
+
</header>
|
| 278 |
|
| 279 |
<div class="chat-container" id="chatContainer">
|
| 280 |
<div class="welcome-center" id="welcomeScreen">
|
| 281 |
<img src="https://i.ibb.co/MyYStcGP/TIRANGA-20260613-131924-0000.png" alt="CODE VED Logo">
|
| 282 |
<h1>What's your focus today?</h1>
|
| 283 |
+
<p id="welcomeGreeting">Hi Divy Patel, I am ready to assist you.</p>
|
| 284 |
</div>
|
| 285 |
</div>
|
| 286 |
|
|
|
|
| 325 |
</div>
|
| 326 |
</main>
|
| 327 |
|
| 328 |
+
<!-- WORKSPACE PANEL -->
|
| 329 |
<aside class="workspace-panel" id="workspacePanel">
|
| 330 |
<div class="ws-header">
|
| 331 |
<div class="ws-tabs">
|
|
|
|
| 347 |
</div>
|
| 348 |
</aside>
|
| 349 |
|
| 350 |
+
<!-- SECURE AUTHENTICATION MODAL -->
|
| 351 |
<div class="auth-overlay" id="authModal">
|
| 352 |
<div class="auth-modal">
|
| 353 |
<button class="auth-close" onclick="Auth.closeModal()"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg></button>
|
|
|
|
| 358 |
<div class="auth-tab" id="tabRegister" onclick="Auth.switchTab('register')">Register</div>
|
| 359 |
</div>
|
| 360 |
|
| 361 |
+
<!-- Login Flow -->
|
| 362 |
<div id="flowLogin">
|
| 363 |
<div class="auth-phase active" id="loginPhase1">
|
| 364 |
<div class="auth-input-group">
|
|
|
|
| 375 |
</div>
|
| 376 |
</div>
|
| 377 |
|
| 378 |
+
<!-- Register Flow -->
|
| 379 |
<div id="flowRegister" style="display:none;">
|
| 380 |
<div class="auth-phase active" id="regPhase1">
|
| 381 |
<div class="auth-input-group">
|
|
|
|
| 401 |
// --- 1. CONFIG & STATE ---
|
| 402 |
const Config = {
|
| 403 |
GAS_URL: "https://script.google.com/macros/s/AKfycbz5vrlB4GrfkfBVYdQ52IQweIXC1cNDwKuTUorxdAiOdSSIrH55mzJlaz9kq1Y94ot5/exec",
|
| 404 |
+
API_ENDPOINT: "/api/chat", // Pointing to your powerful Python backend
|
| 405 |
LOGO: "https://i.ibb.co/MyYStcGP/TIRANGA-20260613-131924-0000.png"
|
| 406 |
};
|
| 407 |
|
|
|
|
| 455 |
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); Chat.handleSend(); }
|
| 456 |
});
|
| 457 |
|
| 458 |
+
// --- 3. AUTHENTICATION & HISTORY DB (RESTORED COMPLETELY) ---
|
| 459 |
const Auth = {
|
| 460 |
init: () => {
|
| 461 |
const uAv = document.getElementById('uAv');
|
|
|
|
| 482 |
uSub.innerText = `Queries: ${State.guestCount}/10`;
|
| 483 |
uSub.style.color = "var(--text-tertiary)";
|
| 484 |
btnLogout.style.display = 'none';
|
| 485 |
+
greeting.innerText = `Hi Divy Patel, I am ready to assist you.`;
|
| 486 |
}
|
| 487 |
},
|
| 488 |
handleLogout: () => {
|
|
|
|
| 558 |
if(data.status === 'success' && data.historyJSON !== "[]") {
|
| 559 |
State.history = JSON.parse(data.historyJSON);
|
| 560 |
document.getElementById('welcomeScreen').style.display = 'none';
|
| 561 |
+
State.history.forEach((msg, idx) => {
|
| 562 |
+
if(msg.role === 'user') {
|
| 563 |
+
Chat.renderUser(msg.content, '');
|
| 564 |
+
// Add to sidebar history list
|
| 565 |
+
const shortText = msg.content.substring(0, 30) + (msg.content.length > 30 ? '...' : '');
|
| 566 |
+
document.getElementById('chatHistory').innerHTML += `<div class="history-item" onclick="alert('History navigation active')">${UI.escape(shortText)}</div>`;
|
| 567 |
+
}
|
| 568 |
else {
|
| 569 |
const botNode = Chat.renderBot();
|
| 570 |
botNode.innerHTML = marked.parse(msg.content.replace(/<think>[\s\S]*?<\/think>/gi, ''));
|
|
|
|
| 582 |
},
|
| 583 |
clearHistory: async () => {
|
| 584 |
if(State.user) {
|
|
|
|
| 585 |
try { await fetch(Config.GAS_URL, { method: 'POST', body: JSON.stringify({action: "delete_history", email: State.user}) }); } catch(e){}
|
| 586 |
}
|
| 587 |
location.reload();
|
| 588 |
}
|
| 589 |
};
|
| 590 |
|
| 591 |
+
// --- 4. FILE HANDLING (Secure) ---
|
| 592 |
const FileSys = {
|
| 593 |
process: async (input, type) => {
|
| 594 |
document.getElementById('attachMenu').classList.remove('active');
|
|
|
|
| 632 |
} else {
|
| 633 |
r.onload = (e) => {
|
| 634 |
let data = e.target.result;
|
| 635 |
+
if(file.name.endsWith('.html')) {
|
| 636 |
+
data = data.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "\n[SCRIPT SANITIZED]\n");
|
| 637 |
+
}
|
| 638 |
State.attachment = { type: 'text', data: data, name: file.name };
|
| 639 |
};
|
| 640 |
r.readAsText(file);
|
|
|
|
| 660 |
Speech.rec.onstart = () => { Speech.isRec = true; document.getElementById('btnStt').classList.add('recording'); };
|
| 661 |
Speech.rec.onresult = (e) => {
|
| 662 |
let trans = '';
|
| 663 |
+
for (let i = e.resultIndex; i < e.results.length; ++i) {
|
| 664 |
+
if (e.results[i].isFinal) trans += e.results[i][0].transcript;
|
| 665 |
+
}
|
| 666 |
+
if (trans) {
|
| 667 |
+
const input = document.getElementById('mainInput');
|
| 668 |
+
input.value += (input.value ? ' ' : '') + trans;
|
| 669 |
+
UI.autoGrow(input);
|
| 670 |
+
}
|
| 671 |
};
|
| 672 |
Speech.rec.onerror = () => Speech.stop();
|
| 673 |
Speech.rec.onend = () => Speech.stop();
|
| 674 |
},
|
| 675 |
+
toggle: () => {
|
| 676 |
+
if (!Speech.rec) Speech.init();
|
| 677 |
+
if (Speech.isRec) Speech.stop();
|
| 678 |
+
else { try { Speech.rec.start(); } catch(e) {} }
|
| 679 |
+
},
|
| 680 |
+
stop: () => {
|
| 681 |
+
if(Speech.rec) Speech.rec.stop();
|
| 682 |
+
Speech.isRec = false;
|
| 683 |
+
document.getElementById('btnStt').classList.remove('recording');
|
| 684 |
+
}
|
| 685 |
};
|
| 686 |
|
| 687 |
// --- 6. WORKSPACE PRO MAX ---
|
| 688 |
const Workspace = {
|
| 689 |
open: (id) => {
|
| 690 |
+
State.currentWs = id;
|
| 691 |
+
const d = State.workspaces[id];
|
| 692 |
+
const b = document.getElementById('wsCodeBlock');
|
| 693 |
+
b.className = `hljs language-${d.lang || 'plaintext'}`;
|
| 694 |
+
b.textContent = d.code;
|
| 695 |
+
hljs.highlightElement(b);
|
| 696 |
+
|
| 697 |
document.getElementById('workspacePanel').classList.add('active');
|
| 698 |
if(window.innerWidth <= 900) { document.getElementById('sidebar').classList.add('collapsed'); }
|
| 699 |
Workspace.switchTab('code');
|
| 700 |
},
|
| 701 |
close: () => document.getElementById('workspacePanel').classList.remove('active'),
|
| 702 |
switchTab: (tab) => {
|
| 703 |
+
document.getElementById('tabCode').classList.remove('active');
|
| 704 |
+
document.getElementById('tabPreview').classList.remove('active');
|
| 705 |
if(tab === 'code') {
|
| 706 |
+
document.getElementById('tabCode').classList.add('active');
|
| 707 |
+
document.getElementById('wsCodeView').style.display = 'block';
|
| 708 |
+
document.getElementById('wsPreviewView').style.display = 'none';
|
| 709 |
} else {
|
| 710 |
+
document.getElementById('tabPreview').classList.add('active');
|
| 711 |
+
document.getElementById('wsCodeView').style.display = 'none';
|
| 712 |
+
document.getElementById('wsPreviewView').style.display = 'flex';
|
| 713 |
Workspace.run();
|
| 714 |
}
|
| 715 |
},
|
| 716 |
+
copy: () => {
|
| 717 |
+
if(State.currentWs !== null) {
|
| 718 |
+
navigator.clipboard.writeText(State.workspaces[State.currentWs].code).then(() => alert('Code Copied!'));
|
| 719 |
+
}
|
| 720 |
+
},
|
| 721 |
run: async () => {
|
| 722 |
if (State.currentWs === null) return;
|
| 723 |
+
const d = State.workspaces[State.currentWs];
|
| 724 |
+
const lang = (d.lang || '').toLowerCase();
|
| 725 |
+
const view = document.getElementById('wsPreviewView');
|
| 726 |
|
| 727 |
if (['html', 'xml', 'javascript', 'js', 'css'].includes(lang)) {
|
| 728 |
let html = d.code;
|
| 729 |
if(lang === 'javascript' || lang === 'js') html = `<script>${d.code}<\/script>`;
|
| 730 |
if(lang === 'css') html = `<style>${d.code}</style><div style="padding:20px;font-family:sans-serif;">CSS Applied. Add HTML to test.</div>`;
|
| 731 |
+
|
| 732 |
+
const iframe = document.createElement('iframe');
|
| 733 |
+
iframe.style.width = '100%'; iframe.style.height = '100%'; iframe.style.border = 'none';
|
| 734 |
+
view.innerHTML = ''; view.appendChild(iframe);
|
| 735 |
+
iframe.contentWindow.document.open(); iframe.contentWindow.document.write(html); iframe.contentWindow.document.close();
|
| 736 |
return;
|
| 737 |
}
|
| 738 |
+
|
| 739 |
view.innerHTML = '<div class="ws-console" style="color:var(--brand-accent);">Compiling code...</div>';
|
| 740 |
+
const pMap = {'python':'python', 'py':'python', 'c':'c', 'cpp':'c++', 'java':'java'};
|
| 741 |
+
const rLang = pMap[lang];
|
| 742 |
+
|
| 743 |
if(!rLang) { view.innerHTML = `<div class="ws-console" style="color:#cc0000;">Live Preview not supported for ${lang}.</div>`; return; }
|
| 744 |
|
| 745 |
try {
|
| 746 |
+
const res = await fetch('https://emkc.org/api/v2/piston/execute', {
|
| 747 |
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
| 748 |
+
body: JSON.stringify({ language: rLang, version: "*", files: [{ content: d.code }] })
|
| 749 |
+
});
|
| 750 |
const data = await res.json();
|
| 751 |
let out = (data.compile?.output || "") + "\n" + (data.run?.output || "") + "\n" + (data.run?.stderr || "");
|
| 752 |
view.innerHTML = `<div class="ws-console">${UI.escape(out.trim() || "[Execution Finished]")}</div>`;
|
|
|
|
| 756 |
|
| 757 |
const MDRenderer = new marked.Renderer();
|
| 758 |
MDRenderer.code = function(code, lang) {
|
| 759 |
+
const id = State.workspaces.length;
|
| 760 |
+
State.workspaces.push({code: code, lang: lang});
|
| 761 |
const highlighted = hljs.highlightAuto(code).value;
|
| 762 |
return `
|
| 763 |
<div style="margin: 16px 0;">
|
|
|
|
| 772 |
};
|
| 773 |
marked.use({ renderer: MDRenderer });
|
| 774 |
|
| 775 |
+
// --- 7. CHAT ENGINE (WITH SMART AUTO-SEARCH UI) ---
|
| 776 |
const Chat = {
|
| 777 |
renderUser: (txt, attachUI) => {
|
| 778 |
const c = document.getElementById('chatContainer');
|
|
|
|
| 806 |
const text = input.value.trim();
|
| 807 |
if(!text && !State.attachment) return;
|
| 808 |
|
| 809 |
+
// Guest Limit Validation
|
| 810 |
if(!State.user) {
|
| 811 |
if(State.guestCount >= 10) { Auth.openModal(); UI.showAuthMsg("Guest limit reached. Secure Login required.", true); return; }
|
| 812 |
State.guestCount++; localStorage.setItem('codeved_guest', State.guestCount);
|
|
|
|
| 819 |
let payloadStr = text;
|
| 820 |
let attachUI = '';
|
| 821 |
let mediaArray = [];
|
| 822 |
+
|
| 823 |
+
// 💡 SMART AUTO-SEARCH DETECTION
|
| 824 |
+
const queryLower = text.toLowerCase();
|
| 825 |
+
const searchTriggers = ["search", "latest", "news", "update", "current", "2026", "today", "price", "who won", "weather", "aaj"];
|
| 826 |
+
let isSearching = searchTriggers.some(kw => queryLower.includes(kw));
|
| 827 |
|
| 828 |
if(State.attachment) {
|
| 829 |
if(State.attachment.type === 'text') {
|
|
|
|
| 836 |
}
|
| 837 |
|
| 838 |
Chat.renderUser(text || '[Attached Media]', attachUI);
|
| 839 |
+
|
| 840 |
+
// Update History UI
|
| 841 |
+
const shortText = (text || 'Media Attached').substring(0, 30) + "...";
|
| 842 |
+
document.getElementById('chatHistory').innerHTML += `<div class="history-item">${UI.escape(shortText)}</div>`;
|
| 843 |
+
|
| 844 |
State.history.push({ role: 'user', content: payloadStr });
|
| 845 |
FileSys.discard();
|
| 846 |
|
|
|
|
| 852 |
}
|
| 853 |
|
| 854 |
try {
|
| 855 |
+
// Call the Powerful Backend
|
| 856 |
const res = await fetch(Config.API_ENDPOINT, {
|
| 857 |
method: 'POST', headers: {'Content-Type': 'application/json'},
|
| 858 |
body: JSON.stringify({
|
| 859 |
+
message: payloadStr,
|
| 860 |
+
attachments: mediaArray,
|
| 861 |
+
is_search: isSearching, // SIGNAL BACKEND TO SEARCH
|
| 862 |
history: State.history
|
| 863 |
})
|
| 864 |
});
|
|
|
|
| 918 |
|
| 919 |
</script>
|
| 920 |
</body>
|
| 921 |
+
</html>
|