Stop a stuck in-flight flag from silently swallowing every later question
A turn that ended without finish() left busy=true, so send() returned at line one for every subsequent click — no fetch, no error, and the original "starting…" still on screen. That is a hang which produces no request and so no server-side trace of any kind. It now says what happened, and the pending indicator carries an elapsed counter so stalled and merely slow look different.
This commit is contained in:
@@ -341,10 +341,22 @@
|
||||
+ `<div class="vv-ai-body">${esc(text)}</div></div>`));
|
||||
scroll();
|
||||
}
|
||||
let pendingTimer = null;
|
||||
function addPending() {
|
||||
const n = el(`<div class="vv-ai-msg bot" id="vv-ai-pending"><div class="vv-ai-role">Varaverk</div>`
|
||||
+ `<div class="vv-ai-pending"><span class="vv-ai-dot"></span><span id="vv-ai-phase">starting…</span></div></div>`);
|
||||
+ `<div class="vv-ai-pending"><span class="vv-ai-dot"></span>`
|
||||
+ `<span id="vv-ai-phase">starting…</span>`
|
||||
+ `<span id="vv-ai-elapsed" style="color:#333;font-family:monospace"></span></div></div>`);
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user