extract dashboard + agent CSS/JS to assets/ (include_str!)
This commit is contained in:
parent
e9b213690e
commit
edf42b7e93
7 changed files with 547 additions and 534 deletions
103
hive-ag3nt/assets/live.js
Normal file
103
hive-ag3nt/assets/live.js
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
(function() {
|
||||
const log = document.getElementById('live');
|
||||
let placeholder = log.firstChild;
|
||||
function setPlaceholder(text) {
|
||||
log.innerHTML = '';
|
||||
const span = document.createElement('div');
|
||||
span.className = 'meta';
|
||||
span.textContent = text;
|
||||
log.appendChild(span);
|
||||
placeholder = span;
|
||||
}
|
||||
function clearPlaceholder() {
|
||||
if (placeholder) { log.innerHTML = ''; placeholder = null; }
|
||||
}
|
||||
function row(cls, text) {
|
||||
clearPlaceholder();
|
||||
const el = document.createElement('div');
|
||||
el.className = 'row ' + (cls || '');
|
||||
el.textContent = text;
|
||||
log.appendChild(el);
|
||||
log.scrollTop = log.scrollHeight;
|
||||
return el;
|
||||
}
|
||||
function trim(s, n) {
|
||||
return s.length > n ? s.slice(0, n) + '…' : s;
|
||||
}
|
||||
function renderStream(v) {
|
||||
if (v.type === 'system' && v.subtype === 'init') {
|
||||
row('sys', '· session init · tools=' + (v.tools||[]).length + ' model=' + (v.model || '?'));
|
||||
return;
|
||||
}
|
||||
if (v.type === 'rate_limit_event') {
|
||||
const u = Math.round((v.rate_limit_info?.utilization || 0) * 100);
|
||||
const s = v.rate_limit_info?.status || '';
|
||||
row('sys', '· rate-limit util=' + u + '% (' + s + ')');
|
||||
return;
|
||||
}
|
||||
if (v.type === 'assistant' && v.message && v.message.content) {
|
||||
for (const c of v.message.content) {
|
||||
if (c.type === 'text' && c.text && c.text.trim())
|
||||
row('text', c.text);
|
||||
else if (c.type === 'thinking')
|
||||
row('thinking', '· thinking …');
|
||||
else if (c.type === 'tool_use')
|
||||
row('tool-use', '→ ' + c.name + ' ' + trim(JSON.stringify(c.input || {}), 240));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (v.type === 'user' && v.message && v.message.content) {
|
||||
for (const c of v.message.content) {
|
||||
if (c.type === 'tool_result') {
|
||||
const txt = Array.isArray(c.content)
|
||||
? c.content.map(p => p.text || '').join(' ')
|
||||
: (c.content || '');
|
||||
row('tool-result', '← ' + trim(txt, 300));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (v.type === 'result') {
|
||||
row('result', '✓ done · ' + (v.subtype || '') + (v.is_error ? ' [error]' : ''));
|
||||
return;
|
||||
}
|
||||
// Fallback: small one-liner for unknown events; don't spam.
|
||||
row('sys', '· ' + trim(JSON.stringify(v), 200));
|
||||
}
|
||||
function handle(ev) {
|
||||
if (ev.kind === 'turn_start') {
|
||||
const block = row('turn-start', '◆ TURN ← ' + ev.from);
|
||||
const body = document.createElement('div');
|
||||
body.className = 'turn-body';
|
||||
body.textContent = ev.body;
|
||||
block.appendChild(body);
|
||||
return;
|
||||
}
|
||||
if (ev.kind === 'turn_end') {
|
||||
const cls = ev.ok ? 'turn-end-ok' : 'turn-end-fail';
|
||||
const sym = ev.ok ? '✓' : '✗';
|
||||
row(cls, sym + ' turn ' + (ev.ok ? 'ok' : 'fail') + (ev.note ? ' — ' + ev.note : ''));
|
||||
return;
|
||||
}
|
||||
if (ev.kind === 'note') {
|
||||
row('note', '· ' + ev.text);
|
||||
return;
|
||||
}
|
||||
if (ev.kind === 'stream') {
|
||||
const v = Object.assign({}, ev); delete v.kind;
|
||||
renderStream(v);
|
||||
return;
|
||||
}
|
||||
row('note', JSON.stringify(ev));
|
||||
}
|
||||
const es = new EventSource('/events/stream');
|
||||
es.onopen = function() { setPlaceholder('(connected — waiting for events)'); };
|
||||
es.onmessage = function(e) {
|
||||
try { handle(JSON.parse(e.data)); }
|
||||
catch (err) { row('note', '[parse err] ' + e.data); }
|
||||
};
|
||||
es.onerror = function() {
|
||||
if (es.readyState === EventSource.CONNECTING) setPlaceholder('(reconnecting…)');
|
||||
else row('note', '[disconnected]');
|
||||
};
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue