var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true });

// api.js var CEREBRAS_MODEL = "gpt-oss-120b"; var CEREBRAS_API_URL = "https://api.cerebras.ai/v1/chat/completions"; var MAX_HISTORY_LENGTH = 50; var HISTORY_TTL = 60 * 60 * 24 * 30; async function handleChatRequest(request, env) { try { const { message, sessionId = "default" } = await request.json(); if (!message || typeof message !== "string" || message.trim().length === 0) { return jsonResponse({ error: "Invalid message" }, 400); } let history = []; if (env.AI_KV) { const historyKey = chat:${sessionId}; const storedHistory = await env.AI_KV.get(historyKey); if (storedHistory) { try { history = JSON.parse(storedHistory); } catch (e) { console.error("Failed to parse history:", e); history = []; } } } const messages = [ { role: "system", content: You are a helpful AI assistant powered by Cerebras GPT-OSS-120B. Format your responses using markdown. Be concise yet thorough. If asked to generate code, use proper syntax highlighting. If asked to create HTML, provide clean, modern code. }, ...history.slice(-20).map(([role, content]) => ({ role, content })), { role: "user", content: message } ]; let reply; if (!env.CEREBRAS_API_KEY) { reply = `\u{1F916} Demo Mode Response

I received your message: "${message}"

To enable real AI responses:

  1. Add your Cerebras API key in Cloudflare Workers settings
  2. Set it as a secret named: \CEREBRAS_API_KEY\\
  3. Get your API key from cerebras.ai

Features available:

Failed to get response from Cerebras API. Error: ${apiError.message}

Please check your API key and try again.; } } const newHistory = [...history, ["user", message], ["assistant", reply]]; if (newHistory.length > MAX_HISTORY_LENGTH * 2) { newHistory.splice(0, newHistory.length - MAX_HISTORY_LENGTH * 2); } if (env.AI_KV) { const historyKey = chat:${sessionId}; await env.AI_KV.put(historyKey, JSON.stringify(newHistory), { expirationTtl: HISTORY_TTL }); await updateSessionMetadata(env, sessionId, newHistory.length / 2); } return jsonResponse({ reply, sessionId, timestamp: (/* @__PURE__ */ new Date()).toISOString(), messageCount: newHistory.length / 2 }); } catch (error) { console.error("Chat request error:", error); return jsonResponse({ error: "Failed to process chat request", details: error.message }, 500); } } __name(handleChatRequest, "handleChatRequest"); async function handleHistoryRequest(request, env) { try { const url = new URL(request.url); const sessionId = url.searchParams.get("session") || "default"; if (!env.AI_KV) { return jsonResponse({ history: [], sessionId }); } const historyKey = chat:${sessionId}; const storedHistory = await env.AI_KV.get(historyKey); let history = []; if (storedHistory) { try { history = JSON.parse(storedHistory); } catch (e) { console.error("Failed to parse history:", e); } } return jsonResponse({ history, sessionId, messageCount: history.length / 2 }); } catch (error) { console.error("History request error:", error); return jsonResponse({ error: "Failed to retrieve history", history: [], sessionId: "default" }, 500); } } __name(handleHistoryRequest, "handleHistoryRequest"); async function handleClearHistory(request, env) { try { const { sessionId = "default" } = await request.json(); if (!env.AI_KV) { return jsonResponse({ success: true }); } const historyKey = chat:${sessionId}`; await env.AI_KV.delete(historyKey); await updateSessionMetadata(env, sessionId, 0); return jsonResponse({ success: true, sessionId, message: "History cleared successfully" }); } catch (error) { console.error("Clear history error:", error); return jsonResponse({ error: "Failed to clear history", success: false }, 500); } } __name(handleClearHistory, "handleClearHistory"); async function updateSessionMetadata(env, sessionId, messageCount) { if (!env.AI_KV) return; try { const sessionsKey = "sessions:list"; const sessionsData = await env.AI_KV.get(sessionsKey); let sessions = sessionsData ? JSON.parse(sessionsData) : []; const sessionIndex = sessions.findIndex((s) => s.id === sessionId); if (sessionIndex >= 0) { sessions[sessionIndex].lastUsed = Date.now(); sessions[sessionIndex].messageCount = messageCount; } else if (sessionId === "default") { sessions.push({ id: "default", name: "Default Chat", created: Date.now(), lastUsed: Date.now(), messageCount }); } await env.AI_KV.put(sessionsKey, JSON.stringify(sessions), { expirationTtl: HISTORY_TTL }); } catch (e) { console.error("Failed to update session metadata:", e); } } __name(updateSessionMetadata, "updateSessionMetadata"); function jsonResponse(data, status = 200) { return new Response(JSON.stringify(data), { status, headers: { "Content-Type": "application/json", "Cache-Control": "no-cache" } }); } __name(jsonResponse, "jsonResponse");

// sessions.js var MAX_SESSIONS = 20; var SESSION_TTL = 60 * 60 * 24 * 30; async function handleSessionsList(request, env) { try { const userId = request.user?.userId || "default"; if (!env.AI_KV) { return jsonResponse2({ sessions: [] }); } const sessionsKey = userId !== "default" ? sessions:user:${userId} : "sessions:list"; const sessionsData = await env.AI_KV.get(sessionsKey); let sessions = []; if (sessionsData) { try { sessions = JSON.parse(sessionsData); } catch (e) { console.error("Failed to parse sessions:", e); } } sessions.sort((a, b) => { return (b.lastUsed || 0) - (a.lastUsed || 0); }); return jsonResponse2({ sessions }); } catch (error) { console.error("List sessions error:", error); return jsonResponse2({ error: "Failed to list sessions", sessions: [] // Return empty array on error, no default session }, 500); } } __name(handleSessionsList, "handleSessionsList"); async function handleNewSession(request, env) { try { const { name } = await request.json(); if (!name || typeof name !== "string" || name.trim().length === 0) { return jsonResponse2({ error: "Session name is required" }, 400); } const sessionId = session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}; const session = { id: sessionId, name: name.trim(), created: Date.now(), lastUsed: Date.now(), messageCount: 0 }; if (!env.AI_KV) { return jsonResponse2({ session }); } const userId = request.user?.userId || "default"; const sessionsKey = userId !== "default" ? sessions:user:${userId} : "sessions:list"; const sessionsData = await env.AI_KV.get(sessionsKey); let sessions = sessionsData ? JSON.parse(sessionsData) : []; sessions.push(session); if (sessions.length > MAX_SESSIONS) { sessions.sort((a, b) => { return (b.lastUsed || 0) - (a.lastUsed || 0); }); const toRemove = sessions.slice(MAX_SESSIONS); for (const oldSession of toRemove) { await env.AI_KV.delete(chat:${oldSession.id}); } sessions = sessions.slice(0, MAX_SESSIONS); } await env.AI_KV.put(sessionsKey, JSON.stringify(sessions), { expirationTtl: SESSION_TTL }); return jsonResponse2({ session, message: "Session created successfully" }); } catch (error) { console.error("New session error:", error); return jsonResponse2({ error: "Failed to create session", details: error.message }, 500); } } __name(handleNewSession, "handleNewSession"); async function handleDeleteSession(request, env) { try { const { sessionId } = await request.json(); if (!sessionId) { return jsonResponse2({ error: "Session ID is required" }, 400); } if (!env.AI_KV) { return jsonResponse2({ success: true }); } const userId = request.user?.userId || "default"; const sessionsKey = userId !== "default" ? sessions:user:${userId} : "sessions:list"; const sessionsData = await env.AI_KV.get(sessionsKey); let sessions = sessionsData ? JSON.parse(sessionsData) : []; sessions = sessions.filter((s) => s.id !== sessionId); await env.AI_KV.delete(chat:${sessionId}); await env.AI_KV.put(sessionsKey, JSON.stringify(sessions), { expirationTtl: SESSION_TTL }); return jsonResponse2({ success: true, message: "Session deleted successfully" }); } catch (error) { console.error("Delete session error:", error); return jsonResponse2({ error: "Failed to delete session", details: error.message }, 500); } } __name(handleDeleteSession, "handleDeleteSession"); async function handleSwitchSession(request, env) { try { const { sessionId } = await request.json(); if (!sessionId) { return jsonResponse2({ error: "Session ID is required" }, 400); } if (env.AI_KV) { const userId = request.user?.userId || "default"; const sessionsKey = userId !== "default" ? sessions:user:${userId} : "sessions:list"; const sessionsData = await env.AI_KV.get(sessionsKey); if (sessionsData) { let sessions = JSON.parse(sessionsData); const sessionIndex = sessions.findIndex((s) => s.id === sessionId); if (sessionIndex >= 0) { sessions[sessionIndex].lastUsed = Date.now(); await env.AI_KV.put(sessionsKey, JSON.stringify(sessions), { expirationTtl: SESSION_TTL }); } } } return jsonResponse2({ success: true, sessionId, message: "Switched to session successfully" }); } catch (error) { console.error("Switch session error:", error); return jsonResponse2({ error: "Failed to switch session", details: error.message }, 500); } } __name(handleSwitchSession, "handleSwitchSession"); function jsonResponse2(data, status = 200) { return new Response(JSON.stringify(data), { status, headers: { "Content-Type": "application/json", "Cache-Control": "no-cache" } }); } __name(jsonResponse2, "jsonResponse");

// ui.js function generateHTML(env) { const hasAuth = !!env.AUTH_PASSWORD; const hasD1Auth = !!env.DB; const html = <!DOCTYPE html> <html lang="en" class="dark"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>AI Chat Assistant</title> <script src="<https://cdn.tailwindcss.com>"><\\/script> <script src="<https://cdn.jsdelivr.net/npm/marked/marked.min.js>"><\\/script> <script src="<https://cdn.jsdelivr.net/npm/dompurify@3/dist/purify.min.js>"><\\/script> <style> .dark body { background: linear-gradient(135deg, #0a0a0f 0%, #1a0f2e 100%); color: #e1e7ef; } .dark .glass { background: rgba(17, 17, 27, 0.8); backdrop-filter: blur(10px); border-color: #1f1f2e; } .dark .message-user { background: linear-gradient(135deg, #9333ea, #7e22ce); } .dark .message-assistant { background: #11111b; border: 1px solid #1f1f2e; } .dark .bg-card { background: #11111b; } .dark .border-border { border-color: #1f1f2e; } .dark .text-muted { color: #71717a; } .dark .session-item:hover { background: #1a1a24; } .dark .session-item.active { background: linear-gradient(135deg, #9333ea20, #7e22ce20); border-left: 3px solid #9333ea; } .light body { background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%); color: #111827; } .light .glass { background: rgba(255, 255, 255, 0.8); backdrop-filter: blur(10px); border-color: #e5e7eb; } .light .message-user { background: linear-gradient(135deg, #9333ea, #7e22ce); color: white; } .light .message-assistant { background: white; border: 1px solid #e5e7eb; color: #111827; } .light .bg-card { background: white; color: #111827; } .light .border-border { border-color: #e5e7eb; } .light .text-muted { color: #6b7280; } .light input { background: white; color: #111827; border-color: #e5e7eb; } .light .session-item:hover { background: #f9fafb; } .light .session-item.active { background: linear-gradient(135deg, #9333ea10, #7e22ce10); border-left: 3px solid #9333ea; } .glass { backdrop-filter: blur(10px); transition: all 0.3s; } .prose { color: inherit; max-width: none; } /* Dark mode styles for code and tables */ .dark .prose pre { background: #1a1a24; border: 1px solid #2a2a3a; border-radius: 0.5rem; padding: 1rem; overflow-x: auto; color: #e1e7ef; } .dark .prose pre code { background: transparent; color: #e1e7ef; padding: 0; } .dark .prose code { background: #2a2a3a; color: #9ca3af; padding: 0.125rem 0.375rem; border-radius: 0.25rem; font-size: 0.875rem; } .dark .prose blockquote { border-left: 3px solid #9333ea; padding-left: 1rem; opacity: 0.9; color: #9ca3af; } .dark .prose table { border-collapse: collapse; margin: 1rem 0; width: 100%; } .dark .prose th, .dark .prose td { border: 1px solid #2a2a3a; padding: 0.5rem; color: #e1e7ef; } .dark .prose th { background: #1a1a24; font-weight: 600; color: #f3f4f6; } .dark .prose td { background: #11111b; } /* Light mode styles for code and tables */ .light .prose pre { background: #f3f4f6; border: 1px solid #d1d5db; border-radius: 0.5rem; padding: 1rem; overflow-x: auto; color: #111827; } .light .prose pre code { background: transparent; color: #111827; padding: 0; } .light .prose code { background: #e5e7eb; color: #4b5563; padding: 0.125rem 0.375rem; border-radius: 0.25rem; font-size: 0.875rem; } .light .prose blockquote { border-left: 3px solid #9333ea; padding-left: 1rem; opacity: 0.9; color: #4b5563; } .light .prose table { border-collapse: collapse; margin: 1rem 0; width: 100%; } .light .prose th, .light .prose td { border: 1px solid #d1d5db; padding: 0.5rem; color: #111827; } .light .prose th { background: #e5e7eb; font-weight: 600; color: #111827; } .light .prose td { background: white; } /* Common styles */ .prose h1, .prose h2, .prose h3 { font-weight: 600; margin-top: 1.5rem; margin-bottom: 0.75rem; } .prose ul, .prose ol { margin: 0.75rem 0; padding-left: 1.5rem; } ::-webkit-scrollbar { width: 8px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: #4b5563; border-radius: 4px; } .session-item { padding: 0.5rem; margin-bottom: 0.25rem; border-radius: 0.375rem; cursor: pointer; transition: all 0.2s; position: relative; padding-left: 0.75rem; } </style> </head> <body class="min-h-screen p-4"> <div class="max-w-7xl mx-auto"> <div class="glass rounded-xl p-4 mb-4 border border-border"> <div class="flex justify-between items-center"> <div> <h1 class="text-2xl font-bold bg-gradient-to-r from-purple-400 to-purple-600 bg-clip-text text-transparent">AI Chat Assistant</h1> <p class="text-sm text-muted">Powered by Cerebras GPT-OSS-120B</p> </div> <div class="flex gap-2"> <button id="themeBtn" class="px-3 py-2 rounded-lg bg-card border border-border text-sm hover:opacity-80"> <span id="themeIcon">\\u{1F319}</span> Theme </button> <button id="scrollBtn" class="px-3 py-2 rounded-lg bg-card border border-border text-sm hover:opacity-80"> <span id="scrollIcon">\\u{1F4CC}</span> <span id="scrollText">Auto-Scroll: ON</span> </button> + (hasD1Auth ? <button id="signOutBtn" class="px-3 py-2 rounded-lg bg-red-600 hover:bg-red-700 text-white text-sm transition-colors"> <span>\\u{1F6AA}</span> Sign Out </button> : hasAuth ? '<form method="POST" action="/logout"><button class="px-4 py-2 rounded-lg bg-card hover:bg-card-hover border border-border text-sm">Sign Out</button></form>' : "") + ` </div> </div> </div>

<div class="grid grid-cols-1 lg:grid-cols-5 gap-4">
  <div class="lg:col-span-1">
    <div class="glass rounded-xl p-4 border border-border">
      <div class="flex justify-between items-center mb-3">
        <h3 class="font-semibold text-sm">Sessions</h3>
        <button id="newSessionBtn" class="text-purple-500 hover:text-purple-400 text-sm">+ New</button>
      </div>
      <div id="sessionsList" class="max-h-96 overflow-y-auto"></div>
    </div>
  </div>

  <div class="lg:col-span-4">
    <div class="glass rounded-xl border border-border" style="height: calc(100vh - 10rem);">
      <div id="sessionInfo" class="border-b border-border px-4 py-2 text-sm text-muted">No session selected</div>
      <div id="messages" class="overflow-y-auto p-4" style="height: calc(100% - 8rem);">
        <div class="text-center text-muted py-8">Start a conversation...</div>
      </div>
      <div class="border-t border-border p-4">
        <div class="flex gap-2">
          <input id="messageInput" type="text" placeholder="Type your message..."
            class="flex-1 p-3 rounded-lg bg-card border border-border focus:border-purple-500 outline-none">
          <button id="sendBtn"
            class="px-6 py-3 rounded-lg bg-gradient-to-r from-purple-600 to-purple-700 hover:from-purple-700 hover:to-purple-800 font-semibold text-white">
            Send
          </button>
        </div>
        <div class="flex justify-between mt-2">
          <button id="clearBtn" class="text-xs text-muted hover:text-purple-500">Clear Session</button>
          <span id="status" class="text-xs text-muted"></span>
        </div>
      </div>
    </div>
  </div>
</div>

</div>

<script> console.log("Script starting to execute"); console.error("DEBUG: Script loaded successfully");