kernelbot 1.0.37 → 1.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/bin/kernel.js +499 -249
  2. package/config.example.yaml +17 -0
  3. package/knowledge_base/active_inference_foraging.md +126 -0
  4. package/knowledge_base/index.md +1 -1
  5. package/package.json +3 -1
  6. package/src/agent.js +355 -82
  7. package/src/bot.js +724 -12
  8. package/src/character.js +406 -0
  9. package/src/characters/builder.js +174 -0
  10. package/src/characters/builtins.js +421 -0
  11. package/src/conversation.js +17 -2
  12. package/src/dashboard/agents.css +469 -0
  13. package/src/dashboard/agents.html +184 -0
  14. package/src/dashboard/agents.js +873 -0
  15. package/src/dashboard/dashboard.css +281 -0
  16. package/src/dashboard/dashboard.js +579 -0
  17. package/src/dashboard/index.html +366 -0
  18. package/src/dashboard/server.js +521 -0
  19. package/src/dashboard/shared.css +700 -0
  20. package/src/dashboard/shared.js +218 -0
  21. package/src/life/engine.js +115 -26
  22. package/src/life/evolution.js +7 -5
  23. package/src/life/journal.js +5 -4
  24. package/src/life/memory.js +12 -9
  25. package/src/life/share-queue.js +7 -5
  26. package/src/prompts/orchestrator.js +76 -14
  27. package/src/prompts/workers.js +22 -0
  28. package/src/self.js +17 -5
  29. package/src/services/linkedin-api.js +190 -0
  30. package/src/services/stt.js +8 -2
  31. package/src/services/tts.js +32 -2
  32. package/src/services/x-api.js +141 -0
  33. package/src/swarm/worker-registry.js +7 -0
  34. package/src/tools/categories.js +4 -0
  35. package/src/tools/index.js +6 -0
  36. package/src/tools/linkedin.js +264 -0
  37. package/src/tools/orchestrator-tools.js +337 -2
  38. package/src/tools/x.js +256 -0
  39. package/src/utils/config.js +190 -139
  40. package/src/utils/display.js +165 -52
  41. package/src/utils/temporal-awareness.js +24 -10
@@ -0,0 +1,469 @@
1
+ /* ═══════ AGENTS PAGE STYLES ═══════ */
2
+
3
+ /* ═══════ STATS BAR ═══════ */
4
+ .agents-stats-bar {
5
+ display: flex;
6
+ align-items: center;
7
+ justify-content: center;
8
+ gap: 32px;
9
+ padding: 10px 24px;
10
+ border-bottom: 1px solid var(--panel-border);
11
+ }
12
+ .agents-stat {
13
+ display: flex;
14
+ flex-direction: column;
15
+ align-items: center;
16
+ gap: 2px;
17
+ }
18
+ .agents-stat-val {
19
+ font-family: var(--font-hud);
20
+ font-size: 16px;
21
+ font-weight: 700;
22
+ color: var(--accent);
23
+ }
24
+ .agents-stat-val.completed { color: var(--accent); }
25
+ .agents-stat-val.failed { color: var(--red); }
26
+ .agents-stat-lbl {
27
+ font-family: var(--font-hud);
28
+ font-size: 7px;
29
+ letter-spacing: 1.5px;
30
+ color: var(--dim);
31
+ }
32
+
33
+ /* ═══════ WORKFLOW CONTAINER ═══════ */
34
+ .workflow-container {
35
+ position: relative;
36
+ height: calc(100vh - 200px);
37
+ overflow: hidden;
38
+ cursor: grab;
39
+ user-select: none;
40
+ }
41
+ .workflow-container.grabbing { cursor: grabbing; }
42
+ .workflow-container.dragging-node { cursor: default; }
43
+
44
+ /* Pannable / zoomable layer */
45
+ .workflow-canvas {
46
+ position: absolute;
47
+ top: 0; left: 0;
48
+ width: 100%; height: 100%;
49
+ transform-origin: 0 0;
50
+ will-change: transform;
51
+ }
52
+
53
+ .workflow-svg {
54
+ position: absolute;
55
+ top: 0; left: 0;
56
+ width: 100%; height: 100%;
57
+ pointer-events: none;
58
+ z-index: 1;
59
+ overflow: visible;
60
+ }
61
+
62
+ /* ═══════ SVG CONNECTIONS ═══════ */
63
+ .connection-path {
64
+ fill: none;
65
+ stroke: rgba(57,255,20,0.12);
66
+ stroke-width: 1.5;
67
+ marker-end: url(#arrow);
68
+ transition: stroke 0.4s, stroke-width 0.4s;
69
+ }
70
+ .connection-path.active {
71
+ stroke: rgba(57,255,20,0.5);
72
+ stroke-width: 2;
73
+ marker-end: url(#arrow-active);
74
+ filter: drop-shadow(0 0 6px rgba(57,255,20,0.3));
75
+ }
76
+
77
+ /* Message particle traveling along path */
78
+ .msg-particle {
79
+ fill: var(--accent);
80
+ filter: drop-shadow(0 0 6px var(--accent));
81
+ transition: r 0.2s;
82
+ }
83
+ .msg-particle.burst {
84
+ fill: var(--amber);
85
+ filter: drop-shadow(0 0 8px var(--amber));
86
+ }
87
+
88
+ /* Glow trail behind particle */
89
+ .msg-trail {
90
+ fill: none;
91
+ stroke: var(--accent);
92
+ stroke-width: 3;
93
+ stroke-linecap: round;
94
+ opacity: 0.3;
95
+ filter: drop-shadow(0 0 4px var(--accent));
96
+ }
97
+
98
+ /* ═══════ WORKFLOW NODES ═══════ */
99
+ .workflow-node {
100
+ position: absolute;
101
+ background: var(--panel-bg);
102
+ border: 1px solid var(--panel-border);
103
+ padding: 12px 16px;
104
+ cursor: grab;
105
+ z-index: 2;
106
+ transition: border-color 0.3s, box-shadow 0.3s;
107
+ min-width: 180px;
108
+ user-select: none;
109
+ }
110
+ .workflow-node.dragging {
111
+ cursor: grabbing;
112
+ z-index: 10;
113
+ box-shadow: 0 0 30px rgba(57,255,20,0.15), 0 8px 32px rgba(0,0,0,0.4);
114
+ border-color: var(--accent);
115
+ }
116
+ .workflow-node:hover {
117
+ border-color: var(--panel-border-hover);
118
+ box-shadow: 0 0 20px rgba(57,255,20,0.08);
119
+ }
120
+ .workflow-node.selected {
121
+ border-color: var(--accent);
122
+ box-shadow: 0 0 24px rgba(57,255,20,0.12), inset 0 0 12px rgba(57,255,20,0.03);
123
+ }
124
+ .workflow-node.has-active-job {
125
+ animation: nodeGlow 2s ease-in-out infinite;
126
+ }
127
+
128
+ /* Ripple flash on new job arrival */
129
+ .workflow-node.ripple::after {
130
+ content: '';
131
+ position: absolute;
132
+ inset: -4px;
133
+ border: 2px solid var(--accent);
134
+ opacity: 1;
135
+ animation: nodeRipple 0.8s ease-out forwards;
136
+ pointer-events: none;
137
+ }
138
+ @keyframes nodeRipple {
139
+ 0% { inset: -4px; opacity: 0.8; border-width: 2px; }
140
+ 100% { inset: -20px; opacity: 0; border-width: 0px; }
141
+ }
142
+ @keyframes nodeGlow {
143
+ 0%, 100% { box-shadow: 0 0 8px rgba(57,255,20,0.05); }
144
+ 50% { box-shadow: 0 0 20px rgba(57,255,20,0.15); }
145
+ }
146
+
147
+ /* Node variants */
148
+ .workflow-node.orchestrator {
149
+ min-width: 220px;
150
+ border-color: rgba(57,255,20,0.25);
151
+ background: linear-gradient(135deg, rgba(8,14,24,0.95), rgba(57,255,20,0.03));
152
+ }
153
+ .workflow-node.user-node {
154
+ border-color: rgba(68,136,255,0.25);
155
+ background: linear-gradient(135deg, rgba(8,14,24,0.95), rgba(68,136,255,0.03));
156
+ }
157
+
158
+ /* Node internals */
159
+ .node-header {
160
+ display: flex;
161
+ align-items: center;
162
+ gap: 8px;
163
+ margin-bottom: 6px;
164
+ }
165
+ .node-emoji {
166
+ font-size: 18px;
167
+ line-height: 1;
168
+ }
169
+ .node-title {
170
+ font-family: var(--font-hud);
171
+ font-size: 10px;
172
+ font-weight: 600;
173
+ letter-spacing: 1.5px;
174
+ color: var(--accent);
175
+ }
176
+ .workflow-node.user-node .node-title { color: var(--blue); }
177
+
178
+ .node-status-dot {
179
+ width: 6px; height: 6px;
180
+ border-radius: 50%;
181
+ margin-left: auto;
182
+ background: var(--dim);
183
+ transition: all 0.3s;
184
+ }
185
+ .node-status-dot.active { background: var(--accent); box-shadow: 0 0 8px var(--accent); }
186
+ .node-status-dot.idle { background: var(--dim); }
187
+
188
+ .node-body {
189
+ font-size: 10px;
190
+ color: var(--text);
191
+ line-height: 1.4;
192
+ }
193
+ .node-meta-row {
194
+ display: flex;
195
+ justify-content: space-between;
196
+ padding: 1px 0;
197
+ font-size: 9px;
198
+ }
199
+ .node-meta-row .k { color: var(--dim); }
200
+ .node-meta-row .v { color: var(--accent); font-family: var(--font-hud); font-size: 8px; }
201
+
202
+ .node-job-indicator {
203
+ margin-top: 6px;
204
+ padding: 4px 6px;
205
+ background: rgba(57,255,20,0.04);
206
+ border: 1px solid rgba(57,255,20,0.08);
207
+ font-size: 9px;
208
+ display: flex;
209
+ align-items: center;
210
+ gap: 6px;
211
+ }
212
+ .node-job-indicator .job-pulse {
213
+ width: 5px; height: 5px;
214
+ border-radius: 50%;
215
+ background: var(--accent);
216
+ box-shadow: 0 0 6px var(--accent);
217
+ animation: blink 1.5s ease-in-out infinite;
218
+ }
219
+ .node-job-indicator .job-id {
220
+ color: var(--amber);
221
+ font-family: var(--font-hud);
222
+ font-size: 8px;
223
+ letter-spacing: 0.5px;
224
+ }
225
+ .node-job-indicator .job-task {
226
+ color: var(--text);
227
+ overflow: hidden;
228
+ text-overflow: ellipsis;
229
+ white-space: nowrap;
230
+ max-width: 120px;
231
+ }
232
+
233
+ /* Node ports (anchor points for connections) */
234
+ .node-port {
235
+ position: absolute;
236
+ width: 8px; height: 8px;
237
+ border-radius: 50%;
238
+ background: rgba(57,255,20,0.15);
239
+ border: 1px solid rgba(57,255,20,0.3);
240
+ z-index: 3;
241
+ transition: all 0.3s;
242
+ }
243
+ .node-port.left { left: -4px; top: 50%; transform: translateY(-50%); }
244
+ .node-port.right { right: -4px; top: 50%; transform: translateY(-50%); }
245
+ .node-port.active {
246
+ background: var(--accent);
247
+ border-color: var(--accent);
248
+ box-shadow: 0 0 8px var(--accent);
249
+ }
250
+
251
+ /* ═══════ ZOOM CONTROLS ═══════ */
252
+ .zoom-controls {
253
+ position: absolute;
254
+ bottom: 16px;
255
+ left: 16px;
256
+ z-index: 50;
257
+ display: flex;
258
+ flex-direction: column;
259
+ gap: 2px;
260
+ }
261
+ .zoom-btn {
262
+ width: 32px; height: 32px;
263
+ background: var(--bg2);
264
+ border: 1px solid var(--panel-border);
265
+ color: var(--accent);
266
+ font-family: var(--font-hud);
267
+ font-size: 14px;
268
+ font-weight: 700;
269
+ cursor: pointer;
270
+ display: flex;
271
+ align-items: center;
272
+ justify-content: center;
273
+ transition: all 0.2s;
274
+ user-select: none;
275
+ }
276
+ .zoom-btn:hover {
277
+ background: var(--accent-bg);
278
+ border-color: var(--accent-dim);
279
+ }
280
+ .zoom-btn:active {
281
+ background: rgba(57,255,20,0.12);
282
+ }
283
+ .zoom-btn.text {
284
+ font-size: 7px;
285
+ letter-spacing: 0.5px;
286
+ }
287
+ .zoom-level {
288
+ width: 32px; height: 24px;
289
+ background: rgba(8,14,24,0.8);
290
+ border: 1px solid var(--panel-border);
291
+ display: flex;
292
+ align-items: center;
293
+ justify-content: center;
294
+ font-family: var(--font-hud);
295
+ font-size: 8px;
296
+ color: var(--dim);
297
+ letter-spacing: 0.5px;
298
+ }
299
+
300
+ /* ═══════ MINIMAP ═══════ */
301
+ .minimap {
302
+ position: absolute;
303
+ bottom: 16px;
304
+ right: 16px;
305
+ width: 160px;
306
+ height: 100px;
307
+ background: rgba(5,8,12,0.85);
308
+ border: 1px solid var(--panel-border);
309
+ z-index: 50;
310
+ overflow: hidden;
311
+ backdrop-filter: blur(4px);
312
+ }
313
+ .minimap-viewport {
314
+ position: absolute;
315
+ border: 1px solid rgba(57,255,20,0.4);
316
+ background: rgba(57,255,20,0.04);
317
+ pointer-events: none;
318
+ }
319
+ .minimap-node {
320
+ position: absolute;
321
+ background: rgba(57,255,20,0.3);
322
+ border: 1px solid rgba(57,255,20,0.5);
323
+ }
324
+ .minimap-node.active {
325
+ background: var(--accent);
326
+ box-shadow: 0 0 4px var(--accent);
327
+ }
328
+ .minimap-node.user { background: rgba(68,136,255,0.4); border-color: rgba(68,136,255,0.6); }
329
+ .minimap-node.orch { background: rgba(57,255,20,0.5); border-color: var(--accent); }
330
+
331
+ /* ═══════ DETAIL PANEL ═══════ */
332
+ .detail-panel {
333
+ position: fixed;
334
+ top: var(--topbar-h);
335
+ right: var(--rightbar-w);
336
+ bottom: 28px;
337
+ width: 360px;
338
+ background: var(--bg2);
339
+ border-left: 1px solid var(--panel-border);
340
+ z-index: 200;
341
+ transform: translateX(100%);
342
+ transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
343
+ display: flex;
344
+ flex-direction: column;
345
+ overflow: hidden;
346
+ }
347
+ .detail-panel.open {
348
+ transform: translateX(0);
349
+ }
350
+
351
+ .detail-panel-header {
352
+ display: flex;
353
+ align-items: center;
354
+ justify-content: space-between;
355
+ padding: 10px 16px;
356
+ background: linear-gradient(90deg, var(--accent-bg), transparent 70%);
357
+ border-bottom: 1px solid var(--panel-border);
358
+ flex-shrink: 0;
359
+ }
360
+ .detail-panel-title {
361
+ font-family: var(--font-hud);
362
+ font-size: 10px;
363
+ font-weight: 600;
364
+ letter-spacing: 2px;
365
+ color: var(--accent);
366
+ }
367
+ .detail-panel-close {
368
+ font-size: 18px;
369
+ color: var(--dim);
370
+ cursor: pointer;
371
+ padding: 0 4px;
372
+ transition: color 0.2s;
373
+ }
374
+ .detail-panel-close:hover { color: var(--accent); }
375
+
376
+ .detail-panel-body {
377
+ flex: 1;
378
+ padding: 12px 16px;
379
+ overflow-y: auto;
380
+ }
381
+ .detail-panel-body::-webkit-scrollbar { width: 3px; }
382
+ .detail-panel-body::-webkit-scrollbar-track { background: transparent; }
383
+ .detail-panel-body::-webkit-scrollbar-thumb { background: var(--accent-dim); border-radius: 2px; }
384
+
385
+ /* Detail panel data rows */
386
+ .detail-section {
387
+ margin-bottom: 12px;
388
+ }
389
+ .detail-section-label {
390
+ font-family: var(--font-hud);
391
+ font-size: 7px;
392
+ letter-spacing: 1.5px;
393
+ color: var(--dim);
394
+ margin-bottom: 4px;
395
+ padding-bottom: 2px;
396
+ border-bottom: 1px solid rgba(57,255,20,0.05);
397
+ }
398
+ .detail-row {
399
+ display: flex;
400
+ justify-content: space-between;
401
+ padding: 2px 0;
402
+ font-size: 10px;
403
+ }
404
+ .detail-row .k { color: var(--dim); }
405
+ .detail-row .v { color: var(--accent); text-align: right; }
406
+
407
+ .detail-tool-tag {
408
+ display: inline-block;
409
+ padding: 1px 5px;
410
+ margin: 1px 2px;
411
+ border: 1px solid rgba(57,255,20,0.12);
412
+ color: var(--accent);
413
+ font-size: 8px;
414
+ font-family: var(--font-mono);
415
+ }
416
+ .detail-cat-tag {
417
+ display: inline-block;
418
+ padding: 1px 5px;
419
+ margin: 1px 2px;
420
+ border: 1px solid rgba(255,0,255,0.15);
421
+ color: var(--magenta);
422
+ font-size: 8px;
423
+ font-family: var(--font-hud);
424
+ letter-spacing: 0.5px;
425
+ }
426
+
427
+ .detail-job-item {
428
+ padding: 6px 0;
429
+ border-bottom: 1px solid rgba(57,255,20,0.03);
430
+ }
431
+ .detail-job-item:last-child { border-bottom: none; }
432
+ .detail-job-meta {
433
+ display: flex;
434
+ gap: 6px;
435
+ align-items: center;
436
+ flex-wrap: wrap;
437
+ }
438
+ .detail-job-task {
439
+ font-size: 10px;
440
+ color: var(--text);
441
+ margin-top: 2px;
442
+ overflow: hidden;
443
+ text-overflow: ellipsis;
444
+ white-space: nowrap;
445
+ }
446
+ .detail-job-sub {
447
+ font-size: 9px;
448
+ color: var(--dim);
449
+ margin-top: 1px;
450
+ }
451
+
452
+ /* ═══════ RESPONSIVE ═══════ */
453
+ @media (max-width: 1100px) {
454
+ .detail-panel {
455
+ right: 0;
456
+ width: 320px;
457
+ }
458
+ .workflow-node { min-width: 150px; }
459
+ .workflow-node.orchestrator { min-width: 180px; }
460
+ .minimap { display: none; }
461
+ }
462
+ @media (max-width: 768px) {
463
+ .detail-panel { width: 100%; right: 0; }
464
+ .workflow-node { min-width: 130px; padding: 8px 10px; }
465
+ .agents-stats-bar { gap: 16px; padding: 8px 12px; }
466
+ .agents-stat-val { font-size: 13px; }
467
+ .zoom-controls { bottom: 8px; left: 8px; }
468
+ .minimap { display: none; }
469
+ }
@@ -0,0 +1,184 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>KERNEL // Agent Topology</title>
7
+ <link rel="stylesheet" href="shared.css">
8
+ <link rel="stylesheet" href="agents.css">
9
+ </head>
10
+ <body>
11
+
12
+ <canvas id="particle-canvas"></canvas>
13
+ <div class="scanlines"></div>
14
+
15
+ <!-- ═══════ SIDEBAR ═══════ -->
16
+ <nav class="sidebar">
17
+ <div class="sidebar-logo">
18
+ <svg viewBox="0 0 32 32" shape-rendering="crispEdges">
19
+ <path fill="rgba(57,255,20,0.35)" d="M10,2h10v2h-10z M8,4h2v2h-2z M6,6h2v4h-2z M4,10h2v8h-2z M6,18h2v2h-2z M8,20h2v2h-2z M10,22h14v2h-14z M24,18h2v4h-2z M26,8h2v10h-2z M24,6h2v2h-2z"/>
20
+ <path fill="rgba(57,255,20,0.6)" d="M12,8h8v2h-8z M10,10h2v10h-2z M20,10h2v6h-2z M18,18h2v2h-2z M12,20h6v2h-6z"/>
21
+ <path fill="#39ff14" d="M14,14h4v2h-2v2h-2z"/>
22
+ </svg>
23
+ </div>
24
+
25
+ <div class="sidebar-nav">
26
+ <a class="nav-item" href="/" title="Dashboard">
27
+ <svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 3"/></svg>
28
+ <span class="nav-label">DASH</span>
29
+ </a>
30
+ <a class="nav-item active" href="/agents.html" title="Agents">
31
+ <svg viewBox="0 0 24 24"><circle cx="12" cy="5" r="3"/><circle cx="5" cy="19" r="3"/><circle cx="19" cy="19" r="3"/><path d="M12 8v4M7.5 17.2l3-4.2M16.5 17.2l-3-4.2"/></svg>
32
+ <span class="nav-label">AGENTS</span>
33
+ </a>
34
+ </div>
35
+
36
+ <!-- Sidebar mini gauges -->
37
+ <div class="sidebar-gauges">
38
+ <div class="mini-gauge" id="sb-cpu">
39
+ <svg viewBox="0 0 38 38"><circle class="track" cx="19" cy="19" r="16"/><circle class="fill" cx="19" cy="19" r="16" stroke-dasharray="100.5" stroke-dashoffset="100.5"/></svg>
40
+ <div class="mini-gauge-label"><span class="val">--%</span><span class="lbl">CPU</span></div>
41
+ </div>
42
+ <div class="mini-gauge" id="sb-ram">
43
+ <svg viewBox="0 0 38 38"><circle class="track" cx="19" cy="19" r="16"/><circle class="fill" cx="19" cy="19" r="16" stroke-dasharray="100.5" stroke-dashoffset="100.5"/></svg>
44
+ <div class="mini-gauge-label"><span class="val">--%</span><span class="lbl">RAM</span></div>
45
+ </div>
46
+ <div class="sidebar-conn connected" id="conn-dot"></div>
47
+ </div>
48
+ </nav>
49
+
50
+ <!-- ═══════ TOP BAR ═══════ -->
51
+ <header class="top-bar">
52
+ <div class="top-bar-left">
53
+ <span class="top-bar-title">KernelBot</span>
54
+ <span class="top-bar-sep">//</span>
55
+ <span class="top-bar-nav">
56
+ <a class="top-bar-nav-item" href="/">DASHBOARD</a>
57
+ <a class="top-bar-nav-item active" href="/agents.html">AGENTS</a>
58
+ </span>
59
+ </div>
60
+ <div class="top-bar-right">
61
+ <span class="top-bar-conn" id="top-conn"></span>
62
+ <span><span class="val" id="hdr-status">ONLINE</span></span>
63
+ <span class="sep">//</span>
64
+ <span>UP <span class="val" id="hdr-uptime">--</span></span>
65
+ <span class="sep">//</span>
66
+ <span class="val" id="hdr-clock">--</span>
67
+ </div>
68
+ </header>
69
+
70
+ <!-- ═══════ RIGHT BAR ═══════ -->
71
+ <aside class="right-bar">
72
+ <div class="right-stat" title="Running Jobs">
73
+ <span class="r-val zero" id="rb-jobs">0</span>
74
+ <span class="r-lbl">RUNNING</span>
75
+ </div>
76
+ <div class="right-divider"></div>
77
+ <div class="right-stat" title="Total Jobs">
78
+ <span class="r-val zero" id="rb-total-jobs">0</span>
79
+ <span class="r-lbl">TOTAL</span>
80
+ </div>
81
+ <div class="right-divider"></div>
82
+ <div class="right-stat" title="Completed">
83
+ <span class="r-val zero" id="rb-completed">0</span>
84
+ <span class="r-lbl">DONE</span>
85
+ </div>
86
+ <div class="right-divider"></div>
87
+ <div class="right-stat" title="Failed">
88
+ <span class="r-val zero" id="rb-failed">0</span>
89
+ <span class="r-lbl">FAIL</span>
90
+ </div>
91
+ <div class="right-divider"></div>
92
+ <div class="right-stat" title="Worker Types">
93
+ <span class="r-val" id="rb-workers">6</span>
94
+ <span class="r-lbl">TYPES</span>
95
+ </div>
96
+ <div class="right-bar-clock" id="rb-clock">--:--</div>
97
+ </aside>
98
+
99
+ <!-- ═══════ MAIN ═══════ -->
100
+ <div class="main">
101
+
102
+ <!-- Hero bar -->
103
+ <div class="hero-bar">
104
+ <canvas id="waveform-canvas"></canvas>
105
+ <div class="hero-pulse">
106
+ <div class="pulse-stat">
107
+ <span class="pulse-label">ORCHESTRATOR</span>
108
+ <span class="pulse-val" id="pulse-orch">--</span>
109
+ </div>
110
+ <div class="pulse-stat">
111
+ <span class="pulse-label">WORKER BRAIN</span>
112
+ <span class="pulse-val" id="pulse-brain">--</span>
113
+ </div>
114
+ <div class="pulse-stat">
115
+ <span class="pulse-label">ACTIVE JOBS</span>
116
+ <span class="pulse-val idle" id="pulse-jobs">0</span>
117
+ </div>
118
+ <div class="pulse-stat">
119
+ <span class="pulse-label">WORKER TYPES</span>
120
+ <span class="pulse-val" id="pulse-workers">6</span>
121
+ </div>
122
+ </div>
123
+ </div>
124
+
125
+ <!-- Stats summary bar -->
126
+ <div class="agents-stats-bar" id="agents-stats-bar">
127
+ <div class="agents-stat"><span class="agents-stat-val" id="stat-running">0</span><span class="agents-stat-lbl">RUNNING</span></div>
128
+ <div class="agents-stat"><span class="agents-stat-val" id="stat-queued">0</span><span class="agents-stat-lbl">QUEUED</span></div>
129
+ <div class="agents-stat"><span class="agents-stat-val completed" id="stat-completed">0</span><span class="agents-stat-lbl">COMPLETED</span></div>
130
+ <div class="agents-stat"><span class="agents-stat-val failed" id="stat-failed">0</span><span class="agents-stat-lbl">FAILED</span></div>
131
+ <div class="agents-stat"><span class="agents-stat-val" id="stat-total-tools">0</span><span class="agents-stat-lbl">TOTAL TOOLS</span></div>
132
+ </div>
133
+
134
+ <!-- Workflow container (pan/zoom) -->
135
+ <div class="workflow-container" id="workflow-container">
136
+ <div class="workflow-canvas" id="workflow-canvas">
137
+ <svg class="workflow-svg" id="workflow-svg">
138
+ <defs>
139
+ <marker id="arrow" viewBox="0 0 10 6" refX="10" refY="3" markerWidth="8" markerHeight="6" orient="auto-start-reverse">
140
+ <path d="M 0 0 L 10 3 L 0 6 z" fill="rgba(57,255,20,0.4)"/>
141
+ </marker>
142
+ <marker id="arrow-active" viewBox="0 0 10 6" refX="10" refY="3" markerWidth="8" markerHeight="6" orient="auto-start-reverse">
143
+ <path d="M 0 0 L 10 3 L 0 6 z" fill="#39ff14"/>
144
+ </marker>
145
+ </defs>
146
+ </svg>
147
+ <div id="workflow-nodes"></div>
148
+ </div>
149
+
150
+ <!-- Zoom controls -->
151
+ <div class="zoom-controls">
152
+ <div class="zoom-btn" id="zoom-in" title="Zoom In">+</div>
153
+ <div class="zoom-level" id="zoom-level">100%</div>
154
+ <div class="zoom-btn" id="zoom-out" title="Zoom Out">&minus;</div>
155
+ <div class="zoom-btn text" id="zoom-fit" title="Fit to View">FIT</div>
156
+ </div>
157
+
158
+ <!-- Minimap -->
159
+ <div class="minimap" id="minimap">
160
+ <div class="minimap-viewport" id="minimap-viewport"></div>
161
+ </div>
162
+ </div>
163
+
164
+ </div>
165
+
166
+ <!-- Detail slide-out panel -->
167
+ <div class="detail-panel" id="detail-panel">
168
+ <div class="detail-panel-header">
169
+ <span class="detail-panel-title" id="detail-title">--</span>
170
+ <span class="detail-panel-close" id="detail-close">&times;</span>
171
+ </div>
172
+ <div class="detail-panel-body" id="detail-body"></div>
173
+ </div>
174
+
175
+ <!-- Scrolling log ticker (sticky bottom) -->
176
+ <div class="log-ticker" id="log-ticker">
177
+ <div class="ticker-label"><span class="dot-pulse"></span>LIVE</div>
178
+ <div class="ticker-track" id="ticker-track"></div>
179
+ </div>
180
+
181
+ <script src="shared.js"></script>
182
+ <script src="agents.js"></script>
183
+ </body>
184
+ </html>