/** * suggest.js — Подсказки промптов из истории и генерация через Codex */ import { apiFetch } from "./api.js"; import { getState, setSuggestRunning } from "./state.js"; function applyPrompt(promptText) { const promptInput = document.querySelector("#prompt"); const promptCounter = document.querySelector("#prompt-counter"); const editButton = document.querySelector("#edit-button"); if (!promptInput) return; promptInput.value = promptText; if (promptCounter) { promptCounter.textContent = `${promptText.length} / 1000`; } const state = getState(); if (editButton) { editButton.disabled = !state.currentVersionId || !promptText.trim() || state.isBusy; } } export function renderSuggestChips(container, items) { if (!container) return; container.innerHTML = ""; for (const item of items) { const text = String(item || "").trim(); if (!text) continue; const chip = document.createElement("button"); chip.type = "button"; chip.className = "suggest-chip"; chip.textContent = text; chip.addEventListener("click", () => applyPrompt(text)); container.appendChild(chip); } } export async function loadSuggestHistoryChips() { const container = document.querySelector("#suggest-history-chips"); if (!container) return; try { const res = await apiFetch("/api/suggest-prompts"); const prompts = Array.isArray(res?.prompts) ? res.prompts : []; if (prompts.length === 0) { container.innerHTML = 'В истории пока нет промптов'; return; } renderSuggestChips(container, prompts); } catch { container.innerHTML = 'Не удалось загрузить подсказки'; } } export function updateSuggestCodexButton() { const suggestBtn = document.querySelector("#suggest-button"); const codexBtn = document.querySelector("#suggest-codex-button"); const state = getState(); const canSuggest = Boolean(state.currentVersionId) && !state.isBusy; if (suggestBtn) { suggestBtn.disabled = !canSuggest; } if (codexBtn) { codexBtn.disabled = !canSuggest || state.suggestRunning; } } export async function runSuggest() { const state = getState(); if (!state.currentVersionId || state.suggestRunning || state.isBusy) { return; } const statusEl = document.querySelector("#suggest-codex-status"); const chipsContainer = document.querySelector("#suggest-codex-chips"); const codexBtn = document.querySelector("#suggest-codex-button"); setSuggestRunning(true); updateSuggestCodexButton(); if (statusEl) statusEl.textContent = "Codex анализирует кадр…"; if (chipsContainer) chipsContainer.innerHTML = ""; try { const res = await apiFetch("/api/suggest", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ sourceId: state.currentVersionId }), }); const jobId = res.jobId; await pollSuggestJob(jobId); } catch (err) { if (statusEl) statusEl.textContent = `Ошибка: ${err.message}`; setSuggestRunning(false); updateSuggestCodexButton(); } } async function pollSuggestJob(jobId) { const statusEl = document.querySelector("#suggest-codex-status"); const chipsContainer = document.querySelector("#suggest-codex-chips"); let failures = 0; const poll = async () => { try { const data = await apiFetch(`/api/jobs/${jobId}/status`); failures = 0; if (data.status === "queued") { if (statusEl) { statusEl.textContent = data.queuePosition ? `В очереди (позиция ${data.queuePosition})…` : "В очереди…"; } setTimeout(poll, 1500); return; } if (data.status === "running") { if (statusEl) statusEl.textContent = "Codex генерирует варианты…"; setTimeout(poll, 1500); return; } if (data.status === "done") { if (statusEl) statusEl.textContent = ""; const suggestions = data.result?.suggestions || []; if (suggestions.length > 0) { renderSuggestChips(chipsContainer, suggestions); } else { if (statusEl) statusEl.textContent = "Codex не вернул вариантов."; } setSuggestRunning(false); updateSuggestCodexButton(); return; } if (data.status === "error" || data.status === "interrupted") { if (statusEl) statusEl.textContent = `Ошибка: ${data.error || "Не удалось получить подсказки."}`; setSuggestRunning(false); updateSuggestCodexButton(); return; } setTimeout(poll, 1500); } catch (err) { failures++; if (failures >= 5) { if (statusEl) statusEl.textContent = `Ошибка связи с сервером: ${err.message}`; setSuggestRunning(false); updateSuggestCodexButton(); return; } setTimeout(poll, 2000); } }; poll(); } export function initSuggest() { const suggestBtn = document.querySelector("#suggest-button"); const suggestPanel = document.querySelector("#suggest-panel"); const codexBtn = document.querySelector("#suggest-codex-button"); if (suggestBtn && suggestPanel) { suggestBtn.addEventListener("click", () => { const isHidden = suggestPanel.hidden; suggestPanel.hidden = !isHidden; if (isHidden) { loadSuggestHistoryChips(); } }); } if (codexBtn) { codexBtn.addEventListener("click", runSuggest); } }