molliexx99 commited on
Commit
8f2503b
·
verified ·
1 Parent(s): 16f4336

Please ensure that the hint/info boxes do not get obstructed by the edges of the timeline's area, ensure that these boxes are on-top/overlay any/all other visual elements on the web-page. - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +1215 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Maias
3
- emoji: 🏆
4
- colorFrom: green
5
- colorTo: gray
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: maias
3
+ emoji: 🐳
4
+ colorFrom: pink
5
+ colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1215 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Multi-Agent Orchestration Demo</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <script>
10
+ tailwind.config = {
11
+ theme: {
12
+ extend: {
13
+ colors: {
14
+ primary: '#3b82f6',
15
+ secondary: '#10b981',
16
+ accent: '#8b5cf6',
17
+ warning: '#f59e0b',
18
+ danger: '#ef4444',
19
+ dark: '#1e293b',
20
+ light: '#f8fafc'
21
+ }
22
+ }
23
+ }
24
+ }
25
+ </script>
26
+ <style>
27
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
28
+
29
+ body {
30
+ font-family: 'Inter', sans-serif;
31
+ background: linear-gradient(135deg, #0f172a, #1e293b);
32
+ color: #f1f5f9;
33
+ }
34
+
35
+ .card {
36
+ background: rgba(30, 41, 59, 0.7);
37
+ backdrop-filter: blur(10px);
38
+ border: 1px solid rgba(100, 116, 139, 0.3);
39
+ border-radius: 16px;
40
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.25);
41
+ }
42
+
43
+ .card-header {
44
+ border-bottom: 1px solid rgba(148, 163, 184, 0.3);
45
+ padding-bottom: 1rem;
46
+ }
47
+
48
+ .btn {
49
+ font-weight: 600;
50
+ padding: 0.75rem 1.5rem;
51
+ border-radius: 12px;
52
+ transition: all 0.3s ease;
53
+ display: inline-flex;
54
+ align-items: center;
55
+ justify-content: center;
56
+ border: none;
57
+ cursor: pointer;
58
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
59
+ }
60
+
61
+ .btn-primary {
62
+ background: linear-gradient(90deg, #3b82f6, #60a5fa);
63
+ color: white;
64
+ }
65
+
66
+ .btn-primary:hover {
67
+ background: linear-gradient(90deg, #2563eb, #3b82f6);
68
+ transform: translateY(-2px);
69
+ box-shadow: 0 10px 15px -3px rgba(59, 130, 246, 0.3);
70
+ }
71
+
72
+ .btn-secondary {
73
+ background: rgba(100, 116, 139, 0.3);
74
+ color: #f1f5f9;
75
+ }
76
+
77
+ .btn-secondary:hover {
78
+ background: rgba(100, 116, 139, 0.5);
79
+ transform: translateY(-2px);
80
+ }
81
+
82
+ .btn-danger {
83
+ background: linear-gradient(90deg, #ef4444, #f87171);
84
+ color: white;
85
+ }
86
+
87
+ .btn-danger:hover {
88
+ background: linear-gradient(90deg, #dc2626, #ef4444);
89
+ transform: translateY(-2px);
90
+ box-shadow: 0 10px 15px -3px rgba(239, 68, 68, 0.3);
91
+ }
92
+
93
+ .btn-icon {
94
+ margin-right: 0.5rem;
95
+ }
96
+
97
+ .toggle-container {
98
+ position: relative;
99
+ display: inline-block;
100
+ width: 60px;
101
+ height: 30px;
102
+ }
103
+
104
+ .toggle-container input {
105
+ opacity: 0;
106
+ width: 0;
107
+ height: 0;
108
+ }
109
+
110
+ .toggle-slider {
111
+ position: absolute;
112
+ cursor: pointer;
113
+ top: 0;
114
+ left: 0;
115
+ right: 0;
116
+ bottom: 0;
117
+ background: linear-gradient(90deg, #334155, #475569);
118
+ transition: .4s;
119
+ border-radius: 30px;
120
+ }
121
+
122
+ .toggle-slider:before {
123
+ position: absolute;
124
+ content: "";
125
+ height: 22px;
126
+ width: 22px;
127
+ left: 4px;
128
+ bottom: 4px;
129
+ background: white;
130
+ transition: .4s;
131
+ border-radius: 50%;
132
+ }
133
+
134
+ input:checked + .toggle-slider {
135
+ background: linear-gradient(90deg, #3b82f6, #60a5fa);
136
+ }
137
+
138
+ input:checked + .toggle-slider:before {
139
+ transform: translateX(30px);
140
+ }
141
+
142
+ .agent-timeline {
143
+ max-height: 500px;
144
+ overflow-y: auto;
145
+ padding-right: 10px;
146
+ }
147
+
148
+ .timeline-container {
149
+ min-height: 600px;
150
+ height: 100%;
151
+ display: flex;
152
+ flex-direction: column;
153
+ flex: 1;
154
+ }
155
+
156
+ .agent-timeline {
157
+ flex: 1;
158
+ overflow-y: auto;
159
+ }
160
+
161
+ .timeline-item {
162
+ position: relative;
163
+ padding-left: 40px;
164
+ margin-bottom: 30px;
165
+ }
166
+
167
+ .timeline-item:before {
168
+ content: '';
169
+ position: absolute;
170
+ left: 15px;
171
+ top: 0;
172
+ bottom: 0;
173
+ width: 2px;
174
+ background: linear-gradient(to bottom, #3b82f6, #94a3b8);
175
+ }
176
+
177
+ .timeline-item:last-child:before {
178
+ height: 20px;
179
+ }
180
+
181
+ .avatar {
182
+ position: absolute;
183
+ left: -15px;
184
+ top: 0;
185
+ width: 36px;
186
+ height: 36px;
187
+ border-radius: 50%;
188
+ display: flex;
189
+ align-items: center;
190
+ justify-content: center;
191
+ color: white;
192
+ font-weight: bold;
193
+ font-size: 14px;
194
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
195
+ z-index: 2;
196
+ }
197
+
198
+ .collapsible-content {
199
+ max-height: 0;
200
+ overflow: hidden;
201
+ transition: max-height 0.3s ease-out;
202
+ }
203
+
204
+ .collapsible-content.active {
205
+ max-height: 500px;
206
+ }
207
+
208
+ .decision-card {
209
+ transition: all 0.3s ease;
210
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
211
+ border-radius: 16px;
212
+ overflow: hidden;
213
+ }
214
+
215
+ .decision-card:hover {
216
+ transform: translateY(-3px);
217
+ box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
218
+ }
219
+
220
+ .tool-call {
221
+ background: rgba(255, 255, 255, 0.05);
222
+ border-left: 3px solid #3b82f6;
223
+ border-radius: 8px;
224
+ margin-bottom: 10px;
225
+ position: relative;
226
+ }
227
+
228
+ .tool-call:hover {
229
+ background: rgba(255, 255, 255, 0.1);
230
+ }
231
+
232
+ /* Hover info tooltip */
233
+ .hover-info {
234
+ position: absolute;
235
+ bottom: 100%;
236
+ left: 50%;
237
+ transform: translateX(-50%);
238
+ background: rgba(30, 41, 59, 0.95);
239
+ color: #f1f5f9;
240
+ padding: 12px;
241
+ border-radius: 8px;
242
+ width: 300px;
243
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
244
+ z-index: 1000;
245
+ opacity: 0;
246
+ visibility: hidden;
247
+ transition: opacity 0.3s ease, visibility 0.3s ease;
248
+ border: 1px solid rgba(100, 116, 139, 0.5);
249
+ font-size: 0.9rem;
250
+ pointer-events: none;
251
+ }
252
+
253
+ .hover-info:before {
254
+ content: '';
255
+ position: absolute;
256
+ top: 100%;
257
+ left: 50%;
258
+ transform: translateX(-50%);
259
+ border: 6px solid transparent;
260
+ border-top-color: rgba(30, 41, 59, 0.95);
261
+ }
262
+
263
+ .timeline-item:hover .hover-info {
264
+ opacity: 1;
265
+ visibility: visible;
266
+ }
267
+
268
+ /* Adjust positioning for edge cases */
269
+ .timeline-item:first-child .hover-info {
270
+ transform: translateX(-50%);
271
+ left: 50%;
272
+ }
273
+
274
+ .timeline-item:last-child .hover-info {
275
+ transform: translateX(-50%);
276
+ left: 50%;
277
+ }
278
+
279
+ /* Ensure tooltip stays within viewport */
280
+ @media (max-width: 768px) {
281
+ .hover-info {
282
+ left: 0;
283
+ transform: none;
284
+ width: calc(100vw - 80px);
285
+ right: 20px;
286
+ }
287
+
288
+ .hover-info:before {
289
+ left: 20px;
290
+ transform: none;
291
+ }
292
+ }
293
+
294
+ .hover-info h4 {
295
+ font-weight: 600;
296
+ margin-bottom: 8px;
297
+ color: #60a5fa;
298
+ }
299
+
300
+ .hover-info p {
301
+ margin: 0 0 10px 0;
302
+ line-height: 1.4;
303
+ }
304
+
305
+ .hover-info .role {
306
+ font-style: italic;
307
+ color: #94a3b8;
308
+ font-size: 0.85rem;
309
+ margin-bottom: 8px;
310
+ }
311
+
312
+ .hover-info .function {
313
+ background: rgba(59, 130, 246, 0.2);
314
+ padding: 8px;
315
+ border-radius: 6px;
316
+ margin-top: 8px;
317
+ }
318
+
319
+ /* Adjust for top edge visibility */
320
+ .agent-timeline {
321
+ padding: 20px 10px 20px 40px;
322
+ position: relative;
323
+ }
324
+
325
+ .scenario-card {
326
+ transition: all 0.2s ease;
327
+ }
328
+
329
+ .scenario-card:hover {
330
+ transform: translateY(-5px);
331
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
332
+ }
333
+
334
+ .pulse {
335
+ animation: pulse 2s infinite;
336
+ }
337
+
338
+ @keyframes pulse {
339
+ 0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4); }
340
+ 70% { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); }
341
+ 100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
342
+ }
343
+
344
+ .form-control {
345
+ background: rgba(15, 23, 42, 0.5);
346
+ border: 1px solid rgba(148, 163, 184, 0.3);
347
+ border-radius: 12px;
348
+ padding: 0.75rem;
349
+ color: #f1f5f9;
350
+ width: 100%;
351
+ transition: all 0.3s ease;
352
+ }
353
+
354
+ .form-control:focus {
355
+ outline: none;
356
+ border-color: #3b82f6;
357
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3);
358
+ }
359
+
360
+ .form-label {
361
+ display: block;
362
+ margin-bottom: 0.5rem;
363
+ font-weight: 500;
364
+ }
365
+
366
+ .status-approved {
367
+ background: linear-gradient(90deg, #10b981, #34d399);
368
+ color: white;
369
+ }
370
+
371
+ .status-blocked {
372
+ background: linear-gradient(90deg, #ef4444, #f87171);
373
+ color: white;
374
+ }
375
+
376
+ .status-manual {
377
+ background: linear-gradient(90deg, #f59e0b, #fbbf24);
378
+ color: #1e293b;
379
+ }
380
+ </style>
381
+ </head>
382
+ <body class="bg-gray-100 min-h-screen">
383
+ <div class="container mx-auto px-4 py-8">
384
+ <!-- Header -->
385
+ <header class="text-center mb-12">
386
+ <h1 class="text-4xl font-bold text-white mb-2">Multi-Agent Orchestration Demo</h1>
387
+ <p class="text-slate-300 max-w-3xl mx-auto">Simulating intelligent coordination between agents across different scenarios</p>
388
+ </header>
389
+
390
+ <!-- Main Content -->
391
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
392
+ <!-- Left Column - Controls -->
393
+ <div class="lg:col-span-1 space-y-6">
394
+ <!-- Scenario Selector -->
395
+ <div class="card p-6">
396
+ <h2 class="text-xl font-bold text-white mb-4">Scenario Selection</h2>
397
+ <div class="space-y-4">
398
+ <div>
399
+ <label class="form-label">Select Scenario</label>
400
+ <select id="scenarioSelector" class="form-control">
401
+ <option value="devops">DevOps Release Gate</option>
402
+ <option value="security">Security Alert Triage</option>
403
+ <option value="data">Data Pipeline Publish</option>
404
+ <option value="it">IT Onboarding (Helpdesk)</option>
405
+ </select>
406
+ </div>
407
+
408
+ <div class="flex items-center justify-between pt-2">
409
+ <div class="flex items-center">
410
+ <span class="mr-3 text-sm font-medium text-slate-300">Mode:</span>
411
+ <div class="toggle-container">
412
+ <input type="checkbox" id="modeToggle">
413
+ <span class="toggle-slider"></span>
414
+ </div>
415
+ <span class="ml-3 text-sm font-medium text-slate-300">Demo</span>
416
+ <span class="ml-1 text-sm font-medium text-slate-300">Live</span>
417
+ </div>
418
+
419
+ <button id="runButton" class="btn btn-primary">
420
+ <i class="fas fa-play btn-icon"></i> Run Orchestration
421
+ </button>
422
+ </div>
423
+ </div>
424
+ </div>
425
+
426
+ <!-- Dynamic Form -->
427
+ <div class="card p-6">
428
+ <h2 class="text-xl font-bold text-white mb-4">Scenario Inputs</h2>
429
+ <div id="dynamicForm" class="space-y-4">
430
+ <!-- Form will be populated dynamically -->
431
+ </div>
432
+ </div>
433
+
434
+ <!-- Final Decision -->
435
+ <div id="decisionCard" class="card p-6 hidden">
436
+ <h2 class="text-xl font-bold text-white mb-4">Final Decision</h2>
437
+ <div id="decisionContent" class="text-center">
438
+ <!-- Decision content will be populated dynamically -->
439
+ </div>
440
+ </div>
441
+ </div>
442
+
443
+ <!-- Right Column - Agent Timeline -->
444
+ <div class="lg:col-span-2 flex flex-col h-full">
445
+ <div class="card p-6 flex-grow flex flex-col timeline-container">
446
+ <div class="flex justify-between items-center mb-6">
447
+ <h2 class="text-xl font-bold text-white">Agent Orchestration Timeline</h2>
448
+ <div class="flex space-x-2">
449
+ <button id="clearTimeline" class="btn btn-secondary">
450
+ <i class="fas fa-trash btn-icon"></i> Clear
451
+ </button>
452
+ </div>
453
+ </div>
454
+
455
+ <div id="agentTimeline" class="agent-timeline flex-grow">
456
+ <!-- Timeline items will be populated dynamically -->
457
+ <div class="text-center py-10 text-slate-400">
458
+ <i class="fas fa-robot text-4xl mb-3"></i>
459
+ <p>No orchestration run yet. Select a scenario and click "Run Orchestration".</p>
460
+ </div>
461
+ </div>
462
+ </div>
463
+ </div>
464
+ </div>
465
+ </div>
466
+
467
+ <script>
468
+ // Agent definitions with role descriptions
469
+ const agents = {
470
+ mastermind: {
471
+ name: "MasterMind",
472
+ color: "#3b82f6",
473
+ icon: "fas fa-brain",
474
+ role: "Orchestration coordinator that manages the workflow and makes final decisions"
475
+ },
476
+ devassist: {
477
+ name: "DevAssist",
478
+ color: "#10b981",
479
+ icon: "fas fa-code",
480
+ role: "Development expert that reviews code quality and technical implementation"
481
+ },
482
+ cyberguard: {
483
+ name: "CyberGuard",
484
+ color: "#ef4444",
485
+ icon: "fas fa-shield-alt",
486
+ role: "Security specialist that identifies risks and ensures compliance"
487
+ },
488
+ dataflow: {
489
+ name: "DataFlow",
490
+ color: "#8b5cf6",
491
+ icon: "fas fa-database",
492
+ role: "Data expert that validates data quality and pipeline integrity"
493
+ }
494
+ };
495
+
496
+ // Scenario definitions
497
+ const scenarios = {
498
+ devops: {
499
+ name: "DevOps Release Gate",
500
+ description: "Coordinate release approval with security and data checks",
501
+ formFields: [
502
+ { id: "title", label: "PR Title", type: "text", placeholder: "Fix authentication bug" },
503
+ { id: "diff", label: "Code Diff", type: "textarea", placeholder: "Paste code changes here..." },
504
+ { id: "environment", label: "Environment", type: "select", options: ["staging", "production"] }
505
+ ],
506
+ flow: ["mastermind", "devassist", "cyberguard", "dataflow", "mastermind"]
507
+ },
508
+ security: {
509
+ name: "Security Alert Triage",
510
+ description: "Automatically triage and respond to security alerts",
511
+ formFields: [
512
+ { id: "alert", label: "Alert JSON", type: "textarea", placeholder: '{"type": "unusual_login", "source": "192.168.1.100"}' },
513
+ { id: "severity", label: "Severity", type: "select", options: ["low", "medium", "high"] }
514
+ ],
515
+ flow: ["mastermind", "cyberguard", "devassist", "mastermind"]
516
+ },
517
+ data: {
518
+ name: "Data Pipeline Publish",
519
+ description: "Validate and publish data pipelines with quality checks",
520
+ formFields: [
521
+ { id: "dataset", label: "Dataset Name", type: "text", placeholder: "sales_data_q3_2023" },
522
+ { id: "environment", label: "Environment", type: "select", options: ["staging", "production"] },
523
+ { id: "notes", label: "Notes", type: "textarea", placeholder: "Additional information about this dataset..." }
524
+ ],
525
+ flow: ["mastermind", "dataflow", "cyberguard", "mastermind"]
526
+ },
527
+ it: {
528
+ name: "IT Onboarding (Helpdesk)",
529
+ description: "Automate employee onboarding with access provisioning",
530
+ formFields: [
531
+ { id: "name", label: "Employee Name", type: "text", placeholder: "John Smith" },
532
+ { id: "department", label: "Department", type: "select", options: ["Engineering", "Marketing", "Finance", "HR", "Operations"] },
533
+ { id: "start_date", label: "Start Date", type: "date" },
534
+ { id: "ticket_id", label: "Ticket ID (Optional)", type: "text", placeholder: "INC-12345" }
535
+ ],
536
+ flow: ["mastermind", "devassist", "cyberguard", "mastermind"]
537
+ }
538
+ };
539
+
540
+ // Tool definitions
541
+ const tools = {
542
+ // DevOps tools
543
+ "github.lint": { name: "GitHub Linter", category: "dev" },
544
+ "sast.scan": { name: "SAST Scanner", category: "security" },
545
+ "ci.build": { name: "CI Build", category: "dev" },
546
+
547
+ // Security tools
548
+ "siem.lookup": { name: "SIEM Lookup", category: "security" },
549
+ "threatintel.query": { name: "Threat Intel Query", category: "security" },
550
+ "ticket.update": { name: "Ticket Update", category: "operations" },
551
+
552
+ // Data tools
553
+ "dbt.test": { name: "DBT Test", category: "data" },
554
+ "airflow.dag_status": { name: "Airflow DAG Status", category: "data" },
555
+ "schema.registry.diff": { name: "Schema Registry Diff", category: "data" },
556
+
557
+ // IT tools
558
+ "okta.create_user": { name: "Okta Create User", category: "identity" },
559
+ "okta.add_group": { name: "Okta Add Group", category: "identity" },
560
+ "slack.invite": { name: "Slack Invite", category: "communication" },
561
+ "servicenow.fetch": { name: "ServiceNow Fetch", category: "operations" }
562
+ };
563
+
564
+ // DOM Elements
565
+ const scenarioSelector = document.getElementById('scenarioSelector');
566
+ const modeToggle = document.getElementById('modeToggle');
567
+ const runButton = document.getElementById('runButton');
568
+ const dynamicForm = document.getElementById('dynamicForm');
569
+ const agentTimeline = document.getElementById('agentTimeline');
570
+ const decisionCard = document.getElementById('decisionCard');
571
+ const decisionContent = document.getElementById('decisionContent');
572
+ const clearTimeline = document.getElementById('clearTimeline');
573
+
574
+ // Current state
575
+ let currentScenario = 'devops';
576
+ let isLiveMode = false;
577
+ let formData = {};
578
+
579
+ // Initialize the page
580
+ document.addEventListener('DOMContentLoaded', function() {
581
+ // Set up event listeners
582
+ scenarioSelector.addEventListener('change', updateScenario);
583
+ modeToggle.addEventListener('change', toggleMode);
584
+ runButton.addEventListener('click', runOrchestration);
585
+ clearTimeline.addEventListener('click', clearTimelineContent);
586
+
587
+ // Initialize form
588
+ updateScenario();
589
+ });
590
+
591
+ // Update form based on selected scenario
592
+ function updateScenario() {
593
+ currentScenario = scenarioSelector.value;
594
+ const scenario = scenarios[currentScenario];
595
+
596
+ // Clear existing form
597
+ dynamicForm.innerHTML = '';
598
+
599
+ // Create form fields
600
+ scenario.formFields.forEach(field => {
601
+ const fieldElement = document.createElement('div');
602
+ fieldElement.className = 'space-y-1';
603
+
604
+ const label = document.createElement('label');
605
+ label.className = 'block text-sm font-medium text-gray-700';
606
+ label.textContent = field.label;
607
+ fieldElement.appendChild(label);
608
+
609
+ if (field.type === 'select') {
610
+ const select = document.createElement('select');
611
+ select.id = field.id;
612
+ select.className = 'w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent';
613
+
614
+ field.options.forEach(option => {
615
+ const optionElement = document.createElement('option');
616
+ optionElement.value = option;
617
+ optionElement.textContent = option.charAt(0).toUpperCase() + option.slice(1);
618
+ select.appendChild(optionElement);
619
+ });
620
+
621
+ fieldElement.appendChild(select);
622
+ } else if (field.type === 'textarea') {
623
+ const textarea = document.createElement('textarea');
624
+ textarea.id = field.id;
625
+ textarea.className = 'w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent';
626
+ textarea.placeholder = field.placeholder || '';
627
+ textarea.rows = 3;
628
+ fieldElement.appendChild(textarea);
629
+ } else {
630
+ const input = document.createElement('input');
631
+ input.type = field.type;
632
+ input.id = field.id;
633
+ input.className = 'w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent';
634
+ input.placeholder = field.placeholder || '';
635
+
636
+ if (field.type === 'date') {
637
+ const today = new Date();
638
+ input.value = today.toISOString().split('T')[0];
639
+ }
640
+
641
+ fieldElement.appendChild(input);
642
+ }
643
+
644
+ dynamicForm.appendChild(fieldElement);
645
+ });
646
+ }
647
+
648
+ // Toggle between Demo and Live mode
649
+ function toggleMode() {
650
+ isLiveMode = modeToggle.checked;
651
+ runButton.innerHTML = isLiveMode ?
652
+ '<i class="fas fa-bolt mr-2"></i> Run Live Orchestration' :
653
+ '<i class="fas fa-play mr-2"></i> Run Orchestration';
654
+
655
+ // In a real implementation, we would check for API key here
656
+ if (isLiveMode) {
657
+ alert("Live mode requires an API key. This demo only supports deterministic mode.");
658
+ modeToggle.checked = false;
659
+ isLiveMode = false;
660
+ runButton.innerHTML = '<i class="fas fa-play mr-2"></i> Run Orchestration';
661
+ }
662
+ }
663
+
664
+ // Clear timeline content
665
+ function clearTimelineContent() {
666
+ agentTimeline.innerHTML = `
667
+ <div class="text-center py-10 text-gray-500">
668
+ <i class="fas fa-robot text-4xl mb-3"></i>
669
+ <p>No orchestration run yet. Select a scenario and click "Run Orchestration".</p>
670
+ </div>
671
+ `;
672
+ decisionCard.classList.add('hidden');
673
+ }
674
+
675
+ // Run the orchestration
676
+ function runOrchestration() {
677
+ // Collect form data
678
+ formData = {};
679
+ const scenario = scenarios[currentScenario];
680
+ scenario.formFields.forEach(field => {
681
+ const element = document.getElementById(field.id);
682
+ if (element) {
683
+ formData[field.id] = element.value;
684
+ }
685
+ });
686
+
687
+ // Clear timeline
688
+ agentTimeline.innerHTML = '';
689
+ decisionCard.classList.add('hidden');
690
+
691
+ // Start orchestration
692
+ simulateOrchestration();
693
+ }
694
+
695
+ // Simulate the orchestration process
696
+ async function simulateOrchestration() {
697
+ const scenario = scenarios[currentScenario];
698
+ const flow = scenario.flow;
699
+
700
+ // Add initial message
701
+ addTimelineItem(agents.mastermind, "Starting orchestration for " + scenario.name, []);
702
+
703
+ // Process each step in the flow
704
+ for (let i = 0; i < flow.length; i++) {
705
+ const agentKey = flow[i];
706
+ const agent = agents[agentKey];
707
+
708
+ // Add thinking message
709
+ addTimelineItem(agent, `Analyzing request...`, []);
710
+
711
+ // Simulate processing time
712
+ await new Promise(resolve => setTimeout(resolve, 800 + Math.random() * 700));
713
+
714
+ // Process agent action
715
+ const result = processAgentAction(agentKey, i);
716
+
717
+ // Add result to timeline
718
+ addTimelineItem(agent, result.message, result.toolCalls);
719
+
720
+ // Simulate processing time
721
+ await new Promise(resolve => setTimeout(resolve, 600 + Math.random() * 500));
722
+ }
723
+
724
+ // Show final decision
725
+ showFinalDecision();
726
+ }
727
+
728
+ // Process agent action based on scenario and agent
729
+ function processAgentAction(agentKey, stepIndex) {
730
+ const scenario = scenarios[currentScenario];
731
+ let message = "";
732
+ let toolCalls = [];
733
+
734
+ switch (currentScenario) {
735
+ case 'devops':
736
+ switch (agentKey) {
737
+ case 'mastermind':
738
+ if (stepIndex === 0) {
739
+ message = "Evaluating release request for: " + (formData.title || "Untitled PR");
740
+ toolCalls = [
741
+ { tool: "github.lint", params: { repo: "my-app", branch: "feature-branch" }, result: "ok" }
742
+ ];
743
+ } else {
744
+ message = "Finalizing release decision";
745
+ }
746
+ break;
747
+ case 'devassist':
748
+ const hasSecurityRisk = formData.diff && (formData.diff.includes("eval(") || formData.diff.includes("raw user input"));
749
+ message = hasSecurityRisk ?
750
+ "Security risk detected in code changes" :
751
+ "Code review completed successfully";
752
+ toolCalls = [
753
+ { tool: "sast.scan", params: { target: "src/", ruleset: "default" }, result: hasSecurityRisk ? "warn" : "ok" }
754
+ ];
755
+ break;
756
+ case 'cyberguard':
757
+ const requiresApproval = formData.diff && (formData.diff.includes("eval(") || formData.diff.includes("raw user input"));
758
+ message = requiresApproval ?
759
+ "Manual approval required due to security policy SEC-12" :
760
+ "Security checks passed";
761
+ toolCalls = [
762
+ { tool: "siem.lookup", params: { query: "suspicious_activity", timeframe: "24h" }, result: "ok" }
763
+ ];
764
+ break;
765
+ case 'dataflow':
766
+ const env = formData.environment || "staging";
767
+ message = env === "production" ?
768
+ "Production deployment requires additional validation" :
769
+ "Staging environment ready for deployment";
770
+ toolCalls = [
771
+ { tool: "airflow.dag_status", params: { dag_id: "deployment_pipeline" }, result: "ok" }
772
+ ];
773
+ break;
774
+ }
775
+ break;
776
+
777
+ case 'security':
778
+ switch (agentKey) {
779
+ case 'mastermind':
780
+ if (stepIndex === 0) {
781
+ message = "Analyzing security alert with severity: " + (formData.severity || "unknown");
782
+ toolCalls = [
783
+ { tool: "siem.lookup", params: { alert_id: "ALERT-001" }, result: "ok" }
784
+ ];
785
+ } else {
786
+ message = "Alert triage completed";
787
+ }
788
+ break;
789
+ case 'cyberguard':
790
+ const severity = formData.severity || "low";
791
+ const requiresManual = severity === "high" || (formData.alert && formData.alert.includes("public_s3"));
792
+ message = requiresManual ?
793
+ "High severity alert requires manual review" :
794
+ "Alert classified and prioritized";
795
+ toolCalls = [
796
+ { tool: "threatintel.query", params: { ip: "192.168.1.100" }, result: "warn" }
797
+ ];
798
+ break;
799
+ case 'devassist':
800
+ message = "Runbook executed for alert response";
801
+ toolCalls = [
802
+ { tool: "ticket.update", params: { ticket_id: "INC-12345", status: "in_progress" }, result: "ok" }
803
+ ];
804
+ break;
805
+ }
806
+ break;
807
+
808
+ case 'data':
809
+ switch (agentKey) {
810
+ case 'mastermind':
811
+ if (stepIndex === 0) {
812
+ message = "Processing dataset: " + (formData.dataset || "Unnamed dataset");
813
+ toolCalls = [
814
+ { tool: "schema.registry.diff", params: { dataset: formData.dataset }, result: "ok" }
815
+ ];
816
+ } else {
817
+ message = "Dataset validation completed";
818
+ }
819
+ break;
820
+ case 'dataflow':
821
+ const dataset = formData.dataset || "";
822
+ const env = formData.environment || "staging";
823
+ const hasSales = dataset.includes("sales");
824
+ const hasPii = dataset.includes("pii");
825
+
826
+ if (hasSales) {
827
+ message = "Dataset contains sales data - late partition detected";
828
+ } else if (hasPii && env === "production") {
829
+ message = "PII detected in production dataset - privacy policy review required";
830
+ } else {
831
+ message = "Dataset quality checks passed";
832
+ }
833
+
834
+ toolCalls = [
835
+ { tool: "dbt.test", params: { model: "sales_model" }, result: hasSales ? "warn" : "ok" }
836
+ ];
837
+ break;
838
+ case 'cyberguard':
839
+ const hasPiiData = (formData.dataset || "").includes("pii");
840
+ const environment = formData.environment || "staging";
841
+ message = hasPiiData && environment === "production" ?
842
+ "PII policy validation required" :
843
+ "Data privacy checks passed";
844
+ toolCalls = [
845
+ { tool: "siem.lookup", params: { query: "data_access", timeframe: "1h" }, result: "ok" }
846
+ ];
847
+ break;
848
+ }
849
+ break;
850
+
851
+ case 'it':
852
+ switch (agentKey) {
853
+ case 'mastermind':
854
+ if (stepIndex === 0) {
855
+ message = "Initiating onboarding for: " + (formData.name || "New Employee");
856
+ toolCalls = [
857
+ { tool: "servicenow.fetch", params: { ticket_id: formData.ticket_id || "TICKET-001" }, result: "ok" }
858
+ ];
859
+ } else {
860
+ message = "Onboarding process completed";
861
+ }
862
+ break;
863
+ case 'devassist':
864
+ const department = formData.department || "";
865
+ const startDate = formData.start_date || "";
866
+ const isToday = new Date(startDate).toDateString() === new Date().toDateString();
867
+ const isWeekend = new Date(startDate).getDay() === 0 || new Date(startDate).getDay() === 6;
868
+
869
+ if (isToday || isWeekend) {
870
+ message = "Scheduling adjustment needed for start date";
871
+ } else {
872
+ message = "Onboarding plan generated successfully";
873
+ }
874
+
875
+ toolCalls = [
876
+ { tool: "okta.create_user", params: { username: "john.smith" }, result: "ok" }
877
+ ];
878
+ break;
879
+ case 'cyberguard':
880
+ const dept = formData.department || "";
881
+ message = dept === "Finance" ?
882
+ "SOX compliance review required for Finance department" :
883
+ "Access provisioning validated";
884
+ toolCalls = [
885
+ { tool: "okta.add_group", params: { user: "john.smith", group: "engineering" }, result: dept === "Finance" ? "warn" : "ok" }
886
+ ];
887
+ break;
888
+ }
889
+ break;
890
+ }
891
+
892
+ return { message, toolCalls };
893
+ }
894
+
895
+ // Add item to timeline with hover info
896
+ function addTimelineItem(agent, message, toolCalls) {
897
+ const timestamp = new Date().toLocaleTimeString();
898
+
899
+ const timelineItem = document.createElement('div');
900
+ timelineItem.className = 'timeline-item';
901
+
902
+ const avatar = document.createElement('div');
903
+ avatar.className = 'avatar';
904
+ avatar.style.backgroundColor = agent.color;
905
+ avatar.innerHTML = `<i class="${agent.icon}"></i>`;
906
+
907
+ const content = document.createElement('div');
908
+ content.className = 'bg-white p-4 rounded-lg shadow-sm';
909
+
910
+ const header = document.createElement('div');
911
+ header.className = 'flex justify-between items-start';
912
+
913
+ const agentInfo = document.createElement('div');
914
+ agentInfo.innerHTML = `
915
+ <div class="font-bold text-gray-800">${agent.name}</div>
916
+ <div class="text-xs text-gray-500">${timestamp}</div>
917
+ `;
918
+
919
+ header.appendChild(agentInfo);
920
+
921
+ const messageDiv = document.createElement('div');
922
+ messageDiv.className = 'mt-2 text-gray-700';
923
+ messageDiv.textContent = message;
924
+
925
+ content.appendChild(header);
926
+ content.appendChild(messageDiv);
927
+
928
+ // Add hover info tooltip
929
+ const hoverInfo = document.createElement('div');
930
+ hoverInfo.className = 'hover-info';
931
+ hoverInfo.innerHTML = `
932
+ <h4>${agent.name}</h4>
933
+ <div class="role">${agent.role}</div>
934
+ <p><strong>Current Action:</strong> ${getAgentActionDescription(agent, message)}</p>
935
+ <div class="function">
936
+ <strong>Agent Function:</strong> ${getAgentFunctionDescription(agent, currentScenario)}
937
+ </div>
938
+ `;
939
+ timelineItem.appendChild(hoverInfo);
940
+
941
+ // Add tool calls if any
942
+ if (toolCalls && toolCalls.length > 0) {
943
+ const toolSection = document.createElement('div');
944
+ toolSection.className = 'mt-3';
945
+
946
+ const toolHeader = document.createElement('div');
947
+ toolHeader.className = 'flex items-center text-sm font-medium text-gray-600 cursor-pointer tool-header';
948
+ toolHeader.innerHTML = `
949
+ <i class="fas fa-tools mr-2"></i>
950
+ <span>Tool Calls (${toolCalls.length})</span>
951
+ <i class="fas fa-chevron-down ml-auto transition-transform"></i>
952
+ `;
953
+
954
+ const toolContent = document.createElement('div');
955
+ toolContent.className = 'collapsible-content mt-2 space-y-2';
956
+
957
+ toolCalls.forEach(toolCall => {
958
+ const toolDiv = document.createElement('div');
959
+ toolDiv.className = 'tool-call p-3 rounded-lg';
960
+
961
+ const toolResultClass = toolCall.result === 'ok' ? 'text-green-600' :
962
+ toolCall.result === 'warn' ? 'text-yellow-600' : 'text-red-600';
963
+
964
+ toolDiv.innerHTML = `
965
+ <div class="font-medium">${tools[toolCall.tool].name}</div>
966
+ <div class="text-sm text-gray-600 mt-1">
967
+ <span class="font-medium">Params:</span>
968
+ <span class="font-mono text-xs">${JSON.stringify(toolCall.params)}</span>
969
+ </div>
970
+ <div class="mt-1">
971
+ <span class="font-medium">Result:</span>
972
+ <span class="${toolResultClass}">${toolCall.result.toUpperCase()}</span>
973
+ </div>
974
+ `;
975
+
976
+ toolContent.appendChild(toolDiv);
977
+ });
978
+
979
+ toolSection.appendChild(toolHeader);
980
+ toolSection.appendChild(toolContent);
981
+
982
+ content.appendChild(toolSection);
983
+
984
+ // Add event listener for collapsible
985
+ toolHeader.addEventListener('click', function() {
986
+ this.querySelector('i:last-child').classList.toggle('fa-chevron-down');
987
+ this.querySelector('i:last-child').classList.toggle('fa-chevron-up');
988
+ toolContent.classList.toggle('active');
989
+ });
990
+ }
991
+
992
+ timelineItem.appendChild(avatar);
993
+ timelineItem.appendChild(content);
994
+
995
+ agentTimeline.appendChild(timelineItem);
996
+
997
+ // Scroll to bottom
998
+ agentTimeline.scrollTop = agentTimeline.scrollHeight;
999
+ }
1000
+
1001
+ // Get agent action description based on message
1002
+ function getAgentActionDescription(agent, message) {
1003
+ const descriptions = {
1004
+ "Starting orchestration": "Initiating the multi-agent workflow process",
1005
+ "Evaluating release request": "Reviewing the release details and context",
1006
+ "Analyzing request": "Processing the incoming task requirements",
1007
+ "Analyzing security alert": "Examining the security event details",
1008
+ "Processing dataset": "Validating the data pipeline information",
1009
+ "Initiating onboarding": "Beginning the employee onboarding process",
1010
+ "Finalizing release decision": "Making the final approval decision",
1011
+ "Alert triage completed": "Finishing the security alert analysis",
1012
+ "Dataset validation completed": "Completing data quality checks",
1013
+ "Onboarding process completed": "Finishing employee setup process"
1014
+ };
1015
+
1016
+ // Check for specific patterns
1017
+ if (message.includes("Code review completed")) {
1018
+ return "Performing code quality assessment and security scanning";
1019
+ }
1020
+ if (message.includes("Security risk detected")) {
1021
+ return "Identifying potential security vulnerabilities in code";
1022
+ }
1023
+ if (message.includes("Manual approval required")) {
1024
+ return "Flagging the task for human review due to policy requirements";
1025
+ }
1026
+ if (message.includes("Security checks passed")) {
1027
+ return "Confirming no security issues were found";
1028
+ }
1029
+ if (message.includes("Production deployment requires")) {
1030
+ return "Identifying additional validation needed for production";
1031
+ }
1032
+ if (message.includes("Alert classified and prioritized")) {
1033
+ return "Categorizing and prioritizing the security alert";
1034
+ }
1035
+ if (message.includes("Runbook executed")) {
1036
+ return "Executing automated response procedures";
1037
+ }
1038
+ if (message.includes("Dataset quality checks passed")) {
1039
+ return "Verifying data integrity and schema compliance";
1040
+ }
1041
+ if (message.includes("Data privacy checks passed")) {
1042
+ return "Ensuring data handling complies with privacy policies";
1043
+ }
1044
+ if (message.includes("Onboarding plan generated")) {
1045
+ return "Creating customized setup plan for new employee";
1046
+ }
1047
+ if (message.includes("Access provisioning validated")) {
1048
+ return "Confirming appropriate system access permissions";
1049
+ }
1050
+
1051
+ // Default to predefined descriptions
1052
+ for (const [key, desc] of Object.entries(descriptions)) {
1053
+ if (message.includes(key)) {
1054
+ return desc;
1055
+ }
1056
+ }
1057
+
1058
+ return "Performing specialized analysis and evaluation";
1059
+ }
1060
+
1061
+ // Get agent function description based on scenario
1062
+ function getAgentFunctionDescription(agent, scenario) {
1063
+ const functions = {
1064
+ devops: {
1065
+ mastermind: "Coordinates the release process, evaluates code changes, and makes final deployment decisions",
1066
+ devassist: "Reviews code quality, performs static analysis, and identifies technical risks",
1067
+ cyberguard: "Checks for security vulnerabilities and ensures compliance with security policies",
1068
+ dataflow: "Validates data pipeline integrity and ensures proper environment deployment"
1069
+ },
1070
+ security: {
1071
+ mastermind: "Manages the security alert workflow and determines response actions",
1072
+ cyberguard: "Analyzes threat intelligence and classifies security events",
1073
+ devassist: "Executes automated security response procedures and updates tickets"
1074
+ },
1075
+ data: {
1076
+ mastermind: "Orchestrates data pipeline validation and publication process",
1077
+ dataflow: "Performs data quality checks and validates schema compliance",
1078
+ cyberguard: "Ensures data privacy policies are followed and access is controlled"
1079
+ },
1080
+ it: {
1081
+ mastermind: "Manages employee onboarding workflow and final access approvals",
1082
+ devassist: "Generates onboarding plans and validates system requirements",
1083
+ cyberguard: "Ensures appropriate access provisioning and compliance checks"
1084
+ }
1085
+ };
1086
+
1087
+ return functions[scenario][agent.name.toLowerCase()] || "Performing specialized analysis";
1088
+ }
1089
+
1090
+ // Show final decision
1091
+ function showFinalDecision() {
1092
+ let decision = "";
1093
+ let status = "";
1094
+ let needsApproval = false;
1095
+
1096
+ switch (currentScenario) {
1097
+ case 'devops':
1098
+ const hasSecurityRisk = formData.diff && (formData.diff.includes("eval(") || formData.diff.includes("raw user input"));
1099
+ const env = formData.environment || "staging";
1100
+ const dataFlowResult = env === "production" ? "amber" : "green";
1101
+
1102
+ if (hasSecurityRisk) {
1103
+ decision = "Manual approval required due to security policy violations";
1104
+ status = "manual";
1105
+ needsApproval = true;
1106
+ } else if (dataFlowResult === "red") {
1107
+ decision = "Release blocked due to data validation failures";
1108
+ status = "blocked";
1109
+ } else {
1110
+ decision = "Release approved for deployment";
1111
+ status = "approved";
1112
+ }
1113
+ break;
1114
+
1115
+ case 'security':
1116
+ const severity = formData.severity || "low";
1117
+ const requiresManual = severity === "high" || (formData.alert && formData.alert.includes("public_s3"));
1118
+
1119
+ if (requiresManual) {
1120
+ decision = "High severity alert requires manual triage";
1121
+ status = "manual";
1122
+ needsApproval = true;
1123
+ } else {
1124
+ decision = "Alert resolved automatically";
1125
+ status = "approved";
1126
+ }
1127
+ break;
1128
+
1129
+ case 'data':
1130
+ const dataset = formData.dataset || "";
1131
+ const environment = formData.environment || "staging";
1132
+ const hasSales = dataset.includes("sales");
1133
+ const hasPii = dataset.includes("pii");
1134
+
1135
+ if (hasPii && environment === "production") {
1136
+ decision = "Manual approval required for PII data in production";
1137
+ status = "manual";
1138
+ needsApproval = true;
1139
+ } else if (hasSales) {
1140
+ decision = "Dataset published with late partition note";
1141
+ status = "approved";
1142
+ } else {
1143
+ decision = "Dataset published successfully";
1144
+ status = "approved";
1145
+ }
1146
+ break;
1147
+
1148
+ case 'it':
1149
+ const department = formData.department || "";
1150
+
1151
+ if (department === "Finance") {
1152
+ decision = "Manual approval required for SOX compliance";
1153
+ status = "manual";
1154
+ needsApproval = true;
1155
+ } else {
1156
+ decision = "Onboarding completed successfully";
1157
+ status = "approved";
1158
+ }
1159
+ break;
1160
+ }
1161
+
1162
+ // Create decision card
1163
+ let statusClass = "";
1164
+ let statusIcon = "";
1165
+
1166
+ switch (status) {
1167
+ case "approved":
1168
+ statusClass = "status-approved";
1169
+ statusIcon = "fas fa-check-circle";
1170
+ break;
1171
+ case "blocked":
1172
+ statusClass = "status-blocked";
1173
+ statusIcon = "fas fa-times-circle";
1174
+ break;
1175
+ case "manual":
1176
+ statusClass = "status-manual";
1177
+ statusIcon = "fas fa-exclamation-circle";
1178
+ break;
1179
+ }
1180
+
1181
+ decisionContent.innerHTML = `
1182
+ <div class="decision-card p-6 ${statusClass}">
1183
+ <div class="flex items-center justify-center mb-4">
1184
+ <i class="${statusIcon} text-3xl mr-3"></i>
1185
+ <h3 class="text-2xl font-bold">${status.charAt(0).toUpperCase() + status.slice(1)}</h3>
1186
+ </div>
1187
+ <p class="text-lg mb-6">${decision}</p>
1188
+ ${needsApproval ? `
1189
+ <button id="approveButton" class="w-full btn btn-primary">
1190
+ <i class="fas fa-thumbs-up btn-icon"></i> Approve Anyway
1191
+ </button>
1192
+ ` : ''}
1193
+ </div>
1194
+ `;
1195
+
1196
+ decisionCard.classList.remove('hidden');
1197
+
1198
+ // Add event listener for approve button if present
1199
+ if (needsApproval) {
1200
+ document.getElementById('approveButton').addEventListener('click', function() {
1201
+ this.innerHTML = '<i class="fas fa-check mr-2"></i> Approved';
1202
+ this.classList.add('bg-green-500', 'hover:bg-green-600');
1203
+ this.classList.remove('bg-primary', 'hover:bg-blue-700');
1204
+ this.disabled = true;
1205
+
1206
+ // Add audit log
1207
+ addTimelineItem(agents.mastermind, "Manual approval granted by user", [
1208
+ { tool: "audit.log", params: { action: "manual_approval", user: "admin" }, result: "ok" }
1209
+ ]);
1210
+ });
1211
+ }
1212
+ }
1213
+ </script>
1214
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=molliexx99/maias" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1215
+ </html>