frontend: rewrite Last Prompt as Prompt History viewer

- status.js: replace loadLastPrompt() with loadPromptHistory() + helpers
  - fetch /prompts with optional source filter, populate dropdown
  - selectPromptEntry() renders metadata bar + collapsible subsections
  - parsePromptSections() splits full_prompt into System/Context/Conversation
  - buildCollapsibleSection() with toggle arrows (▼/▶)
  - copyPromptToClipboard() copies raw text
  - toggleMiddleTruncation() truncates response from middle
  - togglePromptHistoryCollapse() collapses entire section
  - legacy loadLastPrompt() delegates to loadPromptHistory()
- core.js: add promptInterval to polling (10s), visibility resume
  - update switchPromptSource() for 'all' filter + new button IDs
  - update initPromptSourceToggle() default to 'all'
  - declare promptInterval variable
This commit is contained in:
2026-05-02 15:25:05 +03:00
parent f33e2afdf7
commit 6b922d84ae
2 changed files with 249 additions and 23 deletions

View File

@@ -29,6 +29,7 @@ let notificationTimer = null;
let statusInterval = null;
let logsInterval = null;
let argsInterval = null;
let promptInterval = null;
// Mood emoji mapping
const MOOD_EMOJIS = {
@@ -211,12 +212,14 @@ function startPolling() {
if (!statusInterval) statusInterval = setInterval(loadStatus, 10000);
if (!logsInterval) logsInterval = setInterval(loadLogs, 5000);
if (!argsInterval) argsInterval = setInterval(loadActiveArguments, 5000);
if (!promptInterval) promptInterval = setInterval(loadPromptHistory, 10000);
}
function stopPolling() {
clearInterval(statusInterval); statusInterval = null;
clearInterval(logsInterval); logsInterval = null;
clearInterval(argsInterval); argsInterval = null;
clearInterval(promptInterval); promptInterval = null;
}
// ============================================================================
@@ -248,7 +251,7 @@ function initVisibilityPolling() {
stopPolling();
console.log('⏸ Tab hidden — polling paused');
} else {
loadStatus(); loadLogs(); loadActiveArguments();
loadStatus(); loadLogs(); loadActiveArguments(); loadPromptHistory();
startPolling();
console.log('▶️ Tab visible — polling resumed');
}
@@ -296,9 +299,11 @@ function initModalAccessibility() {
}
function initPromptSourceToggle() {
const saved = localStorage.getItem('miku-prompt-source') || 'cat';
const saved = localStorage.getItem('miku-prompt-source') || 'all';
document.querySelectorAll('.prompt-source-btn').forEach(btn => btn.classList.remove('active'));
document.getElementById(`prompt-src-${saved}`).classList.add('active');
const btnId = saved === 'all' ? 'prompt-src-all' : `prompt-src-${saved}`;
const btn = document.getElementById(btnId);
if (btn) btn.classList.add('active');
}
function initLogsScrollDetection() {
@@ -360,8 +365,10 @@ async function loadLogs() {
function switchPromptSource(source) {
localStorage.setItem('miku-prompt-source', source);
document.querySelectorAll('.prompt-source-btn').forEach(btn => btn.classList.remove('active'));
document.getElementById(`prompt-src-${source}`).classList.add('active');
loadLastPrompt();
const btnId = source === 'all' ? 'prompt-src-all' : `prompt-src-${source}`;
const btn = document.getElementById(btnId);
if (btn) btn.classList.add('active');
loadPromptHistory();
}
// ============================================================================