operator inbox view on dashboard; agent ui doesn't clobber typing
This commit is contained in:
parent
070b237d03
commit
06ea0cf283
9 changed files with 132 additions and 12 deletions
|
|
@ -161,27 +161,44 @@
|
|||
}
|
||||
|
||||
let headerSet = false;
|
||||
let lastStatus = null;
|
||||
let lastOutputLen = -1;
|
||||
let pollTimer = null;
|
||||
async function refreshState() {
|
||||
try {
|
||||
const resp = await fetch('/api/state');
|
||||
if (!resp.ok) throw new Error('http ' + resp.status);
|
||||
const s = await resp.json();
|
||||
if (!headerSet) { setHeader(s.label, s.dashboard_port); headerSet = true; }
|
||||
const root = $('status');
|
||||
root.innerHTML = '';
|
||||
if (s.status === 'online') renderOnline(s.label, root);
|
||||
else if (s.status === 'needs_login_idle') renderNeedsLoginIdle(root);
|
||||
else if (s.status === 'needs_login_in_progress') renderLoginInProgress(s.session || {}, root);
|
||||
// Skip the re-render if nothing structurally changed. The most
|
||||
// common case is `online` polling itself — without this guard, the
|
||||
// operator's <input value> gets clobbered every cycle.
|
||||
const outLen = s.session?.output?.length ?? -1;
|
||||
const dirty =
|
||||
s.status !== lastStatus ||
|
||||
(s.status === 'needs_login_in_progress' && outLen !== lastOutputLen);
|
||||
if (dirty) {
|
||||
const root = $('status');
|
||||
root.innerHTML = '';
|
||||
if (s.status === 'online') renderOnline(s.label, root);
|
||||
else if (s.status === 'needs_login_idle') renderNeedsLoginIdle(root);
|
||||
else if (s.status === 'needs_login_in_progress') renderLoginInProgress(s.session || {}, root);
|
||||
lastStatus = s.status;
|
||||
lastOutputLen = outLen;
|
||||
}
|
||||
// Only poll while a login is in flight — otherwise SSE turn_end
|
||||
// events trigger a refresh, and the operator can type into the
|
||||
// send form without it getting cleared every few seconds.
|
||||
if (pollTimer) { clearTimeout(pollTimer); pollTimer = null; }
|
||||
if (s.status === 'needs_login_in_progress') {
|
||||
pollTimer = setTimeout(refreshState, 1500);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('refreshState failed', err);
|
||||
pollTimer = setTimeout(refreshState, 5000);
|
||||
}
|
||||
}
|
||||
refreshState();
|
||||
// Mid-login refresh on a short interval so the output buffer updates.
|
||||
setInterval(() => {
|
||||
// Cheap; api/state is small. Could subscribe to SSE state events later.
|
||||
refreshState();
|
||||
}, 3000);
|
||||
|
||||
// ─── live event stream ──────────────────────────────────────────────────
|
||||
(function() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue