diff --git a/Plugin/unraid/pages/ai.php b/Plugin/unraid/pages/ai.php index 1410962..18a7394 100644 --- a/Plugin/unraid/pages/ai.php +++ b/Plugin/unraid/pages/ai.php @@ -341,10 +341,22 @@ + `
${esc(text)}
`)); scroll(); } + let pendingTimer = null; function addPending() { const n = el(`
Varaverk
` - + `
starting…
`); + + `
` + + `starting…` + + `
`); chat().appendChild(n); scroll(); + // An elapsed counter distinguishes "working" from "wedged" at a glance. Without it a stalled + // turn and a slow one look identical, and the slow case here is legitimately ~40s. + const t0 = Date.now(); + clearInterval(pendingTimer); + pendingTimer = setInterval(() => { + const e = $('vv-ai-elapsed'); + if (!e) { clearInterval(pendingTimer); return; } + e.textContent = Math.round((Date.now() - t0) / 1000) + 's'; + }, 1000); } function phase(t) { const p = $('vv-ai-phase'); if (p) p.textContent = t; } @@ -389,7 +401,16 @@ // ── Ask / poll ────────────────────────────────────────────────────────── function send() { - if (busy) return; + // Never fail silently on a stuck flag. A turn that ends without finish() — a throw, a poll + // loop that stopped, a tab left open across a deploy — would otherwise make every later + // click a no-op with the previous "starting…" still on screen, which reads as a hang that + // produces no request and therefore no server-side trace at all. That cost a diagnosis + // session; it now says so and offers the way out. + if (busy) { + addError('A previous question is still marked in-flight, so this one was not sent. ' + + 'Reload the tab to reset it.'); + return; + } const q = $('vv-ai-input').value.trim(); if (!q) return; @@ -439,7 +460,11 @@ .catch(e => { addError('Request failed: ' + (e && e.message ? e.message : e)); finish(); }); } - function finish() { busy = false; $('vv-ai-send').disabled = false; } + function finish() { + busy = false; + $('vv-ai-send').disabled = false; + clearInterval(pendingTimer); + } function poll(token, started) { if (Date.now() - started > POLL_CEIL) {