Download Game! Currently 101 players. Last logged in:MorkzarStylusJosimToudi

Blitzer's Blog >> 72649

Back to blogs index
Posted: 21 Sep 2026 08:27 [ permalink ]
from fastapi.responses import HTMLResponse

# ==========================================
# 6. GRAAFINEN VALVOMO-KCYTTCLIITTYMC (UI)
# ==========================================
def valvomo_ui():
    return """
    <!DOCTYPE html>
    <html lang="fi">
    <head>
        <meta charset="UTF-8">
        <title>Valvomo Dashboard</title>
        <style>
            body { font-family: system-ui, sans-serif; background: #1e1e1e;
color: #eee; margin: 0; padding: 20px; }
            h1, h2 { border-bottom: 1px solid #333; padding-bottom: 10px; }
            .container { display: flex; gap: 20px; }
            .column { flex: 1; background: #252526; padding: 20px;
border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.3); }
            .card { background: #333; padding: 15px; margin-bottom: 15px;
border-radius: 6px; border-left: 4px solid #007acc; }
            .card.response { border-left-color: #28a745; }
            pre { background: #1e1e1e; padding: 10px; border-radius: 4px;
overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;}
            button { background: #007acc; color: white; border: none; padding:
8px 12px; cursor: pointer; border-radius: 4px; margin-right: 5px; margin-top:
10px;}
            button.danger { background: #dc3545; }
            button.success { background: #28a745; }
            button:hover { opacity: 0.9; }
            input[type="text"], textarea { width: 100%; background: #1e1e1e;
color: #eee; border: 1px solid #444; padding: 8px; margin-top: 5px;
box-sizing: border-box; }
        </style>
    </head>
    <body>
        <h1>Valvomo Proxy - Automaation Ohjauskeskus</h1>
        
        <div class="card" style="border-left-color: #ffc107;">
            <h3>Tila ja reititys</h3>
            <button onclick="setMode('manual')">Tila: Manuaalinen</button>
            <button onclick="setMode('all')">Tila: Salli kaikki</button>
            <br><br>
            <label>RegEx-hyvC$ksyntC$ (auto-approve):</label>
            <input type="text" id="regexInput" placeholder="esim.
'click|liite'" onchange="setMode('regex', this.value)">
        </div>

        <div class="container">
            <!-- PROMPTIT -->
            <div class="column" id="prompts-col">
                <h2>Saapuvat Kyselyt (Odottavat)</h2>
                <div id="prompts-container">PC$ivitetC$C$n...</div>
            </div>

            <!-- VASTAUKSET -->
            <div class="column" id="responses-col">
                <h2>LLM Vastaukset (Odottavat julkaisua)</h2>
                <div id="responses-container">PC$ivitetC$C$n...</div>
            </div>
        </div>

        <script>
            async function fetchData() {
                // Hae promptit
                let pRes = await fetch('/valvomo/prompts/pending');
                let prompts = await pRes.json();
                let pHTML = '';
                for (let [id, data] of Object.entries(prompts)) {
                    let messages = data.request.messages.map(m => `[${m.role}]
${m.content}`).join('\
');
                    pHTML += `
                        <div class="card">
                            <small>ID: ${id}</small>
                            <pre>${messages}</pre>
                            <textarea id="manual-${id}" placeholder="Kirjoita
manuaalinen vastaus tC$hC$n..." rows="3"></textarea>
                            <button class="success" onclick="act('/valvomo/prom
pts/${id}/approve', 'POST')">HyvC$ksy & LC$hetC$ LLM</button>
                            <button onclick="manualAnswer('${id}')">Anna
Manuaalinen Vastaus</button>
                            <button class="danger" onclick="act('/valvomo/promp
ts/${id}/reject', 'POST')">HylkC$C$</button>
                        </div>
                    `;
                }
                document.getElementById('prompts-container').innerHTML = pHTML
|| '<p>Ei odottavia prompteja.</p>';

                // Hae vastaukset
                let rRes = await fetch('/valvomo/responses/pending');
                let responses = await rRes.json();
                let rHTML = '';
                for (let [id, data] of Object.entries(responses)) {
                    rHTML += `
                        <div class="card response">
                            <small>ID: ${id} | LC$hde: ${data.source}</small>
                            <textarea id="edit-resp-${id}" rows="6">${data.cont
ent}</textarea>
                            <button class="success" onclick="editAndApproveResp
onse('${id}')">HyvC$ksy Vastaus (Vapauta botille)</button>
                        </div>
                    `;
                }
                document.getElementById('responses-container').innerHTML =
rHTML || '<p>Ei odottavia vastauksia.</p>';
            }

            async function act(url, method) {
                await fetch(url, { method: method });
                fetchData();
            }

            async function manualAnswer(id) {
                let content = document.getElementById('manual-' + id).value;
                if (!content) return alert("Kirjoita vastaus ensin!");
                await fetch(`/valvomo/prompts/${id}/manual-answer?answer_conten
t=${encodeURIComponent(content)}`, { method: 'POST' });
                fetchData();
            }

            async function editAndApproveResponse(id) {
                let content = document.getElementById('edit-resp-' +
id).value;
                await fetch(`/valvomo/responses/${id}?new_content=${encodeURICo
mponent(content)}`, { method: 'PUT' });
                await fetch(`/valvomo/responses/${id}/approve`, { method:
'POST' });
                fetchData();
            }

            async function setMode(mode, regex='') {
                await fetch('/valvomo/mode', {
                    method: 'PUT',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ mode: mode, regex_pattern: regex })
                });
                alert('Tila vaihdettu: ' + mode);
            }

            // PC$ivitC$ automaattisesti 2 sekunnin vC$lein
            setInterval(fetchData, 2000);
            fetchData();
        </script>
    </body>
    </html>
    """