Skip to content

Commit 3a8839b

Browse files
authored
Merge pull request #2 from SL5TaskForce/dashboard-improvements
Dashboard improvements
2 parents 0d272e6 + e38b8bd commit 3a8839b

4 files changed

Lines changed: 16 additions & 146 deletions

File tree

otel-collector.yaml

Lines changed: 0 additions & 28 deletions
This file was deleted.

public/index.html

Lines changed: 7 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,6 @@
4242
margin-right: 2px;
4343
}
4444

45-
.btn-reset {
46-
padding: 2px 8px;
47-
font-size: 10px;
48-
font-family: var(--font-sans);
49-
font-weight: 500;
50-
color: var(--color-muted);
51-
background: transparent;
52-
border: 1px solid rgba(139, 148, 158, 0.35);
53-
border-radius: 4px;
54-
cursor: pointer;
55-
text-transform: none;
56-
letter-spacing: normal;
57-
transition: background 0.15s, border-color 0.15s, color 0.15s;
58-
}
59-
60-
.btn-reset:hover {
61-
color: var(--color-text);
62-
background: rgba(139, 148, 158, 0.1);
63-
border-color: rgba(139, 148, 158, 0.4);
64-
}
65-
6645
.panel-content {
6746
flex: 1;
6847
overflow-y: auto;
@@ -543,7 +522,6 @@
543522
<span class="status-label">Dashboard Status:</span>
544523
<span class="connection-label connecting" id="connection-label">CONNECTING</span>
545524
</div>
546-
<button class="btn-reset" id="btn-reset-demo" title="Reset demo to initial state">Reset Demo</button>
547525
</div>
548526
</div>
549527
<div class="panel" id="panel-registry">
@@ -649,13 +627,15 @@
649627

650628
switch (eventType) {
651629
case 'agent.created':
652-
return 'Agent ' + (attrs['agent.id'] || '') + ' provisioned';
630+
return (attrs['user.id'] || '') + ' → ' + (attrs['agent.id'] || '');
653631
case 'agent.terminated':
654632
return 'Agent ' + (attrs['agent.id'] || '') + ' terminated';
655633
case 'request.allowed':
656634
return (attrs['http.host'] || '') + ' -- allowed';
657635
case 'request.denied':
658636
return (attrs['http.host'] || '') + ' -- denied' + (attrs['denial.reason'] ? ': ' + attrs['denial.reason'] : '');
637+
case 'agent.prompted':
638+
return (attrs['user.id'] || 'user') + ' → ' + (attrs['agent.id'] || 'agent');
659639
default:
660640
if (attrs['agent.id']) return eventType + ' for ' + attrs['agent.id'];
661641
return eventType;
@@ -694,12 +674,6 @@
694674
const attrs = event.attributes || {};
695675
const agentId = attrs['agent.id'] || '';
696676

697-
// Demo reset — clear all local state
698-
if (eventType === 'demo.reset') {
699-
clearAllDashboardState();
700-
return;
701-
}
702-
703677
// User lifecycle. Event names are speculative until the backend
704678
// settles its vocabulary; the handler shape stays the same.
705679
if (eventType === 'user.created') {
@@ -711,12 +685,11 @@
711685
if (userId) Topology.removeUserNode(userId);
712686
}
713687

714-
// User actions — light up the user→platform edge.
715-
if (eventType === 'agent.requested' || eventType === 'prompt.sent' || eventType === 'permission.change_requested' || eventType === 'termination.requested') {
688+
// agent.prompted: user→platform then platform→agent sequentially
689+
if (eventType === 'agent.prompted') {
716690
const userId = attrs['user.id'] || '';
717-
if (userId) {
718-
Topology.highlightEdge(userId, Topology.EDGE_HIGHLIGHT_MS);
719-
}
691+
if (userId) Topology.highlightEdge(userId, Topology.EDGE_HIGHLIGHT_MS);
692+
if (agentId) setTimeout(() => Topology.highlightEdge('platform-' + agentId, Topology.EDGE_HIGHLIGHT_MS), 400);
720693
}
721694

722695
// Agent lifecycle. Light up the platform→agent edge: the platform is
@@ -731,11 +704,6 @@
731704
Topology.removeAgentRuntimeNode(agentId);
732705
}
733706

734-
// Prompt delivered: platform exec'd into the agent via the supervisor.
735-
if (eventType === 'agent.prompted') {
736-
if (agentId) Topology.highlightEdge('platform-' + agentId, Topology.EDGE_HIGHLIGHT_MS);
737-
}
738-
739707
// Gateway decisions
740708
if (eventType === 'auth.allowed' || eventType === 'request.allowed' || eventType === 'request.denied' || eventType === 'permission.checked') {
741709
const decision = {
@@ -866,27 +834,6 @@
866834
else startRegistryPolling();
867835
});
868836

869-
// ============================================================
870-
// Reset button
871-
// ============================================================
872-
document.getElementById('btn-reset-demo').addEventListener('click', async () => {
873-
const btn = document.getElementById('btn-reset-demo');
874-
btn.disabled = true;
875-
btn.textContent = 'Resetting...';
876-
877-
try {
878-
const res = await fetch('/api/reset', { method: 'POST' });
879-
if (res.ok) {
880-
clearAllDashboardState();
881-
}
882-
} catch (err) {
883-
console.error('Reset failed:', err);
884-
} finally {
885-
btn.disabled = false;
886-
btn.textContent = 'Reset Demo';
887-
}
888-
});
889-
890837
// ============================================================
891838
// Init
892839
// ============================================================

server.js

Lines changed: 7 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,8 @@ const server = http.createServer(async (req, res) => {
123123
attributes: body.attributes || {},
124124
received_at: new Date().toISOString(),
125125
};
126-
if (ev.event_type === 'demo.reset') {
127-
events = [];
128-
} else {
129-
events.push(ev);
130-
if (events.length > MAX_EVENTS) events = events.slice(-MAX_EVENTS);
131-
}
126+
events.push(ev);
127+
if (events.length > MAX_EVENTS) events = events.slice(-MAX_EVENTS);
132128
broadcastEvent(ev);
133129
return sendJson(res, 200, {});
134130
}
@@ -138,12 +134,8 @@ const server = http.createServer(async (req, res) => {
138134
const body = await parseBody(req);
139135
for (const ev of translateOtlpLogs(body)) {
140136
ev.received_at = new Date().toISOString();
141-
if (ev.event_type === 'demo.reset') {
142-
events = [];
143-
} else {
144-
events.push(ev);
145-
if (events.length > MAX_EVENTS) events = events.slice(-MAX_EVENTS);
146-
}
137+
events.push(ev);
138+
if (events.length > MAX_EVENTS) events = events.slice(-MAX_EVENTS);
147139
broadcastEvent(ev);
148140
}
149141
return sendJson(res, 200, { partialSuccess: {} });
@@ -228,48 +220,6 @@ const server = http.createServer(async (req, res) => {
228220
}
229221
}
230222

231-
// POST /api/reset - proxy to demo-admin reset endpoint
232-
if (pathName === '/api/reset' && method === 'POST') {
233-
const adminHost = process.env.ADMIN_HOST || 'demo-admin';
234-
const adminPort = process.env.ADMIN_PORT || '8080';
235-
return new Promise((resolve) => {
236-
let responded = false;
237-
const proxyReq = http.request({
238-
hostname: adminHost,
239-
port: parseInt(adminPort),
240-
path: '/api/reset',
241-
method: 'POST',
242-
headers: { 'Content-Type': 'application/json' },
243-
timeout: 30000,
244-
}, (proxyRes) => {
245-
let body = '';
246-
proxyRes.on('data', chunk => { body += chunk; });
247-
proxyRes.on('end', () => {
248-
if (responded) return;
249-
responded = true;
250-
events = [];
251-
res.writeHead(proxyRes.statusCode, { 'Content-Type': 'application/json' });
252-
res.end(body);
253-
resolve();
254-
});
255-
});
256-
proxyReq.on('error', (err) => {
257-
if (responded) return;
258-
responded = true;
259-
sendJson(res, 502, { error: 'Failed to reach demo-admin: ' + err.message });
260-
resolve();
261-
});
262-
proxyReq.on('timeout', () => {
263-
proxyReq.destroy();
264-
if (responded) return;
265-
responded = true;
266-
sendJson(res, 504, { error: 'demo-admin request timed out' });
267-
resolve();
268-
});
269-
proxyReq.end();
270-
});
271-
}
272-
273223
// Serve static files for everything else
274224
serveStatic(req, res);
275225
} catch (e) {
@@ -283,8 +233,9 @@ const wss = new WebSocketServer({ server, path: '/ws' });
283233
wss.on('connection', (ws) => {
284234
wsClients.add(ws);
285235

286-
// Send event history on connect
287-
ws.send(JSON.stringify({ type: 'history', events }));
236+
// Send event history on connect, sorted chronologically
237+
const sortedEvents = [...events].sort((a, b) => (a.timestamp < b.timestamp ? -1 : a.timestamp > b.timestamp ? 1 : 0));
238+
ws.send(JSON.stringify({ type: 'history', events: sortedEvents }));
288239

289240
ws.on('close', () => {
290241
wsClients.delete(ws);

translate.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function translateOtlpLogs(otlp) {
5353
}
5454
}
5555
}
56-
return out;
56+
return out.sort((a, b) => (a.timestamp < b.timestamp ? -1 : a.timestamp > b.timestamp ? 1 : 0));
5757
}
5858

5959
// ─── Jaeger trace export → flat events ─────────────────────────────────────
@@ -198,7 +198,7 @@ function translateOtlpTraces(payload) {
198198
}
199199
}
200200
}
201-
return out;
201+
return out.sort((a, b) => (a.timestamp < b.timestamp ? -1 : a.timestamp > b.timestamp ? 1 : 0));
202202
}
203203

204204
module.exports = { translateOtlpLogs, translateJaegerTraces, translateOtlpTraces };

0 commit comments

Comments
 (0)