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