const chatWindow = document.getElementById('chat-window'); const userInput = document.getElementById('user-input'); const sendBtn = document.getElementById('send-btn'); const pathInput = document.getElementById('model-path-input'); const loadBtn = document.getElementById('load-model-btn'); const unloadBtn = document.getElementById('unload-model-btn'); const stopBtn = document.getElementById('stop-server-btn'); const statusIndicator = document.getElementById('status-indicator'); // --- Логика Автодополнения --- const suggestionsBox = document.getElementById('suggestions'); let availableModels = []; // Загрузка списка моделей с сервера async function fetchModels() { try { const res = await fetch('/api/models/list'); availableModels = await res.json(); console.log("📂 Найдены модели:", availableModels); } catch (err) { console.error("Не удалось получить список моделей:", err); } } fetchModels(); // Обработка ввода и показ списка pathInput.addEventListener('input', () => { const inputVal = pathInput.value.toLowerCase(); suggestionsBox.innerHTML = ''; // Фильтруем: ищем по имени файла const filtered = availableModels.filter(model => model.toLowerCase().includes(inputVal) ); if (filtered.length > 0) { filtered.forEach(modelName => { const div = document.createElement('div'); div.className = 'suggestion-item'; div.textContent = modelName; div.addEventListener('click', () => { // Собираем путь let basePath = pathInput.value; let folderPath = basePath.substring(0, basePath.lastIndexOf('/') + 1); // Если слеша нет, ставим дефолтный if (!folderPath.endsWith('/')) folderPath = './model/'; pathInput.value = folderPath + modelName; suggestionsBox.style.display = 'none'; pathInput.focus(); }); suggestionsBox.appendChild(div); }); suggestionsBox.style.display = 'block'; } else { suggestionsBox.style.display = 'none'; } }); // Скрывать список при клике вне его document.addEventListener('click', (e) => { if (!pathInput.contains(e.target) && !suggestionsBox.contains(e.target)) { suggestionsBox.style.display = 'none'; } }); // Показывать весь список при клике в инпут (если есть модели) pathInput.addEventListener('focus', () => { // Если инпут пуст, покажем все модели if (pathInput.value === '' && availableModels.length > 0) { suggestionsBox.innerHTML = ''; availableModels.forEach(modelName => { const div = document.createElement('div'); div.className = 'suggestion-item'; div.textContent = modelName; div.addEventListener('click', () => { pathInput.value = `./model/${modelName}`; suggestionsBox.style.display = 'none'; }); suggestionsBox.appendChild(div); }); suggestionsBox.style.display = 'block'; } }); let isModelLoaded = false; // --- Функции Управления Интерфейсом --- function setUIState(loaded) { isModelLoaded = loaded; if (loaded) { // Модель загружена pathInput.disabled = true; loadBtn.disabled = true; unloadBtn.disabled = false; userInput.disabled = false; sendBtn.disabled = false; statusIndicator.textContent = "● Сервер: Активен | Модель: Загружена"; statusIndicator.style.color = "#4ec9b0"; addSystemMessage("Модель успешно загружена и готова к работе."); userInput.focus(); } else { // Модель выгружена pathInput.disabled = false; loadBtn.disabled = false; unloadBtn.disabled = true; userInput.disabled = true; sendBtn.disabled = true; statusIndicator.textContent = "● Сервер: Активен | Модель: Не загружена"; statusIndicator.style.color = "#cca511"; // Желтый addSystemMessage("Модель выгружена."); } } function addSystemMessage(text) { const div = document.createElement('div'); div.className = 'message system'; div.textContent = text; chatWindow.appendChild(div); chatWindow.scrollTop = chatWindow.scrollHeight; } // --- API Запросы Управления --- // 1. Загрузка модели loadBtn.addEventListener('click', async () => { const path = pathInput.value.trim(); if (!path) { alert("Введите путь к модели"); return; } loadBtn.disabled = true; loadBtn.textContent = "Загрузка..."; try { const res = await fetch('/api/model/load', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path }) }); const data = await res.json(); if (data.success) { setUIState(true); } else { alert("Ошибка загрузки: " + data.message); loadBtn.disabled = false; loadBtn.textContent = "Загрузить"; } } catch (err) { alert("Ошибка сети при загрузке: " + err.message); loadBtn.disabled = false; loadBtn.textContent = "Загрузить"; } }); // 2. Выгрузка модели unloadBtn.addEventListener('click', async () => { if (!confirm("Вы уверены, что хотите выгрузить модель?")) return; try { const res = await fetch('/api/model/unload', { method: 'POST' }); const data = await res.json(); if (data.success) { setUIState(false); } else { alert("Ошибка выгрузки: " + data.message); } } catch (err) { alert("Ошибка сети: " + err.message); } }); // 3. Остановка сервера stopBtn.addEventListener('click', async () => { if (!confirm("Внимание! Это остановит веб-сервер. Придется перезапустить его через консоль (npm start).")) return; try { await fetch('/api/server/stop', { method: 'POST' }); document.body.innerHTML = "