@openqa/cli 1.3.0 → 1.3.2

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.
@@ -395,160 +395,484 @@ async function startWebServer() {
395
395
  <head>
396
396
  <title>OpenQA - Professional Dashboard</title>
397
397
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
398
- <script src="https://cdn.jsdelivr.net/npm/vis-network@latest/dist/vis-network.min.js"></script>
398
+ <script src="https://cdn.jsdelivr.net/npm/@xyflow/react@11/dist/umd/index.js"></script>
399
399
  <style>
400
- body { font-family: system-ui; max-width: 1600px; margin: 20px auto; padding: 20px; background: #0f172a; color: #e2e8f0; }
401
- h1 { color: #38bdf8; margin-bottom: 30px; }
402
- .card { background: #1e293b; border: 1px solid #334155; border-radius: 12px; padding: 24px; margin: 20px 0; }
403
- .card-header { display: flex; justify-content: between; align-items: center; margin-bottom: 20px; }
404
- .card-title { font-size: 18px; font-weight: 600; color: #38bdf8; }
405
- .status { display: inline-block; padding: 6px 12px; border-radius: 20px; font-size: 12px; font-weight: 500; }
400
+ * { box-sizing: border-box; margin: 0; padding: 0; }
401
+
402
+ body {
403
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
404
+ background: #0a0a0a;
405
+ color: #ffffff;
406
+ min-height: 100vh;
407
+ overflow-x: hidden;
408
+ line-height: 1.6;
409
+ }
410
+
411
+ .dashboard-container {
412
+ max-width: 1920px;
413
+ margin: 0 auto;
414
+ padding: 20px;
415
+ min-height: 100vh;
416
+ }
417
+
418
+ .dashboard-header {
419
+ display: flex;
420
+ justify-content: space-between;
421
+ align-items: center;
422
+ margin-bottom: 32px;
423
+ padding: 24px 32px;
424
+ background: linear-gradient(135deg, #1a1a1a, #2a2a2a);
425
+ border-radius: 16px;
426
+ border: 1px solid #333333;
427
+ backdrop-filter: blur(10px);
428
+ }
429
+
430
+ .dashboard-title {
431
+ font-size: 32px;
432
+ font-weight: 700;
433
+ color: #f97316;
434
+ margin: 0;
435
+ letter-spacing: -0.5px;
436
+ }
437
+
438
+ .nav {
439
+ display: flex;
440
+ gap: 8px;
441
+ background: rgba(255, 255, 255, 0.05);
442
+ padding: 4px;
443
+ border-radius: 12px;
444
+ }
445
+
446
+ .nav-links a {
447
+ color: #9ca3af;
448
+ text-decoration: none;
449
+ font-weight: 500;
450
+ padding: 12px 24px;
451
+ border-radius: 8px;
452
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
453
+ display: flex;
454
+ align-items: center;
455
+ gap: 8px;
456
+ }
457
+
458
+ .nav-links a:hover, .nav-links a.active {
459
+ color: #ffffff;
460
+ background: #f97316;
461
+ transform: translateY(-1px);
462
+ }
463
+
464
+ .connection-status {
465
+ padding: 8px 16px;
466
+ border-radius: 20px;
467
+ font-size: 12px;
468
+ font-weight: 600;
469
+ text-transform: uppercase;
470
+ letter-spacing: 0.5px;
471
+ }
472
+
406
473
  .status.running { background: linear-gradient(135deg, #10b981, #059669); color: white; }
407
474
  .status.idle { background: linear-gradient(135deg, #f59e0b, #d97706); color: white; }
408
475
  .status.error { background: linear-gradient(135deg, #ef4444, #dc2626); color: white; }
409
476
  .status.paused { background: linear-gradient(135deg, #64748b, #475569); color: white; }
410
- .nav { display: flex; justify-content: space-between; align-items: center; margin: 20px 0; padding: 15px; background: #1e293b; border-radius: 12px; }
411
- .nav-links { display: flex; gap: 30px; }
412
- .nav-links a { color: #94a3b8; text-decoration: none; font-weight: 500; transition: color 0.2s; }
413
- .nav-links a:hover, .nav-links a.active { color: #38bdf8; }
414
- .grid { display: grid; gap: 20px; }
415
- .grid-2 { grid-template-columns: repeat(2, 1fr); }
416
- .grid-3 { grid-template-columns: repeat(3, 1fr); }
417
- .grid-4 { grid-template-columns: repeat(4, 1fr); }
418
- .metric-card {
419
- background: linear-gradient(135deg, #1e293b, #334155);
420
- border: 1px solid #334155;
421
- border-radius: 12px;
422
- padding: 20px;
423
- text-align: center;
477
+
478
+ /* Metrics Grid */
479
+ .metrics-grid {
480
+ display: grid;
481
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
482
+ gap: 24px;
483
+ margin-bottom: 32px;
484
+ }
485
+
486
+ .metric-card {
487
+ background: linear-gradient(145deg, #1a1a1a, #2d2d2d);
488
+ border: 1px solid #333333;
489
+ border-radius: 16px;
490
+ padding: 28px 24px;
424
491
  position: relative;
425
492
  overflow: hidden;
493
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
494
+ min-height: 160px;
495
+ display: flex;
496
+ flex-direction: column;
497
+ justify-content: space-between;
426
498
  }
427
- .metric-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, #38bdf8, #0ea5e9); }
428
- .metric-value { font-size: 32px; font-weight: bold; color: #38bdf8; margin: 10px 0; }
429
- .metric-label { color: #94a3b8; font-size: 14px; font-weight: 500; }
430
- .metric-change { font-size: 12px; margin-top: 5px; }
499
+
500
+ .metric-card::before {
501
+ content: '';
502
+ position: absolute;
503
+ top: 0;
504
+ left: 0;
505
+ right: 0;
506
+ height: 4px;
507
+ background: linear-gradient(90deg, #f97316, #ea580c, #f59e0b);
508
+ background-size: 200% 100%;
509
+ animation: shimmer 3s ease-in-out infinite;
510
+ }
511
+
512
+ @keyframes shimmer {
513
+ 0%, 100% { background-position: -200% 0; }
514
+ 50% { background-position: 200% 0; }
515
+ }
516
+
517
+ .metric-card:hover {
518
+ transform: translateY(-4px);
519
+ border-color: #f97316;
520
+ box-shadow: 0 20px 40px rgba(249, 115, 22, 0.15);
521
+ }
522
+
523
+ .metric-header {
524
+ display: flex;
525
+ justify-content: space-between;
526
+ align-items: flex-start;
527
+ margin-bottom: 16px;
528
+ }
529
+
530
+ .metric-label {
531
+ color: #9ca3af;
532
+ font-size: 14px;
533
+ font-weight: 500;
534
+ text-transform: uppercase;
535
+ letter-spacing: 0.5px;
536
+ }
537
+
538
+ .metric-icon {
539
+ width: 40px;
540
+ height: 40px;
541
+ background: rgba(249, 115, 22, 0.1);
542
+ border-radius: 12px;
543
+ display: flex;
544
+ align-items: center;
545
+ justify-content: center;
546
+ font-size: 20px;
547
+ }
548
+
549
+ .metric-value {
550
+ font-size: 42px;
551
+ font-weight: 700;
552
+ color: #f97316;
553
+ margin: 8px 0;
554
+ line-height: 1;
555
+ background: linear-gradient(135deg, #f97316, #fbbf24);
556
+ -webkit-background-clip: text;
557
+ -webkit-text-fill-color: transparent;
558
+ background-clip: text;
559
+ }
560
+
561
+ .metric-change {
562
+ font-size: 13px;
563
+ font-weight: 600;
564
+ display: flex;
565
+ align-items: center;
566
+ gap: 4px;
567
+ }
568
+
431
569
  .metric-change.positive { color: #10b981; }
432
570
  .metric-change.negative { color: #ef4444; }
433
- .chart-container { position: relative; height: 300px; margin: 20px 0; }
434
- .hierarchy-container { height: 400px; border: 1px solid #334155; border-radius: 8px; background: #0f172a; }
435
- .activity-item {
436
- background: #334155;
437
- padding: 15px;
438
- margin: 10px 0;
439
- border-radius: 8px;
440
- border-left: 4px solid #38bdf8;
571
+
572
+ /* Main Content Grid */
573
+ .main-grid {
574
+ display: grid;
575
+ grid-template-columns: 1fr 1fr;
576
+ gap: 24px;
577
+ margin-bottom: 32px;
578
+ }
579
+
580
+ .card {
581
+ background: linear-gradient(145deg, #1a1a1a, #2d2d2d);
582
+ border: 1px solid #333333;
583
+ border-radius: 16px;
584
+ padding: 28px;
585
+ position: relative;
586
+ overflow: hidden;
587
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
588
+ }
589
+
590
+ .card:hover {
591
+ border-color: #444444;
592
+ transform: translateY(-2px);
593
+ }
594
+
595
+ .card-header {
596
+ display: flex;
597
+ justify-content: space-between;
598
+ align-items: center;
599
+ margin-bottom: 24px;
600
+ }
601
+
602
+ .card-title {
603
+ font-size: 20px;
604
+ font-weight: 600;
605
+ color: #ffffff;
606
+ margin: 0;
607
+ }
608
+
609
+ .tabs {
610
+ display: flex;
611
+ gap: 4px;
612
+ background: rgba(255, 255, 255, 0.05);
613
+ padding: 4px;
614
+ border-radius: 12px;
615
+ }
616
+
617
+ .tab {
618
+ padding: 10px 20px;
619
+ background: transparent;
620
+ border: none;
621
+ border-radius: 8px;
622
+ color: #9ca3af;
623
+ font-weight: 500;
624
+ cursor: pointer;
625
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
626
+ }
627
+
628
+ .tab.active {
629
+ background: #f97316;
630
+ color: white;
631
+ }
632
+
633
+ .tab:hover:not(.active) {
634
+ color: #ffffff;
635
+ background: rgba(255, 255, 255, 0.1);
636
+ }
637
+
638
+ .chart-container {
639
+ position: relative;
640
+ height: 320px;
641
+ margin: 20px 0;
642
+ }
643
+
644
+ .hierarchy-container {
645
+ height: 420px;
646
+ border: 1px solid #333333;
647
+ border-radius: 12px;
648
+ background: #0a0a0a;
649
+ overflow: hidden;
650
+ }
651
+
652
+ /* Activity Feed */
653
+ .activity-feed {
654
+ max-height: 400px;
655
+ overflow-y: auto;
656
+ padding-right: 8px;
657
+ }
658
+
659
+ .activity-feed::-webkit-scrollbar {
660
+ width: 6px;
661
+ }
662
+
663
+ .activity-feed::-webkit-scrollbar-track {
664
+ background: rgba(255, 255, 255, 0.05);
665
+ border-radius: 3px;
666
+ }
667
+
668
+ .activity-feed::-webkit-scrollbar-thumb {
669
+ background: #f97316;
670
+ border-radius: 3px;
671
+ }
672
+
673
+ .activity-item {
674
+ background: rgba(255, 255, 255, 0.03);
675
+ border: 1px solid rgba(255, 255, 255, 0.08);
676
+ border-left: 4px solid #f97316;
677
+ border-radius: 12px;
678
+ padding: 16px 20px;
679
+ margin-bottom: 12px;
441
680
  font-size: 14px;
442
- transition: all 0.2s;
681
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
682
+ position: relative;
683
+ overflow: hidden;
684
+ }
685
+
686
+ .activity-item::before {
687
+ content: '';
688
+ position: absolute;
689
+ top: 0;
690
+ left: 0;
691
+ right: 0;
692
+ height: 1px;
693
+ background: linear-gradient(90deg, transparent, rgba(249, 115, 22, 0.3), transparent);
694
+ opacity: 0;
695
+ transition: opacity 0.3s;
443
696
  }
444
- .activity-item:hover { transform: translateX(4px); background: #475569; }
697
+
698
+ .activity-item:hover {
699
+ background: rgba(255, 255, 255, 0.06);
700
+ border-left-color: #fbbf24;
701
+ transform: translateX(8px);
702
+ }
703
+
704
+ .activity-item:hover::before {
705
+ opacity: 1;
706
+ }
707
+
445
708
  .activity-item.error { border-left-color: #ef4444; }
446
709
  .activity-item.success { border-left-color: #10b981; }
447
710
  .activity-item.warning { border-left-color: #f59e0b; }
448
- .activity-time { color: #64748b; font-size: 12px; }
449
- .intervention-request {
450
- background: linear-gradient(135deg, #7c2d12, #92400e);
451
- border: 1px solid #dc2626;
452
- padding: 20px;
453
- border-radius: 12px;
454
- margin: 15px 0;
711
+
712
+ .activity-time {
713
+ color: #6b7280;
714
+ font-size: 12px;
715
+ margin-top: 8px;
716
+ display: flex;
717
+ align-items: center;
718
+ gap: 4px;
719
+ }
720
+
721
+ /* Buttons */
722
+ .btn {
723
+ background: linear-gradient(135deg, #f97316, #ea580c);
724
+ color: white;
725
+ border: none;
726
+ padding: 12px 24px;
727
+ border-radius: 10px;
728
+ cursor: pointer;
729
+ font-size: 14px;
730
+ font-weight: 600;
731
+ margin: 4px;
732
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
455
733
  position: relative;
734
+ overflow: hidden;
456
735
  }
457
- .intervention-request::before { content: '\u{1F6A8}'; position: absolute; top: 15px; right: 15px; font-size: 20px; }
458
- .intervention-request h4 { color: #fbbf24; margin: 0 0 10px 0; }
459
- .btn {
460
- background: linear-gradient(135deg, #38bdf8, #0ea5e9);
461
- color: white;
462
- border: none;
463
- padding: 10px 20px;
464
- border-radius: 8px;
465
- cursor: pointer;
466
- font-size: 14px;
467
- font-weight: 500;
468
- margin: 5px;
469
- transition: all 0.2s;
736
+
737
+ .btn::before {
738
+ content: '';
739
+ position: absolute;
740
+ top: 0;
741
+ left: -100%;
742
+ width: 100%;
743
+ height: 100%;
744
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
745
+ transition: left 0.5s;
470
746
  }
471
- .btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(56, 189, 248, 0.3); }
747
+
748
+ .btn:hover {
749
+ transform: translateY(-2px);
750
+ box-shadow: 0 8px 24px rgba(249, 115, 22, 0.3);
751
+ }
752
+
753
+ .btn:hover::before {
754
+ left: 100%;
755
+ }
756
+
472
757
  .btn-success { background: linear-gradient(135deg, #10b981, #059669); }
473
- .btn-success:hover { box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3); }
758
+ .btn-success:hover { box-shadow: 0 8px 24px rgba(16, 185, 129, 0.3); }
474
759
  .btn-danger { background: linear-gradient(135deg, #ef4444, #dc2626); }
475
- .btn-danger:hover { box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3); }
476
- .pulse { animation: pulse 2s infinite; }
477
- @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } }
478
- .loading { color: #f59e0b; }
479
- .tabs { display: flex; gap: 10px; margin-bottom: 20px; }
480
- .tab { padding: 10px 20px; background: #334155; border-radius: 8px; cursor: pointer; transition: all 0.2s; }
481
- .tab.active { background: #38bdf8; color: white; }
482
- .tab-content { display: none; }
483
- .tab-content.active { display: block; }
484
- .agent-node {
485
- background: #1e293b;
486
- border: 2px solid #38bdf8;
487
- border-radius: 8px;
488
- padding: 10px;
489
- margin: 10px;
490
- text-align: center;
491
- }
492
- .performance-bar {
493
- height: 8px;
494
- background: #334155;
495
- border-radius: 4px;
496
- overflow: hidden;
497
- margin: 10px 0;
760
+ .btn-danger:hover { box-shadow: 0 8px 24px rgba(239, 68, 68, 0.3); }
761
+
762
+ /* Performance bars */
763
+ .performance-bar {
764
+ height: 6px;
765
+ background: rgba(255, 255, 255, 0.1);
766
+ border-radius: 3px;
767
+ overflow: hidden;
768
+ margin: 8px 0;
498
769
  }
499
- .performance-fill {
500
- height: 100%;
501
- background: linear-gradient(90deg, #10b981, #38bdf8);
502
- transition: width 1s ease;
770
+
771
+ .performance-fill {
772
+ height: 100%;
773
+ background: linear-gradient(90deg, #10b981, #f97316);
774
+ transition: width 1s cubic-bezier(0.4, 0, 0.2, 1);
775
+ border-radius: 3px;
503
776
  }
777
+
778
+ /* Responsive */
779
+ @media (max-width: 1200px) {
780
+ .main-grid {
781
+ grid-template-columns: 1fr;
782
+ }
783
+ }
784
+
785
+ @media (max-width: 768px) {
786
+ .dashboard-container {
787
+ padding: 16px;
788
+ }
789
+
790
+ .metrics-grid {
791
+ grid-template-columns: 1fr;
792
+ gap: 16px;
793
+ }
794
+
795
+ .dashboard-header {
796
+ flex-direction: column;
797
+ gap: 16px;
798
+ padding: 20px;
799
+ }
800
+
801
+ .dashboard-title {
802
+ font-size: 24px;
803
+ }
804
+
805
+ .metric-value {
806
+ font-size: 32px;
807
+ }
808
+ }
809
+
810
+ /* Loading animation */
811
+ .pulse { animation: pulse 2s infinite; }
812
+ @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } }
813
+ </style>
504
814
  </style>
505
815
  </head>
506
816
  <body>
507
- <div class="nav">
508
- <div class="nav-links">
509
- <a href="/" class="active">\u{1F4CA} Dashboard</a>
510
- <a href="/kanban">\u{1F4CB} Kanban</a>
511
- <a href="/config">\u2699\uFE0F Config</a>
512
- </div>
513
- <div>
514
- <span id="connection-status" class="status idle">\u{1F50C} Connecting...</span>
515
- </div>
516
- </div>
517
-
518
- <!-- Key Metrics -->
519
- <div class="grid-4">
520
- <div class="metric-card">
521
- <div class="metric-label">\u{1F916} Active Agents</div>
522
- <div class="metric-value" id="active-agents">0</div>
523
- <div class="metric-change positive">\u2191 2 from last hour</div>
524
- </div>
525
- <div class="metric-card">
526
- <div class="metric-label">\u{1F4CB} Total Actions</div>
527
- <div class="metric-value" id="total-actions">0</div>
528
- <div class="metric-change positive">\u2191 12% increase</div>
529
- </div>
530
- <div class="metric-card">
531
- <div class="metric-label">\u{1F41B} Bugs Found</div>
532
- <div class="metric-value" id="bugs-found">0</div>
533
- <div class="metric-change negative">\u2193 3 from yesterday</div>
534
- </div>
535
- <div class="metric-card">
536
- <div class="metric-label">\u26A1 Success Rate</div>
537
- <div class="metric-value" id="success-rate">0%</div>
538
- <div class="metric-change positive">\u2191 5% improvement</div>
817
+ <div class="dashboard-container">
818
+ <header class="dashboard-header">
819
+ <h1 class="dashboard-title">\u{1F916} OpenQA Professional Dashboard</h1>
820
+ <nav class="nav">
821
+ <div class="nav-links">
822
+ <a href="/" class="active">\u{1F4CA} Dashboard</a>
823
+ <a href="/kanban">\u{1F4CB} Kanban</a>
824
+ <a href="/config">\u2699\uFE0F Config</a>
825
+ </div>
826
+ <span id="connection-status" class="connection-status status idle">\u{1F50C} Connecting...</span>
827
+ </nav>
828
+ </header>
829
+
830
+ <!-- Key Metrics -->
831
+ <div class="metrics-grid">
832
+ <div class="metric-card">
833
+ <div class="metric-header">
834
+ <div class="metric-label">\u{1F916} Active Agents</div>
835
+ <div class="metric-icon">\u{1F916}</div>
836
+ </div>
837
+ <div class="metric-value" id="active-agents">0</div>
838
+ <div class="metric-change positive">\u2191 2 from last hour</div>
839
+ </div>
840
+ <div class="metric-card">
841
+ <div class="metric-header">
842
+ <div class="metric-label">\u{1F4CB} Total Actions</div>
843
+ <div class="metric-icon">\u{1F4CB}</div>
844
+ </div>
845
+ <div class="metric-value" id="total-actions">0</div>
846
+ <div class="metric-change positive">\u2191 12% increase</div>
847
+ </div>
848
+ <div class="metric-card">
849
+ <div class="metric-header">
850
+ <div class="metric-label">\u{1F41B} Bugs Found</div>
851
+ <div class="metric-icon">\u{1F41B}</div>
852
+ </div>
853
+ <div class="metric-value" id="bugs-found">0</div>
854
+ <div class="metric-change negative">\u2193 3 from yesterday</div>
855
+ </div>
856
+ <div class="metric-card">
857
+ <div class="metric-header">
858
+ <div class="metric-label">\u26A1 Success Rate</div>
859
+ <div class="metric-icon">\u26A1</div>
860
+ </div>
861
+ <div class="metric-value" id="success-rate">0%</div>
862
+ <div class="metric-change positive">\u2191 5% improvement</div>
863
+ </div>
539
864
  </div>
540
- </div>
541
865
 
542
866
  <!-- Charts and Hierarchy -->
543
- <div class="grid-2">
867
+ <div class="main-grid">
544
868
  <div class="card">
545
869
  <div class="card-header">
546
870
  <h2 class="card-title">\u{1F4C8} Performance Metrics</h2>
547
- </div>
548
- <div class="tabs">
549
- <div class="tab active" onclick="switchTab('performance')">Performance</div>
550
- <div class="tab" onclick="switchTab('activity')">Activity</div>
551
- <div class="tab" onclick="switchTab('errors')">Error Rate</div>
871
+ <div class="tabs">
872
+ <div class="tab active" onclick="switchTab('performance')">Performance</div>
873
+ <div class="tab" onclick="switchTab('activity')">Activity</div>
874
+ <div class="tab" onclick="switchTab('errors')">Error Rate</div>
875
+ </div>
552
876
  </div>
553
877
  <div class="chart-container">
554
878
  <canvas id="performanceChart"></canvas>
@@ -573,36 +897,36 @@ async function startWebServer() {
573
897
  <div class="card">
574
898
  <div class="card-header">
575
899
  <h2 class="card-title">\u{1F916} Agent Details</h2>
576
- </div>
577
- <div class="tabs">
578
- <div class="tab active" onclick="switchAgentTab('active')">Active Agents</div>
579
- <div class="tab" onclick="switchAgentTab('specialists')">Specialists</div>
580
- <div class="tab" onclick="switchAgentTab('performance')">Performance</div>
900
+ <div class="tabs">
901
+ <div class="tab active" onclick="switchAgentTab('active')">Active Agents</div>
902
+ <div class="tab" onclick="switchAgentTab('specialists')">Specialists</div>
903
+ <div class="tab" onclick="switchAgentTab('performance')">Performance</div>
904
+ </div>
581
905
  </div>
582
906
  <div id="active-agents-content" class="tab-content active">
583
907
  <div id="active-agents-list">
584
- <p style="color: #64748b;">Loading agents...</p>
908
+ <p style="color: #9ca3af;">Loading agents...</p>
585
909
  </div>
586
910
  </div>
587
911
  <div id="specialists-content" class="tab-content">
588
912
  <div id="specialists-list">
589
- <p style="color: #64748b;">No specialists active</p>
913
+ <p style="color: #9ca3af;">No specialists active</p>
590
914
  </div>
591
915
  </div>
592
916
  <div id="performance-content" class="tab-content">
593
917
  <div id="performance-metrics">
594
- <p style="color: #64748b;">Performance data loading...</p>
918
+ <p style="color: #9ca3af;">Performance data loading...</p>
595
919
  </div>
596
920
  </div>
597
921
  </div>
598
922
 
599
923
  <!-- Activity and Interventions -->
600
- <div class="grid-2">
924
+ <div class="main-grid">
601
925
  <div class="card">
602
926
  <div class="card-header">
603
927
  <h2 class="card-title">\u26A1 Recent Activity</h2>
604
928
  </div>
605
- <div id="recent-activities" style="max-height: 400px; overflow-y: auto;">
929
+ <div class="activity-feed" id="recent-activities">
606
930
  <div class="activity-item">
607
931
  <div>\u{1F504} Waiting for agent activity...</div>
608
932
  <div class="activity-time">System ready</div>
@@ -614,20 +938,20 @@ async function startWebServer() {
614
938
  <div class="card-header">
615
939
  <h2 class="card-title">\u{1F6A8} Human Interventions</h2>
616
940
  </div>
617
- <div id="interventions-list" style="max-height: 400px; overflow-y: auto;">
618
- <p style="color: #64748b;">No interventions required</p>
941
+ <div class="activity-feed" id="interventions-list">
942
+ <p style="color: #9ca3af;">No interventions required</p>
619
943
  </div>
620
944
  </div>
621
945
  </div>
622
946
 
623
947
  <!-- Tasks and Issues -->
624
- <div class="grid-2">
948
+ <div class="main-grid">
625
949
  <div class="card">
626
950
  <div class="card-header">
627
951
  <h2 class="card-title">\u{1F4DD} Current Tasks</h2>
628
952
  </div>
629
- <div id="current-tasks" style="max-height: 400px; overflow-y: auto;">
630
- <p style="color: #64748b;">No active tasks</p>
953
+ <div class="activity-feed" id="current-tasks">
954
+ <p style="color: #9ca3af;">No active tasks</p>
631
955
  </div>
632
956
  </div>
633
957
 
@@ -635,40 +959,8 @@ async function startWebServer() {
635
959
  <div class="card-header">
636
960
  <h2 class="card-title">\u26A0\uFE0F Issues Encountered</h2>
637
961
  </div>
638
- <div id="issues-list" style="max-height: 400px; overflow-y: auto;">
639
- <p style="color: #64748b;">No issues</p>
640
- </div>
641
- </div>
642
- </div>
643
-
644
- <div class="grid">
645
- <div class="card">
646
- <h2>\u{1F916} Active Agents</h2>
647
- <div id="active-agents-list">
648
- <p style="color: #64748b;">No active agents</p>
649
- </div>
650
- </div>
651
-
652
- <div class="card">
653
- <h2>\u{1F6A8} Human Interventions</h2>
654
- <div id="interventions-list">
655
- <p style="color: #64748b;">No interventions required</p>
656
- </div>
657
- </div>
658
- </div>
659
-
660
- <div class="grid">
661
- <div class="card">
662
- <h2>\u{1F4DD} Current Tasks</h2>
663
- <div id="current-tasks">
664
- <p style="color: #64748b;">No active tasks</p>
665
- </div>
666
- </div>
667
-
668
- <div class="card">
669
- <h2>\u26A0\uFE0F Issues Encountered</h2>
670
- <div id="issues-list">
671
- <p style="color: #64748b;">No issues</p>
962
+ <div class="activity-feed" id="issues-list">
963
+ <p style="color: #9ca3af;">No issues</p>
672
964
  </div>
673
965
  </div>
674
966
  </div>
@@ -690,8 +982,8 @@ async function startWebServer() {
690
982
  datasets: [{
691
983
  label: 'Actions/min',
692
984
  data: [12, 19, 15, 25, 22, 30, 28],
693
- borderColor: '#38bdf8',
694
- backgroundColor: 'rgba(56, 189, 248, 0.1)',
985
+ borderColor: '#f97316',
986
+ backgroundColor: 'rgba(249, 115, 22, 0.1)',
695
987
  tension: 0.4
696
988
  }, {
697
989
  label: 'Success Rate %',
@@ -723,7 +1015,7 @@ async function startWebServer() {
723
1015
  datasets: [{
724
1016
  label: 'Tests Generated',
725
1017
  data: [65, 78, 90, 81, 56, 45, 30],
726
- backgroundColor: '#38bdf8'
1018
+ backgroundColor: '#f97316'
727
1019
  }, {
728
1020
  label: 'Bugs Found',
729
1021
  data: [12, 19, 15, 25, 22, 15, 8],
@@ -751,7 +1043,7 @@ async function startWebServer() {
751
1043
  labels: ['Success', 'Warnings', 'Errors', 'Critical'],
752
1044
  datasets: [{
753
1045
  data: [75, 15, 8, 2],
754
- backgroundColor: ['#10b981', '#f59e0b', '#ef4444', '#dc2626']
1046
+ backgroundColor: ['#10b981', '#f97316', '#ef4444', '#dc2626']
755
1047
  }]
756
1048
  },
757
1049
  options: {
@@ -764,51 +1056,166 @@ async function startWebServer() {
764
1056
  });
765
1057
  }
766
1058
 
767
- // Initialize Agent Hierarchy
1059
+ // Initialize Agent Hierarchy with React Flow
768
1060
  function initHierarchy() {
769
1061
  const container = document.getElementById('hierarchy-container');
770
1062
 
1063
+ // Create React Flow nodes
771
1064
  const nodes = [
772
- { id: 'main', label: 'Main Agent', shape: 'box', color: '#38bdf8' },
773
- { id: 'browser', label: 'Browser Specialist', shape: 'box', color: '#10b981' },
774
- { id: 'api', label: 'API Tester', shape: 'box', color: '#f59e0b' },
775
- { id: 'auth', label: 'Auth Specialist', shape: 'box', color: '#ef4444' },
776
- { id: 'ui', label: 'UI Tester', shape: 'box', color: '#8b5cf6' },
777
- { id: 'perf', label: 'Performance Tester', shape: 'box', color: '#06b6d4' },
778
- { id: 'security', label: 'Security Scanner', shape: 'box', color: '#f97316' }
1065
+ {
1066
+ id: 'main',
1067
+ type: 'default',
1068
+ position: { x: 400, y: 50 },
1069
+ data: { label: '\u{1F916} Main Agent' },
1070
+ style: {
1071
+ background: '#f97316',
1072
+ color: 'white',
1073
+ border: '2px solid #ea580c',
1074
+ borderRadius: '8px',
1075
+ padding: '10px 20px',
1076
+ fontSize: '14px',
1077
+ fontWeight: 'bold'
1078
+ }
1079
+ },
1080
+ {
1081
+ id: 'browser',
1082
+ type: 'default',
1083
+ position: { x: 150, y: 200 },
1084
+ data: { label: '\u{1F310} Browser Specialist' },
1085
+ style: {
1086
+ background: '#10b981',
1087
+ color: 'white',
1088
+ border: '2px solid #059669',
1089
+ borderRadius: '8px',
1090
+ padding: '8px 16px',
1091
+ fontSize: '13px'
1092
+ }
1093
+ },
1094
+ {
1095
+ id: 'api',
1096
+ type: 'default',
1097
+ position: { x: 400, y: 200 },
1098
+ data: { label: '\u{1F50C} API Tester' },
1099
+ style: {
1100
+ background: '#f59e0b',
1101
+ color: 'white',
1102
+ border: '2px solid #d97706',
1103
+ borderRadius: '8px',
1104
+ padding: '8px 16px',
1105
+ fontSize: '13px'
1106
+ }
1107
+ },
1108
+ {
1109
+ id: 'auth',
1110
+ type: 'default',
1111
+ position: { x: 650, y: 200 },
1112
+ data: { label: '\u{1F510} Auth Specialist' },
1113
+ style: {
1114
+ background: '#ef4444',
1115
+ color: 'white',
1116
+ border: '2px solid #dc2626',
1117
+ borderRadius: '8px',
1118
+ padding: '8px 16px',
1119
+ fontSize: '13px'
1120
+ }
1121
+ },
1122
+ {
1123
+ id: 'ui',
1124
+ type: 'default',
1125
+ position: { x: 150, y: 350 },
1126
+ data: { label: '\u{1F3A8} UI Tester' },
1127
+ style: {
1128
+ background: '#8b5cf6',
1129
+ color: 'white',
1130
+ border: '2px solid #7c3aed',
1131
+ borderRadius: '8px',
1132
+ padding: '8px 16px',
1133
+ fontSize: '13px'
1134
+ }
1135
+ },
1136
+ {
1137
+ id: 'perf',
1138
+ type: 'default',
1139
+ position: { x: 400, y: 350 },
1140
+ data: { label: '\u26A1 Performance Tester' },
1141
+ style: {
1142
+ background: '#06b6d4',
1143
+ color: 'white',
1144
+ border: '2px solid #0891b2',
1145
+ borderRadius: '8px',
1146
+ padding: '8px 16px',
1147
+ fontSize: '13px'
1148
+ }
1149
+ },
1150
+ {
1151
+ id: 'security',
1152
+ type: 'default',
1153
+ position: { x: 650, y: 350 },
1154
+ data: { label: '\u{1F6E1}\uFE0F Security Scanner' },
1155
+ style: {
1156
+ background: '#f97316',
1157
+ color: 'white',
1158
+ border: '2px solid #ea580c',
1159
+ borderRadius: '8px',
1160
+ padding: '8px 16px',
1161
+ fontSize: '13px'
1162
+ }
1163
+ }
779
1164
  ];
780
1165
 
781
1166
  const edges = [
782
- { from: 'main', to: 'browser' },
783
- { from: 'main', to: 'api' },
784
- { from: 'main', to: 'auth' },
785
- { from: 'browser', to: 'ui' },
786
- { from: 'api', to: 'perf' },
787
- { from: 'auth', to: 'security' }
1167
+ { id: 'e1', source: 'main', target: 'browser', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
1168
+ { id: 'e2', source: 'main', target: 'api', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
1169
+ { id: 'e3', source: 'main', target: 'auth', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
1170
+ { id: 'e4', source: 'browser', target: 'ui', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
1171
+ { id: 'e5', source: 'api', target: 'perf', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
1172
+ { id: 'e6', source: 'auth', target: 'security', animated: true, style: { stroke: '#334155', strokeWidth: 2 } }
788
1173
  ];
789
1174
 
790
- const data = { nodes, edges };
791
-
792
- hierarchyNetwork = new vis.Network(container, data, {
793
- nodes: {
794
- font: { color: '#e2e8f0', size: 14 },
795
- borderWidth: 2,
796
- shadow: true
797
- },
798
- edges: {
799
- color: { color: '#334155' },
800
- width: 2,
801
- shadow: true
802
- },
803
- physics: {
804
- enabled: true,
805
- stabilization: { iterations: 100 }
806
- },
807
- interaction: {
808
- hover: true,
809
- tooltipDelay: 200
810
- }
811
- });
1175
+ // Simple React Flow implementation without React dependency
1176
+ container.innerHTML = \`
1177
+ <svg width="100%" height="100%" style="background: #0f172a; border-radius: 8px;">
1178
+ <!-- Edges -->
1179
+ \${edges.map(edge => {
1180
+ const sourceNode = nodes.find(n => n.id === edge.source);
1181
+ const targetNode = nodes.find(n => n.id === edge.target);
1182
+ return \`
1183
+ <line
1184
+ x1="\${sourceNode.position.x + 60}"
1185
+ y1="\${sourceNode.position.y + 20}"
1186
+ x2="\${targetNode.position.x + 60}"
1187
+ y2="\${targetNode.position.y + 20}"
1188
+ stroke="\${edge.style.stroke}"
1189
+ stroke-width="\${edge.style.strokeWidth}"
1190
+ stroke-dasharray="5,5"
1191
+ opacity="0.6">
1192
+ <animate attributeName="stroke-dashoffset" values="0;10" dur="1s" repeatCount="indefinite"/>
1193
+ </line>
1194
+ \`;
1195
+ }).join('')}
1196
+
1197
+ <!-- Nodes -->
1198
+ \${nodes.map(node => \`
1199
+ <g transform="translate(\${node.position.x}, \${node.position.y})">
1200
+ <rect
1201
+ x="0" y="0" width="120" height="40"
1202
+ fill="\${node.style.background}"
1203
+ stroke="\${node.style.border}"
1204
+ stroke-width="\${node.style.border.split(' ')[0].replace('px', '')}"
1205
+ rx="8" ry="8"
1206
+ style="filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.3))"/>
1207
+ <text
1208
+ x="60" y="25"
1209
+ text-anchor="middle"
1210
+ fill="\${node.style.color}"
1211
+ font-size="\${node.style.fontSize}"
1212
+ font-weight="bold">
1213
+ \${node.data.label}
1214
+ </text>
1215
+ </g>
1216
+ \`).join('')}
1217
+ </svg>
1218
+ \`;
812
1219
  }
813
1220
 
814
1221
  // Tab switching
@@ -1019,7 +1426,7 @@ async function startWebServer() {
1019
1426
  <strong>\${task.name}</strong>
1020
1427
  <span class="status \${task.status.replace(' ', '-')}">\${task.status}</span>
1021
1428
  </div>
1022
- \${task.progress ? \`<div style="color: #38bdf8;">\${task.progress}</div>\` : ''}
1429
+ \${task.progress ? \`<div style="color: #f97316;">\${task.progress}</div>\` : ''}
1023
1430
  </div>
1024
1431
  <div class="activity-time">Agent: \${task.agent} | Started: \${new Date(task.started_at).toLocaleTimeString()}</div>
1025
1432
  \${task.result ? \`<div style="color: #10b981; margin-top: 8px; padding: 8px; background: rgba(16, 185, 129, 0.1); border-radius: 6px;">\${task.result}</div>\` : ''}