CxWebApp/static/js/panes/websocket.js
CxAI Agent d057e09fa2
Some checks are pending
build-and-push / image (push) Waiting to run
feat: add new panes for demand, diffusion, inbox, items, lang, mac, slack, system, tools, and websocket
- Implemented demand pane for managing trend-driven design jobs.
- Created diffusion pane for generating images via Stable Diffusion.
- Added inbox pane for sweeping and routing artifacts through the CxAI inbox classifier.
- Developed items pane for CRUD operations against /api/items.
- Introduced lang pane for running language pipelines.
- Established mac pane for macOS app distribution information.
- Integrated slack pane for sending messages and displaying diagnostics.
- Built system pane for process introspection and version information.
- Launched tools pane for browsing and invoking MCP tools.
- Set up websocket pane for connecting to the /ws/echo service.
2026-05-16 19:23:30 -05:00

67 lines
2.4 KiB
JavaScript

// panes/websocket.js — /ws/echo console.
import { registerPane } from '../app.js';
const TPL = `
<div class="pane-head">
<div><div class="title">WebSocket</div><div class="sub">Connect to <code>/ws/echo</code>.</div></div>
<div class="grow"></div>
<span class="pill" id="ws-pill"><span class="dot"></span><span id="ws-state">idle</span></span>
</div>
<div class="card">
<div class="btn-row mb-3">
<button class="btn btn-primary" id="ws-connect">Connect</button>
<button class="btn btn-secondary" id="ws-disconnect">Disconnect</button>
</div>
<pre class="console h-64" id="ws-log"></pre>
<form id="ws-form" class="flex gap-2 mt-3">
<input class="input" id="ws-input" placeholder="message…" />
<button class="btn btn-primary" type="submit">Send</button>
</form>
</div>
`;
let ws = null;
function setState(host, state, klass) {
host.querySelector('#ws-state').textContent = state;
const p = host.querySelector('#ws-pill');
p.classList.remove('ok', 'err', 'warn', 'info');
if (klass) p.classList.add(klass);
}
function append(host, line) {
const pre = host.querySelector('#ws-log');
pre.textContent += line + '\n';
pre.scrollTop = pre.scrollHeight;
}
function connect(host) {
if (ws && ws.readyState <= 1) return;
const proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
const url = `${proto}//${location.host}/ws/echo`;
ws = new WebSocket(url);
setState(host, 'connecting…', 'warn');
ws.onopen = () => { setState(host, 'connected', 'ok'); append(host, `< connected ${url}`); };
ws.onclose = () => { setState(host, 'disconnected', 'err'); append(host, '< closed'); };
ws.onerror = () => append(host, '! error');
ws.onmessage = (e) => append(host, '< ' + e.data);
}
registerPane('websocket', {
label: 'WebSocket',
init(host) {
host.innerHTML = TPL;
host.querySelector('#ws-connect').addEventListener('click', () => connect(host));
host.querySelector('#ws-disconnect').addEventListener('click', () => ws && ws.close());
host.querySelector('#ws-form').addEventListener('submit', (e) => {
e.preventDefault();
const v = host.querySelector('#ws-input').value;
if (!v) return;
if (!ws || ws.readyState !== 1) { append(host, '! not connected'); return; }
ws.send(v);
append(host, '> ' + v);
host.querySelector('#ws-input').value = '';
});
},
});