Spaces:
Running
Running
now remove this login logic and i want that users can only use chatbot is they provide openrouter api key once they provide they can use chatbot and after refreshing or reloading they have to provide again the api key
Browse files- index.html +21 -306
index.html
CHANGED
|
@@ -69,48 +69,11 @@
|
|
| 69 |
<i data-feather="cpu" class="w-8 h-8 text-indigo-300"></i>
|
| 70 |
<h1 class="text-2xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-indigo-300 to-purple-300">ChatRouter</h1>
|
| 71 |
</div>
|
| 72 |
-
<
|
| 73 |
-
<
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
</button>
|
| 77 |
-
<button id="settingsBtn" class="flex items-center space-x-2 bg-indigo-800 hover:bg-indigo-700 px-4 py-2 rounded-lg transition-all">
|
| 78 |
-
<i data-feather="settings" class="w-5 h-5"></i>
|
| 79 |
-
<span>Settings</span>
|
| 80 |
-
</button>
|
| 81 |
-
<button id="authBtn" class="flex items-center space-x-2 bg-indigo-800 hover:bg-indigo-700 px-4 py-2 rounded-lg transition-all">
|
| 82 |
-
<i data-feather="user" class="w-5 h-5"></i>
|
| 83 |
-
<span>Login</span>
|
| 84 |
-
</button>
|
| 85 |
-
</div>
|
| 86 |
</header>
|
| 87 |
-
<!-- Auth Modal -->
|
| 88 |
-
<div id="authModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
|
| 89 |
-
<div class="bg-gray-800 rounded-xl p-6 w-full max-w-md">
|
| 90 |
-
<div class="flex justify-between items-center mb-4">
|
| 91 |
-
<h2 class="text-xl font-bold" id="authModalTitle">Login</h2>
|
| 92 |
-
<button id="closeAuth" class="text-gray-400 hover:text-white">
|
| 93 |
-
<i data-feather="x"></i>
|
| 94 |
-
</button>
|
| 95 |
-
</div>
|
| 96 |
-
<div id="authForm" class="space-y-4">
|
| 97 |
-
<div id="registerFields" class="hidden">
|
| 98 |
-
<label class="block text-sm font-medium mb-1">Username</label>
|
| 99 |
-
<input type="text" id="regUsername" placeholder="Choose a username" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500">
|
| 100 |
-
</div>
|
| 101 |
-
<div>
|
| 102 |
-
<label class="block text-sm font-medium mb-1">Password</label>
|
| 103 |
-
<input type="password" id="authPassword" placeholder="Enter your password" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500">
|
| 104 |
-
</div>
|
| 105 |
-
<button id="authActionBtn" class="w-full bg-indigo-600 hover:bg-indigo-500 text-white py-2 rounded-lg transition-colors">Login</button>
|
| 106 |
-
<div class="text-center text-sm">
|
| 107 |
-
<span id="authToggleText">Don't have an account? </span>
|
| 108 |
-
<button id="authToggleBtn" class="text-indigo-400 hover:text-indigo-300">Register</button>
|
| 109 |
-
</div>
|
| 110 |
-
</div>
|
| 111 |
-
</div>
|
| 112 |
-
</div>
|
| 113 |
-
|
| 114 |
<!-- Settings Modal -->
|
| 115 |
<div id="settingsModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
|
| 116 |
<div class="bg-gray-800 rounded-xl p-6 w-full max-w-md">
|
|
@@ -238,37 +201,6 @@ const settingsBtn = document.getElementById('settingsBtn');
|
|
| 238 |
const typingIndicator = document.getElementById('typingIndicator');
|
| 239 |
const modelIndicator = document.getElementById('modelIndicator');
|
| 240 |
const themeBtns = document.querySelectorAll('.theme-btn');
|
| 241 |
-
// User management
|
| 242 |
-
let isRegistering = false;
|
| 243 |
-
|
| 244 |
-
function updateAuthUI() {
|
| 245 |
-
const loggedInUser = localStorage.getItem('chatRouterUser');
|
| 246 |
-
if (loggedInUser) {
|
| 247 |
-
authBtn.innerHTML = `<i data-feather="log-out" class="w-5 h-5"></i><span>Logout</span>`;
|
| 248 |
-
authBtn.dataset.state = 'logout';
|
| 249 |
-
document.querySelector('#newChatBtn').disabled = false;
|
| 250 |
-
document.querySelector('#settingsBtn').disabled = false;
|
| 251 |
-
sendBtn.disabled = false;
|
| 252 |
-
} else {
|
| 253 |
-
authBtn.innerHTML = `<i data-feather="user" class="w-5 h-5"></i><span>Login</span>`;
|
| 254 |
-
authBtn.dataset.state = 'login';
|
| 255 |
-
document.querySelector('#newChatBtn').disabled = true;
|
| 256 |
-
document.querySelector('#settingsBtn').disabled = true;
|
| 257 |
-
sendBtn.disabled = true;
|
| 258 |
-
showAuthModal();
|
| 259 |
-
}
|
| 260 |
-
feather.replace();
|
| 261 |
-
}
|
| 262 |
-
|
| 263 |
-
function showAuthModal(register = false) {
|
| 264 |
-
isRegistering = register;
|
| 265 |
-
authModalTitle.textContent = register ? 'Register' : 'Login';
|
| 266 |
-
authActionBtn.textContent = register ? 'Register' : 'Login';
|
| 267 |
-
authToggleText.textContent = register ? 'Already have an account? ' : 'Don\'t have an account? ';
|
| 268 |
-
authToggleBtn.textContent = register ? 'Login' : 'Register';
|
| 269 |
-
registerFields.classList.toggle('hidden', !register);
|
| 270 |
-
authModal.classList.remove('hidden');
|
| 271 |
-
}
|
| 272 |
// Chat management
|
| 273 |
let currentChatId = null;
|
| 274 |
|
|
@@ -276,172 +208,24 @@ const settingsBtn = document.getElementById('settingsBtn');
|
|
| 276 |
return 'chat_' + Date.now().toString(36) + Math.random().toString(36).substr(2, 5);
|
| 277 |
}
|
| 278 |
|
| 279 |
-
function loginUser(username, password) {
|
| 280 |
-
// Simple auth - store user in localStorage
|
| 281 |
-
localStorage.setItem('chatRouterUser', username);
|
| 282 |
-
localStorage.setItem(`chatRouterPass_${username}`, password); // Not secure for production!
|
| 283 |
-
updateAuthUI();
|
| 284 |
-
|
| 285 |
-
// Create a new chat session
|
| 286 |
-
createNewChat();
|
| 287 |
-
|
| 288 |
-
// Load user's chat list
|
| 289 |
-
loadChatList(username);
|
| 290 |
-
}
|
| 291 |
-
function logoutUser() {
|
| 292 |
-
const username = localStorage.getItem('chatRouterUser');
|
| 293 |
-
localStorage.removeItem('chatRouterUser');
|
| 294 |
-
updateAuthUI();
|
| 295 |
-
|
| 296 |
-
// Clear current chat and sidebar
|
| 297 |
-
chatContainer.innerHTML = '';
|
| 298 |
-
chatList.innerHTML = '';
|
| 299 |
-
currentChatId = null;
|
| 300 |
-
addMessage('system', 'Please log in to start chatting.');
|
| 301 |
-
}
|
| 302 |
function createNewChat() {
|
| 303 |
-
const username = localStorage.getItem('chatRouterUser');
|
| 304 |
-
if (!username) return;
|
| 305 |
-
|
| 306 |
currentChatId = generateChatId();
|
| 307 |
chatContainer.innerHTML = '';
|
| 308 |
addMessage('system', 'π New chat started.');
|
| 309 |
-
saveChatHistory(username, currentChatId);
|
| 310 |
-
addChatToList(username, currentChatId, 'New Chat');
|
| 311 |
-
}
|
| 312 |
-
|
| 313 |
-
function loadChatHistory(username, chatId) {
|
| 314 |
-
const history = localStorage.getItem(`chatHistory_${username}_${chatId}`);
|
| 315 |
-
if (history) {
|
| 316 |
-
chatContainer.innerHTML = history;
|
| 317 |
-
chatContainer.scrollTop = chatContainer.scrollHeight;
|
| 318 |
-
currentChatId = chatId;
|
| 319 |
-
}
|
| 320 |
-
}
|
| 321 |
-
|
| 322 |
-
function saveChatHistory(username, chatId) {
|
| 323 |
-
if (!chatId) chatId = currentChatId;
|
| 324 |
-
if (!username || !chatId) return;
|
| 325 |
-
|
| 326 |
-
localStorage.setItem(`chatHistory_${username}_${chatId}`, chatContainer.innerHTML);
|
| 327 |
-
|
| 328 |
-
// Update the chat title if it's the first message
|
| 329 |
-
const messages = chatContainer.querySelectorAll('.message-bubble');
|
| 330 |
-
if (messages.length === 1) {
|
| 331 |
-
updateChatTitle(username, chatId, messages[0].textContent.substring(0, 30));
|
| 332 |
-
}
|
| 333 |
}
|
| 334 |
|
| 335 |
-
function loadChatList(username) {
|
| 336 |
-
chatList.innerHTML = '';
|
| 337 |
-
const chats = [];
|
| 338 |
-
|
| 339 |
-
// Find all chats for this user
|
| 340 |
-
for (let i = 0; i < localStorage.length; i++) {
|
| 341 |
-
const key = localStorage.key(i);
|
| 342 |
-
if (key.startsWith(`chatHistory_${username}_`)) {
|
| 343 |
-
const chatId = key.split('_')[2];
|
| 344 |
-
const title = localStorage.getItem(`chatTitle_${username}_${chatId}`) || 'New Chat';
|
| 345 |
-
chats.push({ id: chatId, title });
|
| 346 |
-
}
|
| 347 |
-
}
|
| 348 |
-
|
| 349 |
-
// Sort by most recent first
|
| 350 |
-
chats.sort((a, b) => b.id.localeCompare(a.id));
|
| 351 |
-
|
| 352 |
-
// Add to sidebar
|
| 353 |
-
chats.forEach(chat => {
|
| 354 |
-
addChatToList(username, chat.id, chat.title);
|
| 355 |
-
});
|
| 356 |
-
}
|
| 357 |
-
|
| 358 |
-
function addChatToList(username, chatId, title) {
|
| 359 |
-
const chatItem = document.createElement('div');
|
| 360 |
-
chatItem.className = 'flex justify-between items-center p-2 hover:bg-gray-700 rounded-lg cursor-pointer';
|
| 361 |
-
chatItem.dataset.chatId = chatId;
|
| 362 |
-
|
| 363 |
-
const titleSpan = document.createElement('span');
|
| 364 |
-
titleSpan.className = 'truncate flex-1';
|
| 365 |
-
titleSpan.textContent = title;
|
| 366 |
-
|
| 367 |
-
const actionsDiv = document.createElement('div');
|
| 368 |
-
actionsDiv.className = 'flex space-x-2';
|
| 369 |
-
|
| 370 |
-
const renameBtn = document.createElement('button');
|
| 371 |
-
renameBtn.className = 'text-gray-400 hover:text-white';
|
| 372 |
-
renameBtn.innerHTML = '<i data-feather="edit-2" class="w-4 h-4"></i>';
|
| 373 |
-
renameBtn.onclick = (e) => {
|
| 374 |
-
e.stopPropagation();
|
| 375 |
-
renameChat(username, chatId, titleSpan);
|
| 376 |
-
};
|
| 377 |
-
|
| 378 |
-
const deleteBtn = document.createElement('button');
|
| 379 |
-
deleteBtn.className = 'text-gray-400 hover:text-white';
|
| 380 |
-
deleteBtn.innerHTML = '<i data-feather="trash-2" class="w-4 h-4"></i>';
|
| 381 |
-
deleteBtn.onclick = (e) => {
|
| 382 |
-
e.stopPropagation();
|
| 383 |
-
deleteChat(username, chatId, chatItem);
|
| 384 |
-
};
|
| 385 |
-
|
| 386 |
-
actionsDiv.appendChild(renameBtn);
|
| 387 |
-
actionsDiv.appendChild(deleteBtn);
|
| 388 |
-
chatItem.appendChild(titleSpan);
|
| 389 |
-
chatItem.appendChild(actionsDiv);
|
| 390 |
-
|
| 391 |
-
chatItem.addEventListener('click', () => {
|
| 392 |
-
loadChatHistory(username, chatId);
|
| 393 |
-
});
|
| 394 |
-
|
| 395 |
-
chatList.prepend(chatItem);
|
| 396 |
-
feather.replace();
|
| 397 |
-
}
|
| 398 |
-
|
| 399 |
-
function updateChatTitle(username, chatId, title) {
|
| 400 |
-
localStorage.setItem(`chatTitle_${username}_${chatId}`, title);
|
| 401 |
-
const chatItem = chatList.querySelector(`[data-chat-id="${chatId}"]`);
|
| 402 |
-
if (chatItem) {
|
| 403 |
-
chatItem.querySelector('span').textContent = title;
|
| 404 |
-
}
|
| 405 |
-
}
|
| 406 |
-
|
| 407 |
-
function renameChat(username, chatId, titleElement) {
|
| 408 |
-
const newTitle = prompt('Enter new chat title:', titleElement.textContent);
|
| 409 |
-
if (newTitle && newTitle.trim()) {
|
| 410 |
-
localStorage.setItem(`chatTitle_${username}_${chatId}`, newTitle.trim());
|
| 411 |
-
titleElement.textContent = newTitle.trim();
|
| 412 |
-
}
|
| 413 |
-
}
|
| 414 |
-
|
| 415 |
-
function deleteChat(username, chatId, element) {
|
| 416 |
-
if (confirm('Are you sure you want to delete this chat?')) {
|
| 417 |
-
localStorage.removeItem(`chatHistory_${username}_${chatId}`);
|
| 418 |
-
localStorage.removeItem(`chatTitle_${username}_${chatId}`);
|
| 419 |
-
element.remove();
|
| 420 |
-
|
| 421 |
-
if (currentChatId === chatId) {
|
| 422 |
-
createNewChat();
|
| 423 |
-
}
|
| 424 |
-
}
|
| 425 |
-
}
|
| 426 |
// Load saved settings
|
| 427 |
async function loadSettings() {
|
| 428 |
-
const savedApiKey = localStorage.getItem('chatRouterApiKey');
|
| 429 |
-
const savedModel = localStorage.getItem('chatRouterModel');
|
| 430 |
const savedTheme = localStorage.getItem('chatRouterTheme') || 'indigo';
|
| 431 |
-
|
| 432 |
-
if (savedApiKey) {
|
| 433 |
-
apiKeyInput.value = savedApiKey;
|
| 434 |
-
sendBtn.disabled = false;
|
| 435 |
-
await fetchModels(savedApiKey); // Load models when API key exists
|
| 436 |
-
}
|
| 437 |
-
if (savedModel) {
|
| 438 |
-
modelSelect.value = savedModel;
|
| 439 |
-
modelIndicator.textContent = `Using: ${savedModel.split('/').pop()}`;
|
| 440 |
-
}
|
| 441 |
-
|
| 442 |
// Apply theme
|
| 443 |
document.body.className = `bg-gradient-to-br from-${savedTheme}-900 to-purple-900 text-white`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 444 |
}
|
|
|
|
| 445 |
// Free models from OpenRouter
|
| 446 |
const freeModels = [
|
| 447 |
'alibaba/tongyi-deepresearch-30b-a3b:free',
|
|
@@ -480,7 +264,7 @@ async function loadSettings() {
|
|
| 480 |
'mistralai/mistral-nemo:free',
|
| 481 |
'google/gemma-2-9b-it:free'
|
| 482 |
];
|
| 483 |
-
// Fetch available free models
|
| 484 |
async function fetchModels(apiKey) {
|
| 485 |
try {
|
| 486 |
// Clear existing options
|
|
@@ -501,11 +285,7 @@ async function loadSettings() {
|
|
| 501 |
option.textContent = modelId;
|
| 502 |
modelSelect.appendChild(option);
|
| 503 |
});
|
| 504 |
-
|
| 505 |
-
if (!apiKey) {
|
| 506 |
-
addMessage('system', 'Free models selected. Some features may require an API key.');
|
| 507 |
-
}
|
| 508 |
-
} catch (error) {
|
| 509 |
addMessage('system', `Error loading models: ${error.message}`);
|
| 510 |
}
|
| 511 |
}
|
|
@@ -528,27 +308,19 @@ async function loadSettings() {
|
|
| 528 |
// Verify API key by fetching models
|
| 529 |
await fetchModels(apiKey);
|
| 530 |
|
| 531 |
-
// If successful,
|
| 532 |
-
localStorage.setItem('chatRouterApiKey', apiKey);
|
| 533 |
-
localStorage.setItem('chatRouterModel', model);
|
| 534 |
sendBtn.disabled = false;
|
| 535 |
modelIndicator.textContent = `Using: ${model.split('/').pop()}`;
|
| 536 |
settingsModal.classList.add('hidden');
|
| 537 |
|
| 538 |
// Add confirmation message to chat
|
| 539 |
-
addMessage('system', '
|
|
|
|
| 540 |
} catch (error) {
|
| 541 |
addMessage('system', `Error verifying API key: ${error.message}`);
|
| 542 |
}
|
| 543 |
});
|
| 544 |
|
| 545 |
-
// Load models when API key changes
|
| 546 |
-
apiKeyInput.addEventListener('blur', async () => {
|
| 547 |
-
const apiKey = apiKeyInput.value.trim();
|
| 548 |
-
if (apiKey) {
|
| 549 |
-
await fetchModels(apiKey);
|
| 550 |
-
}
|
| 551 |
-
});
|
| 552 |
// Theme selection
|
| 553 |
themeBtns.forEach(btn => {
|
| 554 |
btn.addEventListener('click', () => {
|
|
@@ -655,54 +427,6 @@ async function sendMessage() {
|
|
| 655 |
typingIndicator.classList.add('hidden');
|
| 656 |
}
|
| 657 |
}
|
| 658 |
-
// Event listeners
|
| 659 |
-
authBtn.addEventListener('click', () => {
|
| 660 |
-
if (authBtn.dataset.state === 'logout') {
|
| 661 |
-
logoutUser();
|
| 662 |
-
} else {
|
| 663 |
-
showAuthModal();
|
| 664 |
-
}
|
| 665 |
-
});
|
| 666 |
-
|
| 667 |
-
closeAuth.addEventListener('click', () => {
|
| 668 |
-
authModal.classList.add('hidden');
|
| 669 |
-
});
|
| 670 |
-
|
| 671 |
-
authToggleBtn.addEventListener('click', () => {
|
| 672 |
-
showAuthModal(!isRegistering);
|
| 673 |
-
});
|
| 674 |
-
|
| 675 |
-
authActionBtn.addEventListener('click', () => {
|
| 676 |
-
if (isRegistering) {
|
| 677 |
-
const username = regUsername.value.trim();
|
| 678 |
-
const password = authPassword.value.trim();
|
| 679 |
-
|
| 680 |
-
if (!username || !password) {
|
| 681 |
-
alert('Please enter both username and password');
|
| 682 |
-
return;
|
| 683 |
-
}
|
| 684 |
-
|
| 685 |
-
if (localStorage.getItem(`chatRouterPass_${username}`)) {
|
| 686 |
-
alert('Username already exists');
|
| 687 |
-
return;
|
| 688 |
-
}
|
| 689 |
-
|
| 690 |
-
loginUser(username, password);
|
| 691 |
-
} else {
|
| 692 |
-
const username = regUsername.value.trim();
|
| 693 |
-
const password = authPassword.value.trim();
|
| 694 |
-
const storedPass = localStorage.getItem(`chatRouterPass_${username}`);
|
| 695 |
-
|
| 696 |
-
if (!storedPass || storedPass !== password) {
|
| 697 |
-
alert('Invalid username or password');
|
| 698 |
-
return;
|
| 699 |
-
}
|
| 700 |
-
|
| 701 |
-
loginUser(username, password);
|
| 702 |
-
}
|
| 703 |
-
authModal.classList.add('hidden');
|
| 704 |
-
});
|
| 705 |
-
newChatBtn.addEventListener('click', createNewChat);
|
| 706 |
newSidebarChat.addEventListener('click', createNewChat);
|
| 707 |
|
| 708 |
// Sidebar toggle for mobile
|
|
@@ -715,26 +439,13 @@ messageInput.addEventListener('keydown', (e) => {
|
|
| 715 |
sendMessage();
|
| 716 |
}
|
| 717 |
});
|
| 718 |
-
sendBtn.addEventListener('click',
|
| 719 |
-
const username = localStorage.getItem('chatRouterUser');
|
| 720 |
-
if (username) {
|
| 721 |
-
sendMessage();
|
| 722 |
-
saveChatHistory(username, currentChatId);
|
| 723 |
-
}
|
| 724 |
-
});
|
| 725 |
// Initialize
|
| 726 |
loadSettings();
|
| 727 |
-
updateAuthUI();
|
| 728 |
|
| 729 |
// Welcome message
|
| 730 |
setTimeout(() => {
|
| 731 |
-
|
| 732 |
-
addMessage('system', 'Welcome to ChatRouter! Please log in to start chatting.');
|
| 733 |
-
} else if (!localStorage.getItem('chatRouterModel')) {
|
| 734 |
-
addMessage('system', 'Please select a free model from settings to begin.');
|
| 735 |
-
} else if (!currentChatId) {
|
| 736 |
-
createNewChat();
|
| 737 |
-
}
|
| 738 |
}, 1000);
|
| 739 |
|
| 740 |
// Close sidebar when clicking outside on mobile
|
|
@@ -743,6 +454,10 @@ messageInput.addEventListener('keydown', (e) => {
|
|
| 743 |
sidebar.classList.add('hidden');
|
| 744 |
}
|
| 745 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
| 746 |
</script>
|
| 747 |
</body>
|
| 748 |
</html>
|
|
|
|
| 69 |
<i data-feather="cpu" class="w-8 h-8 text-indigo-300"></i>
|
| 70 |
<h1 class="text-2xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-indigo-300 to-purple-300">ChatRouter</h1>
|
| 71 |
</div>
|
| 72 |
+
<button id="settingsBtn" class="flex items-center space-x-2 bg-indigo-800 hover:bg-indigo-700 px-4 py-2 rounded-lg transition-all">
|
| 73 |
+
<i data-feather="settings" class="w-5 h-5"></i>
|
| 74 |
+
<span>Settings</span>
|
| 75 |
+
</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
</header>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
<!-- Settings Modal -->
|
| 78 |
<div id="settingsModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
|
| 79 |
<div class="bg-gray-800 rounded-xl p-6 w-full max-w-md">
|
|
|
|
| 201 |
const typingIndicator = document.getElementById('typingIndicator');
|
| 202 |
const modelIndicator = document.getElementById('modelIndicator');
|
| 203 |
const themeBtns = document.querySelectorAll('.theme-btn');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
// Chat management
|
| 205 |
let currentChatId = null;
|
| 206 |
|
|
|
|
| 208 |
return 'chat_' + Date.now().toString(36) + Math.random().toString(36).substr(2, 5);
|
| 209 |
}
|
| 210 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
function createNewChat() {
|
|
|
|
|
|
|
|
|
|
| 212 |
currentChatId = generateChatId();
|
| 213 |
chatContainer.innerHTML = '';
|
| 214 |
addMessage('system', 'π New chat started.');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
}
|
| 216 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
// Load saved settings
|
| 218 |
async function loadSettings() {
|
|
|
|
|
|
|
| 219 |
const savedTheme = localStorage.getItem('chatRouterTheme') || 'indigo';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 220 |
// Apply theme
|
| 221 |
document.body.className = `bg-gradient-to-br from-${savedTheme}-900 to-purple-900 text-white`;
|
| 222 |
+
|
| 223 |
+
// Clear any saved API key on reload
|
| 224 |
+
localStorage.removeItem('chatRouterApiKey');
|
| 225 |
+
localStorage.removeItem('chatRouterModel');
|
| 226 |
+
sendBtn.disabled = true;
|
| 227 |
}
|
| 228 |
+
|
| 229 |
// Free models from OpenRouter
|
| 230 |
const freeModels = [
|
| 231 |
'alibaba/tongyi-deepresearch-30b-a3b:free',
|
|
|
|
| 264 |
'mistralai/mistral-nemo:free',
|
| 265 |
'google/gemma-2-9b-it:free'
|
| 266 |
];
|
| 267 |
+
// Fetch available free models
|
| 268 |
async function fetchModels(apiKey) {
|
| 269 |
try {
|
| 270 |
// Clear existing options
|
|
|
|
| 285 |
option.textContent = modelId;
|
| 286 |
modelSelect.appendChild(option);
|
| 287 |
});
|
| 288 |
+
} catch (error) {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 289 |
addMessage('system', `Error loading models: ${error.message}`);
|
| 290 |
}
|
| 291 |
}
|
|
|
|
| 308 |
// Verify API key by fetching models
|
| 309 |
await fetchModels(apiKey);
|
| 310 |
|
| 311 |
+
// If successful, enable chat
|
|
|
|
|
|
|
| 312 |
sendBtn.disabled = false;
|
| 313 |
modelIndicator.textContent = `Using: ${model.split('/').pop()}`;
|
| 314 |
settingsModal.classList.add('hidden');
|
| 315 |
|
| 316 |
// Add confirmation message to chat
|
| 317 |
+
addMessage('system', 'API key verified. You can now start chatting!');
|
| 318 |
+
createNewChat();
|
| 319 |
} catch (error) {
|
| 320 |
addMessage('system', `Error verifying API key: ${error.message}`);
|
| 321 |
}
|
| 322 |
});
|
| 323 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 324 |
// Theme selection
|
| 325 |
themeBtns.forEach(btn => {
|
| 326 |
btn.addEventListener('click', () => {
|
|
|
|
| 427 |
typingIndicator.classList.add('hidden');
|
| 428 |
}
|
| 429 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 430 |
newSidebarChat.addEventListener('click', createNewChat);
|
| 431 |
|
| 432 |
// Sidebar toggle for mobile
|
|
|
|
| 439 |
sendMessage();
|
| 440 |
}
|
| 441 |
});
|
| 442 |
+
sendBtn.addEventListener('click', sendMessage);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 443 |
// Initialize
|
| 444 |
loadSettings();
|
|
|
|
| 445 |
|
| 446 |
// Welcome message
|
| 447 |
setTimeout(() => {
|
| 448 |
+
addMessage('system', 'Welcome to ChatRouter! Please enter your OpenRouter API key in settings to start chatting.');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 449 |
}, 1000);
|
| 450 |
|
| 451 |
// Close sidebar when clicking outside on mobile
|
|
|
|
| 454 |
sidebar.classList.add('hidden');
|
| 455 |
}
|
| 456 |
});
|
| 457 |
+
|
| 458 |
+
// Clear chat history on page load
|
| 459 |
+
localStorage.removeItem('chatRouterApiKey');
|
| 460 |
+
localStorage.removeItem('chatRouterModel');
|
| 461 |
</script>
|
| 462 |
</body>
|
| 463 |
</html>
|