Vedika-API-endpoint / index.html
Aura Gen
Create index.html
960ea1a verified
<!DOCTYPE html>
<html lang="hi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vedika AI - Premium Workspace</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/atom-one-dark.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;800&display=swap');
body { font-family: 'Inter', sans-serif; background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 100%); color: #f8fafc; height: 100vh; margin: 0; overflow: hidden; }
.glass-panel { background: rgba(255, 255, 255, 0.03); backdrop-filter: blur(16px); border: 1px solid rgba(255, 255, 255, 0.05); box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5); }
.chat-container { height: calc(100vh - 180px); overflow-y: auto; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.2) transparent; }
.chat-container::-webkit-scrollbar { width: 6px; }
.chat-container::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.2); border-radius: 10px; }
.user-message { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); border-radius: 20px 20px 0 20px; }
.ai-message { background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 20px 20px 20px 0; }
.typing-indicator span { display: inline-block; width: 8px; height: 8px; background-color: #60a5fa; border-radius: 50%; margin-right: 4px; animation: typing 1.4s infinite both; }
.typing-indicator span:nth-child(1) { animation-delay: -0.32s; } .typing-indicator span:nth-child(2) { animation-delay: -0.16s; }
@keyframes typing { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1); } }
.markdown-body pre { background: #1e1e1e; padding: 15px; border-radius: 10px; overflow-x: auto; margin-top: 10px; }
.markdown-body code { font-family: 'Courier New', monospace; color: #a78bfa; }
</style>
</head>
<body class="flex flex-col h-screen">
<header class="glass-panel py-4 px-8 flex justify-between items-center z-10">
<div class="flex items-center gap-3">
<div class="w-10 h-10 rounded-full bg-blue-600 flex items-center justify-center text-xl font-bold shadow-lg shadow-blue-500/50">V</div>
<div><h1 class="text-xl font-bold tracking-wide">Vedika AI</h1><p class="text-xs text-blue-300">Enterprise Edition - Designed by Divy Patel</p></div>
</div>
<div class="flex items-center gap-4">
<select id="modelSelector" class="glass-panel bg-transparent text-sm text-white px-4 py-2 rounded-lg outline-none cursor-pointer">
<option value="FLASH" class="text-black">⚡ Vedika Flash</option>
<option value="PRO" class="text-black">🧠 Vedika Pro</option>
<option value="DEEP_THINKER" class="text-black">🤔 Deep Thinker</option>
<option value="IMAGE" class="text-black">🎨 Chitrakaar</option>
<option value="CODE" class="text-black">💻 Code Genesis</option>
<option value="COMPOUND" class="text-black">🌌 Next Gen Compound</option>
</select>
<div id="tokenUI" class="flex items-center gap-2">
<button onclick="generateAndSaveToken()" class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-lg text-sm font-semibold transition-all shadow-lg flex items-center gap-2">
<i class="fa-solid fa-key"></i> Generate Security Token
</button>
</div>
<div id="tokenActiveUI" class="hidden flex items-center gap-2 text-green-400 text-sm font-semibold">
<i class="fa-solid fa-shield-check"></i> <span id="tokenDisplay">Secured</span>
<button onclick="clearToken()" class="text-red-400 hover:text-red-300 ml-2" title="Revoke Token"><i class="fa-solid fa-power-off"></i></button>
</div>
</div>
</header>
<main class="flex-1 overflow-hidden relative w-full max-w-6xl mx-auto p-4">
<div id="chatBox" class="chat-container w-full h-full pr-4 pb-20 flex flex-col gap-6">
<div class="flex w-full mt-4">
<div class="ai-message glass-panel p-5 max-w-3xl text-sm md:text-base markdown-body shadow-lg">
<p>नमस्कार आदरणीय दिव्य जी! 🙏</p>
<p>मैं <b>Vedika AI</b> हूँ। आपका एंटरप्राइज-ग्रेड सर्वर और सिक्योरिटी सिस्टम इसी स्पेस में सफलतापूर्वक लाइव है।</p>
</div>
</div>
</div>
</main>
<footer class="fixed bottom-0 w-full p-4 z-20">
<div class="max-w-4xl mx-auto glass-panel rounded-2xl p-2 flex items-end gap-2 shadow-2xl relative">
<input type="file" id="fileInput" class="hidden" accept="image/*, audio/*, video/*" onchange="handleFileSelect(event)">
<button onclick="document.getElementById('fileInput').click()" class="p-4 text-gray-400 hover:text-blue-400 transition-colors rounded-xl hover:bg-white/5"><i class="fa-solid fa-paperclip text-xl"></i></button>
<div id="filePreview" class="hidden absolute -top-12 left-4 glass-panel px-4 py-2 rounded-lg text-xs flex items-center gap-2 text-blue-300">
<i class="fa-solid fa-file"></i> <span id="fileName">file.jpg</span>
<button onclick="removeFile()" class="text-red-400 hover:text-red-500 ml-2"><i class="fa-solid fa-times"></i></button>
</div>
<textarea id="userInput" rows="1" placeholder="Type your command here..." class="flex-1 bg-transparent text-white outline-none resize-none max-h-32 p-3 text-sm" oninput="this.style.height = ''; this.style.height = this.scrollHeight + 'px'"></textarea>
<button id="sendBtn" onclick="sendMessage()" class="bg-blue-600 hover:bg-blue-500 text-white p-4 rounded-xl transition-all shadow-lg flex items-center justify-center min-w-[60px]"><i class="fa-solid fa-paper-plane text-xl"></i></button>
</div>
</footer>
<script>
const GAS_URL = "https://script.google.com/macros/s/AKfycbx9QkGDBk7dvkbcDAy2Kl1SD8ypYF5JV4GF7V-2IyFEFg1fSR0FDonIhdKA1MMsga2H/exec";
const BACKEND_CHAT_URL = "/chat";
let chatHistory = [];
let currentFileBase64 = null;
let currentFileType = null;
marked.setOptions({ highlight: (code, lang) => hljs.highlight(code, { language: hljs.getLanguage(lang) ? lang : 'plaintext' }).value });
window.onload = () => {
const token = localStorage.getItem("vedika_token");
if (token) activateTokenUI(token);
};
function activateTokenUI(token) {
document.getElementById("tokenUI").classList.add("hidden");
document.getElementById("tokenActiveUI").classList.remove("hidden");
document.getElementById("tokenDisplay").innerText = "Token: " + token.substring(0,6) + "...";
}
async function generateAndSaveToken() {
const btn = document.querySelector("#tokenUI button");
btn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Generating...';
try {
const newToken = crypto.randomUUID();
await fetch(GAS_URL, { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: JSON.stringify({ action: "generate", token: newToken }) });
localStorage.setItem("vedika_token", newToken);
activateTokenUI(newToken);
addMessageToUI("System", "नया सुरक्षा टोकन सफलतापूर्वक जनरेट हो गया है।", "ai-message text-green-400");
} catch (error) {
alert("टोकन जनरेट करने में समस्या आई।");
btn.innerHTML = '<i class="fa-solid fa-key"></i> Generate Security Token';
}
}
function clearToken() {
localStorage.removeItem("vedika_token");
document.getElementById("tokenUI").classList.remove("hidden");
document.getElementById("tokenActiveUI").classList.add("hidden");
document.querySelector("#tokenUI button").innerHTML = '<i class="fa-solid fa-key"></i> Generate Security Token';
}
function handleFileSelect(event) {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = e => {
currentFileBase64 = e.target.result;
currentFileType = file.type.split('/')[0];
document.getElementById("fileName").innerText = file.name;
document.getElementById("filePreview").classList.remove("hidden");
};
reader.readAsDataURL(file);
}
function removeFile() {
currentFileBase64 = null; currentFileType = null;
document.getElementById("fileInput").value = "";
document.getElementById("filePreview").classList.add("hidden");
}
async function sendMessage() {
const token = localStorage.getItem("vedika_token");
if (!token) return alert("आदरणीय दिव्य जी, कृपया पहले सुरक्षा टोकन जनरेट करें!");
const inputField = document.getElementById("userInput");
let text = inputField.value.trim();
if (!text && !currentFileBase64) return;
const sendBtn = document.getElementById("sendBtn");
let userContent = text;
if (currentFileBase64) userContent += `\n<${currentFileType} src="${currentFileBase64}" />`;
addMessageToUI("You", text + (currentFileBase64 ? " [File Attached]" : ""), "user-message");
chatHistory.push({ role: "user", content: userContent });
inputField.value = ""; inputField.style.height = ''; removeFile();
sendBtn.disabled = true; sendBtn.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i>';
const typingId = "typing-" + Date.now();
addTypingIndicator(typingId);
try {
const response = await fetch(BACKEND_CHAT_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
body: JSON.stringify({ mode: document.getElementById("modelSelector").value, messages: chatHistory })
});
document.getElementById(typingId)?.remove();
if (!response.ok) throw new Error((await response.json()).error || "HTTP error");
const reader = response.body.getReader();
const decoder = new TextDecoder("utf-8");
let aiResponseText = "";
const msgId = "ai-msg-" + Date.now();
createEmptyBubble(msgId, "ai-message");
const msgContainer = document.getElementById(msgId);
while (true) {
const { done, value } = await reader.read();
if (done) break;
const lines = decoder.decode(value, { stream: true }).split("\n");
for (const line of lines) {
if (line.startsWith("data: ") && line !== "data: [DONE]") {
try {
const json = JSON.parse(line.substring(6));
if (json.choices?.[0]?.delta?.content) {
aiResponseText += json.choices[0].delta.content;
msgContainer.innerHTML = marked.parse(aiResponseText);
document.getElementById("chatBox").scrollTop = document.getElementById("chatBox").scrollHeight;
}
} catch(e) {}
}
}
}
chatHistory.push({ role: "assistant", content: aiResponseText });
} catch (error) {
document.getElementById(typingId)?.remove();
addMessageToUI("System", "⚠️ त्रुटि: " + error.message, "ai-message text-red-400 border-red-500/50");
if(error.message.includes("Token")) clearToken();
} finally {
sendBtn.disabled = false; sendBtn.innerHTML = '<i class="fa-solid fa-paper-plane text-xl"></i>';
}
}
function addMessageToUI(sender, text, className) {
const box = document.getElementById("chatBox");
box.insertAdjacentHTML('beforeend', `<div class="flex w-full mt-4 ${sender === 'You' ? 'justify-end' : ''}"><div class="${className} p-4 max-w-3xl text-sm md:text-base markdown-body shadow-lg">${sender === 'You' ? text.replace(/[&<>'"]/g, tag => ({'&': '&amp;', '<': '&lt;', '>': '&gt;', "'": '&#39;', '"': '&quot;'}[tag])) : marked.parse(text)}</div></div>`);
box.scrollTop = box.scrollHeight;
}
function createEmptyBubble(id, className) {
document.getElementById("chatBox").insertAdjacentHTML('beforeend', `<div class="flex w-full mt-4"><div id="${id}" class="${className} p-4 max-w-3xl text-sm md:text-base markdown-body shadow-lg"></div></div>`);
}
function addTypingIndicator(id) {
document.getElementById("chatBox").insertAdjacentHTML('beforeend', `<div id="${id}" class="flex w-full mt-4"><div class="ai-message p-5 max-w-3xl flex items-center shadow-lg"><div class="typing-indicator"><span></span><span></span><span></span></div></div></div>`);
document.getElementById("chatBox").scrollTop = document.getElementById("chatBox").scrollHeight;
}
document.getElementById('userInput').addEventListener('keydown', e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); } });
</script>
</body>
</html>