main
html 271 lines 7.74 KB
Raw
1 <html>
2 <head>
3 <title>WebSocket Event Console</title>
4 <script type="module">
5 import { store as websocketEventConsoleStore } from "/components/settings/developer/websocket-event-console-store.js";
6 </script>
7 </head>
8 <body>
9 <div x-data>
10 <template x-if="window.runtimeInfo?.isDevelopment && $store.websocketEventConsoleStore">
11 <div
12 class="ws-console"
13 x-create="$store.websocketEventConsoleStore.onOpen()"
14 x-destroy="$store.websocketEventConsoleStore.detach({ notify: false })"
15 >
16 <h2>WebSocket Event Console</h2>
17 <p class="ws-description">
18 Capture inbound/outbound WebSocket envelopes, lifecycle broadcasts, and diagnostic metadata while capture is enabled.
19 This modal is the display layer for the bounded in-memory buffer.
20 </p>
21
22 <div class="ws-controls">
23 <button
24 class="btn"
25 x-show="!$store.websocketEventConsoleStore.captureEnabled"
26 @click="$store.websocketEventConsoleStore.startCapture()"
27 >
28 Start capture
29 </button>
30 <button
31 class="btn"
32 x-show="$store.websocketEventConsoleStore.captureEnabled"
33 @click="$store.websocketEventConsoleStore.stopCapture()"
34 >
35 Stop capture
36 </button>
37 <button
38 class="btn"
39 :disabled="!$store.websocketEventConsoleStore.captureEnabled"
40 @click="$store.websocketEventConsoleStore.reconnect()"
41 >
42 Resubscribe
43 </button>
44 <button class="btn" @click="$store.websocketEventConsoleStore.clear()">Clear</button>
45 <label class="ws-toggle">
46 <input
47 type="checkbox"
48 x-model="$store.websocketEventConsoleStore.showHandledOnly"
49 />
50 Show inbound events with handlers only
51 </label>
52 </div>
53
54 <div class="ws-status">
55 <span
56 class="badge"
57 :class="($store.websocketEventConsoleStore.captureEnabled && $store.websocketEventConsoleStore.subscriptionActive) ? 'badge-success' : 'badge-warning'"
58 x-text="!$store.websocketEventConsoleStore.captureEnabled ? 'Capture OFF' : ($store.websocketEventConsoleStore.subscriptionActive ? 'Capture ON' : 'Capture ON (not subscribed)')"
59 ></span>
60 <span
61 class="ws-error"
62 x-show="$store.websocketEventConsoleStore.lastError"
63 x-text="$store.websocketEventConsoleStore.lastError"
64 ></span>
65 </div>
66
67 <div class="ws-entries">
68 <template
69 x-for="entry in $store.websocketEventConsoleStore.filteredEntries().slice().reverse()"
70 :key="entry.eventId"
71 >
72 <div class="ws-entry">
73 <div class="ws-entry-header">
74 <span class="badge" :class="`badge-${entry.kind}`" x-text="entry.kind"></span>
75 <strong x-text="entry.eventType"></strong>
76 <span class="ws-meta" x-text="entry.timestamp"></span>
77 </div>
78 <div class="ws-entry-body">
79 <div class="ws-row">
80 <div>
81 <span class="ws-label">Correlation:</span>
82 <span x-text="entry.correlationId || '—'"></span>
83 </div>
84 <div>
85 <span class="ws-label">SID:</span>
86 <span x-text="entry.sid || (entry.targets && entry.targets.join(', ') ) || '—'"></span>
87 </div>
88 <div>
89 <span class="ws-label">Handlers:</span>
90 <span
91 x-text="entry.resultSummary?.handlerCount ?? entry.resultSummary?.handlers?.length ?? 0"
92 ></span>
93 <template x-if="entry.resultSummary?.ok || entry.resultSummary?.error">
94 <span class="ws-inline-summary">
95 <span>OK: <span x-text="entry.resultSummary.ok || 0"></span></span>
96 <span>Errors: <span x-text="entry.resultSummary.error || 0"></span></span>
97 </span>
98 </template>
99 </div>
100 </div>
101
102 <div class="ws-json-grid">
103 <div>
104 <h4>Payload Summary</h4>
105 <pre x-text="JSON.stringify(entry.payloadSummary || {}, null, 2)"></pre>
106 </div>
107 <div>
108 <h4>Result Summary</h4>
109 <pre x-text="JSON.stringify(entry.resultSummary || {}, null, 2)"></pre>
110 </div>
111 </div>
112 </div>
113 </div>
114 </template>
115 </div>
116 </div>
117 </template>
118
119 <template x-if="!window.runtimeInfo?.isDevelopment">
120 <div class="ws-console ws-disabled">
121 <h2>WebSocket Event Console</h2>
122 <p class="ws-description">
123 The event console is available only when Agent Zero runs in development mode.
124 </p>
125 </div>
126 </template>
127 </div>
128
129 <style>
130 .ws-console {
131 display: flex;
132 flex-direction: column;
133 gap: 1rem;
134 color: var(--color-text-primary);
135 }
136
137 .ws-description {
138 margin: 0;
139 color: var(--color-text-secondary);
140 }
141
142 .ws-controls {
143 display: flex;
144 align-items: center;
145 gap: 0.75rem;
146 flex-wrap: wrap;
147 }
148
149 .ws-toggle {
150 display: flex;
151 align-items: center;
152 gap: 0.4rem;
153 font-size: 0.9rem;
154 color: var(--color-text-secondary);
155 }
156
157 .ws-status {
158 display: flex;
159 align-items: center;
160 gap: 0.75rem;
161 }
162
163 .ws-error {
164 color: var(--color-danger);
165 font-size: 0.9rem;
166 }
167
168 .ws-entries {
169 display: flex;
170 flex-direction: column;
171 gap: 0.75rem;
172 max-height: 60vh;
173 overflow-y: auto;
174 }
175
176 .ws-entry {
177 border: 1px solid var(--color-border);
178 border-radius: 6px;
179 padding: 0.75rem;
180 background: var(--color-bg-secondary);
181 }
182
183 .ws-entry-header {
184 display: flex;
185 align-items: center;
186 gap: 0.5rem;
187 flex-wrap: wrap;
188 }
189
190 .ws-entry-body {
191 margin-top: 0.5rem;
192 display: flex;
193 flex-direction: column;
194 gap: 0.5rem;
195 }
196
197 .ws-row {
198 display: flex;
199 flex-wrap: wrap;
200 gap: 1rem;
201 font-size: 0.9rem;
202 }
203
204 .ws-label {
205 font-weight: 600;
206 margin-right: 0.25rem;
207 }
208
209 .ws-inline-summary {
210 display: inline-flex;
211 gap: 0.5rem;
212 margin-left: 0.5rem;
213 }
214
215 .ws-json-grid {
216 display: grid;
217 grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
218 gap: 0.5rem;
219 }
220
221 .ws-json-grid pre {
222 background: var(--color-bg-primary);
223 border: 1px solid var(--color-border);
224 border-radius: 4px;
225 padding: 0.5rem;
226 font-size: 0.8rem;
227 max-height: 160px;
228 overflow: auto;
229 }
230
231 .badge {
232 padding: 0.1rem 0.4rem;
233 border-radius: 3px;
234 font-size: 0.75rem;
235 text-transform: uppercase;
236 letter-spacing: 0.03em;
237 }
238
239 .badge-success {
240 background: var(--color-success, #16a34a);
241 color: var(--color-bg-primary);
242 }
243
244 .badge-warning {
245 background: var(--color-warning, #f59e0b);
246 color: var(--color-bg-primary);
247 }
248
249 .badge-inbound {
250 background: var(--color-accent, #6366f1);
251 color: var(--color-bg-primary);
252 }
253
254 .badge-outbound {
255 background: var(--color-info, #0ea5e9);
256 color: var(--color-bg-primary);
257 }
258
259 .badge-lifecycle {
260 background: var(--color-success, #16a34a);
261 color: var(--color-bg-primary);
262 }
263
264 .ws-disabled {
265 border: 1px dashed var(--color-border);
266 padding: 1rem;
267 border-radius: 6px;
268 }
269 </style>
270 </body>
271 </html>