Frontend refactored to ES6 modules (no bundler): js/main.js — entry point, wires all modules js/auth.js — OIDC login, token management js/ws.js — /ws, /ws/test, /ws/trace connections + HUD handler js/chat.js — messages, send, streaming js/graph.js — Cytoscape visualization + animation js/trace.js — trace panel js/dashboard.js — workspace controls rendering js/awareness.js — state panel, sensors, meters js/tests.js — test status display js/util.js — shared utilities New 2-row layout: Top: test status | connection status Middle: Workspace | Node Details | Graph Bottom: Chat | Awareness | Trace PA routing: routes ALL tool requests to expert (DB, UI, buttons, machines) Dashboard integration test: 15/15 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
63 lines
1.6 KiB
JavaScript
63 lines
1.6 KiB
JavaScript
/** Chat panel: messages, send, streaming. */
|
|
|
|
import { scroll, renderMarkdown, esc } from './util.js';
|
|
import { addTrace } from './trace.js';
|
|
|
|
let msgs, inputEl, currentEl;
|
|
let _ws = null;
|
|
let _currentDashboard = [];
|
|
|
|
export function initChat() {
|
|
msgs = document.getElementById('messages');
|
|
inputEl = document.getElementById('input');
|
|
inputEl.addEventListener('keydown', e => { if (e.key === 'Enter') send(); });
|
|
}
|
|
|
|
export function setWs(ws) { _ws = ws; }
|
|
export function setDashboard(d) { _currentDashboard = d; }
|
|
export function getDashboard() { return _currentDashboard; }
|
|
|
|
export function addMsg(role, text) {
|
|
const div = document.createElement('div');
|
|
div.className = 'msg ' + role;
|
|
div.textContent = text;
|
|
msgs.appendChild(div);
|
|
scroll(msgs);
|
|
return div;
|
|
}
|
|
|
|
export function handleDelta(content) {
|
|
if (!currentEl) {
|
|
currentEl = addMsg('assistant', '');
|
|
currentEl.classList.add('streaming');
|
|
}
|
|
currentEl.textContent += content;
|
|
scroll(msgs);
|
|
}
|
|
|
|
export function handleDone() {
|
|
if (currentEl) {
|
|
currentEl.classList.remove('streaming');
|
|
currentEl.innerHTML = renderMarkdown(currentEl.textContent);
|
|
}
|
|
currentEl = null;
|
|
}
|
|
|
|
export function clearChat() {
|
|
if (msgs) msgs.innerHTML = '';
|
|
currentEl = null;
|
|
_currentDashboard = [];
|
|
}
|
|
|
|
export function send() {
|
|
const text = inputEl.value.trim();
|
|
if (!text || !_ws || _ws.readyState !== 1) return;
|
|
addMsg('user', text);
|
|
addTrace('runtime', 'user_msg', text.slice(0, 60));
|
|
_ws.send(JSON.stringify({ text, dashboard: _currentDashboard }));
|
|
inputEl.value = '';
|
|
}
|
|
|
|
// Expose for HTML onclick
|
|
window.send = send;
|