Stamp the AI page build and tear down stale copies of its script

The tab bar uses Unraid's localURL, which swaps content by AJAX without
tearing down the previous page's JavaScript, so old copies keep their timers
and their state. That makes "is the browser running what I deployed"
unanswerable from the server, and explains banner polls arriving far faster
than the 30s timer. The page now stamps its build, says plainly when its own
script is not the one running, and stops the previous copy's timers.
This commit is contained in:
Gmer4Lfe
2026-08-02 18:06:10 -04:00
parent ae7555a423
commit ca678b1784
+26 -2
View File
@@ -57,6 +57,17 @@
// api/ai.php stats / ask / poll / clear
// api/readscript.php source viewer contents
// ═══════════════════════════════════════════════════════════════════════════════════════════════
<?php
// Build stamp. The tab bar uses Unraid's localURL, which swaps content by AJAX without tearing
// down the previous page's JavaScript — so a stale copy of this script can keep running, and
// its timers keep firing, while a new copy is injected. That makes "is the browser executing
// the code I just deployed" unanswerable from the server alone. Rendered into the DOM and
// logged on every render so both sides can be compared.
$_vv_ai_build = substr(md5_file(__FILE__), 0, 8);
if (is_dir('/var/log/varaverk')) {
@file_put_contents('/var/log/varaverk/ai.log',
date('Y-m-d H:i:s') . ' RENDER page build=' . $_vv_ai_build . "\n", FILE_APPEND | LOCK_EX);
}
?>
<style>
#vv-ai-wrap { display:flex; flex-direction:column; gap:12px; }
@@ -190,7 +201,8 @@
</select>
<label class="vv-ai-toggle"><input type="checkbox" id="vv-ai-think" checked> reasoning</label>
<button class="vv-ai-btn ghost" id="vv-ai-clear" type="button">Clear</button>
<span class="vv-ai-hint">Ctrl+Enter to send · history capped at 3 turns</span>
<span class="vv-ai-hint">Ctrl+Enter to send · 3-turn history · build <?=$_vv_ai_build?>
<span id="vv-ai-live" style="color:#e57">· JS NOT RUNNING</span></span>
<button class="vv-ai-btn" id="vv-ai-send" type="button">Ask</button>
</div>
</div>
@@ -533,7 +545,19 @@
finish();
});
// Proves to the page itself that this copy of the script is the one running, and that its
// click handler is attached. If the marker still reads NOT RUNNING, the browser is executing
// an older copy and no amount of server-side deployment will change what the button does.
const live = $('vv-ai-live');
if (live) { live.style.color = '#4a4a4a'; live.textContent = '· JS live'; }
// Old copies of this script survive a tab swap and keep their timers. Tearing the previous
// one down stops N banners polling in parallel, and stops a stale closure's busy flag from
// being the thing the user is actually looking at.
if (window.__vvAiTeardown) { try { window.__vvAiTeardown(); } catch (e) {} }
const bannerTimer = setInterval(loadBanner, 30000);
window.__vvAiTeardown = function () { clearInterval(bannerTimer); clearInterval(pendingTimer); };
loadBanner();
setInterval(loadBanner, 30000);
})();
</script>