// ============================================================================ // Miku Control Panel — Status Module // Status display, last prompt, autonomous stats // ============================================================================ // ===== Status ===== async function loadStatus() { try { const result = await apiCall('/status'); const statusDiv = document.getElementById('status'); if (result.evil_mode !== undefined && result.evil_mode !== evilMode) { evilMode = result.evil_mode; updateEvilModeUI(); if (evilMode && result.mood) { const moodSelect = document.getElementById('mood'); if (moodSelect) moodSelect.value = result.mood; } } if (result.mood) { const moodSelect = document.getElementById('mood'); if (moodSelect && moodSelect.querySelector(`option[value="${result.mood}"]`)) { moodSelect.value = result.mood; } currentMood = result.mood; } let serverMoodsHtml = ''; if (result.server_moods) { serverMoodsHtml = '
Server Moods:
'; for (const [guildId, mood] of Object.entries(result.server_moods)) { const server = servers.find(s => s.guild_id == guildId); const serverName = server ? server.guild_name : `Server ${guildId}`; const emojiMap = evilMode ? EVIL_MOOD_EMOJIS : MOOD_EMOJIS; serverMoodsHtml += `• ${serverName}: ${mood} ${emojiMap[mood] || ''}
`; } serverMoodsHtml += '
'; } const moodEmoji = evilMode ? (EVIL_MOOD_EMOJIS[result.mood] || '') : (MOOD_EMOJIS[result.mood] || ''); const moodLabel = evilMode ? `😈 ${result.mood} ${moodEmoji}` : `${result.mood} ${moodEmoji}`; statusDiv.innerHTML = `
Status: ${result.status}
DM Mood: ${moodLabel}
Servers: ${result.servers}
Active Schedulers: ${result.active_schedulers}
💬 DM Support: Users can message Miku directly in DMs. She responds to every DM message using the DM mood (auto-rotating every 2 hours).
${serverMoodsHtml} `; } catch (error) { console.error('Failed to load status:', error); } } // ===== Last Prompt ===== async function loadLastPrompt() { const source = localStorage.getItem('miku-prompt-source') || 'cat'; const promptEl = document.getElementById('last-prompt'); const infoEl = document.getElementById('prompt-cat-info'); try { if (source === 'cat') { const result = await apiCall('/prompt/cat'); if (result.timestamp) { infoEl.innerHTML = `User: ${escapeHtml(result.user || '?')}  |  Mood: ${escapeHtml(result.mood || '?')}  |  Time: ${new Date(result.timestamp).toLocaleString()}`; promptEl.textContent = result.full_prompt + `\n\n${'═'.repeat(60)}\n[Cat Response]\n${result.response}`; } else { infoEl.textContent = ''; promptEl.textContent = result.full_prompt || 'No Cheshire Cat interaction yet.'; } } else { infoEl.textContent = ''; const result = await apiCall('/prompt'); promptEl.textContent = result.prompt; } } catch (error) { console.error('Failed to load last prompt:', error); } } // ===== Autonomous Stats ===== async function loadAutonomousStats() { const serverSelect = document.getElementById('autonomous-server-select'); const selectedGuildId = serverSelect.value; if (!selectedGuildId) { document.getElementById('autonomous-stats-display').innerHTML = '

Please select a server to view autonomous stats.

'; return; } try { const data = await apiCall('/autonomous/stats'); if (!data.servers || !data.servers[selectedGuildId]) { document.getElementById('autonomous-stats-display').innerHTML = '

Server not found or not initialized.

'; return; } const serverData = data.servers[selectedGuildId]; displayAutonomousStats(serverData); } catch (error) { console.error('Failed to load autonomous stats:', error); } } function displayAutonomousStats(data) { const container = document.getElementById('autonomous-stats-display'); if (!data.context) { container.innerHTML = `

⚠️ Context Not Initialized

This server hasn't had any activity yet. Context tracking will begin once messages are sent.

Current Mood: ${data.mood} ${MOOD_EMOJIS[data.mood] || ''}
Energy: ${data.mood_profile.energy}
Sociability: ${data.mood_profile.sociability}
Impulsiveness: ${data.mood_profile.impulsiveness}
`; return; } const ctx = data.context; const profile = data.mood_profile; const lastActionMin = Math.floor(ctx.time_since_last_action / 60); const lastInteractionMin = Math.floor(ctx.time_since_last_interaction / 60); container.innerHTML = `

🎭 Mood & Personality Profile

Current Mood
${data.mood} ${MOOD_EMOJIS[data.mood] || ''}
Energy Level
${(profile.energy * 100).toFixed(0)}%
Sociability
${(profile.sociability * 100).toFixed(0)}%
Impulsiveness
${(profile.impulsiveness * 100).toFixed(0)}%

📈 Activity Metrics

Messages (Last 5 min) ⚡ ephemeral
${ctx.messages_last_5min}
Messages (Last Hour) ⚡ ephemeral
${ctx.messages_last_hour}
Conversation Momentum 💾 saved
${(ctx.conversation_momentum * 100).toFixed(0)}%
Decays with downtime (half-life: 10min)
Unique Users Active ⚡ ephemeral
${ctx.unique_users_active}

👥 User Events

Users Joined Recently
${ctx.users_joined_recently}
Status Changes
${ctx.users_status_changed}
Active Activities
${ctx.users_started_activity.length}
${ctx.users_started_activity.length > 0 ? `
${ctx.users_started_activity.join(', ')}
` : ''}

⏱️ Timing & Context

Time Since Last Action 💾 saved
${lastActionMin} min
${ctx.time_since_last_action.toFixed(1)}s
Time Since Last Interaction 💾 saved
${lastInteractionMin} min
${ctx.time_since_last_interaction.toFixed(1)}s
Messages Since Last Appearance 💾 saved
${ctx.messages_since_last_appearance}
Current Time Context ⚡ ephemeral
${ctx.hour_of_day}:00
${ctx.is_weekend ? '📅 Weekend' : '📆 Weekday'}

🧠 Base Energy Level

From current mood personality
${(ctx.mood_energy_level * 100).toFixed(0)}%
💡 Combined with activity metrics to determine action likelihood.
📝 High energy = shorter wait times, higher action chance.
💾 Persisted across restarts
`; } function getStatColor(value) { if (value >= 0.8) return '#4caf50'; if (value >= 0.6) return '#8bc34a'; if (value >= 0.4) return '#ffc107'; if (value >= 0.2) return '#ff9800'; return '#f44336'; } function getMomentumColor(value) { if (value >= 0.7) return '#4caf50'; if (value >= 0.4) return '#2196f3'; return '#9e9e9e'; } function populateAutonomousServerDropdown() { const select = document.getElementById('autonomous-server-select'); if (!select) return; const currentValue = select.value; select.innerHTML = ''; servers.forEach(server => { const option = document.createElement('option'); option.value = server.guild_id; option.textContent = `${server.guild_name} (${server.guild_id})`; select.appendChild(option); }); if (currentValue && servers.some(s => String(s.guild_id) === currentValue)) { select.value = currentValue; } }