Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Slide Viewer with Grok Chat</title> | |
| <link rel="stylesheet" href="style.css"> | |
| <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> | |
| </head> | |
| <body> | |
| <!-- Sidebar --> | |
| <div class="sidebar"> | |
| <div class="prompt-icon" id="promptIcon"> | |
| <img src="prompt-icon.png" alt="Prompt Icon"> | |
| <span>Prompt</span> | |
| </div> | |
| <div class="video-icon" id="videoIcon"> | |
| <img src="video-icon.png" alt="Video Icon"> | |
| <span>Video</span> | |
| </div> | |
| </div> | |
| <!-- Main Container --> | |
| <div class="container"> | |
| <div class="top-bar"> | |
| <div class="nav-buttons"> | |
| <button id="prev-btn">← Previous</button> | |
| <button id="next-btn">Next →</button> | |
| </div> | |
| <h1 id="slide-title">Slide Viewer</h1> | |
| </div> | |
| <div class="main"> | |
| <div class="content"> | |
| <img id="slide-image" src="images/01_mg.png" alt="Slide Image"> | |
| <div class="prompt-box" id="promptBox"> | |
| <textarea id="promptText"></textarea> | |
| <button id="queryButton">Query Grok</button> | |
| </div> | |
| <div class="response-box" id="responseBox"> | |
| <div id="responseContent"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="video-overlay" id="videoOverlay" style="display: none;"> | |
| <iframe id="videoPlayer" src="" allowfullscreen></iframe> | |
| <button class="close-button" id="closeVideo">×</button> | |
| </div> | |
| </div> | |
| <script> | |
| const BASE_URL = "https://api.x.ai/v1"; | |
| const API_KEY = "xai-hOb0j9QUXVVQMe86ULxWrvyWQQm2LqnWVdxh5hanvqsiVDsXcSPY9EA7YAM5uLCXaThgJscWxxFCHJFy"; | |
| // DOM elements | |
| const slideTitle = document.getElementById('slide-title'); | |
| const slideImage = document.getElementById('slide-image'); | |
| const prevBtn = document.getElementById('prev-btn'); | |
| const nextBtn = document.getElementById('next-btn'); | |
| const promptBox = document.getElementById('promptBox'); | |
| const promptText = document.getElementById('promptText'); | |
| const responseBox = document.getElementById('responseBox'); | |
| const responseContent = document.getElementById('responseContent'); | |
| const promptIcon = document.getElementById('promptIcon'); | |
| const videoIcon = document.getElementById('videoIcon'); | |
| const videoOverlay = document.getElementById('videoOverlay'); | |
| const videoPlayer = document.getElementById('videoPlayer'); | |
| const closeVideo = document.getElementById('closeVideo'); | |
| const queryButton = document.getElementById('queryButton'); | |
| let slides = []; | |
| let currentIndex = 0; | |
| // Define agentic workers | |
| const agents = [ | |
| { | |
| name: "Zoe Kim", | |
| systemMessage: ` | |
| You are Zoe Kim, a Software Engineer specializing in full-stack development. | |
| Discuss application development requirements in 1-2 sentences. | |
| `, | |
| }, | |
| { | |
| name: "Alex Patel", | |
| systemMessage: ` | |
| You are Alex Patel, a DevOps Engineer focusing on CI/CD pipelines. | |
| Respond to Zoe’s suggestions in 1-2 sentences and discuss infrastructure adjustments. | |
| `, | |
| }, | |
| { | |
| name: "Jack Dawson", | |
| systemMessage: ` | |
| You are Jack Dawson, a QA and SRE specializing in system reliability. | |
| Provide concise feedback on Alex’s design in 1-2 sentences, addressing risks or gaps. | |
| `, | |
| }, | |
| ]; | |
| async function fetchSlides() { | |
| try { | |
| const response = await fetch('slide_config.json'); | |
| const data = await response.json(); | |
| slides = data.slides; | |
| loadSlide(currentIndex); | |
| } catch (error) { | |
| console.error('Error loading slides:', error); | |
| } | |
| } | |
| function loadSlide(index) { | |
| if (!slides.length) return; | |
| const slide = slides[index]; | |
| slideTitle.textContent = slide.id.replace('_', ' '); | |
| slideImage.src = slide.image; | |
| // Clear prompt and Grok info | |
| promptBox.style.display = 'none'; | |
| responseBox.style.display = 'none'; | |
| responseContent.innerHTML = ''; | |
| // Reset video player | |
| videoPlayer.src = ''; | |
| } | |
| prevBtn.addEventListener('click', () => { | |
| currentIndex = (currentIndex - 1 + slides.length) % slides.length; | |
| loadSlide(currentIndex); | |
| }); | |
| nextBtn.addEventListener('click', () => { | |
| currentIndex = (currentIndex + 1) % slides.length; | |
| loadSlide(currentIndex); | |
| }); | |
| promptIcon.addEventListener('click', () => { | |
| const slideText = slides[currentIndex]?.text || "No prompt text available."; | |
| promptBox.style.display = promptBox.style.display === 'block' ? 'none' : 'block'; | |
| promptText.value = slideText; // Set prompt text from the slide config | |
| }); | |
| videoIcon.addEventListener('click', () => { | |
| const videoURL = slides[currentIndex]?.video || ''; | |
| if (videoURL) { | |
| videoPlayer.src = videoURL; | |
| videoOverlay.style.display = 'flex'; | |
| } | |
| }); | |
| closeVideo.addEventListener('click', () => { | |
| videoOverlay.style.display = 'none'; | |
| videoPlayer.src = ''; | |
| }); | |
| queryButton.addEventListener('click', async () => { | |
| const userPrompt = promptText.value.trim(); | |
| if (!userPrompt) return; | |
| responseBox.style.display = "block"; | |
| responseContent.innerHTML = "Loading..."; | |
| try { | |
| let conversationLog = []; | |
| const numIterations = 2; // Number of back-and-forth interactions | |
| for (let iteration = 0; iteration < numIterations; iteration++) { | |
| for (const agent of agents) { | |
| const response = await fetch(`${BASE_URL}/chat/completions`, { | |
| method: "POST", | |
| headers: { | |
| "Authorization": `Bearer ${API_KEY}`, | |
| "Content-Type": "application/json" | |
| }, | |
| body: JSON.stringify({ | |
| model: "grok-beta", | |
| messages: [ | |
| { role: "system", content: agent.systemMessage }, | |
| { role: "user", content: userPrompt }, | |
| ...conversationLog.map((log) => ({ | |
| role: "assistant", | |
| content: log.response, | |
| })), | |
| ], | |
| }), | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`Error: ${response.statusText}`); | |
| } | |
| const data = await response.json(); | |
| const agentResponse = data.choices?.[0]?.message?.content || "Unexpected API response."; | |
| conversationLog.push({ | |
| agent: agent.name, | |
| response: agentResponse, | |
| }); | |
| // Append response with styled agent name | |
| responseContent.innerHTML += ` | |
| <p><span class="agent-name">${agent.name}:</span> ${agentResponse}</p> | |
| `; | |
| } | |
| } | |
| } catch (error) { | |
| responseContent.textContent = `Error: ${error.message}`; | |
| } | |
| }); | |
| fetchSlides(); | |
| </script> | |
| </body> | |
| </html> | |