codetether 1.2.2__py3-none-any.whl

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.
Files changed (66) hide show
  1. a2a_server/__init__.py +29 -0
  2. a2a_server/a2a_agent_card.py +365 -0
  3. a2a_server/a2a_errors.py +1133 -0
  4. a2a_server/a2a_executor.py +926 -0
  5. a2a_server/a2a_router.py +1033 -0
  6. a2a_server/a2a_types.py +344 -0
  7. a2a_server/agent_card.py +408 -0
  8. a2a_server/agents_server.py +271 -0
  9. a2a_server/auth_api.py +349 -0
  10. a2a_server/billing_api.py +638 -0
  11. a2a_server/billing_service.py +712 -0
  12. a2a_server/billing_webhooks.py +501 -0
  13. a2a_server/config.py +96 -0
  14. a2a_server/database.py +2165 -0
  15. a2a_server/email_inbound.py +398 -0
  16. a2a_server/email_notifications.py +486 -0
  17. a2a_server/enhanced_agents.py +919 -0
  18. a2a_server/enhanced_server.py +160 -0
  19. a2a_server/hosted_worker.py +1049 -0
  20. a2a_server/integrated_agents_server.py +347 -0
  21. a2a_server/keycloak_auth.py +750 -0
  22. a2a_server/livekit_bridge.py +439 -0
  23. a2a_server/marketing_tools.py +1364 -0
  24. a2a_server/mcp_client.py +196 -0
  25. a2a_server/mcp_http_server.py +2256 -0
  26. a2a_server/mcp_server.py +191 -0
  27. a2a_server/message_broker.py +725 -0
  28. a2a_server/mock_mcp.py +273 -0
  29. a2a_server/models.py +494 -0
  30. a2a_server/monitor_api.py +5904 -0
  31. a2a_server/opencode_bridge.py +1594 -0
  32. a2a_server/redis_task_manager.py +518 -0
  33. a2a_server/server.py +726 -0
  34. a2a_server/task_manager.py +668 -0
  35. a2a_server/task_queue.py +742 -0
  36. a2a_server/tenant_api.py +333 -0
  37. a2a_server/tenant_middleware.py +219 -0
  38. a2a_server/tenant_service.py +760 -0
  39. a2a_server/user_auth.py +721 -0
  40. a2a_server/vault_client.py +576 -0
  41. a2a_server/worker_sse.py +873 -0
  42. agent_worker/__init__.py +8 -0
  43. agent_worker/worker.py +4877 -0
  44. codetether/__init__.py +10 -0
  45. codetether/__main__.py +4 -0
  46. codetether/cli.py +112 -0
  47. codetether/worker_cli.py +57 -0
  48. codetether-1.2.2.dist-info/METADATA +570 -0
  49. codetether-1.2.2.dist-info/RECORD +66 -0
  50. codetether-1.2.2.dist-info/WHEEL +5 -0
  51. codetether-1.2.2.dist-info/entry_points.txt +4 -0
  52. codetether-1.2.2.dist-info/licenses/LICENSE +202 -0
  53. codetether-1.2.2.dist-info/top_level.txt +5 -0
  54. codetether_voice_agent/__init__.py +6 -0
  55. codetether_voice_agent/agent.py +445 -0
  56. codetether_voice_agent/codetether_mcp.py +345 -0
  57. codetether_voice_agent/config.py +16 -0
  58. codetether_voice_agent/functiongemma_caller.py +380 -0
  59. codetether_voice_agent/session_playback.py +247 -0
  60. codetether_voice_agent/tools/__init__.py +21 -0
  61. codetether_voice_agent/tools/definitions.py +135 -0
  62. codetether_voice_agent/tools/handlers.py +380 -0
  63. run_server.py +314 -0
  64. ui/monitor-tailwind.html +1790 -0
  65. ui/monitor.html +1775 -0
  66. ui/monitor.js +2662 -0
ui/monitor.html ADDED
@@ -0,0 +1,1775 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>A2A Agent Monitor - Real-time Agent Conversations</title>
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ body {
16
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
17
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
18
+ min-height: 100vh;
19
+ padding: 20px;
20
+ }
21
+
22
+ .container {
23
+ max-width: 1600px;
24
+ margin: 0 auto;
25
+ background: rgba(255, 255, 255, 0.95);
26
+ border-radius: 20px;
27
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
28
+ overflow: hidden;
29
+ }
30
+
31
+ .header {
32
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
33
+ color: white;
34
+ padding: 30px;
35
+ text-align: center;
36
+ }
37
+
38
+ .header h1 {
39
+ font-size: 2.5em;
40
+ margin-bottom: 10px;
41
+ }
42
+
43
+ .header p {
44
+ opacity: 0.9;
45
+ font-size: 1.1em;
46
+ }
47
+
48
+ .status-bar {
49
+ display: flex;
50
+ justify-content: space-around;
51
+ padding: 20px;
52
+ background: #f8f9fa;
53
+ border-bottom: 2px solid #e9ecef;
54
+ }
55
+
56
+ .status-item {
57
+ text-align: center;
58
+ }
59
+
60
+ .status-label {
61
+ font-size: 0.85em;
62
+ color: #6c757d;
63
+ text-transform: uppercase;
64
+ letter-spacing: 1px;
65
+ margin-bottom: 5px;
66
+ }
67
+
68
+ .status-value {
69
+ font-size: 1.8em;
70
+ font-weight: bold;
71
+ color: #667eea;
72
+ }
73
+
74
+ .status-indicator {
75
+ display: inline-block;
76
+ width: 12px;
77
+ height: 12px;
78
+ border-radius: 50%;
79
+ margin-right: 8px;
80
+ animation: pulse 2s infinite;
81
+ }
82
+
83
+ .status-indicator.active {
84
+ background: #28a745;
85
+ }
86
+
87
+ .status-indicator.idle {
88
+ background: #ffc107;
89
+ }
90
+
91
+ @keyframes pulse {
92
+
93
+ 0%,
94
+ 100% {
95
+ opacity: 1;
96
+ }
97
+
98
+ 50% {
99
+ opacity: 0.5;
100
+ }
101
+ }
102
+
103
+ .main-content {
104
+ display: grid;
105
+ grid-template-columns: 280px 1fr 1fr 280px 350px;
106
+ gap: 0;
107
+ height: calc(100vh - 300px);
108
+ }
109
+
110
+ .conversation-panel {
111
+ padding: 20px;
112
+ overflow-y: auto;
113
+ background: white;
114
+ border-right: 2px solid #e9ecef;
115
+ }
116
+
117
+ .controls-panel {
118
+ background: #f8f9fa;
119
+ padding: 20px;
120
+ overflow-y: auto;
121
+ }
122
+
123
+ .conversation-header {
124
+ display: flex;
125
+ justify-content: space-between;
126
+ align-items: center;
127
+ margin-bottom: 20px;
128
+ padding-bottom: 15px;
129
+ border-bottom: 2px solid #e9ecef;
130
+ }
131
+
132
+ .conversation-header h2 {
133
+ color: #343a40;
134
+ }
135
+
136
+ .filter-buttons {
137
+ display: flex;
138
+ gap: 10px;
139
+ }
140
+
141
+ .filter-btn {
142
+ padding: 8px 16px;
143
+ border: 2px solid #667eea;
144
+ background: white;
145
+ color: #667eea;
146
+ border-radius: 8px;
147
+ cursor: pointer;
148
+ font-weight: 600;
149
+ transition: all 0.3s;
150
+ }
151
+
152
+ .filter-btn.active {
153
+ background: #667eea;
154
+ color: white;
155
+ }
156
+
157
+ .filter-btn:hover {
158
+ transform: translateY(-2px);
159
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
160
+ }
161
+
162
+ .message {
163
+ margin-bottom: 20px;
164
+ padding: 15px;
165
+ border-radius: 12px;
166
+ animation: slideIn 0.3s ease-out;
167
+ position: relative;
168
+ }
169
+
170
+ @keyframes slideIn {
171
+ from {
172
+ opacity: 0;
173
+ transform: translateY(20px);
174
+ }
175
+
176
+ to {
177
+ opacity: 1;
178
+ transform: translateY(0);
179
+ }
180
+ }
181
+
182
+ .message.agent {
183
+ background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
184
+ border-left: 4px solid #2196f3;
185
+ }
186
+
187
+ .message.human {
188
+ background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%);
189
+ border-left: 4px solid #ff9800;
190
+ }
191
+
192
+ .message.system {
193
+ background: linear-gradient(135deg, #f3e5f5 0%, #e1bee7 100%);
194
+ border-left: 4px solid #9c27b0;
195
+ }
196
+
197
+ .message.tool {
198
+ background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);
199
+ border-left: 4px solid #4caf50;
200
+ }
201
+
202
+ .message-header {
203
+ display: flex;
204
+ justify-content: space-between;
205
+ align-items: center;
206
+ margin-bottom: 10px;
207
+ }
208
+
209
+ .message-meta {
210
+ display: flex;
211
+ gap: 15px;
212
+ align-items: center;
213
+ }
214
+
215
+ .agent-name {
216
+ font-weight: bold;
217
+ font-size: 1.1em;
218
+ color: #343a40;
219
+ }
220
+
221
+ .timestamp {
222
+ font-size: 0.85em;
223
+ color: #6c757d;
224
+ }
225
+
226
+ .message-actions {
227
+ display: flex;
228
+ gap: 8px;
229
+ }
230
+
231
+ .action-btn {
232
+ padding: 4px 10px;
233
+ border: none;
234
+ border-radius: 6px;
235
+ cursor: pointer;
236
+ font-size: 0.85em;
237
+ font-weight: 600;
238
+ transition: all 0.2s;
239
+ }
240
+
241
+ .action-btn:hover {
242
+ transform: scale(1.05);
243
+ }
244
+
245
+ .btn-flag {
246
+ background: #ffc107;
247
+ color: #000;
248
+ }
249
+
250
+ .btn-intervene {
251
+ background: #dc3545;
252
+ color: white;
253
+ }
254
+
255
+ .btn-copy {
256
+ background: #6c757d;
257
+ color: white;
258
+ }
259
+
260
+ .message-content {
261
+ color: #212529;
262
+ line-height: 1.6;
263
+ white-space: pre-wrap;
264
+ word-wrap: break-word;
265
+ }
266
+
267
+ .message-details {
268
+ margin-top: 10px;
269
+ padding-top: 10px;
270
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
271
+ font-size: 0.9em;
272
+ color: #6c757d;
273
+ }
274
+
275
+ .control-section {
276
+ margin-bottom: 25px;
277
+ background: white;
278
+ padding: 20px;
279
+ border-radius: 12px;
280
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
281
+ }
282
+
283
+ .control-section h3 {
284
+ margin-bottom: 15px;
285
+ color: #343a40;
286
+ font-size: 1.2em;
287
+ }
288
+
289
+ .agent-list {
290
+ list-style: none;
291
+ }
292
+
293
+ .agent-item {
294
+ padding: 12px;
295
+ margin-bottom: 10px;
296
+ background: #f8f9fa;
297
+ border-radius: 8px;
298
+ display: flex;
299
+ justify-content: space-between;
300
+ align-items: center;
301
+ transition: all 0.2s;
302
+ }
303
+
304
+ .agent-item:hover {
305
+ background: #e9ecef;
306
+ transform: translateX(5px);
307
+ }
308
+
309
+ .agent-status {
310
+ display: flex;
311
+ align-items: center;
312
+ gap: 10px;
313
+ }
314
+
315
+ .intervene-form {
316
+ display: flex;
317
+ flex-direction: column;
318
+ gap: 10px;
319
+ }
320
+
321
+ .intervene-form textarea {
322
+ padding: 12px;
323
+ border: 2px solid #ced4da;
324
+ border-radius: 8px;
325
+ font-family: inherit;
326
+ resize: vertical;
327
+ min-height: 100px;
328
+ }
329
+
330
+ .intervene-form textarea:focus {
331
+ outline: none;
332
+ border-color: #667eea;
333
+ }
334
+
335
+ .intervene-form select {
336
+ padding: 10px;
337
+ border: 2px solid #ced4da;
338
+ border-radius: 8px;
339
+ font-family: inherit;
340
+ }
341
+
342
+ .btn-primary {
343
+ padding: 12px 24px;
344
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
345
+ color: white;
346
+ border: none;
347
+ border-radius: 8px;
348
+ font-weight: 600;
349
+ cursor: pointer;
350
+ transition: all 0.3s;
351
+ }
352
+
353
+ .btn-primary:hover {
354
+ transform: translateY(-2px);
355
+ box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
356
+ }
357
+
358
+ .btn-secondary {
359
+ padding: 10px 20px;
360
+ background: #6c757d;
361
+ color: white;
362
+ border: none;
363
+ border-radius: 8px;
364
+ font-weight: 600;
365
+ cursor: pointer;
366
+ }
367
+
368
+ .log-controls {
369
+ display: flex;
370
+ gap: 10px;
371
+ margin-top: 10px;
372
+ }
373
+
374
+ .stats-grid {
375
+ display: grid;
376
+ grid-template-columns: 1fr 1fr;
377
+ gap: 15px;
378
+ margin-top: 15px;
379
+ }
380
+
381
+ .stat-box {
382
+ padding: 15px;
383
+ background: #f8f9fa;
384
+ border-radius: 8px;
385
+ text-align: center;
386
+ }
387
+
388
+ .stat-number {
389
+ font-size: 2em;
390
+ font-weight: bold;
391
+ color: #667eea;
392
+ }
393
+
394
+ .stat-label {
395
+ font-size: 0.85em;
396
+ color: #6c757d;
397
+ margin-top: 5px;
398
+ }
399
+
400
+ .search-box {
401
+ margin-bottom: 15px;
402
+ }
403
+
404
+ .search-box input {
405
+ width: 100%;
406
+ padding: 12px;
407
+ border: 2px solid #ced4da;
408
+ border-radius: 8px;
409
+ font-size: 1em;
410
+ }
411
+
412
+ .search-box input:focus {
413
+ outline: none;
414
+ border-color: #667eea;
415
+ }
416
+
417
+ .search-box {
418
+ display: flex;
419
+ gap: 10px;
420
+ margin-bottom: 15px;
421
+ }
422
+
423
+ .search-box input {
424
+ flex: 1;
425
+ }
426
+
427
+ .btn-search {
428
+ padding: 12px 16px;
429
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
430
+ color: white;
431
+ border: none;
432
+ border-radius: 8px;
433
+ cursor: pointer;
434
+ font-weight: 600;
435
+ white-space: nowrap;
436
+ }
437
+
438
+ .btn-search:hover {
439
+ transform: translateY(-2px);
440
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
441
+ }
442
+
443
+ .search-results {
444
+ background: white;
445
+ border: 2px solid #667eea;
446
+ border-radius: 12px;
447
+ margin-bottom: 20px;
448
+ max-height: 400px;
449
+ overflow-y: auto;
450
+ }
451
+
452
+ .search-results-header {
453
+ display: flex;
454
+ justify-content: space-between;
455
+ align-items: center;
456
+ padding: 15px;
457
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
458
+ color: white;
459
+ border-radius: 10px 10px 0 0;
460
+ }
461
+
462
+ .search-results-header h3 {
463
+ margin: 0;
464
+ }
465
+
466
+ .btn-close {
467
+ background: none;
468
+ border: none;
469
+ color: white;
470
+ font-size: 1.5em;
471
+ cursor: pointer;
472
+ }
473
+
474
+ #searchResultsContent {
475
+ padding: 15px;
476
+ }
477
+
478
+ .search-result-item {
479
+ padding: 12px;
480
+ margin-bottom: 10px;
481
+ background: #f8f9fa;
482
+ border-radius: 8px;
483
+ border-left: 4px solid #667eea;
484
+ }
485
+
486
+ .search-result-item:last-child {
487
+ margin-bottom: 0;
488
+ }
489
+
490
+ .storage-info {
491
+ font-size: 0.9em;
492
+ color: #28a745;
493
+ margin-bottom: 15px;
494
+ padding: 10px;
495
+ background: #d4edda;
496
+ border-radius: 8px;
497
+ }
498
+
499
+ .toast {
500
+ position: fixed;
501
+ bottom: 20px;
502
+ right: 20px;
503
+ padding: 15px 25px;
504
+ background: #28a745;
505
+ color: white;
506
+ border-radius: 8px;
507
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
508
+ animation: slideInRight 0.3s ease-out;
509
+ z-index: 1000;
510
+ }
511
+
512
+ @keyframes slideInRight {
513
+ from {
514
+ transform: translateX(400px);
515
+ opacity: 0;
516
+ }
517
+
518
+ to {
519
+ transform: translateX(0);
520
+ opacity: 1;
521
+ }
522
+ }
523
+
524
+ .export-section {
525
+ display: flex;
526
+ gap: 10px;
527
+ flex-wrap: wrap;
528
+ }
529
+
530
+ .connection-status {
531
+ padding: 10px 15px;
532
+ border-radius: 8px;
533
+ font-weight: 600;
534
+ display: inline-flex;
535
+ align-items: center;
536
+ gap: 8px;
537
+ }
538
+
539
+ .connection-status.connected {
540
+ background: #d4edda;
541
+ color: #155724;
542
+ }
543
+
544
+ .connection-status.disconnected {
545
+ background: #f8d7da;
546
+ color: #721c24;
547
+ }
548
+
549
+ /* OpenCode Agent Panel Styles */
550
+ .opencode-panel {
551
+ padding: 20px;
552
+ overflow-y: auto;
553
+ background: #f0f4ff;
554
+ border-right: 2px solid #e9ecef;
555
+ max-height: calc(100vh - 300px);
556
+ }
557
+
558
+ .codebase-item {
559
+ margin-bottom: 15px;
560
+ padding: 15px;
561
+ background: white;
562
+ border-radius: 12px;
563
+ border-left: 4px solid #667eea;
564
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
565
+ transition: all 0.2s;
566
+ }
567
+
568
+ .codebase-item:hover {
569
+ transform: translateX(5px);
570
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
571
+ }
572
+
573
+ .codebase-item.idle {
574
+ border-left-color: #6c757d;
575
+ }
576
+
577
+ .codebase-item.running {
578
+ border-left-color: #28a745;
579
+ }
580
+
581
+ .codebase-item.watching {
582
+ border-left-color: #17a2b8;
583
+ animation: pulse-border-cyan 2s infinite;
584
+ }
585
+
586
+ @keyframes pulse-border-cyan {
587
+
588
+ 0%,
589
+ 100% {
590
+ border-left-color: #17a2b8;
591
+ }
592
+
593
+ 50% {
594
+ border-left-color: #138496;
595
+ }
596
+ }
597
+
598
+ .codebase-item.busy {
599
+ border-left-color: #ffc107;
600
+ animation: pulse-border 2s infinite;
601
+ }
602
+
603
+ .codebase-item.error {
604
+ border-left-color: #dc3545;
605
+ }
606
+
607
+ @keyframes pulse-border {
608
+
609
+ 0%,
610
+ 100% {
611
+ border-left-color: #ffc107;
612
+ }
613
+
614
+ 50% {
615
+ border-left-color: #ff9800;
616
+ }
617
+ }
618
+
619
+ .codebase-header {
620
+ display: flex;
621
+ justify-content: space-between;
622
+ align-items: start;
623
+ margin-bottom: 10px;
624
+ }
625
+
626
+ .codebase-name {
627
+ font-weight: bold;
628
+ font-size: 1.1em;
629
+ color: #343a40;
630
+ }
631
+
632
+ .codebase-path {
633
+ font-size: 0.85em;
634
+ color: #6c757d;
635
+ font-family: monospace;
636
+ word-break: break-all;
637
+ }
638
+
639
+ .codebase-status {
640
+ padding: 4px 12px;
641
+ border-radius: 20px;
642
+ font-size: 0.8em;
643
+ font-weight: 600;
644
+ text-transform: uppercase;
645
+ }
646
+
647
+ .codebase-status.idle {
648
+ background: #e9ecef;
649
+ color: #495057;
650
+ }
651
+
652
+ .codebase-status.running {
653
+ background: #d4edda;
654
+ color: #155724;
655
+ }
656
+
657
+ .codebase-status.watching {
658
+ background: #d1ecf1;
659
+ color: #0c5460;
660
+ }
661
+
662
+ .codebase-status.busy {
663
+ background: #fff3cd;
664
+ color: #856404;
665
+ }
666
+
667
+ .codebase-status.error {
668
+ background: #f8d7da;
669
+ color: #842029;
670
+ }
671
+
672
+ .codebase-actions {
673
+ display: flex;
674
+ gap: 8px;
675
+ margin-top: 12px;
676
+ flex-wrap: wrap;
677
+ }
678
+
679
+ .codebase-actions button {
680
+ flex: 1;
681
+ min-width: 80px;
682
+ }
683
+
684
+ .trigger-form {
685
+ margin-top: 15px;
686
+ padding: 15px;
687
+ background: #f8f9fa;
688
+ border-radius: 8px;
689
+ display: none;
690
+ }
691
+
692
+ .trigger-form.show {
693
+ display: block;
694
+ }
695
+
696
+ .trigger-form textarea {
697
+ width: 100%;
698
+ padding: 10px;
699
+ border: 2px solid #ced4da;
700
+ border-radius: 8px;
701
+ font-family: inherit;
702
+ resize: vertical;
703
+ min-height: 80px;
704
+ margin-bottom: 10px;
705
+ }
706
+
707
+ .trigger-form select {
708
+ width: 100%;
709
+ padding: 10px;
710
+ border: 2px solid #ced4da;
711
+ border-radius: 8px;
712
+ font-family: inherit;
713
+ margin-bottom: 10px;
714
+ }
715
+
716
+ .trigger-form select.model-selector {
717
+ background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
718
+ font-size: 0.9em;
719
+ }
720
+
721
+ .trigger-form select.model-selector option {
722
+ padding: 8px;
723
+ }
724
+
725
+ /* Task Queue Styles */
726
+ .codebase-tasks {
727
+ margin-top: 12px;
728
+ padding-top: 12px;
729
+ border-top: 1px solid #e9ecef;
730
+ }
731
+
732
+ .tasks-header {
733
+ display: flex;
734
+ justify-content: space-between;
735
+ align-items: center;
736
+ margin-bottom: 8px;
737
+ }
738
+
739
+ .tasks-header h4 {
740
+ margin: 0;
741
+ font-size: 0.9em;
742
+ color: #495057;
743
+ }
744
+
745
+ .task-count {
746
+ background: #667eea;
747
+ color: white;
748
+ padding: 2px 8px;
749
+ border-radius: 10px;
750
+ font-size: 0.75em;
751
+ }
752
+
753
+ .task-item {
754
+ padding: 10px;
755
+ margin-bottom: 6px;
756
+ background: #f8f9fa;
757
+ border-radius: 6px;
758
+ border-left: 3px solid #6c757d;
759
+ font-size: 0.9em;
760
+ }
761
+
762
+ .task-item.pending {
763
+ border-left-color: #ffc107;
764
+ }
765
+
766
+ .task-item.running {
767
+ border-left-color: #17a2b8;
768
+ background: #e3f2fd;
769
+ }
770
+
771
+ .task-item.completed {
772
+ border-left-color: #28a745;
773
+ background: #e8f5e9;
774
+ }
775
+
776
+ .task-item.failed {
777
+ border-left-color: #dc3545;
778
+ background: #ffebee;
779
+ }
780
+
781
+ .task-title {
782
+ font-weight: 600;
783
+ color: #343a40;
784
+ margin-bottom: 4px;
785
+ }
786
+
787
+ .task-meta {
788
+ font-size: 0.8em;
789
+ color: #6c757d;
790
+ display: flex;
791
+ justify-content: space-between;
792
+ }
793
+
794
+ .watch-controls {
795
+ margin-top: 12px;
796
+ padding: 12px;
797
+ background: #e3f2fd;
798
+ border-radius: 8px;
799
+ display: flex;
800
+ align-items: center;
801
+ gap: 10px;
802
+ }
803
+
804
+ .watch-controls.active {
805
+ background: #c8e6c9;
806
+ }
807
+
808
+ .watch-indicator {
809
+ width: 12px;
810
+ height: 12px;
811
+ border-radius: 50%;
812
+ background: #6c757d;
813
+ }
814
+
815
+ .watch-indicator.active {
816
+ background: #28a745;
817
+ animation: pulse 1.5s infinite;
818
+ }
819
+
820
+ /* Task Modal Styles */
821
+ .task-modal {
822
+ display: none;
823
+ position: fixed;
824
+ top: 0;
825
+ left: 0;
826
+ width: 100%;
827
+ height: 100%;
828
+ background: rgba(0, 0, 0, 0.5);
829
+ z-index: 1000;
830
+ align-items: center;
831
+ justify-content: center;
832
+ }
833
+
834
+ .task-modal.show {
835
+ display: flex;
836
+ }
837
+
838
+ .task-form {
839
+ background: white;
840
+ padding: 30px;
841
+ border-radius: 12px;
842
+ width: 550px;
843
+ max-width: 90%;
844
+ max-height: 90vh;
845
+ overflow-y: auto;
846
+ }
847
+
848
+ .task-form h3 {
849
+ margin-top: 0;
850
+ margin-bottom: 20px;
851
+ color: #343a40;
852
+ }
853
+
854
+ .task-form label {
855
+ display: block;
856
+ margin-bottom: 5px;
857
+ font-weight: 600;
858
+ color: #495057;
859
+ }
860
+
861
+ .task-form input,
862
+ .task-form textarea,
863
+ .task-form select {
864
+ width: 100%;
865
+ padding: 12px;
866
+ border: 2px solid #ced4da;
867
+ border-radius: 8px;
868
+ margin-bottom: 15px;
869
+ font-family: inherit;
870
+ }
871
+
872
+ .task-form input:focus,
873
+ .task-form textarea:focus,
874
+ .task-form select:focus {
875
+ outline: none;
876
+ border-color: #667eea;
877
+ }
878
+
879
+ .task-form textarea {
880
+ min-height: 120px;
881
+ resize: vertical;
882
+ }
883
+
884
+ .priority-select {
885
+ display: flex;
886
+ gap: 10px;
887
+ margin-bottom: 15px;
888
+ }
889
+
890
+ .priority-option {
891
+ flex: 1;
892
+ padding: 10px;
893
+ text-align: center;
894
+ border: 2px solid #ced4da;
895
+ border-radius: 8px;
896
+ cursor: pointer;
897
+ transition: all 0.2s;
898
+ }
899
+
900
+ .priority-option:hover {
901
+ border-color: #667eea;
902
+ }
903
+
904
+ .priority-option.selected {
905
+ border-color: #667eea;
906
+ background: #667eea;
907
+ color: white;
908
+ }
909
+
910
+ /* Agent Output Panel Styles */
911
+ .agent-output-panel {
912
+ padding: 20px;
913
+ overflow-y: auto;
914
+ background: #1e1e1e;
915
+ color: #d4d4d4;
916
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
917
+ max-height: calc(100vh - 300px);
918
+ }
919
+
920
+ .agent-output-header {
921
+ display: flex;
922
+ justify-content: space-between;
923
+ align-items: center;
924
+ margin-bottom: 15px;
925
+ padding-bottom: 10px;
926
+ border-bottom: 1px solid #333;
927
+ }
928
+
929
+ .agent-output-header h2 {
930
+ color: #fff;
931
+ margin: 0;
932
+ }
933
+
934
+ .output-controls {
935
+ display: flex;
936
+ gap: 8px;
937
+ }
938
+
939
+ .output-controls button {
940
+ padding: 6px 12px;
941
+ background: #333;
942
+ color: #d4d4d4;
943
+ border: 1px solid #555;
944
+ border-radius: 4px;
945
+ cursor: pointer;
946
+ font-size: 0.85em;
947
+ }
948
+
949
+ .output-controls button:hover {
950
+ background: #444;
951
+ }
952
+
953
+ .output-controls button.active {
954
+ background: #667eea;
955
+ border-color: #667eea;
956
+ color: white;
957
+ }
958
+
959
+ .agent-selector {
960
+ padding: 10px;
961
+ background: #252526;
962
+ border-radius: 8px;
963
+ margin-bottom: 15px;
964
+ }
965
+
966
+ .agent-selector select {
967
+ width: 100%;
968
+ padding: 8px;
969
+ background: #3c3c3c;
970
+ color: #d4d4d4;
971
+ border: 1px solid #555;
972
+ border-radius: 4px;
973
+ }
974
+
975
+ #agentOutputContainer {
976
+ overflow-y: auto;
977
+ max-height: calc(100vh - 450px);
978
+ }
979
+
980
+ .output-entry {
981
+ padding: 12px;
982
+ margin-bottom: 8px;
983
+ border-radius: 6px;
984
+ background: #252526;
985
+ border-left: 3px solid #6c757d;
986
+ animation: fadeIn 0.2s ease-out;
987
+ }
988
+
989
+ @keyframes fadeIn {
990
+ from {
991
+ opacity: 0;
992
+ transform: translateY(-5px);
993
+ }
994
+
995
+ to {
996
+ opacity: 1;
997
+ transform: translateY(0);
998
+ }
999
+ }
1000
+
1001
+ .output-entry.text {
1002
+ border-left-color: #4ec9b0;
1003
+ }
1004
+
1005
+ .output-entry.reasoning {
1006
+ border-left-color: #dcdcaa;
1007
+ background: #2d2d30;
1008
+ }
1009
+
1010
+ .output-entry.tool-pending {
1011
+ border-left-color: #569cd6;
1012
+ }
1013
+
1014
+ .output-entry.tool-running {
1015
+ border-left-color: #ce9178;
1016
+ animation: pulse-bg 1.5s infinite;
1017
+ }
1018
+
1019
+ @keyframes pulse-bg {
1020
+
1021
+ 0%,
1022
+ 100% {
1023
+ background: #252526;
1024
+ }
1025
+
1026
+ 50% {
1027
+ background: #2d2a2e;
1028
+ }
1029
+ }
1030
+
1031
+ .output-entry.tool-completed {
1032
+ border-left-color: #4ec9b0;
1033
+ }
1034
+
1035
+ .output-entry.tool-error {
1036
+ border-left-color: #f14c4c;
1037
+ background: #3b2424;
1038
+ }
1039
+
1040
+ .output-entry.step-finish {
1041
+ border-left-color: #c586c0;
1042
+ background: #2d282d;
1043
+ }
1044
+
1045
+ .output-entry.file-edit {
1046
+ border-left-color: #b5cea8;
1047
+ }
1048
+
1049
+ .output-entry.command {
1050
+ border-left-color: #d7ba7d;
1051
+ }
1052
+
1053
+ .output-entry.status {
1054
+ border-left-color: #9cdcfe;
1055
+ text-align: center;
1056
+ font-style: italic;
1057
+ }
1058
+
1059
+ .output-meta {
1060
+ font-size: 0.75em;
1061
+ color: #858585;
1062
+ margin-bottom: 6px;
1063
+ display: flex;
1064
+ justify-content: space-between;
1065
+ }
1066
+
1067
+ .output-content {
1068
+ white-space: pre-wrap;
1069
+ word-break: break-word;
1070
+ line-height: 1.5;
1071
+ }
1072
+
1073
+ .output-content.streaming {
1074
+ border-right: 2px solid #d4d4d4;
1075
+ animation: blink 1s infinite;
1076
+ }
1077
+
1078
+ @keyframes blink {
1079
+
1080
+ 0%,
1081
+ 100% {
1082
+ border-color: #d4d4d4;
1083
+ }
1084
+
1085
+ 50% {
1086
+ border-color: transparent;
1087
+ }
1088
+ }
1089
+
1090
+ .tool-input,
1091
+ .tool-output {
1092
+ margin-top: 8px;
1093
+ padding: 8px;
1094
+ background: #1e1e1e;
1095
+ border-radius: 4px;
1096
+ font-size: 0.85em;
1097
+ overflow-x: auto;
1098
+ }
1099
+
1100
+ .tool-input {
1101
+ border: 1px dashed #569cd6;
1102
+ }
1103
+
1104
+ .tool-output {
1105
+ border: 1px dashed #4ec9b0;
1106
+ max-height: 300px;
1107
+ overflow-y: auto;
1108
+ }
1109
+
1110
+ .tool-output.error {
1111
+ border-color: #f14c4c;
1112
+ color: #f14c4c;
1113
+ }
1114
+
1115
+ .tool-title {
1116
+ font-weight: bold;
1117
+ color: #9cdcfe;
1118
+ margin-bottom: 4px;
1119
+ }
1120
+
1121
+ .tokens-badge {
1122
+ display: inline-block;
1123
+ padding: 2px 8px;
1124
+ background: #333;
1125
+ border-radius: 10px;
1126
+ font-size: 0.75em;
1127
+ margin-left: 8px;
1128
+ }
1129
+
1130
+ .cost-badge {
1131
+ color: #b5cea8;
1132
+ }
1133
+
1134
+ .empty-output {
1135
+ text-align: center;
1136
+ padding: 40px;
1137
+ color: #6c757d;
1138
+ }
1139
+
1140
+ .empty-output-icon {
1141
+ font-size: 3em;
1142
+ margin-bottom: 15px;
1143
+ }
1144
+
1145
+ .register-codebase-modal {
1146
+ display: none;
1147
+ position: fixed;
1148
+ top: 0;
1149
+ left: 0;
1150
+ width: 100%;
1151
+ height: 100%;
1152
+ background: rgba(0, 0, 0, 0.5);
1153
+ z-index: 1000;
1154
+ align-items: center;
1155
+ justify-content: center;
1156
+ }
1157
+
1158
+ .register-codebase-modal.show {
1159
+ display: flex;
1160
+ }
1161
+
1162
+ .register-form {
1163
+ background: white;
1164
+ padding: 30px;
1165
+ border-radius: 12px;
1166
+ width: 500px;
1167
+ max-width: 90%;
1168
+ }
1169
+
1170
+ .register-form input,
1171
+ .register-form textarea {
1172
+ width: 100%;
1173
+ padding: 12px;
1174
+ border: 2px solid #ced4da;
1175
+ border-radius: 8px;
1176
+ margin-bottom: 15px;
1177
+ font-family: inherit;
1178
+ }
1179
+
1180
+ .register-form input:focus,
1181
+ .register-form textarea:focus {
1182
+ outline: none;
1183
+ border-color: #667eea;
1184
+ }
1185
+
1186
+ .task-queue-panel {
1187
+ padding: 20px;
1188
+ overflow-y: auto;
1189
+ background: #fafafa;
1190
+ border-right: 2px solid #e9ecef;
1191
+ }
1192
+
1193
+ .task-controls {
1194
+ display: flex;
1195
+ gap: 10px;
1196
+ margin-bottom: 20px;
1197
+ }
1198
+
1199
+ .task-item {
1200
+ margin-bottom: 15px;
1201
+ padding: 15px;
1202
+ background: white;
1203
+ border-radius: 12px;
1204
+ border-left: 4px solid #667eea;
1205
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
1206
+ cursor: pointer;
1207
+ transition: all 0.2s;
1208
+ animation: slideIn 0.3s ease-out;
1209
+ }
1210
+
1211
+ .task-item:hover {
1212
+ transform: translateX(5px);
1213
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1214
+ }
1215
+
1216
+ .task-item.pending {
1217
+ border-left-color: #ffc107;
1218
+ }
1219
+
1220
+ .task-item.working {
1221
+ border-left-color: #2196f3;
1222
+ }
1223
+
1224
+ .task-item.completed {
1225
+ border-left-color: #4caf50;
1226
+ opacity: 0.7;
1227
+ }
1228
+
1229
+ .task-item.failed {
1230
+ border-left-color: #dc3545;
1231
+ }
1232
+
1233
+ .task-header {
1234
+ display: flex;
1235
+ justify-content: space-between;
1236
+ align-items: start;
1237
+ margin-bottom: 10px;
1238
+ }
1239
+
1240
+ .task-title {
1241
+ font-weight: bold;
1242
+ font-size: 1.1em;
1243
+ color: #343a40;
1244
+ margin-bottom: 5px;
1245
+ }
1246
+
1247
+ .task-status {
1248
+ padding: 4px 12px;
1249
+ border-radius: 20px;
1250
+ font-size: 0.85em;
1251
+ font-weight: 600;
1252
+ text-transform: uppercase;
1253
+ }
1254
+
1255
+ .task-status.pending {
1256
+ background: #fff3cd;
1257
+ color: #856404;
1258
+ }
1259
+
1260
+ .task-status.working {
1261
+ background: #cfe2ff;
1262
+ color: #084298;
1263
+ }
1264
+
1265
+ .task-status.completed {
1266
+ background: #d1e7dd;
1267
+ color: #0f5132;
1268
+ }
1269
+
1270
+ .task-status.failed {
1271
+ background: #f8d7da;
1272
+ color: #842029;
1273
+ }
1274
+
1275
+ .task-description {
1276
+ color: #6c757d;
1277
+ font-size: 0.95em;
1278
+ line-height: 1.5;
1279
+ margin-bottom: 10px;
1280
+ max-height: 60px;
1281
+ overflow: hidden;
1282
+ text-overflow: ellipsis;
1283
+ }
1284
+
1285
+ .task-meta {
1286
+ display: flex;
1287
+ flex-wrap: wrap;
1288
+ gap: 8px;
1289
+ font-size: 0.85em;
1290
+ color: #6c757d;
1291
+ margin-top: 10px;
1292
+ padding-top: 10px;
1293
+ border-top: 1px solid #e9ecef;
1294
+ }
1295
+
1296
+ .task-badges {
1297
+ display: flex;
1298
+ flex-wrap: wrap;
1299
+ gap: 6px;
1300
+ margin-bottom: 8px;
1301
+ }
1302
+
1303
+ .task-badges .task-badge {
1304
+ font-size: 0.75em;
1305
+ padding: 3px 8px;
1306
+ }
1307
+
1308
+ .task-actions {
1309
+ display: flex;
1310
+ gap: 8px;
1311
+ margin-top: 10px;
1312
+ }
1313
+
1314
+ /* Task Badges */
1315
+ .task-badge {
1316
+ display: inline-flex;
1317
+ align-items: center;
1318
+ gap: 4px;
1319
+ padding: 4px 10px;
1320
+ border-radius: 12px;
1321
+ font-size: 0.8em;
1322
+ font-weight: 600;
1323
+ }
1324
+
1325
+ .task-badge.pending {
1326
+ background: #fff3cd;
1327
+ color: #856404;
1328
+ }
1329
+
1330
+ .task-badge.working {
1331
+ background: #cfe2ff;
1332
+ color: #084298;
1333
+ }
1334
+
1335
+ .task-badge.agent-type {
1336
+ background: #e8eaf6;
1337
+ color: #3f51b5;
1338
+ }
1339
+
1340
+ .task-badge.codebase {
1341
+ background: #f3e5f5;
1342
+ color: #7b1fa2;
1343
+ }
1344
+
1345
+ .task-badge.priority-low {
1346
+ background: #d4edda;
1347
+ color: #155724;
1348
+ }
1349
+
1350
+ .task-badge.priority-normal {
1351
+ background: #fff3cd;
1352
+ color: #856404;
1353
+ }
1354
+
1355
+ .task-badge.priority-high {
1356
+ background: #ffe0b2;
1357
+ color: #e65100;
1358
+ }
1359
+
1360
+ .task-badge.priority-urgent {
1361
+ background: #f8d7da;
1362
+ color: #842029;
1363
+ }
1364
+
1365
+ .codebase-tasks {
1366
+ display: flex;
1367
+ gap: 8px;
1368
+ margin: 8px 0;
1369
+ flex-wrap: wrap;
1370
+ }
1371
+
1372
+ /* Watch Indicator */
1373
+ .watch-indicator {
1374
+ display: flex;
1375
+ align-items: center;
1376
+ gap: 8px;
1377
+ padding: 8px 12px;
1378
+ background: rgba(0, 200, 200, 0.1);
1379
+ border-radius: 8px;
1380
+ font-size: 0.9em;
1381
+ color: #00c8c8;
1382
+ }
1383
+
1384
+ .watch-indicator.active .watch-dot {
1385
+ width: 10px;
1386
+ height: 10px;
1387
+ background: #00c8c8;
1388
+ border-radius: 50%;
1389
+ animation: pulse 1.5s infinite;
1390
+ }
1391
+
1392
+ @keyframes pulse {
1393
+
1394
+ 0%,
1395
+ 100% {
1396
+ opacity: 1;
1397
+ transform: scale(1);
1398
+ }
1399
+
1400
+ 50% {
1401
+ opacity: 0.5;
1402
+ transform: scale(1.2);
1403
+ }
1404
+ }
1405
+
1406
+ /* Button Small */
1407
+ .btn-small {
1408
+ padding: 6px 12px !important;
1409
+ font-size: 0.85em !important;
1410
+ }
1411
+
1412
+ .btn-danger {
1413
+ background: #dc3545 !important;
1414
+ color: white !important;
1415
+ }
1416
+
1417
+ .btn-danger:hover {
1418
+ background: #c82333 !important;
1419
+ }
1420
+
1421
+ .empty-state {
1422
+ text-align: center;
1423
+ padding: 60px 20px;
1424
+ color: #6c757d;
1425
+ }
1426
+
1427
+ .empty-state-icon {
1428
+ font-size: 4em;
1429
+ margin-bottom: 20px;
1430
+ opacity: 0.5;
1431
+ }
1432
+
1433
+ .task-detail-modal {
1434
+ display: none;
1435
+ position: fixed;
1436
+ top: 0;
1437
+ left: 0;
1438
+ width: 100%;
1439
+ height: 100%;
1440
+ background: rgba(0, 0, 0, 0.5);
1441
+ z-index: 1000;
1442
+ align-items: center;
1443
+ justify-content: center;
1444
+ }
1445
+
1446
+ .task-detail-modal.show {
1447
+ display: flex;
1448
+ }
1449
+
1450
+ .modal-content {
1451
+ background: white;
1452
+ border-radius: 12px;
1453
+ max-width: 800px;
1454
+ max-height: 80vh;
1455
+ overflow-y: auto;
1456
+ padding: 30px;
1457
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
1458
+ }
1459
+
1460
+ .modal-header {
1461
+ display: flex;
1462
+ justify-content: space-between;
1463
+ align-items: center;
1464
+ margin-bottom: 20px;
1465
+ padding-bottom: 15px;
1466
+ border-bottom: 2px solid #e9ecef;
1467
+ }
1468
+
1469
+ .close-modal {
1470
+ background: none;
1471
+ border: none;
1472
+ font-size: 2em;
1473
+ cursor: pointer;
1474
+ color: #6c757d;
1475
+ }
1476
+
1477
+ .close-modal:hover {
1478
+ color: #343a40;
1479
+ }
1480
+ </style>
1481
+ </head>
1482
+
1483
+ <body>
1484
+ <div class="container">
1485
+ <div class="header">
1486
+ <h1>🤖 A2A Agent Monitor</h1>
1487
+ <p>Real-time Agent Conversation Auditing & Control</p>
1488
+ </div>
1489
+
1490
+ <div class="status-bar">
1491
+ <div class="status-item">
1492
+ <div class="status-label">Connection</div>
1493
+ <div class="status-value">
1494
+ <span class="status-indicator active"></span>
1495
+ <span id="connectionStatus">Connected</span>
1496
+ </div>
1497
+ </div>
1498
+ <div class="status-item">
1499
+ <div class="status-label">Active Agents</div>
1500
+ <div class="status-value" id="activeAgents">0</div>
1501
+ </div>
1502
+ <div class="status-item">
1503
+ <div class="status-label">Messages (Session)</div>
1504
+ <div class="status-value" id="messageCount">0</div>
1505
+ </div>
1506
+ <div class="status-item">
1507
+ <div class="status-label">Total Stored</div>
1508
+ <div class="status-value" id="totalStoredMessages">0</div>
1509
+ </div>
1510
+ <div class="status-item">
1511
+ <div class="status-label">Interventions</div>
1512
+ <div class="status-value" id="interventionCount">0</div>
1513
+ </div>
1514
+ </div>
1515
+
1516
+ <div class="main-content">
1517
+ <!-- OpenCode Codebases Panel -->
1518
+ <div class="opencode-panel">
1519
+ <div class="conversation-header">
1520
+ <h2>🚀 OpenCode Agents</h2>
1521
+ <button class="btn-primary" onclick="openRegisterModal()">➕ Register Codebase</button>
1522
+ </div>
1523
+
1524
+ <div id="opencodeStatus" class="storage-info" style="margin-bottom: 15px;">
1525
+ Checking OpenCode status...
1526
+ </div>
1527
+
1528
+ <div id="codebasesContainer">
1529
+ <!-- Registered codebases will be added here dynamically -->
1530
+ <div class="empty-state" id="noCodebasesMessage">
1531
+ <div class="empty-state-icon">📂</div>
1532
+ <p>No codebases registered</p>
1533
+ <p style="font-size: 0.9em; margin-top: 10px;">Click "Register Codebase" to add a project</p>
1534
+ </div>
1535
+ </div>
1536
+ </div>
1537
+
1538
+ <!-- Agent Output Panel - Shows detailed logs, traces, and tool calls -->
1539
+ <div class="agent-output-panel">
1540
+ <div class="agent-output-header">
1541
+ <h2>🔬 Agent Output</h2>
1542
+ <div class="output-controls">
1543
+ <button id="btnAutoScroll" class="active" onclick="toggleAutoScroll()">📜 Auto-scroll</button>
1544
+ <button onclick="clearAgentOutput()">🗑️ Clear</button>
1545
+ <button onclick="downloadAgentOutput()">💾 Export</button>
1546
+ </div>
1547
+ </div>
1548
+
1549
+ <div class="agent-selector">
1550
+ <select id="outputAgentSelect" onchange="switchAgentOutput()">
1551
+ <option value="">Select an agent to view output...</option>
1552
+ </select>
1553
+ </div>
1554
+
1555
+ <div id="agentOutputContainer">
1556
+ <div class="empty-output" id="noOutputMessage">
1557
+ <div class="empty-output-icon">📋</div>
1558
+ <p>No agent output yet</p>
1559
+ <p style="font-size: 0.9em; margin-top: 10px;">Trigger an agent to see logs, tool calls, and
1560
+ traces</p>
1561
+ </div>
1562
+ </div>
1563
+ </div>
1564
+
1565
+ <div class="conversation-panel">
1566
+ <div class="conversation-header">
1567
+ <h2>💬 Live Conversation</h2>
1568
+ <div class="filter-buttons">
1569
+ <button class="filter-btn active" onclick="filterMessages('all')">All</button>
1570
+ <button class="filter-btn" onclick="filterMessages('agent')">Agents</button>
1571
+ <button class="filter-btn" onclick="filterMessages('human')">Human</button>
1572
+ <button class="filter-btn" onclick="filterMessages('system')">System</button>
1573
+ </div>
1574
+ </div>
1575
+
1576
+ <div class="search-box">
1577
+ <input type="text" id="searchInput" placeholder="🔍 Search messages..." onkeyup="searchMessages()">
1578
+ <button class="btn-search" onclick="searchPersistent()">🔎 Search All History</button>
1579
+ </div>
1580
+
1581
+ <div id="searchResults" class="search-results" style="display: none;">
1582
+ <div class="search-results-header">
1583
+ <h3>Search Results</h3>
1584
+ <button class="btn-close" onclick="closeSearchResults()">×</button>
1585
+ </div>
1586
+ <div id="searchResultsContent"></div>
1587
+ </div>
1588
+
1589
+ <div id="messagesContainer">
1590
+ <!-- Messages will be added here dynamically -->
1591
+ </div>
1592
+ </div>
1593
+
1594
+ <div class="task-queue-panel">
1595
+ <div class="conversation-header">
1596
+ <h2>📋 Task Queue</h2>
1597
+ <div class="filter-buttons">
1598
+ <button class="filter-btn active" onclick="filterTasks('all')">All</button>
1599
+ <button class="filter-btn" onclick="filterTasks('pending')">Pending</button>
1600
+ <button class="filter-btn" onclick="filterTasks('working')">Working</button>
1601
+ <button class="filter-btn" onclick="filterTasks('completed')">Completed</button>
1602
+ </div>
1603
+ </div>
1604
+
1605
+ <div class="task-controls">
1606
+ <button class="btn-primary" onclick="createNewTask()">➕ Create Task</button>
1607
+ <button class="btn-secondary" onclick="refreshTasks()">🔄 Refresh</button>
1608
+ </div>
1609
+
1610
+ <div id="tasksContainer">
1611
+ <!-- Tasks will be added here dynamically -->
1612
+ </div>
1613
+ </div>
1614
+
1615
+ <div class="controls-panel">
1616
+ <div class="control-section">
1617
+ <h3>📊 Statistics</h3>
1618
+ <div class="stats-grid">
1619
+ <div class="stat-box">
1620
+ <div class="stat-number" id="avgResponseTime">0ms</div>
1621
+ <div class="stat-label">Avg Response</div>
1622
+ </div>
1623
+ <div class="stat-box">
1624
+ <div class="stat-number" id="toolCalls">0</div>
1625
+ <div class="stat-label">Tool Calls</div>
1626
+ </div>
1627
+ <div class="stat-box">
1628
+ <div class="stat-number" id="errorCount">0</div>
1629
+ <div class="stat-label">Errors</div>
1630
+ </div>
1631
+ <div class="stat-box">
1632
+ <div class="stat-number" id="tokenCount">0</div>
1633
+ <div class="stat-label">Tokens Used</div>
1634
+ </div>
1635
+ </div>
1636
+ </div>
1637
+
1638
+ <div class="control-section">
1639
+ <h3>🤖 Active Agents</h3>
1640
+ <ul class="agent-list" id="agentList">
1641
+ <!-- Agent list will be populated dynamically -->
1642
+ </ul>
1643
+ </div>
1644
+
1645
+ <div class="control-section">
1646
+ <h3>✋ Human Intervention</h3>
1647
+ <form class="intervene-form" onsubmit="sendIntervention(event)">
1648
+ <select id="targetAgent" required>
1649
+ <option value="">Select Agent...</option>
1650
+ </select>
1651
+ <textarea id="interventionMessage" placeholder="Enter your message or instruction..."
1652
+ required></textarea>
1653
+ <button type="submit" class="btn-primary">Send Intervention</button>
1654
+ </form>
1655
+ </div>
1656
+
1657
+ <div class="control-section">
1658
+ <h3>💾 Export & Logs</h3>
1659
+ <p class="storage-info">📊 All logs are <strong>permanently stored</strong> in the database.</p>
1660
+ <div class="export-section">
1661
+ <button class="btn-secondary" onclick="exportJSON()">Export JSON (Recent)</button>
1662
+ <button class="btn-secondary" onclick="exportAllJSON()">Export All JSON</button>
1663
+ <button class="btn-secondary" onclick="exportCSV()">Export CSV (Recent)</button>
1664
+ <button class="btn-secondary" onclick="exportAllCSV()">Export All CSV</button>
1665
+ </div>
1666
+ <div class="log-controls">
1667
+ <button class="btn-secondary" onclick="loadHistoricalMessages()">📜 Load History</button>
1668
+ <button class="btn-secondary" onclick="clearLogs()">Clear View</button>
1669
+ <button class="btn-secondary" onclick="pauseMonitoring()">Pause</button>
1670
+ </div>
1671
+ </div>
1672
+ </div>
1673
+ </div>
1674
+ </div>
1675
+
1676
+ <!-- Register Codebase Modal -->
1677
+ <div id="registerCodebaseModal" class="register-codebase-modal">
1678
+ <div class="register-form">
1679
+ <div class="modal-header" style="margin-bottom: 20px;">
1680
+ <h2>📂 Register Codebase</h2>
1681
+ <button class="close-modal" onclick="closeRegisterModal()">×</button>
1682
+ </div>
1683
+ <form onsubmit="registerCodebase(event)">
1684
+ <label style="font-weight: 600; margin-bottom: 5px; display: block;">Codebase Name *</label>
1685
+ <input type="text" id="codebaseName" placeholder="My Project" required>
1686
+
1687
+ <label style="font-weight: 600; margin-bottom: 5px; display: block;">Absolute Path *</label>
1688
+ <input type="text" id="codebasePath" placeholder="/home/user/projects/myproject" required>
1689
+
1690
+ <label style="font-weight: 600; margin-bottom: 5px; display: block;">Description</label>
1691
+ <textarea id="codebaseDescription" placeholder="Brief description of the project..."
1692
+ rows="3"></textarea>
1693
+
1694
+ <div style="display: flex; gap: 10px; margin-top: 10px;">
1695
+ <button type="submit" class="btn-primary" style="flex: 1;">Register</button>
1696
+ <button type="button" class="btn-secondary" style="flex: 1;"
1697
+ onclick="closeRegisterModal()">Cancel</button>
1698
+ </div>
1699
+ </form>
1700
+ </div>
1701
+ </div>
1702
+
1703
+ <!-- Task Creation Modal -->
1704
+ <div id="taskModal" class="task-modal">
1705
+ <div class="task-form">
1706
+ <div class="modal-header" style="margin-bottom: 20px;">
1707
+ <h2>📋 Create Task</h2>
1708
+ <button class="close-modal" onclick="closeTaskModal()">×</button>
1709
+ </div>
1710
+ <form onsubmit="submitTask(event)">
1711
+ <label style="font-weight: 600; margin-bottom: 5px; display: block;">Codebase</label>
1712
+ <select id="taskCodebase">
1713
+ <option value="global">Global (Any Worker)</option>
1714
+ </select>
1715
+
1716
+ <label style="font-weight: 600; margin-bottom: 5px; display: block;">Agent Type *</label>
1717
+ <select id="taskAgentType" required>
1718
+ <option value="build">Build</option>
1719
+ <option value="plan">Plan</option>
1720
+ <option value="general" selected>General</option>
1721
+ <option value="explore">Explore</option>
1722
+ </select>
1723
+
1724
+ <label style="font-weight: 600; margin-bottom: 5px; display: block;">Task Title *</label>
1725
+ <input type="text" id="taskTitle" placeholder="e.g., Add user authentication" required>
1726
+
1727
+ <label style="font-weight: 600; margin-bottom: 5px; display: block;">Task Description *</label>
1728
+ <textarea id="taskDescription" placeholder="Describe what you want the agent to do..." rows="4"
1729
+ required></textarea>
1730
+
1731
+ <label style="font-weight: 600; margin-bottom: 5px; display: block;">Priority</label>
1732
+ <select id="taskPriority" class="priority-select">
1733
+ <option value="1" class="priority-option priority-low">🟢 Low</option>
1734
+ <option value="2" class="priority-option priority-normal" selected>🟡 Normal</option>
1735
+ <option value="3" class="priority-option priority-high">🟠 High</option>
1736
+ <option value="4" class="priority-option priority-urgent">🔴 Urgent</option>
1737
+ </select>
1738
+
1739
+ <label style="font-weight: 600; margin-bottom: 5px; display: block;">Additional Context
1740
+ (Optional)</label>
1741
+ <textarea id="taskContext" placeholder="Any additional files, requirements, or context..."
1742
+ rows="3"></textarea>
1743
+
1744
+ <div style="display: flex; gap: 10px; margin-top: 15px;">
1745
+ <button type="submit" class="btn-primary" style="flex: 1;">🚀 Create Task</button>
1746
+ <button type="button" class="btn-secondary" style="flex: 1;"
1747
+ onclick="closeTaskModal()">Cancel</button>
1748
+ </div>
1749
+ </form>
1750
+ </div>
1751
+ </div>
1752
+
1753
+ <!-- Agent Output Modal -->
1754
+ <div id="agentOutputModal" class="task-modal">
1755
+ <div class="task-form" style="max-width: 900px; width: 90%;">
1756
+ <div class="modal-header" style="margin-bottom: 20px;">
1757
+ <h2>🤖 Agent Output</h2>
1758
+ <button class="close-modal" onclick="closeAgentOutputModal()">×</button>
1759
+ </div>
1760
+ <div id="agentOutputContent"
1761
+ style="max-height: 500px; overflow-y: auto; background: #1a1a2e; padding: 15px; border-radius: 8px; font-family: monospace; font-size: 13px;">
1762
+ <div class="loading">Waiting for agent output...</div>
1763
+ </div>
1764
+ <div style="display: flex; gap: 10px; margin-top: 15px;">
1765
+ <button class="btn-secondary" onclick="clearAgentOutput()">Clear Output</button>
1766
+ <button class="btn-secondary" onclick="exportAgentOutput()">Export Log</button>
1767
+ <button class="btn-primary" onclick="closeAgentOutputModal()">Close</button>
1768
+ </div>
1769
+ </div>
1770
+ </div>
1771
+
1772
+ <script src="monitor.js"></script>
1773
+ </body>
1774
+
1775
+ </html>