@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 +168 -53
- package/dist/cli/server.js +168 -53
- package/package.json +1 -1
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/
|
|
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: #
|
|
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: #
|
|
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: #
|
|
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, #
|
|
465
|
-
.metric-value { font-size: 32px; font-weight: bold; color: #
|
|
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 #
|
|
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, #
|
|
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(
|
|
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: #
|
|
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 #
|
|
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, #
|
|
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: '#
|
|
731
|
-
backgroundColor: 'rgba(
|
|
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: '#
|
|
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', '#
|
|
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
|
-
{
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
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
|
-
{
|
|
820
|
-
{
|
|
821
|
-
{
|
|
822
|
-
{
|
|
823
|
-
{
|
|
824
|
-
{
|
|
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
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
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: #
|
|
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>\` : ''}
|
package/dist/cli/server.js
CHANGED
|
@@ -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/
|
|
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: #
|
|
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: #
|
|
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: #
|
|
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, #
|
|
428
|
-
.metric-value { font-size: 32px; font-weight: bold; color: #
|
|
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 #
|
|
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, #
|
|
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(
|
|
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: #
|
|
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 #
|
|
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, #
|
|
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: '#
|
|
694
|
-
backgroundColor: 'rgba(
|
|
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: '#
|
|
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', '#
|
|
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
|
-
{
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
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
|
-
{
|
|
783
|
-
{
|
|
784
|
-
{
|
|
785
|
-
{
|
|
786
|
-
{
|
|
787
|
-
{
|
|
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
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
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: #
|
|
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>\` : ''}
|