@openqa/cli 1.3.0 → 1.3.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.
package/dist/cli/index.js CHANGED
@@ -432,13 +432,13 @@ 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
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; }
438
+ h1 { color: #f97316; margin-bottom: 30px; }
439
439
  .card { background: #1e293b; border: 1px solid #334155; border-radius: 12px; padding: 24px; margin: 20px 0; }
440
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; }
441
+ .card-title { font-size: 18px; font-weight: 600; color: #f97316; }
442
442
  .status { display: inline-block; padding: 6px 12px; border-radius: 20px; font-size: 12px; font-weight: 500; }
443
443
  .status.running { background: linear-gradient(135deg, #10b981, #059669); color: white; }
444
444
  .status.idle { background: linear-gradient(135deg, #f59e0b, #d97706); color: white; }
@@ -447,7 +447,7 @@ async function startWebServer() {
447
447
  .nav { display: flex; justify-content: space-between; align-items: center; margin: 20px 0; padding: 15px; background: #1e293b; border-radius: 12px; }
448
448
  .nav-links { display: flex; gap: 30px; }
449
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; }
450
+ .nav-links a:hover, .nav-links a.active { color: #f97316; }
451
451
  .grid { display: grid; gap: 20px; }
452
452
  .grid-2 { grid-template-columns: repeat(2, 1fr); }
453
453
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
@@ -461,8 +461,8 @@ async function startWebServer() {
461
461
  position: relative;
462
462
  overflow: hidden;
463
463
  }
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; }
464
+ .metric-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, #f97316, #ea580c); }
465
+ .metric-value { font-size: 32px; font-weight: bold; color: #f97316; margin: 10px 0; }
466
466
  .metric-label { color: #94a3b8; font-size: 14px; font-weight: 500; }
467
467
  .metric-change { font-size: 12px; margin-top: 5px; }
468
468
  .metric-change.positive { color: #10b981; }
@@ -474,7 +474,7 @@ async function startWebServer() {
474
474
  padding: 15px;
475
475
  margin: 10px 0;
476
476
  border-radius: 8px;
477
- border-left: 4px solid #38bdf8;
477
+ border-left: 4px solid #f97316;
478
478
  font-size: 14px;
479
479
  transition: all 0.2s;
480
480
  }
@@ -494,7 +494,7 @@ async function startWebServer() {
494
494
  .intervention-request::before { content: '\u{1F6A8}'; position: absolute; top: 15px; right: 15px; font-size: 20px; }
495
495
  .intervention-request h4 { color: #fbbf24; margin: 0 0 10px 0; }
496
496
  .btn {
497
- background: linear-gradient(135deg, #38bdf8, #0ea5e9);
497
+ background: linear-gradient(135deg, #f97316, #ea580c);
498
498
  color: white;
499
499
  border: none;
500
500
  padding: 10px 20px;
@@ -505,7 +505,7 @@ async function startWebServer() {
505
505
  margin: 5px;
506
506
  transition: all 0.2s;
507
507
  }
508
- .btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(56, 189, 248, 0.3); }
508
+ .btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(249, 115, 22, 0.3); }
509
509
  .btn-success { background: linear-gradient(135deg, #10b981, #059669); }
510
510
  .btn-success:hover { box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3); }
511
511
  .btn-danger { background: linear-gradient(135deg, #ef4444, #dc2626); }
@@ -515,12 +515,12 @@ async function startWebServer() {
515
515
  .loading { color: #f59e0b; }
516
516
  .tabs { display: flex; gap: 10px; margin-bottom: 20px; }
517
517
  .tab { padding: 10px 20px; background: #334155; border-radius: 8px; cursor: pointer; transition: all 0.2s; }
518
- .tab.active { background: #38bdf8; color: white; }
518
+ .tab.active { background: #f97316; color: white; }
519
519
  .tab-content { display: none; }
520
520
  .tab-content.active { display: block; }
521
521
  .agent-node {
522
522
  background: #1e293b;
523
- border: 2px solid #38bdf8;
523
+ border: 2px solid #f97316;
524
524
  border-radius: 8px;
525
525
  padding: 10px;
526
526
  margin: 10px;
@@ -535,7 +535,7 @@ async function startWebServer() {
535
535
  }
536
536
  .performance-fill {
537
537
  height: 100%;
538
- background: linear-gradient(90deg, #10b981, #38bdf8);
538
+ background: linear-gradient(90deg, #10b981, #f97316);
539
539
  transition: width 1s ease;
540
540
  }
541
541
  </style>
@@ -727,8 +727,8 @@ async function startWebServer() {
727
727
  datasets: [{
728
728
  label: 'Actions/min',
729
729
  data: [12, 19, 15, 25, 22, 30, 28],
730
- borderColor: '#38bdf8',
731
- backgroundColor: 'rgba(56, 189, 248, 0.1)',
730
+ borderColor: '#f97316',
731
+ backgroundColor: 'rgba(249, 115, 22, 0.1)',
732
732
  tension: 0.4
733
733
  }, {
734
734
  label: 'Success Rate %',
@@ -760,7 +760,7 @@ async function startWebServer() {
760
760
  datasets: [{
761
761
  label: 'Tests Generated',
762
762
  data: [65, 78, 90, 81, 56, 45, 30],
763
- backgroundColor: '#38bdf8'
763
+ backgroundColor: '#f97316'
764
764
  }, {
765
765
  label: 'Bugs Found',
766
766
  data: [12, 19, 15, 25, 22, 15, 8],
@@ -788,7 +788,7 @@ async function startWebServer() {
788
788
  labels: ['Success', 'Warnings', 'Errors', 'Critical'],
789
789
  datasets: [{
790
790
  data: [75, 15, 8, 2],
791
- backgroundColor: ['#10b981', '#f59e0b', '#ef4444', '#dc2626']
791
+ backgroundColor: ['#10b981', '#f97316', '#ef4444', '#dc2626']
792
792
  }]
793
793
  },
794
794
  options: {
@@ -801,51 +801,166 @@ async function startWebServer() {
801
801
  });
802
802
  }
803
803
 
804
- // Initialize Agent Hierarchy
804
+ // Initialize Agent Hierarchy with React Flow
805
805
  function initHierarchy() {
806
806
  const container = document.getElementById('hierarchy-container');
807
807
 
808
+ // Create React Flow nodes
808
809
  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' }
810
+ {
811
+ id: 'main',
812
+ type: 'default',
813
+ position: { x: 400, y: 50 },
814
+ data: { label: '\u{1F916} Main Agent' },
815
+ style: {
816
+ background: '#f97316',
817
+ color: 'white',
818
+ border: '2px solid #ea580c',
819
+ borderRadius: '8px',
820
+ padding: '10px 20px',
821
+ fontSize: '14px',
822
+ fontWeight: 'bold'
823
+ }
824
+ },
825
+ {
826
+ id: 'browser',
827
+ type: 'default',
828
+ position: { x: 150, y: 200 },
829
+ data: { label: '\u{1F310} Browser Specialist' },
830
+ style: {
831
+ background: '#10b981',
832
+ color: 'white',
833
+ border: '2px solid #059669',
834
+ borderRadius: '8px',
835
+ padding: '8px 16px',
836
+ fontSize: '13px'
837
+ }
838
+ },
839
+ {
840
+ id: 'api',
841
+ type: 'default',
842
+ position: { x: 400, y: 200 },
843
+ data: { label: '\u{1F50C} API Tester' },
844
+ style: {
845
+ background: '#f59e0b',
846
+ color: 'white',
847
+ border: '2px solid #d97706',
848
+ borderRadius: '8px',
849
+ padding: '8px 16px',
850
+ fontSize: '13px'
851
+ }
852
+ },
853
+ {
854
+ id: 'auth',
855
+ type: 'default',
856
+ position: { x: 650, y: 200 },
857
+ data: { label: '\u{1F510} Auth Specialist' },
858
+ style: {
859
+ background: '#ef4444',
860
+ color: 'white',
861
+ border: '2px solid #dc2626',
862
+ borderRadius: '8px',
863
+ padding: '8px 16px',
864
+ fontSize: '13px'
865
+ }
866
+ },
867
+ {
868
+ id: 'ui',
869
+ type: 'default',
870
+ position: { x: 150, y: 350 },
871
+ data: { label: '\u{1F3A8} UI Tester' },
872
+ style: {
873
+ background: '#8b5cf6',
874
+ color: 'white',
875
+ border: '2px solid #7c3aed',
876
+ borderRadius: '8px',
877
+ padding: '8px 16px',
878
+ fontSize: '13px'
879
+ }
880
+ },
881
+ {
882
+ id: 'perf',
883
+ type: 'default',
884
+ position: { x: 400, y: 350 },
885
+ data: { label: '\u26A1 Performance Tester' },
886
+ style: {
887
+ background: '#06b6d4',
888
+ color: 'white',
889
+ border: '2px solid #0891b2',
890
+ borderRadius: '8px',
891
+ padding: '8px 16px',
892
+ fontSize: '13px'
893
+ }
894
+ },
895
+ {
896
+ id: 'security',
897
+ type: 'default',
898
+ position: { x: 650, y: 350 },
899
+ data: { label: '\u{1F6E1}\uFE0F Security Scanner' },
900
+ style: {
901
+ background: '#f97316',
902
+ color: 'white',
903
+ border: '2px solid #ea580c',
904
+ borderRadius: '8px',
905
+ padding: '8px 16px',
906
+ fontSize: '13px'
907
+ }
908
+ }
816
909
  ];
817
910
 
818
911
  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' }
912
+ { id: 'e1', source: 'main', target: 'browser', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
913
+ { id: 'e2', source: 'main', target: 'api', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
914
+ { id: 'e3', source: 'main', target: 'auth', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
915
+ { id: 'e4', source: 'browser', target: 'ui', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
916
+ { id: 'e5', source: 'api', target: 'perf', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
917
+ { id: 'e6', source: 'auth', target: 'security', animated: true, style: { stroke: '#334155', strokeWidth: 2 } }
825
918
  ];
826
919
 
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
- });
920
+ // Simple React Flow implementation without React dependency
921
+ container.innerHTML = \`
922
+ <svg width="100%" height="100%" style="background: #0f172a; border-radius: 8px;">
923
+ <!-- Edges -->
924
+ \${edges.map(edge => {
925
+ const sourceNode = nodes.find(n => n.id === edge.source);
926
+ const targetNode = nodes.find(n => n.id === edge.target);
927
+ return \`
928
+ <line
929
+ x1="\${sourceNode.position.x + 60}"
930
+ y1="\${sourceNode.position.y + 20}"
931
+ x2="\${targetNode.position.x + 60}"
932
+ y2="\${targetNode.position.y + 20}"
933
+ stroke="\${edge.style.stroke}"
934
+ stroke-width="\${edge.style.strokeWidth}"
935
+ stroke-dasharray="5,5"
936
+ opacity="0.6">
937
+ <animate attributeName="stroke-dashoffset" values="0;10" dur="1s" repeatCount="indefinite"/>
938
+ </line>
939
+ \`;
940
+ }).join('')}
941
+
942
+ <!-- Nodes -->
943
+ \${nodes.map(node => \`
944
+ <g transform="translate(\${node.position.x}, \${node.position.y})">
945
+ <rect
946
+ x="0" y="0" width="120" height="40"
947
+ fill="\${node.style.background}"
948
+ stroke="\${node.style.border}"
949
+ stroke-width="\${node.style.border.split(' ')[0].replace('px', '')}"
950
+ rx="8" ry="8"
951
+ style="filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.3))"/>
952
+ <text
953
+ x="60" y="25"
954
+ text-anchor="middle"
955
+ fill="\${node.style.color}"
956
+ font-size="\${node.style.fontSize}"
957
+ font-weight="bold">
958
+ \${node.data.label}
959
+ </text>
960
+ </g>
961
+ \`).join('')}
962
+ </svg>
963
+ \`;
849
964
  }
850
965
 
851
966
  // Tab switching
@@ -1056,7 +1171,7 @@ async function startWebServer() {
1056
1171
  <strong>\${task.name}</strong>
1057
1172
  <span class="status \${task.status.replace(' ', '-')}">\${task.status}</span>
1058
1173
  </div>
1059
- \${task.progress ? \`<div style="color: #38bdf8;">\${task.progress}</div>\` : ''}
1174
+ \${task.progress ? \`<div style="color: #f97316;">\${task.progress}</div>\` : ''}
1060
1175
  </div>
1061
1176
  <div class="activity-time">Agent: \${task.agent} | Started: \${new Date(task.started_at).toLocaleTimeString()}</div>
1062
1177
  \${task.result ? \`<div style="color: #10b981; margin-top: 8px; padding: 8px; background: rgba(16, 185, 129, 0.1); border-radius: 6px;">\${task.result}</div>\` : ''}
@@ -395,13 +395,13 @@ 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
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; }
401
+ h1 { color: #f97316; margin-bottom: 30px; }
402
402
  .card { background: #1e293b; border: 1px solid #334155; border-radius: 12px; padding: 24px; margin: 20px 0; }
403
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; }
404
+ .card-title { font-size: 18px; font-weight: 600; color: #f97316; }
405
405
  .status { display: inline-block; padding: 6px 12px; border-radius: 20px; font-size: 12px; font-weight: 500; }
406
406
  .status.running { background: linear-gradient(135deg, #10b981, #059669); color: white; }
407
407
  .status.idle { background: linear-gradient(135deg, #f59e0b, #d97706); color: white; }
@@ -410,7 +410,7 @@ async function startWebServer() {
410
410
  .nav { display: flex; justify-content: space-between; align-items: center; margin: 20px 0; padding: 15px; background: #1e293b; border-radius: 12px; }
411
411
  .nav-links { display: flex; gap: 30px; }
412
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; }
413
+ .nav-links a:hover, .nav-links a.active { color: #f97316; }
414
414
  .grid { display: grid; gap: 20px; }
415
415
  .grid-2 { grid-template-columns: repeat(2, 1fr); }
416
416
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
@@ -424,8 +424,8 @@ async function startWebServer() {
424
424
  position: relative;
425
425
  overflow: hidden;
426
426
  }
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; }
427
+ .metric-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, #f97316, #ea580c); }
428
+ .metric-value { font-size: 32px; font-weight: bold; color: #f97316; margin: 10px 0; }
429
429
  .metric-label { color: #94a3b8; font-size: 14px; font-weight: 500; }
430
430
  .metric-change { font-size: 12px; margin-top: 5px; }
431
431
  .metric-change.positive { color: #10b981; }
@@ -437,7 +437,7 @@ async function startWebServer() {
437
437
  padding: 15px;
438
438
  margin: 10px 0;
439
439
  border-radius: 8px;
440
- border-left: 4px solid #38bdf8;
440
+ border-left: 4px solid #f97316;
441
441
  font-size: 14px;
442
442
  transition: all 0.2s;
443
443
  }
@@ -457,7 +457,7 @@ async function startWebServer() {
457
457
  .intervention-request::before { content: '\u{1F6A8}'; position: absolute; top: 15px; right: 15px; font-size: 20px; }
458
458
  .intervention-request h4 { color: #fbbf24; margin: 0 0 10px 0; }
459
459
  .btn {
460
- background: linear-gradient(135deg, #38bdf8, #0ea5e9);
460
+ background: linear-gradient(135deg, #f97316, #ea580c);
461
461
  color: white;
462
462
  border: none;
463
463
  padding: 10px 20px;
@@ -468,7 +468,7 @@ async function startWebServer() {
468
468
  margin: 5px;
469
469
  transition: all 0.2s;
470
470
  }
471
- .btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(56, 189, 248, 0.3); }
471
+ .btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(249, 115, 22, 0.3); }
472
472
  .btn-success { background: linear-gradient(135deg, #10b981, #059669); }
473
473
  .btn-success:hover { box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3); }
474
474
  .btn-danger { background: linear-gradient(135deg, #ef4444, #dc2626); }
@@ -478,12 +478,12 @@ async function startWebServer() {
478
478
  .loading { color: #f59e0b; }
479
479
  .tabs { display: flex; gap: 10px; margin-bottom: 20px; }
480
480
  .tab { padding: 10px 20px; background: #334155; border-radius: 8px; cursor: pointer; transition: all 0.2s; }
481
- .tab.active { background: #38bdf8; color: white; }
481
+ .tab.active { background: #f97316; color: white; }
482
482
  .tab-content { display: none; }
483
483
  .tab-content.active { display: block; }
484
484
  .agent-node {
485
485
  background: #1e293b;
486
- border: 2px solid #38bdf8;
486
+ border: 2px solid #f97316;
487
487
  border-radius: 8px;
488
488
  padding: 10px;
489
489
  margin: 10px;
@@ -498,7 +498,7 @@ async function startWebServer() {
498
498
  }
499
499
  .performance-fill {
500
500
  height: 100%;
501
- background: linear-gradient(90deg, #10b981, #38bdf8);
501
+ background: linear-gradient(90deg, #10b981, #f97316);
502
502
  transition: width 1s ease;
503
503
  }
504
504
  </style>
@@ -690,8 +690,8 @@ async function startWebServer() {
690
690
  datasets: [{
691
691
  label: 'Actions/min',
692
692
  data: [12, 19, 15, 25, 22, 30, 28],
693
- borderColor: '#38bdf8',
694
- backgroundColor: 'rgba(56, 189, 248, 0.1)',
693
+ borderColor: '#f97316',
694
+ backgroundColor: 'rgba(249, 115, 22, 0.1)',
695
695
  tension: 0.4
696
696
  }, {
697
697
  label: 'Success Rate %',
@@ -723,7 +723,7 @@ async function startWebServer() {
723
723
  datasets: [{
724
724
  label: 'Tests Generated',
725
725
  data: [65, 78, 90, 81, 56, 45, 30],
726
- backgroundColor: '#38bdf8'
726
+ backgroundColor: '#f97316'
727
727
  }, {
728
728
  label: 'Bugs Found',
729
729
  data: [12, 19, 15, 25, 22, 15, 8],
@@ -751,7 +751,7 @@ async function startWebServer() {
751
751
  labels: ['Success', 'Warnings', 'Errors', 'Critical'],
752
752
  datasets: [{
753
753
  data: [75, 15, 8, 2],
754
- backgroundColor: ['#10b981', '#f59e0b', '#ef4444', '#dc2626']
754
+ backgroundColor: ['#10b981', '#f97316', '#ef4444', '#dc2626']
755
755
  }]
756
756
  },
757
757
  options: {
@@ -764,51 +764,166 @@ async function startWebServer() {
764
764
  });
765
765
  }
766
766
 
767
- // Initialize Agent Hierarchy
767
+ // Initialize Agent Hierarchy with React Flow
768
768
  function initHierarchy() {
769
769
  const container = document.getElementById('hierarchy-container');
770
770
 
771
+ // Create React Flow nodes
771
772
  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' }
773
+ {
774
+ id: 'main',
775
+ type: 'default',
776
+ position: { x: 400, y: 50 },
777
+ data: { label: '\u{1F916} Main Agent' },
778
+ style: {
779
+ background: '#f97316',
780
+ color: 'white',
781
+ border: '2px solid #ea580c',
782
+ borderRadius: '8px',
783
+ padding: '10px 20px',
784
+ fontSize: '14px',
785
+ fontWeight: 'bold'
786
+ }
787
+ },
788
+ {
789
+ id: 'browser',
790
+ type: 'default',
791
+ position: { x: 150, y: 200 },
792
+ data: { label: '\u{1F310} Browser Specialist' },
793
+ style: {
794
+ background: '#10b981',
795
+ color: 'white',
796
+ border: '2px solid #059669',
797
+ borderRadius: '8px',
798
+ padding: '8px 16px',
799
+ fontSize: '13px'
800
+ }
801
+ },
802
+ {
803
+ id: 'api',
804
+ type: 'default',
805
+ position: { x: 400, y: 200 },
806
+ data: { label: '\u{1F50C} API Tester' },
807
+ style: {
808
+ background: '#f59e0b',
809
+ color: 'white',
810
+ border: '2px solid #d97706',
811
+ borderRadius: '8px',
812
+ padding: '8px 16px',
813
+ fontSize: '13px'
814
+ }
815
+ },
816
+ {
817
+ id: 'auth',
818
+ type: 'default',
819
+ position: { x: 650, y: 200 },
820
+ data: { label: '\u{1F510} Auth Specialist' },
821
+ style: {
822
+ background: '#ef4444',
823
+ color: 'white',
824
+ border: '2px solid #dc2626',
825
+ borderRadius: '8px',
826
+ padding: '8px 16px',
827
+ fontSize: '13px'
828
+ }
829
+ },
830
+ {
831
+ id: 'ui',
832
+ type: 'default',
833
+ position: { x: 150, y: 350 },
834
+ data: { label: '\u{1F3A8} UI Tester' },
835
+ style: {
836
+ background: '#8b5cf6',
837
+ color: 'white',
838
+ border: '2px solid #7c3aed',
839
+ borderRadius: '8px',
840
+ padding: '8px 16px',
841
+ fontSize: '13px'
842
+ }
843
+ },
844
+ {
845
+ id: 'perf',
846
+ type: 'default',
847
+ position: { x: 400, y: 350 },
848
+ data: { label: '\u26A1 Performance Tester' },
849
+ style: {
850
+ background: '#06b6d4',
851
+ color: 'white',
852
+ border: '2px solid #0891b2',
853
+ borderRadius: '8px',
854
+ padding: '8px 16px',
855
+ fontSize: '13px'
856
+ }
857
+ },
858
+ {
859
+ id: 'security',
860
+ type: 'default',
861
+ position: { x: 650, y: 350 },
862
+ data: { label: '\u{1F6E1}\uFE0F Security Scanner' },
863
+ style: {
864
+ background: '#f97316',
865
+ color: 'white',
866
+ border: '2px solid #ea580c',
867
+ borderRadius: '8px',
868
+ padding: '8px 16px',
869
+ fontSize: '13px'
870
+ }
871
+ }
779
872
  ];
780
873
 
781
874
  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' }
875
+ { id: 'e1', source: 'main', target: 'browser', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
876
+ { id: 'e2', source: 'main', target: 'api', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
877
+ { id: 'e3', source: 'main', target: 'auth', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
878
+ { id: 'e4', source: 'browser', target: 'ui', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
879
+ { id: 'e5', source: 'api', target: 'perf', animated: true, style: { stroke: '#334155', strokeWidth: 2 } },
880
+ { id: 'e6', source: 'auth', target: 'security', animated: true, style: { stroke: '#334155', strokeWidth: 2 } }
788
881
  ];
789
882
 
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
- });
883
+ // Simple React Flow implementation without React dependency
884
+ container.innerHTML = \`
885
+ <svg width="100%" height="100%" style="background: #0f172a; border-radius: 8px;">
886
+ <!-- Edges -->
887
+ \${edges.map(edge => {
888
+ const sourceNode = nodes.find(n => n.id === edge.source);
889
+ const targetNode = nodes.find(n => n.id === edge.target);
890
+ return \`
891
+ <line
892
+ x1="\${sourceNode.position.x + 60}"
893
+ y1="\${sourceNode.position.y + 20}"
894
+ x2="\${targetNode.position.x + 60}"
895
+ y2="\${targetNode.position.y + 20}"
896
+ stroke="\${edge.style.stroke}"
897
+ stroke-width="\${edge.style.strokeWidth}"
898
+ stroke-dasharray="5,5"
899
+ opacity="0.6">
900
+ <animate attributeName="stroke-dashoffset" values="0;10" dur="1s" repeatCount="indefinite"/>
901
+ </line>
902
+ \`;
903
+ }).join('')}
904
+
905
+ <!-- Nodes -->
906
+ \${nodes.map(node => \`
907
+ <g transform="translate(\${node.position.x}, \${node.position.y})">
908
+ <rect
909
+ x="0" y="0" width="120" height="40"
910
+ fill="\${node.style.background}"
911
+ stroke="\${node.style.border}"
912
+ stroke-width="\${node.style.border.split(' ')[0].replace('px', '')}"
913
+ rx="8" ry="8"
914
+ style="filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.3))"/>
915
+ <text
916
+ x="60" y="25"
917
+ text-anchor="middle"
918
+ fill="\${node.style.color}"
919
+ font-size="\${node.style.fontSize}"
920
+ font-weight="bold">
921
+ \${node.data.label}
922
+ </text>
923
+ </g>
924
+ \`).join('')}
925
+ </svg>
926
+ \`;
812
927
  }
813
928
 
814
929
  // Tab switching
@@ -1019,7 +1134,7 @@ async function startWebServer() {
1019
1134
  <strong>\${task.name}</strong>
1020
1135
  <span class="status \${task.status.replace(' ', '-')}">\${task.status}</span>
1021
1136
  </div>
1022
- \${task.progress ? \`<div style="color: #38bdf8;">\${task.progress}</div>\` : ''}
1137
+ \${task.progress ? \`<div style="color: #f97316;">\${task.progress}</div>\` : ''}
1023
1138
  </div>
1024
1139
  <div class="activity-time">Agent: \${task.agent} | Started: \${new Date(task.started_at).toLocaleTimeString()}</div>
1025
1140
  \${task.result ? \`<div style="color: #10b981; margin-top: 8px; padding: 8px; background: rgba(16, 185, 129, 0.1); border-radius: 6px;">\${task.result}</div>\` : ''}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openqa/cli",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Autonomous QA testing agent powered by Orka.js",
5
5
  "type": "module",
6
6
  "main": "./dist/cli/index.js",