agentflow-dashboard 0.7.1 → 0.8.1

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.
@@ -1,1385 +0,0 @@
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>AgentFlow Dashboard</title>
7
- <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
8
- <meta http-equiv="Pragma" content="no-cache">
9
- <script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.28.1/cytoscape.min.js"></script>
10
- <style>
11
- :root {
12
- --bg-primary: #0d1117;
13
- --bg-secondary: #161b22;
14
- --bg-tertiary: #21262d;
15
- --text-primary: #c9d1d9;
16
- --text-secondary: #8b949e;
17
- --accent-primary: #58a6ff;
18
- --accent-success: #238636;
19
- --accent-error: #da3633;
20
- --accent-warning: #f0883e;
21
- --border-color: #30363d;
22
- }
23
-
24
- * { margin: 0; padding: 0; box-sizing: border-box; }
25
-
26
- body {
27
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
28
- background: var(--bg-primary);
29
- color: var(--text-primary);
30
- min-height: 100vh;
31
- overflow: hidden;
32
- }
33
-
34
- /* Header */
35
- .header {
36
- background: var(--bg-secondary);
37
- border-bottom: 1px solid var(--border-color);
38
- padding: 0.75rem 1.5rem;
39
- display: flex;
40
- justify-content: space-between;
41
- align-items: center;
42
- height: 56px;
43
- z-index: 100;
44
- }
45
- .header h1 {
46
- font-size: 1.35rem;
47
- font-weight: 600;
48
- display: flex;
49
- align-items: center;
50
- gap: 0.5rem;
51
- }
52
- .header h1 span { color: var(--accent-primary); }
53
- .header-right {
54
- display: flex;
55
- align-items: center;
56
- gap: 1rem;
57
- }
58
- .connection-status {
59
- display: flex;
60
- align-items: center;
61
- gap: 0.5rem;
62
- font-size: 0.8rem;
63
- color: var(--text-secondary);
64
- }
65
- .status-dot {
66
- width: 8px;
67
- height: 8px;
68
- border-radius: 50%;
69
- background: var(--accent-error);
70
- transition: background 0.3s;
71
- }
72
- .status-dot.connected {
73
- background: var(--accent-success);
74
- animation: pulse 2s infinite;
75
- }
76
- @keyframes pulse {
77
- 0%, 100% { opacity: 1; }
78
- 50% { opacity: 0.5; }
79
- }
80
-
81
- /* Layout */
82
- .container {
83
- display: flex;
84
- height: calc(100vh - 56px);
85
- }
86
-
87
- /* Sidebar */
88
- .sidebar {
89
- width: 280px;
90
- min-width: 280px;
91
- background: var(--bg-secondary);
92
- border-right: 1px solid var(--border-color);
93
- display: flex;
94
- flex-direction: column;
95
- overflow: hidden;
96
- }
97
- .sidebar-header {
98
- padding: 0.75rem 1rem;
99
- border-bottom: 1px solid var(--border-color);
100
- }
101
- .sidebar-header h3 {
102
- font-size: 0.75rem;
103
- text-transform: uppercase;
104
- letter-spacing: 0.5px;
105
- color: var(--text-secondary);
106
- margin-bottom: 0.5rem;
107
- }
108
- .search-box {
109
- position: relative;
110
- }
111
- .search-box input {
112
- width: 100%;
113
- padding: 0.5rem 0.75rem;
114
- padding-left: 2rem;
115
- background: var(--bg-tertiary);
116
- border: 1px solid var(--border-color);
117
- border-radius: 6px;
118
- color: var(--text-primary);
119
- font-size: 0.8rem;
120
- outline: none;
121
- }
122
- .search-box input:focus {
123
- border-color: var(--accent-primary);
124
- }
125
- .search-box::before {
126
- content: "\1F50D";
127
- position: absolute;
128
- left: 0.5rem;
129
- top: 50%;
130
- transform: translateY(-50%);
131
- font-size: 0.75rem;
132
- opacity: 0.5;
133
- }
134
-
135
- /* Sidebar filters */
136
- .sidebar-filters {
137
- padding: 0.5rem 1rem;
138
- border-bottom: 1px solid var(--border-color);
139
- display: flex;
140
- flex-direction: column;
141
- gap: 0.5rem;
142
- }
143
- .filter-row {
144
- display: flex;
145
- gap: 0.5rem;
146
- }
147
- .filter-group {
148
- flex: 1;
149
- }
150
- .filter-group label {
151
- display: block;
152
- font-size: 0.65rem;
153
- color: var(--text-secondary);
154
- margin-bottom: 0.15rem;
155
- text-transform: uppercase;
156
- letter-spacing: 0.5px;
157
- }
158
- .filter-group select {
159
- width: 100%;
160
- padding: 0.25rem 0.4rem;
161
- background: var(--bg-tertiary);
162
- border: 1px solid var(--border-color);
163
- border-radius: 4px;
164
- color: var(--text-primary);
165
- font-size: 0.75rem;
166
- outline: none;
167
- }
168
- .filter-group select:focus {
169
- border-color: var(--accent-primary);
170
- }
171
-
172
- /* Trace list */
173
- .trace-list {
174
- flex: 1;
175
- overflow-y: auto;
176
- padding: 0.25rem 0;
177
- }
178
- .trace-list::-webkit-scrollbar { width: 6px; }
179
- .trace-list::-webkit-scrollbar-track { background: transparent; }
180
- .trace-list::-webkit-scrollbar-thumb { background: var(--border-color); border-radius: 3px; }
181
-
182
- .session-item {
183
- padding: 0.6rem 1rem;
184
- cursor: pointer;
185
- border-left: 3px solid transparent;
186
- border-bottom: 1px solid rgba(48, 54, 61, 0.5);
187
- transition: all 0.15s;
188
- }
189
- .session-item:hover {
190
- background: var(--bg-tertiary);
191
- }
192
- .session-item.active {
193
- background: var(--bg-tertiary);
194
- border-left-color: var(--accent-primary);
195
- }
196
- .session-id {
197
- font-size: 0.8rem;
198
- font-weight: 500;
199
- white-space: nowrap;
200
- overflow: hidden;
201
- text-overflow: ellipsis;
202
- margin-bottom: 0.2rem;
203
- }
204
- .session-meta {
205
- display: flex;
206
- justify-content: space-between;
207
- align-items: center;
208
- font-size: 0.7rem;
209
- color: var(--text-secondary);
210
- gap: 0.5rem;
211
- }
212
- .session-agent {
213
- color: var(--accent-primary);
214
- white-space: nowrap;
215
- overflow: hidden;
216
- text-overflow: ellipsis;
217
- }
218
-
219
- .badge {
220
- display: inline-flex;
221
- align-items: center;
222
- padding: 0.1rem 0.45rem;
223
- border-radius: 12px;
224
- font-size: 0.65rem;
225
- font-weight: 500;
226
- flex-shrink: 0;
227
- }
228
- .badge-success {
229
- background: rgba(35, 134, 54, 0.2);
230
- color: #3fb950;
231
- }
232
- .badge-error {
233
- background: rgba(218, 54, 51, 0.2);
234
- color: #f85149;
235
- }
236
- .badge-running {
237
- background: rgba(88, 166, 255, 0.2);
238
- color: var(--accent-primary);
239
- }
240
- .badge-unknown {
241
- background: rgba(139, 148, 158, 0.2);
242
- color: var(--text-secondary);
243
- }
244
-
245
- /* Node type badges */
246
- .badge-type {
247
- font-size: 0.6rem;
248
- padding: 0.05rem 0.35rem;
249
- border-radius: 8px;
250
- font-weight: 600;
251
- letter-spacing: 0.02em;
252
- }
253
- .badge-agent {
254
- background: rgba(88, 166, 255, 0.15);
255
- color: #79b8ff;
256
- }
257
- .badge-tool {
258
- background: rgba(240, 136, 62, 0.15);
259
- color: #f0883e;
260
- }
261
- .badge-subagent {
262
- background: rgba(188, 140, 255, 0.15);
263
- color: #bc8cff;
264
- }
265
- .badge-other, .badge-custom, .badge-wait, .badge-decision, .badge-exec {
266
- background: rgba(139, 148, 158, 0.15);
267
- color: #8b949e;
268
- }
269
- .badge-unknown {
270
- background: rgba(139, 148, 158, 0.1);
271
- color: #6e7681;
272
- }
273
-
274
- .trace-count-badge {
275
- padding: 0.5rem 1rem;
276
- font-size: 0.75rem;
277
- color: var(--text-secondary);
278
- border-top: 1px solid var(--border-color);
279
- background: var(--bg-secondary);
280
- text-align: center;
281
- }
282
-
283
- /* Main content */
284
- .main-content {
285
- flex: 1;
286
- display: flex;
287
- flex-direction: column;
288
- overflow: hidden;
289
- min-width: 0;
290
- }
291
-
292
- /* Stats overview */
293
- .stats-overview {
294
- display: grid;
295
- grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
296
- gap: 0.75rem;
297
- padding: 0.75rem 1rem;
298
- border-bottom: 1px solid var(--border-color);
299
- background: var(--bg-secondary);
300
- }
301
- .stat-card-mini {
302
- padding: 0.4rem 0.6rem;
303
- }
304
- .stat-card-mini .metric-label { font-size: 0.65rem; margin-bottom: 0.15rem; }
305
- .stat-card-mini .metric-value { font-size: 1.2rem; }
306
-
307
- /* Tabs */
308
- .tabs {
309
- display: flex;
310
- background: var(--bg-secondary);
311
- border-bottom: 1px solid var(--border-color);
312
- padding: 0 1rem;
313
- gap: 0;
314
- overflow-x: auto;
315
- }
316
- .tab {
317
- padding: 0.7rem 1rem;
318
- font-size: 0.8rem;
319
- color: var(--text-secondary);
320
- cursor: pointer;
321
- border-bottom: 2px solid transparent;
322
- transition: all 0.15s;
323
- white-space: nowrap;
324
- user-select: none;
325
- }
326
- .tab:hover { color: var(--text-primary); }
327
- .tab.active {
328
- color: var(--accent-primary);
329
- border-bottom-color: var(--accent-primary);
330
- }
331
-
332
- /* Toolbar */
333
- .toolbar {
334
- display: flex;
335
- justify-content: space-between;
336
- align-items: center;
337
- padding: 0.5rem 1rem;
338
- background: var(--bg-secondary);
339
- border-bottom: 1px solid var(--border-color);
340
- min-height: 40px;
341
- }
342
- .toolbar-group {
343
- display: flex;
344
- gap: 0.5rem;
345
- align-items: center;
346
- }
347
- .toolbar-info {
348
- font-size: 0.75rem;
349
- color: var(--text-secondary);
350
- }
351
- .btn {
352
- padding: 0.3rem 0.7rem;
353
- border-radius: 6px;
354
- font-size: 0.8rem;
355
- cursor: pointer;
356
- border: 1px solid var(--border-color);
357
- background: var(--bg-tertiary);
358
- color: var(--text-primary);
359
- transition: all 0.15s;
360
- white-space: nowrap;
361
- }
362
- .btn:hover {
363
- border-color: var(--accent-primary);
364
- background: rgba(88, 166, 255, 0.1);
365
- }
366
- .btn-primary {
367
- background: var(--accent-primary);
368
- color: #fff;
369
- border-color: var(--accent-primary);
370
- }
371
- .btn-primary:hover { background: #79b8ff; }
372
- .btn-icon {
373
- padding: 0.3rem;
374
- }
375
-
376
- .live-indicator {
377
- display: flex;
378
- align-items: center;
379
- gap: 0.4rem;
380
- font-size: 0.8rem;
381
- color: var(--text-secondary);
382
- }
383
- .live-indicator.active {
384
- color: var(--accent-error);
385
- }
386
- .live-indicator .live-dot {
387
- font-size: 0.7rem;
388
- }
389
-
390
- /* Alert Panel */
391
- .alert-panel {
392
- background: rgba(218, 54, 51, 0.1);
393
- border: 1px solid var(--accent-error);
394
- border-radius: 0;
395
- padding: 0.75rem 1rem;
396
- display: none;
397
- font-size: 0.8rem;
398
- }
399
- .alert-panel.show {
400
- display: block;
401
- }
402
- .alert-panel ul {
403
- margin: 0.3rem 0 0 1.2rem;
404
- font-size: 0.75rem;
405
- }
406
-
407
- /* Content area */
408
- .content-area {
409
- flex: 1;
410
- overflow: auto;
411
- position: relative;
412
- }
413
- .tab-panel {
414
- display: none;
415
- height: 100%;
416
- }
417
- .tab-panel.active {
418
- display: flex;
419
- flex-direction: column;
420
- }
421
-
422
- /* Graph */
423
- #cy {
424
- flex: 1;
425
- min-height: 0;
426
- background: var(--bg-primary);
427
- }
428
-
429
- /* Empty / placeholder states */
430
- .empty-state {
431
- display: flex;
432
- flex-direction: column;
433
- align-items: center;
434
- justify-content: center;
435
- height: 100%;
436
- color: var(--text-secondary);
437
- gap: 0.75rem;
438
- padding: 2rem;
439
- }
440
- .empty-state-icon {
441
- font-size: 2.5rem;
442
- opacity: 0.4;
443
- }
444
- .empty-state-title {
445
- font-size: 1.1rem;
446
- font-weight: 500;
447
- color: var(--text-primary);
448
- }
449
- .empty-state-text {
450
- font-size: 0.85rem;
451
- text-align: center;
452
- max-width: 360px;
453
- }
454
-
455
- /* Node detail panel */
456
- .node-detail-panel {
457
- position: absolute;
458
- top: 1rem;
459
- right: 1rem;
460
- width: 320px;
461
- background: var(--bg-secondary);
462
- border: 1px solid var(--border-color);
463
- border-radius: 8px;
464
- z-index: 50;
465
- display: none;
466
- box-shadow: 0 8px 32px rgba(0,0,0,0.4);
467
- max-height: calc(100% - 2rem);
468
- overflow-y: auto;
469
- }
470
- .node-detail-panel.active { display: block; }
471
- .node-detail-header {
472
- display: flex;
473
- justify-content: space-between;
474
- align-items: center;
475
- padding: 0.75rem 1rem;
476
- border-bottom: 1px solid var(--border-color);
477
- }
478
- .node-detail-header h4 { font-size: 0.9rem; }
479
- .node-detail-close {
480
- background: none;
481
- border: none;
482
- color: var(--text-secondary);
483
- cursor: pointer;
484
- font-size: 1.2rem;
485
- padding: 0.25rem;
486
- line-height: 1;
487
- }
488
- .node-detail-close:hover { color: var(--text-primary); }
489
- .node-detail-body { padding: 0.75rem 1rem; }
490
- .detail-row {
491
- display: flex;
492
- justify-content: space-between;
493
- align-items: flex-start;
494
- padding: 0.4rem 0;
495
- border-bottom: 1px solid rgba(48, 54, 61, 0.4);
496
- font-size: 0.8rem;
497
- }
498
- .detail-row:last-child { border-bottom: none; }
499
- .detail-label { color: var(--text-secondary); min-width: 80px; }
500
- .detail-value {
501
- color: var(--text-primary);
502
- text-align: right;
503
- word-break: break-all;
504
- font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
505
- font-size: 0.75rem;
506
- }
507
- .detail-value.status-completed { color: var(--accent-success); }
508
- .detail-value.status-failed { color: var(--accent-error); }
509
- .detail-value.status-running { color: var(--accent-primary); }
510
- .detail-value.status-hung { color: var(--accent-warning); }
511
- .detail-value.status-timeout { color: var(--accent-warning); }
512
- .detail-metadata {
513
- margin-top: 0.5rem;
514
- padding: 0.5rem;
515
- background: var(--bg-tertiary);
516
- border-radius: 4px;
517
- font-size: 0.7rem;
518
- font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
519
- color: var(--text-secondary);
520
- max-height: 200px;
521
- overflow-y: auto;
522
- white-space: pre-wrap;
523
- word-break: break-all;
524
- }
525
-
526
- /* Timeline view */
527
- .timeline-container {
528
- padding: 1rem;
529
- overflow-y: auto;
530
- flex: 1;
531
- }
532
- .timeline-item {
533
- display: flex;
534
- margin-bottom: 0.75rem;
535
- padding: 0.75rem 1rem;
536
- background: var(--bg-secondary);
537
- border: 1px solid var(--border-color);
538
- border-radius: 8px;
539
- transition: all 0.2s;
540
- }
541
- .timeline-item:hover {
542
- border-color: var(--accent-primary);
543
- }
544
- .timeline-marker {
545
- width: 12px;
546
- height: 12px;
547
- border-radius: 50%;
548
- margin-right: 1rem;
549
- flex-shrink: 0;
550
- margin-top: 0.2rem;
551
- }
552
- .timeline-marker.agent { background: var(--accent-primary); }
553
- .timeline-marker.tool { background: var(--accent-warning); }
554
- .timeline-marker.subagent { background: #a371f7; }
555
- .timeline-marker.completed { background: var(--accent-success); }
556
- .timeline-marker.failed { background: var(--accent-error); }
557
- .timeline-marker.running { background: var(--accent-primary); }
558
- .timeline-marker.hung, .timeline-marker.timeout { background: var(--accent-warning); }
559
-
560
- .timeline-content {
561
- flex: 1;
562
- min-width: 0;
563
- }
564
- .timeline-header {
565
- display: flex;
566
- justify-content: space-between;
567
- margin-bottom: 0.35rem;
568
- }
569
- .event-type {
570
- font-weight: 500;
571
- font-size: 0.85rem;
572
- }
573
- .event-time {
574
- font-size: 0.7rem;
575
- color: var(--text-secondary);
576
- font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
577
- }
578
- .event-details {
579
- font-size: 0.8rem;
580
- color: var(--text-secondary);
581
- }
582
- .event-duration {
583
- display: inline-block;
584
- margin-top: 0.25rem;
585
- font-size: 0.7rem;
586
- padding: 0.1rem 0.4rem;
587
- background: var(--bg-tertiary);
588
- border-radius: 4px;
589
- font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
590
- color: var(--text-secondary);
591
- }
592
-
593
- /* Metrics view */
594
- .metrics-container {
595
- padding: 1rem;
596
- overflow-y: auto;
597
- flex: 1;
598
- }
599
- .metrics-grid {
600
- display: grid;
601
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
602
- gap: 1rem;
603
- margin-bottom: 1.5rem;
604
- }
605
- .metric-card {
606
- background: var(--bg-secondary);
607
- border: 1px solid var(--border-color);
608
- border-radius: 8px;
609
- padding: 1rem 1.25rem;
610
- }
611
- .metric-label {
612
- font-size: 0.7rem;
613
- text-transform: uppercase;
614
- letter-spacing: 0.5px;
615
- color: var(--text-secondary);
616
- margin-bottom: 0.4rem;
617
- }
618
- .metric-value {
619
- font-size: 1.75rem;
620
- font-weight: 700;
621
- }
622
- .metric-value.primary { color: var(--accent-primary); }
623
- .metric-value.success { color: var(--accent-success); }
624
- .metric-value.error { color: var(--accent-error); }
625
- .metric-value.warning { color: var(--accent-warning); }
626
- .metric-sub {
627
- font-size: 0.7rem;
628
- color: var(--text-secondary);
629
- margin-top: 0.2rem;
630
- }
631
-
632
- /* Process health */
633
- .process-health-section {
634
- padding: 0.75rem 1rem;
635
- border-bottom: 1px solid var(--border-color);
636
- background: var(--bg-secondary);
637
- }
638
- .process-health-section h4 {
639
- font-size: 0.7rem;
640
- text-transform: uppercase;
641
- letter-spacing: 0.05em;
642
- color: var(--text-secondary);
643
- margin-bottom: 0.5rem;
644
- }
645
- .ph-row {
646
- display: flex;
647
- align-items: center;
648
- gap: 0.75rem;
649
- margin-bottom: 0.35rem;
650
- font-size: 0.75rem;
651
- }
652
- .ph-label {
653
- color: var(--text-secondary);
654
- min-width: 70px;
655
- }
656
- .ph-value {
657
- color: var(--text-primary);
658
- font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
659
- font-size: 0.75rem;
660
- }
661
- .ph-value.ok { color: var(--accent-success); }
662
- .ph-value.warn { color: var(--accent-warning); }
663
- .ph-value.bad { color: var(--accent-error); }
664
- .worker-dots { display: flex; gap: 4px; align-items: center; flex-wrap: wrap; }
665
- .worker-dot {
666
- width: 8px;
667
- height: 8px;
668
- border-radius: 50%;
669
- }
670
- .worker-dot.alive { background: var(--accent-success); }
671
- .worker-dot.stale { background: var(--accent-error); }
672
- .worker-dot.unknown { background: var(--text-secondary); }
673
- .worker-dot-label { font-size: 0.65rem; color: var(--text-secondary); margin-left: 1px; }
674
- .orphan-table {
675
- width: 100%;
676
- border-collapse: collapse;
677
- font-size: 0.7rem;
678
- font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
679
- margin-top: 0.5rem;
680
- }
681
- .orphan-table th {
682
- text-align: left;
683
- color: var(--text-secondary);
684
- font-weight: 500;
685
- padding: 0.3rem 0.5rem;
686
- border-bottom: 1px solid var(--border-color);
687
- }
688
- .orphan-table td {
689
- padding: 0.25rem 0.5rem;
690
- color: var(--text-primary);
691
- border-bottom: 1px solid rgba(48,54,61,0.4);
692
- white-space: nowrap;
693
- overflow: hidden;
694
- text-overflow: ellipsis;
695
- max-width: 250px;
696
- }
697
- .orphan-table tr:hover td { background: var(--bg-tertiary); }
698
- .problems-list {
699
- list-style: none;
700
- padding: 0;
701
- margin: 0.3rem 0 0 0;
702
- }
703
- .problems-list li {
704
- font-size: 0.7rem;
705
- color: var(--accent-error);
706
- padding: 0.15rem 0;
707
- }
708
- .problems-list li::before {
709
- content: "\2022";
710
- margin-right: 0.4rem;
711
- }
712
-
713
- /* Enhanced Process Health */
714
- .ph-service {
715
- margin-bottom: 1rem;
716
- padding: 0.6rem 0.8rem;
717
- border: 1px solid var(--border-color, #30363d);
718
- border-radius: 6px;
719
- }
720
- .ph-service-name {
721
- font-weight: 600;
722
- font-size: 0.95rem;
723
- margin-bottom: 0.4rem;
724
- color: var(--fg-primary, #e6edf3);
725
- text-transform: capitalize;
726
- }
727
- .ph-section {
728
- margin-bottom: 1rem;
729
- }
730
- .process-grid {
731
- display: grid;
732
- grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
733
- gap: 0.4rem;
734
- margin-top: 0.5rem;
735
- }
736
-
737
- /* Worker cards */
738
- .worker-card {
739
- background: var(--bg-tertiary);
740
- border-radius: 4px;
741
- padding: 0.5rem;
742
- border-left: 3px solid var(--border-color);
743
- }
744
- .worker-card.ok { border-left-color: var(--accent-success); }
745
- .worker-card.warn { border-left-color: var(--accent-warning); }
746
- .worker-card.bad { border-left-color: var(--accent-error); }
747
- .worker-name {
748
- font-weight: 600;
749
- font-size: 0.75rem;
750
- margin-bottom: 0.25rem;
751
- }
752
- .worker-details {
753
- display: flex;
754
- flex-direction: column;
755
- gap: 0.1rem;
756
- font-size: 0.65rem;
757
- color: var(--text-secondary);
758
- }
759
-
760
- /* Service cards */
761
- .service-card, .infra-card {
762
- background: var(--bg-tertiary);
763
- border-radius: 4px;
764
- padding: 0.5rem;
765
- border-left: 3px solid var(--border-color);
766
- }
767
- .service-card.low, .infra-card.low { border-left-color: var(--accent-success); }
768
- .service-card.medium, .infra-card.medium { border-left-color: var(--accent-warning); }
769
- .service-card.high, .infra-card.high { border-left-color: var(--accent-error); }
770
- .service-name, .infra-name {
771
- font-weight: 600;
772
- font-size: 0.75rem;
773
- margin-bottom: 0.25rem;
774
- }
775
- .service-details, .infra-details {
776
- display: grid;
777
- grid-template-columns: 1fr 1fr;
778
- gap: 0.1rem 0.5rem;
779
- font-size: 0.65rem;
780
- color: var(--text-secondary);
781
- }
782
-
783
- /* Process Tree View */
784
- .process-tree {
785
- margin-top: 0.5rem;
786
- font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
787
- }
788
- .process-node {
789
- display: flex;
790
- align-items: center;
791
- padding: 0.3rem 0.5rem;
792
- margin-bottom: 0.2rem;
793
- background: var(--bg-tertiary);
794
- border-radius: 4px;
795
- border-left: 3px solid var(--border-color);
796
- transition: all 0.2s ease;
797
- }
798
- .process-node:hover {
799
- background: var(--bg-secondary);
800
- }
801
- .process-node.agent-node.low { border-left-color: var(--accent-success); }
802
- .process-node.agent-node.medium { border-left-color: var(--accent-warning); }
803
- .process-node.agent-node.high { border-left-color: var(--accent-error); }
804
- .process-node.infrastructure-node.low { border-left-color: var(--accent-success); }
805
- .process-node.infrastructure-node.medium { border-left-color: var(--accent-warning); }
806
- .process-node.infrastructure-node.high { border-left-color: var(--accent-error); }
807
-
808
- .tree-connector {
809
- color: var(--text-secondary);
810
- font-weight: 400;
811
- margin-right: 0.3rem;
812
- }
813
- .process-main {
814
- display: flex;
815
- align-items: center;
816
- justify-content: space-between;
817
- width: 100%;
818
- min-height: 1.5rem;
819
- }
820
- .process-name {
821
- font-weight: 600;
822
- font-size: 0.75rem;
823
- color: var(--text-primary);
824
- flex: 1;
825
- }
826
- .process-metrics {
827
- display: flex;
828
- gap: 0.4rem;
829
- align-items: center;
830
- }
831
- .pid-badge, .cpu-badge, .mem-badge, .time-badge {
832
- font-size: 0.65rem;
833
- padding: 0.1rem 0.3rem;
834
- border-radius: 3px;
835
- font-family: monospace;
836
- }
837
- .pid-badge {
838
- background: var(--accent-primary);
839
- color: var(--bg-primary);
840
- font-weight: 600;
841
- }
842
- .cpu-badge {
843
- background: var(--bg-primary);
844
- color: var(--accent-warning);
845
- border: 1px solid var(--border-color);
846
- }
847
- .mem-badge {
848
- background: var(--bg-primary);
849
- color: var(--accent-primary);
850
- border: 1px solid var(--border-color);
851
- }
852
- .time-badge {
853
- background: var(--bg-primary);
854
- color: var(--text-secondary);
855
- border: 1px solid var(--border-color);
856
- }
857
-
858
- /* Activity Tags */
859
- .activity-tag {
860
- font-size: 0.6rem;
861
- padding: 0.1rem 0.3rem;
862
- border-radius: 2px;
863
- margin-left: 0.3rem;
864
- font-weight: 600;
865
- text-transform: uppercase;
866
- }
867
- .tag-main { background: var(--accent-primary); color: var(--bg-primary); }
868
- .tag-agents { background: var(--accent-success); color: var(--bg-primary); }
869
- .tag-browser { background: var(--accent-warning); color: var(--bg-primary); }
870
- .tag-context { background: #bc8cff; color: var(--bg-primary); }
871
- .tag-exec { background: #f0883e; color: var(--bg-primary); }
872
- .tag-read { background: #58a6ff; color: var(--bg-primary); }
873
- .tag-tool { background: #da3633; color: var(--bg-primary); }
874
- .tag-think { background: #bc8cff; color: var(--bg-primary); }
875
- .tag-user { background: #3fb950; color: var(--bg-primary); }
876
- .tag-write { background: #f0883e; color: var(--bg-primary); }
877
- .tag-other { background: var(--text-secondary); color: var(--bg-primary); }
878
-
879
- /* Enhanced orphans */
880
- .orphan-list {
881
- margin-top: 0.5rem;
882
- }
883
- .orphan-row {
884
- display: flex;
885
- gap: 0.5rem;
886
- padding: 0.25rem;
887
- background: var(--bg-tertiary);
888
- border-radius: 3px;
889
- margin-bottom: 0.25rem;
890
- font-size: 0.7rem;
891
- }
892
- .orphan-pid {
893
- min-width: 60px;
894
- font-family: monospace;
895
- color: var(--accent-primary);
896
- }
897
- .orphan-resources {
898
- min-width: 120px;
899
- color: var(--text-secondary);
900
- }
901
- .orphan-cmd {
902
- flex: 1;
903
- color: var(--text-primary);
904
- overflow: hidden;
905
- text-overflow: ellipsis;
906
- }
907
-
908
- /* Enhanced problems */
909
- .problems-section {
910
- border-top: 1px solid var(--border-color);
911
- padding-top: 0.5rem;
912
- }
913
- .problem-item {
914
- background: rgba(218, 54, 51, 0.1);
915
- border: 1px solid rgba(218, 54, 51, 0.3);
916
- border-radius: 3px;
917
- padding: 0.4rem;
918
- margin-bottom: 0.25rem;
919
- font-size: 0.7rem;
920
- color: var(--accent-error);
921
- }
922
-
923
- /* Error Heatmap */
924
- .heatmap-container {
925
- padding: 1rem;
926
- overflow-y: auto;
927
- flex: 1;
928
- }
929
- .heatmap-header {
930
- font-size: 0.9rem;
931
- margin-bottom: 1rem;
932
- color: var(--text-primary);
933
- }
934
- .heatmap-grid {
935
- display: grid;
936
- grid-template-columns: repeat(10, 1fr);
937
- gap: 4px;
938
- margin-bottom: 1rem;
939
- }
940
- .heatmap-cell {
941
- aspect-ratio: 1;
942
- border-radius: 4px;
943
- cursor: pointer;
944
- transition: transform 0.2s;
945
- display: flex;
946
- align-items: center;
947
- justify-content: center;
948
- font-size: 0.65rem;
949
- font-weight: 600;
950
- color: rgba(255,255,255,0.7);
951
- position: relative;
952
- }
953
- .heatmap-cell:hover {
954
- transform: scale(1.15);
955
- z-index: 2;
956
- }
957
- .heatmap-tooltip {
958
- position: absolute;
959
- bottom: calc(100% + 6px);
960
- left: 50%;
961
- transform: translateX(-50%);
962
- background: var(--bg-secondary);
963
- border: 1px solid var(--border-color);
964
- border-radius: 4px;
965
- padding: 0.4rem 0.6rem;
966
- font-size: 0.7rem;
967
- white-space: nowrap;
968
- display: none;
969
- z-index: 100;
970
- color: var(--text-primary);
971
- box-shadow: 0 4px 12px rgba(0,0,0,0.4);
972
- }
973
- .heatmap-cell:hover .heatmap-tooltip {
974
- display: block;
975
- }
976
-
977
- /* State Machine */
978
- .state-machine-container {
979
- padding: 1rem;
980
- overflow-y: auto;
981
- flex: 1;
982
- }
983
- .state-machine {
984
- display: flex;
985
- justify-content: center;
986
- align-items: center;
987
- gap: 1.5rem;
988
- padding: 2rem;
989
- flex-wrap: wrap;
990
- }
991
- .state {
992
- display: flex;
993
- flex-direction: column;
994
- align-items: center;
995
- gap: 0.5rem;
996
- }
997
- .state-circle {
998
- width: 80px;
999
- height: 80px;
1000
- border-radius: 50%;
1001
- display: flex;
1002
- flex-direction: column;
1003
- align-items: center;
1004
- justify-content: center;
1005
- font-size: 0.65rem;
1006
- font-weight: 600;
1007
- border: 3px solid var(--border-color);
1008
- transition: all 0.3s;
1009
- }
1010
- .state-circle .state-count {
1011
- font-size: 1.2rem;
1012
- font-weight: 700;
1013
- margin-bottom: 0.1rem;
1014
- }
1015
- .state-circle.pending {
1016
- border-color: var(--text-secondary);
1017
- background: rgba(139, 148, 158, 0.1);
1018
- }
1019
- .state-circle.running {
1020
- border-color: var(--accent-primary);
1021
- background: rgba(88, 166, 255, 0.1);
1022
- animation: glow 2s infinite;
1023
- }
1024
- .state-circle.completed {
1025
- border-color: var(--accent-success);
1026
- background: rgba(35, 134, 54, 0.1);
1027
- }
1028
- .state-circle.failed {
1029
- border-color: var(--accent-error);
1030
- background: rgba(218, 54, 51, 0.1);
1031
- }
1032
- @keyframes glow {
1033
- 0%, 100% { box-shadow: 0 0 5px var(--accent-primary); }
1034
- 50% { box-shadow: 0 0 20px var(--accent-primary); }
1035
- }
1036
- .state-label {
1037
- font-size: 0.75rem;
1038
- color: var(--text-secondary);
1039
- }
1040
- .state-arrow {
1041
- font-size: 1.5rem;
1042
- color: var(--text-secondary);
1043
- }
1044
-
1045
- /* Summary View */
1046
- .summary-container {
1047
- padding: 1rem;
1048
- overflow-y: auto;
1049
- flex: 1;
1050
- }
1051
- .summary-card {
1052
- background: var(--bg-secondary);
1053
- border: 1px solid var(--border-color);
1054
- border-radius: 8px;
1055
- padding: 1.5rem;
1056
- margin-bottom: 1rem;
1057
- }
1058
- .summary-title {
1059
- font-size: 1.1rem;
1060
- margin-bottom: 0.75rem;
1061
- padding-bottom: 0.5rem;
1062
- border-bottom: 1px solid var(--border-color);
1063
- }
1064
- .summary-text {
1065
- font-size: 0.85rem;
1066
- line-height: 1.6;
1067
- color: var(--text-secondary);
1068
- margin-bottom: 0.75rem;
1069
- }
1070
- .summary-details {
1071
- list-style: none;
1072
- padding: 0;
1073
- margin: 0 0 1rem 0;
1074
- }
1075
- .summary-details li {
1076
- font-size: 0.8rem;
1077
- padding: 0.25rem 0;
1078
- color: var(--text-secondary);
1079
- }
1080
- .summary-details li::before {
1081
- content: "\2022";
1082
- margin-right: 0.5rem;
1083
- color: var(--accent-primary);
1084
- }
1085
- .summary-recommendations {
1086
- margin-top: 0.75rem;
1087
- padding: 0.75rem;
1088
- background: var(--bg-tertiary);
1089
- border-radius: 6px;
1090
- font-size: 0.8rem;
1091
- color: var(--text-secondary);
1092
- }
1093
- .summary-recommendations strong {
1094
- color: var(--text-primary);
1095
- }
1096
- .confidence-bar {
1097
- display: flex;
1098
- align-items: center;
1099
- gap: 0.75rem;
1100
- margin-top: 1rem;
1101
- font-size: 0.8rem;
1102
- }
1103
- .bar {
1104
- flex: 1;
1105
- height: 8px;
1106
- background: var(--bg-tertiary);
1107
- border-radius: 4px;
1108
- overflow: hidden;
1109
- }
1110
- .bar-fill {
1111
- height: 100%;
1112
- background: linear-gradient(90deg, var(--accent-error), var(--accent-warning), var(--accent-success));
1113
- transition: width 0.3s;
1114
- }
1115
-
1116
- /* Loading spinner */
1117
- .spinner {
1118
- width: 20px;
1119
- height: 20px;
1120
- border: 2px solid var(--border-color);
1121
- border-top-color: var(--accent-primary);
1122
- border-radius: 50%;
1123
- animation: spin 0.8s linear infinite;
1124
- margin: 0 auto;
1125
- }
1126
- @keyframes spin { to { transform: rotate(360deg); } }
1127
-
1128
- /* Scrollbars */
1129
- ::-webkit-scrollbar { width: 6px; height: 6px; }
1130
- ::-webkit-scrollbar-track { background: transparent; }
1131
- ::-webkit-scrollbar-thumb { background: var(--border-color); border-radius: 3px; }
1132
- ::-webkit-scrollbar-thumb:hover { background: var(--text-secondary); }
1133
-
1134
- /* Chat bubbles for transcript */
1135
- .chat-bubble { max-width: 80%; padding: 0.75rem 1rem; border-radius: 12px; margin-bottom: 0.5rem; font-size: 0.85rem; line-height: 1.5; white-space: pre-wrap; word-break: break-word; }
1136
- .chat-user { margin-left: auto; background: rgba(88,166,255,0.15); border: 1px solid rgba(88,166,255,0.3); }
1137
- .chat-assistant { margin-right: auto; background: var(--bg-secondary); border: 1px solid var(--border-color); }
1138
- .chat-tool { margin: 0 auto; max-width: 90%; background: rgba(240,136,62,0.1); border: 1px solid rgba(240,136,62,0.3); font-family: monospace; font-size: 0.8rem; }
1139
- .chat-thinking { margin-right: auto; background: rgba(188,140,255,0.08); border: 1px solid rgba(188,140,255,0.2); font-style: italic; color: var(--text-secondary); }
1140
- .chat-meta { font-size: 0.7rem; color: var(--text-secondary); margin-top: 4px; }
1141
- .chat-tokens { font-size: 0.65rem; color: #bc8cff; }
1142
- .chat-thinking-toggle { cursor: pointer; user-select: none; font-size: 0.75rem; color: #bc8cff; }
1143
- .chat-thinking-body { display: none; margin-top: 0.5rem; }
1144
- .chat-thinking-body.open { display: block; }
1145
-
1146
- /* Responsive */
1147
- @media (max-width: 900px) {
1148
- .sidebar { width: 240px; min-width: 240px; }
1149
- }
1150
- @media (max-width: 768px) {
1151
- .container { flex-direction: column; }
1152
- .sidebar { width: 100%; min-width: 100%; max-height: 200px; }
1153
- .state-machine { gap: 0.75rem; }
1154
- .state-circle { width: 60px; height: 60px; font-size: 0.6rem; }
1155
- }
1156
- </style>
1157
- </head>
1158
- <body>
1159
- <header class="header">
1160
- <h1><span>AgentFlow</span> Dashboard <span style="font-size:0.6rem;color:var(--text-secondary);font-weight:400;margin-left:8px;">v0.4.0</span></h1>
1161
- <div class="header-right">
1162
- <div class="connection-status">
1163
- <span class="status-dot" id="connectionDot"></span>
1164
- <span id="connectionText">Connecting...</span>
1165
- </div>
1166
- </div>
1167
- </header>
1168
-
1169
- <div class="container">
1170
- <aside class="sidebar">
1171
- <div class="sidebar-header">
1172
- <h3>Traces</h3>
1173
- <div class="search-box">
1174
- <input type="text" id="traceSearch" placeholder="Filter by name or agent ID...">
1175
- </div>
1176
- </div>
1177
- <div class="sidebar-filters">
1178
- <div class="filter-row">
1179
- <div class="filter-group">
1180
- <label>Time Range</label>
1181
- <select id="timeRangeFilter">
1182
- <option value="all">All Time</option>
1183
- <option value="1h">Last Hour</option>
1184
- <option value="24h">Last 24 Hours</option>
1185
- <option value="7d">Last 7 Days</option>
1186
- </select>
1187
- </div>
1188
- <div class="filter-group">
1189
- <label>Status</label>
1190
- <select id="statusFilter">
1191
- <option value="all">All</option>
1192
- <option value="success">Completed</option>
1193
- <option value="failure">Failed</option>
1194
- <option value="running">Running</option>
1195
- </select>
1196
- </div>
1197
- <div class="filter-group">
1198
- <label>Activity</label>
1199
- <select id="activityFilter">
1200
- <option value="all">All</option>
1201
- <option value="main">Main</option>
1202
- <option value="agents">Agents</option>
1203
- <option value="browser">Browser</option>
1204
- <option value="context">Context</option>
1205
- <option value="exec">Exec</option>
1206
- <option value="read">Read</option>
1207
- <option value="tool">Tool</option>
1208
- <option value="think">Think</option>
1209
- <option value="user">User</option>
1210
- <option value="write">Write</option>
1211
- <option value="other">Other</option>
1212
- </select>
1213
- </div>
1214
- </div>
1215
- </div>
1216
- <div class="trace-list" id="traceList"></div>
1217
- <div class="trace-count-badge" id="traceCount">0 traces</div>
1218
- </aside>
1219
-
1220
- <main class="main-content">
1221
- <!-- Process Health (above metrics, not a tab) -->
1222
- <div class="process-health-section" id="processHealthSection" style="display:none;"></div>
1223
-
1224
- <div class="stats-overview" id="statsOverview">
1225
- <div class="stat-card-mini">
1226
- <div class="metric-label">Agents</div>
1227
- <div class="metric-value primary" id="statAgents">--</div>
1228
- </div>
1229
- <div class="stat-card-mini">
1230
- <div class="metric-label">Executions</div>
1231
- <div class="metric-value primary" id="statExecutions">--</div>
1232
- </div>
1233
- <div class="stat-card-mini">
1234
- <div class="metric-label">Success Rate</div>
1235
- <div class="metric-value success" id="statSuccessRate">--</div>
1236
- </div>
1237
- <div class="stat-card-mini">
1238
- <div class="metric-label">Active</div>
1239
- <div class="metric-value warning" id="statActive">--</div>
1240
- </div>
1241
- </div>
1242
-
1243
- <div class="tabs">
1244
- <div class="tab active" data-tab="timeline">Timeline</div>
1245
- <div class="tab" data-tab="metrics">Metrics</div>
1246
- <div class="tab" data-tab="graph">Dependency Graph</div>
1247
- <div class="tab" data-tab="heatmap">Error Heatmap</div>
1248
- <div class="tab" data-tab="state">State Machine</div>
1249
- <div class="tab" data-tab="summary">Summary</div>
1250
- <div class="tab" data-tab="transcript">Transcript</div>
1251
- <div class="tab" data-tab="agenttimeline">Agent Timeline</div>
1252
- <div class="tab" data-tab="processmap">Process Map</div>
1253
- </div>
1254
-
1255
- <div class="toolbar" id="toolbar">
1256
- <div class="toolbar-group">
1257
- <button class="btn btn-icon" id="btnPlayPause" title="Pause/Resume live tail">&#9208;</button>
1258
- <div class="live-indicator" id="liveIndicator">
1259
- <span class="live-dot">&#9679;</span> Live Tail
1260
- </div>
1261
- <span class="toolbar-info" id="toolbarInfo"></span>
1262
- </div>
1263
- <div class="toolbar-group">
1264
- <button class="btn" id="btnRefresh" title="Refresh data">Refresh</button>
1265
- <button class="btn" id="btnExportPng" title="Export graph as PNG">Export PNG</button>
1266
- <button class="btn" id="btnFit" title="Fit graph to view">Fit</button>
1267
- <button class="btn" id="btnLayout" title="Re-run layout">Layout</button>
1268
- </div>
1269
- </div>
1270
-
1271
- <div class="alert-panel" id="alertPanel">
1272
- <strong>Alerts:</strong>
1273
- <ul id="alertList"></ul>
1274
- </div>
1275
-
1276
- <div class="content-area">
1277
- <!-- Timeline tab -->
1278
- <div class="tab-panel active" id="panel-timeline">
1279
- <div class="timeline-container" id="timelineContent">
1280
- <div class="empty-state">
1281
- <div class="empty-state-icon">&#9776;</div>
1282
- <div class="empty-state-title">Select a trace</div>
1283
- <div class="empty-state-text">Choose a trace from the sidebar to view its execution timeline.</div>
1284
- </div>
1285
- </div>
1286
- </div>
1287
-
1288
- <!-- Metrics tab -->
1289
- <div class="tab-panel" id="panel-metrics">
1290
- <div class="metrics-container" id="metricsContent">
1291
- <div class="empty-state">
1292
- <div class="empty-state-text">Select a trace to view metrics.</div>
1293
- </div>
1294
- </div>
1295
- </div>
1296
-
1297
- <!-- Dependency Graph tab -->
1298
- <div class="tab-panel" id="panel-graph">
1299
- <div id="cy">
1300
- <div class="empty-state" id="graphEmpty">
1301
- <div class="empty-state-icon">&#9651;</div>
1302
- <div class="empty-state-title">Select a trace</div>
1303
- <div class="empty-state-text">Choose a trace from the sidebar to view its dependency graph.</div>
1304
- </div>
1305
- </div>
1306
- <div class="node-detail-panel" id="nodeDetailPanel">
1307
- <div class="node-detail-header">
1308
- <h4 id="nodeDetailTitle">Node Details</h4>
1309
- <button class="node-detail-close" id="nodeDetailClose">&times;</button>
1310
- </div>
1311
- <div class="node-detail-body" id="nodeDetailBody"></div>
1312
- </div>
1313
- </div>
1314
-
1315
- <!-- Error Heatmap tab -->
1316
- <div class="tab-panel" id="panel-heatmap">
1317
- <div class="heatmap-container" id="heatmapContent">
1318
- <div class="empty-state">
1319
- <div class="empty-state-text">Select a trace to view the error heatmap.</div>
1320
- </div>
1321
- </div>
1322
- </div>
1323
-
1324
- <!-- State Machine tab -->
1325
- <div class="tab-panel" id="panel-state">
1326
- <div class="state-machine-container" id="stateContent">
1327
- <div class="empty-state">
1328
- <div class="empty-state-text">Select a trace to view state machine.</div>
1329
- </div>
1330
- </div>
1331
- </div>
1332
-
1333
- <!-- Summary tab -->
1334
- <div class="tab-panel" id="panel-summary">
1335
- <div class="summary-container" id="summaryContent">
1336
- <div class="empty-state">
1337
- <div class="empty-state-text">Select a trace to view summary.</div>
1338
- </div>
1339
- </div>
1340
- </div>
1341
-
1342
- <!-- Transcript tab -->
1343
- <div class="tab-panel" id="panel-transcript">
1344
- <div class="timeline-container" id="transcriptContent">
1345
- <div class="empty-state">
1346
- <div class="empty-state-text">Select a session trace to view transcript.</div>
1347
- </div>
1348
- </div>
1349
- </div>
1350
-
1351
- <!-- Agent Timeline (Gantt) tab -->
1352
- <div class="tab-panel" id="panel-agenttimeline">
1353
- <div class="timeline-container" id="agentTimelineContent" style="overflow:auto;">
1354
- <div class="empty-state" id="agentTimelineEmpty">
1355
- <div class="empty-state-icon">&#9776;</div>
1356
- <div class="empty-state-title">Agent Timeline</div>
1357
- <div class="empty-state-text">Select a trace to view all executions for its agent as a Gantt chart.</div>
1358
- </div>
1359
- </div>
1360
- </div>
1361
-
1362
- <!-- Process Map tab -->
1363
- <div class="tab-panel" id="panel-processmap">
1364
- <div id="cyProcessMap" style="width:100%;height:100%;min-height:500px;">
1365
- <div class="empty-state" id="processMapEmpty">
1366
- <div class="empty-state-icon">&#9881;</div>
1367
- <div class="empty-state-title">Process Map</div>
1368
- <div class="empty-state-text">Select a trace to view the process mining graph for its agent.<br>Shows activity flows aggregated across all executions.</div>
1369
- </div>
1370
- </div>
1371
- <div class="node-detail-panel" id="processMapDetailPanel">
1372
- <div class="node-detail-header">
1373
- <h4 id="processMapDetailTitle">Activity Details</h4>
1374
- <button class="node-detail-close" id="processMapDetailClose">&times;</button>
1375
- </div>
1376
- <div class="node-detail-body" id="processMapDetailBody"></div>
1377
- </div>
1378
- </div>
1379
- </div>
1380
- </main>
1381
- </div>
1382
-
1383
- <script src="dashboard.js?v=0.2.2"></script>
1384
- </body>
1385
- </html>