Spaces:
Configuration error
Configuration error
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Claude 3.5 Sonnet Chat</title> | |
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet"> | |
| <link rel="icon" type="image/png" href="https://img.icons8.com/fluency/48/000000/robot.png"> <!-- Robot favicon --> | |
| <script src="https://js.puter.com/v2/"></script> | |
| <style> | |
| :root { | |
| --primary-color: #7c4dff; | |
| --secondary-color: #b388ff; | |
| --background-dark: #121212; | |
| --surface-dark: #1e1e1e; | |
| --text-primary: #ffffff; | |
| --text-secondary: #b3b3b3; | |
| } | |
| body { | |
| font-family: 'Roboto', sans-serif; | |
| margin: 0; | |
| padding: 0; | |
| background-color: var(--background-dark); | |
| color: var(--text-primary); | |
| min-height: 100vh; | |
| max-height: 100vh; | |
| overflow: hidden; | |
| } | |
| .main-container { | |
| display: flex; | |
| height: 100vh; | |
| max-height: 100vh; | |
| } | |
| .sidebar { | |
| width: 300px; | |
| background-color: var(--surface-dark); | |
| padding: 20px; | |
| border-right: 1px solid rgba(255, 255, 255, 0.1); | |
| transition: all 0.3s ease; | |
| display: flex; | |
| flex-direction: column; | |
| z-index: 1000; | |
| } | |
| .sidebar-content { | |
| flex-grow: 1; | |
| overflow-y: auto; | |
| } | |
| .brand { | |
| text-align: center; | |
| margin-bottom: 30px; | |
| padding: 15px; | |
| border-bottom: 1px solid rgba(255, 255, 255, 0.1); | |
| } | |
| .brand h1 { | |
| font-size: 24px; | |
| color: var(--primary-color); | |
| margin: 0; | |
| } | |
| .chat-list { | |
| margin-top: 20px; | |
| } | |
| .chat-item { | |
| display: flex; | |
| align-items: center; | |
| padding: 8px; | |
| margin-bottom: 8px; | |
| background-color: rgba(255, 255, 255, 0.05); | |
| border-radius: 8px; | |
| position: relative; | |
| transition: all 0.2s ease; | |
| } | |
| .chat-item:hover { | |
| background-color: rgba(255, 255, 255, 0.1); | |
| } | |
| .chat-button { | |
| flex: 1; | |
| text-align: left; | |
| padding: 8px; | |
| background: none; | |
| border: none; | |
| color: var(--text-primary); | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| width: 100%; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| white-space: nowrap; | |
| } | |
| .chat-button.active { | |
| background-color: var(--primary-color); | |
| } | |
| .chat-text { | |
| flex: 1; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| white-space: nowrap; | |
| } | |
| .delete-chat-btn { | |
| display: inline-block; | |
| background: none; | |
| border: none; | |
| color: #fbfbfb; | |
| font-size: 16px; | |
| margin-left: 10px; | |
| padding: 5px; | |
| cursor: pointer; | |
| } | |
| .delete-chat-btn:hover { | |
| color: #ff0000; | |
| } | |
| .chat-container { | |
| flex: 1; | |
| padding: 20px; | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| display: flex; | |
| flex-direction: column; | |
| height: 100vh; | |
| } | |
| .chat-history { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding: 15px; | |
| background-color: rgba(255, 255, 255, 0.05); | |
| border-radius: 10px; | |
| margin-bottom: 20px; | |
| } | |
| .chat-message { | |
| margin-bottom: 20px; | |
| padding: 15px; | |
| border-radius: 10px; | |
| animation: fadeIn 0.3s ease; | |
| } | |
| .user-message { | |
| background-color: var(--primary-color); | |
| margin-left: 20%; | |
| } | |
| .ai-message { | |
| background-color: var(--surface-dark); | |
| margin-right: 20%; | |
| } | |
| .message-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 10px; | |
| } | |
| .message-actions { | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .message-content { | |
| white-space: pre-wrap; | |
| word-wrap: break-word; | |
| } | |
| .input-container { | |
| background-color: var(--surface-dark); | |
| border-radius: 10px; | |
| padding: 20px; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| } | |
| .message-input-wrapper { | |
| position: relative; | |
| margin-bottom: 15px; | |
| } | |
| textarea { | |
| width: 100%; | |
| padding: 15px; | |
| padding-right: 60px; | |
| font-size: 16px; | |
| background-color: rgba(255, 255, 255, 0.05); | |
| border: 1px solid rgba(255, 255, 255, 0.1); | |
| border-radius: 8px; | |
| color: var(--text-primary); | |
| resize: none; | |
| } | |
| .send-button { | |
| position: absolute; | |
| right: 10px; | |
| top: 50%; | |
| transform: translateY(-50%); | |
| background-color: var(--primary-color); | |
| border: none; | |
| border-radius: 50%; | |
| width: 40px; | |
| height: 40px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| } | |
| .send-button:hover { | |
| background-color: var(--secondary-color); | |
| } | |
| .sidebar-footer { | |
| padding-top: 20px; | |
| border-top: 1px solid rgba(255, 255, 255, 0.1); | |
| margin-top: auto; | |
| text-align: center; | |
| font-size: 0.9em; | |
| color: var(--text-secondary); | |
| } | |
| .github-link { | |
| position: absolute; | |
| bottom: 12px; | |
| left: 8px; | |
| color: var(--text-secondary); | |
| transition: color 0.3s ease; | |
| font-size: 25px; | |
| } | |
| .github-link:hover { | |
| color: var(--primary-color); | |
| } | |
| .btn-custom { | |
| padding: 12px 24px; | |
| border: none; | |
| border-radius: 8px; | |
| font-weight: 500; | |
| transition: all 0.3s ease; | |
| cursor: pointer; | |
| } | |
| .btn-primary { | |
| background-color: var(--primary-color); | |
| color: white; | |
| } | |
| .btn-secondary { | |
| background-color: transparent; | |
| border: 1px solid var(--primary-color); | |
| color: var(--primary-color); | |
| } | |
| .btn-icon { | |
| padding: 8px; | |
| border-radius: 50%; | |
| background-color: rgba(255, 255, 255, 0.1); | |
| border: none; | |
| color: var(--text-primary); | |
| cursor: pointer; | |
| transition: all 0.2s ease; | |
| } | |
| .btn-icon:hover { | |
| background-color: rgba(255, 255, 255, 0.2); | |
| } | |
| .notification { | |
| position: fixed; | |
| top: 20px; | |
| right: 20px; | |
| background-color: var(--primary-color); | |
| color: white; | |
| padding: 12px 24px; | |
| border-radius: 8px; | |
| z-index: 1000; | |
| animation: fadeInOut 2s ease forwards; | |
| } | |
| @media (max-width: 768px) { | |
| .main-container { | |
| padding-top: 60px; | |
| height: calc(100vh - 60px); | |
| } | |
| .sidebar { | |
| position: fixed; | |
| left: -100%; | |
| top: 0; | |
| bottom: 0; | |
| width: 85%; | |
| max-width: 320px; | |
| height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| transition: left 0.3s ease; | |
| box-shadow: 2px 0 10px rgba(0, 0, 0, 0.3); | |
| } | |
| .github-link { | |
| position: absolute; | |
| bottom: 12px; | |
| left: 1px; | |
| color: var(--text-secondary); | |
| transition: color 0.3s ease; | |
| font-size: 30px; | |
| } | |
| .delete-chat-btn { | |
| display: inline-block; | |
| background: none; | |
| border: none; | |
| color: #fbfbfb; | |
| font-size: 16px; | |
| margin-left: 10px; | |
| padding: 5px; | |
| cursor: pointer; | |
| } | |
| .delete-chat-btn:hover { | |
| color: #ff0000; | |
| } | |
| .sidebar.active { | |
| left: 0; | |
| } | |
| .sidebar-content { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding-bottom: 20px; | |
| } | |
| .sidebar-footer { | |
| position: relative; | |
| padding: 10px; | |
| margin-top: 10px; | |
| margin-bottom: 55px; | |
| background-color: var(--surface-dark); | |
| } | |
| .mobile-top-bar { | |
| height: 60px; | |
| background-color: var(--surface-dark); | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| z-index: 998; | |
| box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); | |
| } | |
| .mobile-actions { | |
| height: 100%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 0 15px; | |
| } | |
| .menu-toggle { | |
| background: none; | |
| border: none; | |
| color: var(--text-primary); | |
| font-size: 20px; | |
| padding: 8px; | |
| cursor: pointer; | |
| } | |
| .chat-container { | |
| height: 100vh; | |
| padding: 10px; | |
| padding-bottom: 120px; | |
| margin-top: 0; | |
| } | |
| .chat-history { | |
| flex: 1; | |
| overflow-y: auto; | |
| margin-bottom: 20px; | |
| max-height: calc(100vh - 220px); | |
| padding-bottom: 20px; | |
| } | |
| .input-container { | |
| position: fixed; | |
| bottom: 0; | |
| left: 0; | |
| right: 0; | |
| padding: 15px; | |
| background-color: var(--surface-dark); | |
| border-radius: 10px 10px 0 0; | |
| margin: 0; | |
| z-index: 997; | |
| box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); | |
| } | |
| .message-input-wrapper { | |
| margin-bottom: 8px; | |
| } | |
| textarea { | |
| max-height: 100px; | |
| min-height: 50px; | |
| padding: 12px; | |
| } | |
| .user-message, | |
| .ai-message { | |
| margin-left: 5px; | |
| margin-right: 5px; | |
| } | |
| .sidebar-overlay { | |
| display: none; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background-color: rgba(0, 0, 0, 0.5); | |
| z-index: 999; | |
| } | |
| .sidebar-overlay.active { | |
| display: block; | |
| } | |
| .btn-secondary { | |
| display: none; | |
| } | |
| .d-md-block { | |
| display: none ; | |
| } | |
| } | |
| @keyframes fadeInOut { | |
| 0% { opacity: 0; transform: translateY(-20px); } | |
| 20% { opacity: 1; transform: translateY(0); } | |
| 80% { opacity: 1; transform: translateY(0); } | |
| 100% { opacity: 0; transform: translateY(-20px); } | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| ::-webkit-scrollbar { | |
| width: 8px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: var(--background-dark); | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: var(--primary-color); | |
| border-radius: 4px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="sidebar-overlay" onclick="toggleSidebar()"></div> | |
| <div class="mobile-top-bar d-md-none"> | |
| <div class="mobile-actions"> | |
| <button class="menu-toggle" onclick="toggleSidebar()"> | |
| <i class="fas fa-bars"></i> | |
| </button> | |
| <div class="mobile-right-actions"> | |
| <button class="btn-custom btn-primary me-2" onclick="startNewChat()"> | |
| <i class="fas fa-plus"></i> | |
| </button> | |
| <button class="btn-custom btn-danger" onclick="clearChat()"> | |
| <i class="fas fa-trash"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="main-container"> | |
| <div class="sidebar"> | |
| <div class="sidebar-content"> | |
| <div class="brand"> | |
| <h1>Claude 3.5</h1> | |
| <p class="text-secondary">Sonnet Chat</p> | |
| </div> | |
| <button class="btn-custom btn-primary mb-4 w-100 d-none d-md-block" onclick="startNewChat()"> | |
| <i class="fas fa-plus me-2"></i>New Chat | |
| </button> | |
| <div class="chat-list" id="chatList"> | |
| </div> | |
| </div> | |
| <div class="sidebar-footer"> | |
| <p>Powered by Claude 3.5 Sonnet</p> | |
| <small>Created with ❤️ and AI assistance</small> | |
| <a href="https://github.com/usualdork" target="_blank" class="github-link" title="Visit my GitHub"> | |
| <i class="fab fa-github"></i> | |
| </a> | |
| </div> | |
| </div> | |
| <div class="chat-container"> | |
| <div class="chat-history" id="chatHistory"> | |
| </div> | |
| <div class="input-container"> | |
| <div class="message-input-wrapper"> | |
| <textarea id="query" rows="3" placeholder="Type your message here..."></textarea> | |
| <button class="send-button" id="submit" onclick="sendQuery()"> | |
| <i class="fas fa-paper-plane"></i> | |
| <span></span> | |
| </button> | |
| </div> | |
| <button class="btn-custom btn-secondary d-none d-md-block" onclick="clearChat()"> | |
| <i class="fas fa-trash"></i> | |
| <span>Clear Chat</span> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> | |
| <script> | |
| let allChats = []; | |
| let chatHistory = []; | |
| let currentChatId = null; | |
| function toggleSidebar() { | |
| const sidebar = document.querySelector('.sidebar'); | |
| const overlay = document.querySelector('.sidebar-overlay'); | |
| sidebar.classList.toggle('active'); | |
| overlay.classList.toggle('active'); | |
| document.body.style.overflow = sidebar.classList.contains('active')? 'hidden' : ''; | |
| } | |
| function updateChatList() { | |
| const chatList = document.getElementById('chatList'); | |
| chatList.innerHTML = ''; | |
| allChats.forEach(chat => { | |
| const chatItem = document.createElement('div'); | |
| chatItem.className = 'chat-item'; | |
| const chatButton = document.createElement('button'); | |
| chatButton.className = `chat-button ${chat.id === currentChatId? 'active' : ''}`; | |
| const firstMessage = chat.messages[0]?.content || 'New Chat'; | |
| const truncatedMessage = firstMessage.substring(0, 30) + (firstMessage.length > 30? '...' : ''); | |
| chatButton.innerHTML = ` | |
| <i class="fas fa-message"></i> | |
| <span class="chat-text">${truncatedMessage}</span> | |
| `; | |
| const deleteButton = document.createElement('button'); | |
| deleteButton.className = 'delete-chat-btn'; | |
| deleteButton.innerHTML = '<i class="fas fa-trash"></i>'; | |
| deleteButton.onclick = (e) => { | |
| e.stopPropagation(); | |
| deleteChat(chat.id); | |
| }; | |
| chatButton.onclick = () => { | |
| loadChat(chat.id); | |
| if (window.innerWidth <= 768) { | |
| toggleSidebar(); | |
| } | |
| }; | |
| chatItem.appendChild(chatButton); | |
| chatItem.appendChild(deleteButton); | |
| chatList.appendChild(chatItem); | |
| }); | |
| } | |
| function loadChat(chatId) { | |
| const previousChatButton = document.querySelector('.chat-button.active'); | |
| if (previousChatButton) { | |
| previousChatButton.classList.remove('active'); | |
| } | |
| currentChatId = chatId; | |
| const chat = allChats.find(c => c.id === chatId); | |
| if (chat) { | |
| chatHistory = chat.messages; | |
| updateChatDisplay(); | |
| const currentChatButton = document.querySelector(`.chat-button[data-chat-id="${chatId}"]`); | |
| if (currentChatButton) { | |
| currentChatButton.classList.add('active'); | |
| } | |
| } | |
| updateChatList(); | |
| } | |
| function showNotification(message) { | |
| const notification = document.createElement('div'); | |
| notification.className = 'notification'; | |
| notification.textContent = message; | |
| document.body.appendChild(notification); | |
| setTimeout(() => { | |
| document.body.removeChild(notification); | |
| }, 2000); | |
| } | |
| function addMessage(content, isUser = false) { | |
| const message = { | |
| content: content, | |
| timestamp: new Date().toLocaleTimeString(), | |
| isUser: isUser | |
| }; | |
| chatHistory.push(message); | |
| const currentChat = allChats.find(chat => chat.id === currentChatId); | |
| if (currentChat) { | |
| currentChat.messages = chatHistory; | |
| } | |
| updateChatDisplay(); | |
| updateChatList(); | |
| saveHistory(); | |
| } | |
| function updateChatDisplay() { | |
| const chatHistoryDiv = document.getElementById('chatHistory'); | |
| chatHistoryDiv.innerHTML = ''; | |
| chatHistory.forEach((message) => { | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.className = `chat-message ${message.isUser ? 'user-message' : 'ai-message'}`; | |
| messageDiv.innerHTML = ` | |
| <div class="message-header"> | |
| <span>${message.isUser ? 'You' : 'Claude'} • ${message.timestamp}</span> | |
| <div class="message-actions"> | |
| <button class="btn-icon" onclick="copyMessage('${message.content.replace(/'/g, "\\'")}')"> | |
| <i class="fas fa-copy"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="message-content">${message.content}</div> | |
| `; | |
| chatHistoryDiv.appendChild(messageDiv); | |
| }); | |
| chatHistoryDiv.scrollTop = chatHistoryDiv.scrollHeight; | |
| } | |
| function copyMessage(content) { | |
| const textarea = document.createElement('textarea'); | |
| textarea.value = content; | |
| document.body.appendChild(textarea); | |
| textarea.select(); | |
| document.execCommand('copy'); | |
| document.body.removeChild(textarea); | |
| showNotification('Copied to clipboard!'); | |
| } | |
| function saveHistory() { | |
| localStorage.setItem('allChats', JSON.stringify(allChats)); | |
| } | |
| function loadHistory() { | |
| const saved = localStorage.getItem('allChats'); | |
| if (saved) { | |
| allChats = JSON.parse(saved); | |
| updateChatList(); | |
| if (allChats.length > 0) { | |
| loadChat(allChats[allChats.length - 1].id); | |
| } else { | |
| startNewChat(); | |
| } | |
| } else { | |
| startNewChat(); | |
| } | |
| } | |
| function deleteChat(chatId) { | |
| if (confirm('Are you sure you want to delete this chat?')) { | |
| allChats = allChats.filter(chat => chat.id !== chatId); | |
| if (chatId === currentChatId) { | |
| if (allChats.length > 0) { | |
| loadChat(allChats[allChats.length - 1].id); | |
| } else { | |
| startNewChat(); | |
| } | |
| } | |
| saveHistory(); | |
| updateChatList(); | |
| showNotification('Chat deleted successfully!'); | |
| } | |
| } | |
| function startNewChat() { | |
| const newChat = { | |
| id: Date.now().toString(), | |
| messages: [] | |
| }; | |
| allChats.push(newChat); | |
| loadChat(newChat.id); | |
| saveHistory(); | |
| showNotification('New chat started!'); | |
| } | |
| async function sendQuery() { | |
| const queryInput = document.getElementById("query"); | |
| const query = queryInput.value; | |
| const submitButton = document.getElementById("submit"); | |
| if (!query.trim()) { | |
| showNotification("Please enter a message!"); | |
| return; | |
| } | |
| addMessage(query, true); | |
| queryInput.value = ''; | |
| submitButton.disabled = true; | |
| try { | |
| const response = await puter.ai.chat(query, { | |
| model: "claude-3-5-sonnet", | |
| stream: true | |
| }); | |
| let fullResponse = ''; | |
| for await (const part of response) { | |
| fullResponse += part?.text || ""; | |
| } | |
| addMessage(fullResponse, false); | |
| } catch (error) { | |
| showNotification(`Error: ${error.message}`); | |
| addMessage(`Error: ${error.message}`, false); | |
| } finally { | |
| submitButton.disabled = false; | |
| } | |
| } | |
| document.addEventListener('DOMContentLoaded', loadHistory); | |
| document.getElementById('query').addEventListener('keypress', function(e) { | |
| if (e.key === 'Enter' && !e.shiftKey) { | |
| e.preventDefault(); | |
| sendQuery(); | |
| } | |
| }); | |
| </script> | |
| <script> | |
| function clearChat() { | |
| if (confirm('Are you sure you want to clear the current chat?')) { | |
| chatHistory = []; | |
| updateChatDisplay(); | |
| const currentChat = allChats.find(chat => chat.id === currentChatId); | |
| if (currentChat) { | |
| currentChat.messages = []; | |
| saveHistory(); | |
| } | |
| showNotification('Chat cleared successfully!'); | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> | |