Really-amin commited on
Commit
1e98c7f
Β·
verified Β·
1 Parent(s): c293798

Upload 4 files

Browse files
Files changed (4) hide show
  1. ai_models.py +12 -0
  2. api_server_extended.py +83 -0
  3. config.py +42 -39
  4. index.html +203 -8
ai_models.py CHANGED
@@ -14,6 +14,7 @@ try:
14
  TRANSFORMERS_AVAILABLE = True
15
  except ImportError:
16
  TRANSFORMERS_AVAILABLE = False
 
17
 
18
  try:
19
  from huggingface_hub.errors import RepositoryNotFoundError
@@ -32,6 +33,17 @@ if HF_MODE not in ("off", "public", "auth"):
32
  HF_MODE = "public"
33
  logger.warning(f"Invalid HF_MODE, resetting to 'public'")
34
 
 
 
 
 
 
 
 
 
 
 
 
35
  if HF_MODE == "auth" and not HF_TOKEN_ENV:
36
  logger.error("⚠️ HF_MODE='auth' but no HF_TOKEN found!")
37
  logger.error(" Falling back to 'public' mode")
 
14
  TRANSFORMERS_AVAILABLE = True
15
  except ImportError:
16
  TRANSFORMERS_AVAILABLE = False
17
+ pipeline = None
18
 
19
  try:
20
  from huggingface_hub.errors import RepositoryNotFoundError
 
33
  HF_MODE = "public"
34
  logger.warning(f"Invalid HF_MODE, resetting to 'public'")
35
 
36
+ # Log initial status
37
+ if TRANSFORMERS_AVAILABLE:
38
+ logger.info(f"βœ… Transformers library available")
39
+ if HF_TOKEN_ENV:
40
+ logger.info(f"βœ… HF Token found (mode: {HF_MODE})")
41
+ else:
42
+ logger.warning(f"⚠️ No HF Token found (mode: {HF_MODE}) - public models only")
43
+ else:
44
+ logger.warning("⚠️ Transformers library NOT available - using fallback only")
45
+ HF_MODE = "off"
46
+
47
  if HF_MODE == "auth" and not HF_TOKEN_ENV:
48
  logger.error("⚠️ HF_MODE='auth' but no HF_TOKEN found!")
49
  logger.error(" Falling back to 'public' mode")
api_server_extended.py CHANGED
@@ -1951,6 +1951,89 @@ async def get_diagnostics_health():
1951
  }
1952
 
1953
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1954
  @app.post("/api/diagnostics/self-heal")
1955
  async def trigger_self_heal(model_key: Optional[str] = None):
1956
  """
 
1951
  }
1952
 
1953
 
1954
+ @app.post("/api/diagnostics/run-test")
1955
+ async def run_diagnostic_test():
1956
+ """
1957
+ Run test_models_diagnostic.py and return results.
1958
+ Execute the Python script and capture stdout/stderr.
1959
+ """
1960
+ import subprocess
1961
+ import time
1962
+
1963
+ start_time = time.time()
1964
+
1965
+ try:
1966
+ # Execute the diagnostic script
1967
+ result = subprocess.run(
1968
+ ["python3", "test_models_diagnostic.py"],
1969
+ capture_output=True,
1970
+ text=True,
1971
+ timeout=60, # 60 second timeout
1972
+ cwd=WORKSPACE_ROOT
1973
+ )
1974
+
1975
+ duration = time.time() - start_time
1976
+
1977
+ # Combine stdout and stderr
1978
+ full_output = result.stdout
1979
+ if result.stderr:
1980
+ full_output += "\n--- STDERR ---\n" + result.stderr
1981
+
1982
+ # Parse output for summary information
1983
+ summary = {
1984
+ "transformers_available": "βœ… transformers:" in full_output and "OK" in full_output,
1985
+ "hf_hub_connected": "βœ… Hub connection:" in full_output and "OK" in full_output,
1986
+ "models_loaded": 0, # Would need more parsing to count actual loaded models
1987
+ "critical_issues": []
1988
+ }
1989
+
1990
+ # Check for critical issues
1991
+ if "❌ transformers:" in full_output:
1992
+ summary["critical_issues"].append("Transformers library not available")
1993
+ if "❌ Authenticated access:" in full_output and "FAILED" in full_output:
1994
+ summary["critical_issues"].append("HuggingFace authentication failed")
1995
+ if "❌ Model not available" in full_output:
1996
+ summary["critical_issues"].append("AI models failed to load")
1997
+
1998
+ return {
1999
+ "status": "success",
2000
+ "output": full_output,
2001
+ "timestamp": datetime.now().isoformat(),
2002
+ "duration_seconds": round(duration, 2),
2003
+ "summary": summary
2004
+ }
2005
+
2006
+ except subprocess.TimeoutExpired:
2007
+ duration = time.time() - start_time
2008
+ return {
2009
+ "status": "timeout",
2010
+ "output": f"Test timed out after {duration:.1f} seconds",
2011
+ "timestamp": datetime.now().isoformat(),
2012
+ "duration_seconds": round(duration, 2),
2013
+ "summary": {
2014
+ "transformers_available": False,
2015
+ "hf_hub_connected": False,
2016
+ "models_loaded": 0,
2017
+ "critical_issues": ["Test execution timed out"]
2018
+ }
2019
+ }
2020
+
2021
+ except Exception as e:
2022
+ duration = time.time() - start_time
2023
+ return {
2024
+ "status": "error",
2025
+ "output": f"Error running diagnostic test: {str(e)}",
2026
+ "timestamp": datetime.now().isoformat(),
2027
+ "duration_seconds": round(duration, 2),
2028
+ "summary": {
2029
+ "transformers_available": False,
2030
+ "hf_hub_connected": False,
2031
+ "models_loaded": 0,
2032
+ "critical_issues": [f"Execution error: {str(e)}"]
2033
+ }
2034
+ }
2035
+
2036
+
2037
  @app.post("/api/diagnostics/self-heal")
2038
  async def trigger_self_heal(model_key: Optional[str] = None):
2039
  """
config.py CHANGED
@@ -1,39 +1,42 @@
1
- #!/usr/bin/env python3
2
- """Configuration module for Hugging Face models."""
3
-
4
- import os
5
- from typing import Optional, Dict, Any
6
-
7
- HUGGINGFACE_MODELS: Dict[str, str] = {
8
- "sentiment_twitter": "cardiffnlp/twitter-roberta-base-sentiment-latest",
9
- "sentiment_financial": "ProsusAI/finbert",
10
- "summarization": "facebook/bart-large-cnn",
11
- "crypto_sentiment": "ElKulako/cryptobert",
12
- }
13
-
14
- # Self-Healing Configuration
15
- SELF_HEALING_CONFIG = {
16
- "error_threshold": int(os.getenv("HEALTH_ERROR_THRESHOLD", "3")), # Failures before degraded
17
- "cooldown_seconds": int(os.getenv("HEALTH_COOLDOWN_SECONDS", "300")), # 5 minutes default
18
- "success_recovery_count": int(os.getenv("HEALTH_RECOVERY_COUNT", "2")), # Successes to recover
19
- "enable_auto_reinit": os.getenv("HEALTH_AUTO_REINIT", "true").lower() == "true",
20
- "reinit_cooldown_seconds": int(os.getenv("HEALTH_REINIT_COOLDOWN", "600")), # 10 minutes
21
- }
22
-
23
- class Settings:
24
- """Application settings."""
25
- def __init__(self):
26
- self.hf_token: Optional[str] = os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACE_TOKEN")
27
- # Self-healing settings
28
- self.health_error_threshold: int = SELF_HEALING_CONFIG["error_threshold"]
29
- self.health_cooldown_seconds: int = SELF_HEALING_CONFIG["cooldown_seconds"]
30
- self.health_success_recovery_count: int = SELF_HEALING_CONFIG["success_recovery_count"]
31
- self.health_enable_auto_reinit: bool = SELF_HEALING_CONFIG["enable_auto_reinit"]
32
- self.health_reinit_cooldown_seconds: int = SELF_HEALING_CONFIG["reinit_cooldown_seconds"]
33
-
34
- _settings = Settings()
35
-
36
- def get_settings() -> Settings:
37
- """Get application settings instance."""
38
- return _settings
39
-
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Configuration module for the application."""
3
+
4
+ import os
5
+ from typing import Optional, Dict, Any
6
+
7
+ # Legacy model definitions (for backward compatibility)
8
+ # NOTE: ai_models.py now defines models directly
9
+ HUGGINGFACE_MODELS: Dict[str, str] = {
10
+ "sentiment_twitter": "cardiffnlp/twitter-roberta-base-sentiment-latest",
11
+ "sentiment_financial": "ProsusAI/finbert",
12
+ "summarization": "facebook/bart-large-cnn",
13
+ "crypto_sentiment": "ElKulako/cryptobert",
14
+ }
15
+
16
+ # Self-Healing Configuration
17
+ SELF_HEALING_CONFIG = {
18
+ "error_threshold": int(os.getenv("HEALTH_ERROR_THRESHOLD", "3")),
19
+ "cooldown_seconds": int(os.getenv("HEALTH_COOLDOWN_SECONDS", "300")),
20
+ "success_recovery_count": int(os.getenv("HEALTH_RECOVERY_COUNT", "2")),
21
+ "enable_auto_reinit": os.getenv("HEALTH_AUTO_REINIT", "true").lower() == "true",
22
+ "reinit_cooldown_seconds": int(os.getenv("HEALTH_REINIT_COOLDOWN", "60")),
23
+ }
24
+
25
+ class Settings:
26
+ """Application settings."""
27
+ def __init__(self):
28
+ # HuggingFace authentication
29
+ self.hf_token: Optional[str] = os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACE_TOKEN")
30
+
31
+ # Self-healing settings
32
+ self.health_error_threshold: int = SELF_HEALING_CONFIG["error_threshold"]
33
+ self.health_cooldown_seconds: int = SELF_HEALING_CONFIG["cooldown_seconds"]
34
+ self.health_success_recovery_count: int = SELF_HEALING_CONFIG["success_recovery_count"]
35
+ self.health_enable_auto_reinit: bool = SELF_HEALING_CONFIG["enable_auto_reinit"]
36
+ self.health_reinit_cooldown_seconds: int = SELF_HEALING_CONFIG["reinit_cooldown_seconds"]
37
+
38
+ _settings = Settings()
39
+
40
+ def get_settings() -> Settings:
41
+ """Get application settings instance."""
42
+ return _settings
index.html CHANGED
@@ -30,7 +30,7 @@
30
  <!-- Sidebar Navigation -->
31
  <aside class="sidebar" id="sidebar">
32
  <div class="sidebar-header">
33
- <div class="sidebar-logo">
34
  <div class="logo-icon">
35
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
36
  <path d="M12 2L2 7l10 5 10-5-10-5z"></path>
@@ -110,13 +110,23 @@
110
  </svg>
111
  <span>AI Design Tools</span>
112
  </button>
113
- <button class="nav-item" data-tab="settings" onclick="switchTab('settings')">
114
- <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
115
- <circle cx="12" cy="12" r="3"></circle>
116
- <path d="M12 1v6m0 6v6m9-9h-6m-6 0H3m15.364 6.364l-4.243-4.243m-4.242 0L5.636 17.364m12.728 0l-4.243-4.243m-4.242 0L5.636 6.636"></path>
117
- </svg>
118
- <span>Settings</span>
119
- </button>
 
 
 
 
 
 
 
 
 
 
120
  </nav>
121
 
122
  <div class="sidebar-footer">
@@ -483,6 +493,191 @@
483
  <div id="api-info"></div>
484
  </div>
485
  </section>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
486
  </main>
487
  </div>
488
  </div>
 
30
  <!-- Sidebar Navigation -->
31
  <aside class="sidebar" id="sidebar">
32
  <div class="sidebar-header">
33
+ <div class="sidebar-logo" onclick="switchTab('dashboard')" style="cursor: pointer;">
34
  <div class="logo-icon">
35
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
36
  <path d="M12 2L2 7l10 5 10-5-10-5z"></path>
 
110
  </svg>
111
  <span>AI Design Tools</span>
112
  </button>
113
+ <div class="nav-section">
114
+ <div class="nav-section-header">
115
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
116
+ <circle cx="12" cy="12" r="3"></circle>
117
+ <path d="M12 1v6m0 6v6m9-9h-6m-6 0H3m15.364 6.364l-4.243-4.243m-4.242 0L5.636 17.364m12.728 0l-4.243-4.243m-4.242 0L5.636 6.636"></path>
118
+ </svg>
119
+ <span>Settings</span>
120
+ </div>
121
+ <div class="nav-section-items">
122
+ <button class="nav-item nav-subitem" data-tab="settings" onclick="switchTab('settings')">
123
+ <span>βš™οΈ System Status</span>
124
+ </button>
125
+ <button class="nav-item nav-subitem" data-tab="diagnostics" onclick="switchTab('diagnostics')">
126
+ <span>πŸ” Test & Diagnostics</span>
127
+ </button>
128
+ </div>
129
+ </div>
130
  </nav>
131
 
132
  <div class="sidebar-footer">
 
493
  <div id="api-info"></div>
494
  </div>
495
  </section>
496
+
497
+ <!-- Providers Placeholder Tab -->
498
+ <section id="tab-providers" class="tab-panel">
499
+ <div class="placeholder-page">
500
+ <div class="placeholder-icon">🧩</div>
501
+ <h2>Providers</h2>
502
+ <p>This feature is under development.</p>
503
+ <p class="text-secondary">Provider management and configuration will be available here.</p>
504
+ <button class="btn-primary" onclick="switchTab('diagnostics')">
505
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: inline-block; vertical-align: middle; margin-right: 6px;">
506
+ <path d="M12 2L2 7l10 5 10-5-10-5z"></path>
507
+ <path d="M2 17l10 5 10-5"></path>
508
+ <path d="M2 12l10 5 10-5"></path>
509
+ </svg>
510
+ Run Diagnostics
511
+ </button>
512
+ </div>
513
+ </section>
514
+
515
+ <!-- Resources Placeholder Tab -->
516
+ <section id="tab-resources" class="tab-panel">
517
+ <div class="placeholder-page">
518
+ <div class="placeholder-icon">πŸ“š</div>
519
+ <h2>Resources</h2>
520
+ <p>This feature is under development.</p>
521
+ <p class="text-secondary">Resource management and monitoring will be available here.</p>
522
+ <button class="btn-primary" onclick="switchTab('diagnostics')">
523
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: inline-block; vertical-align: middle; margin-right: 6px;">
524
+ <path d="M12 2L2 7l10 5 10-5-10-5z"></path>
525
+ <path d="M2 17l10 5 10-5"></path>
526
+ <path d="M2 12l10 5 10-5"></path>
527
+ </svg>
528
+ Run Diagnostics
529
+ </button>
530
+ </div>
531
+ </section>
532
+
533
+ <!-- DeFi Analytics Placeholder Tab -->
534
+ <section id="tab-defi" class="tab-panel">
535
+ <div class="placeholder-page">
536
+ <div class="placeholder-icon">πŸ’Ž</div>
537
+ <h2>DeFi Analytics</h2>
538
+ <p>This feature is under development.</p>
539
+ <p class="text-secondary">DeFi protocol analytics and insights will be available here.</p>
540
+ <button class="btn-primary" onclick="switchTab('diagnostics')">
541
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: inline-block; vertical-align: middle; margin-right: 6px;">
542
+ <path d="M12 2L2 7l10 5 10-5-10-5z"></path>
543
+ <path d="M2 17l10 5 10-5"></path>
544
+ <path d="M2 12l10 5 10-5"></path>
545
+ </svg>
546
+ Run Diagnostics
547
+ </button>
548
+ </div>
549
+ </section>
550
+
551
+ <!-- System Status Placeholder Tab -->
552
+ <section id="tab-system-status" class="tab-panel">
553
+ <div class="placeholder-page">
554
+ <div class="placeholder-icon">βš™οΈ</div>
555
+ <h2>System Status</h2>
556
+ <p>This feature is under development.</p>
557
+ <p class="text-secondary">System health monitoring and status dashboard will be available here.</p>
558
+ <button class="btn-primary" onclick="switchTab('diagnostics')">
559
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: inline-block; vertical-align: middle; margin-right: 6px;">
560
+ <path d="M12 2L2 7l10 5 10-5-10-5z"></path>
561
+ <path d="M2 17l10 5 10-5"></path>
562
+ <path d="M2 12l10 5 10-5"></path>
563
+ </svg>
564
+ Run Diagnostics
565
+ </button>
566
+ </div>
567
+ </section>
568
+
569
+ <!-- Test & Diagnostics Tab -->
570
+ <section id="tab-diagnostics" class="tab-panel">
571
+ <div class="diagnostic-header">
572
+ <div class="diagnostic-title">
573
+ <h2>πŸ” System Diagnostics & Model Testing</h2>
574
+ <p>Run comprehensive tests on AI models, transformers, and HuggingFace Hub connectivity</p>
575
+ </div>
576
+ </div>
577
+
578
+ <!-- Quick Status Cards -->
579
+ <div class="status-cards-grid">
580
+ <div class="status-card" id="transformers-status">
581
+ <div class="status-icon">πŸ“š</div>
582
+ <div class="status-content">
583
+ <div class="status-label">Transformers Library</div>
584
+ <div class="status-value" id="transformers-status-value">Checking...</div>
585
+ </div>
586
+ </div>
587
+
588
+ <div class="status-card" id="hf-status">
589
+ <div class="status-icon">πŸ€—</div>
590
+ <div class="status-content">
591
+ <div class="status-label">HuggingFace Hub</div>
592
+ <div class="status-value" id="hf-status-value">Checking...</div>
593
+ </div>
594
+ </div>
595
+
596
+ <div class="status-card" id="models-status">
597
+ <div class="status-icon">🧠</div>
598
+ <div class="status-content">
599
+ <div class="status-label">Models Loaded</div>
600
+ <div class="status-value" id="models-status-value">0</div>
601
+ </div>
602
+ </div>
603
+
604
+ <div class="status-card" id="last-test-status">
605
+ <div class="status-icon">πŸ•’</div>
606
+ <div class="status-content">
607
+ <div class="status-label">Last Test Run</div>
608
+ <div class="status-value" id="last-test-value">Never</div>
609
+ </div>
610
+ </div>
611
+ </div>
612
+
613
+ <!-- Action Buttons -->
614
+ <div class="diagnostic-actions">
615
+ <button class="btn-primary" id="run-diagnostics-btn" onclick="runDiagnostic()">
616
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: inline-block; vertical-align: middle; margin-right: 6px;">
617
+ <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon>
618
+ </svg>
619
+ ▢️ Run Full Diagnostic
620
+ </button>
621
+ <button class="btn-secondary" onclick="refreshDiagnosticStatus()">
622
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: inline-block; vertical-align: middle; margin-right: 6px;">
623
+ <polyline points="23 4 23 10 17 10"></polyline>
624
+ <polyline points="1 20 1 14 7 14"></polyline>
625
+ <path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>
626
+ </svg>
627
+ πŸ”„ Refresh Status
628
+ </button>
629
+ <button class="btn-secondary" onclick="downloadDiagnosticLog()">
630
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: inline-block; vertical-align: middle; margin-right: 6px;">
631
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
632
+ <polyline points="7 10 12 15 17 10"></polyline>
633
+ <line x1="12" y1="15" x2="12" y2="3"></line>
634
+ </svg>
635
+ πŸ“₯ Download Log
636
+ </button>
637
+ </div>
638
+
639
+ <!-- Test Output Section -->
640
+ <div class="diagnostic-output-section">
641
+ <div class="glass-card">
642
+ <div class="card-header">
643
+ <h3>Test Output</h3>
644
+ <div id="test-progress" style="display: none;">
645
+ <div class="spinner"></div>
646
+ <span>Running diagnostic tests...</span>
647
+ </div>
648
+ </div>
649
+ <div class="diagnostic-output-container">
650
+ <pre id="diagnostic-output" class="diagnostic-output"></pre>
651
+ </div>
652
+ </div>
653
+ </div>
654
+
655
+ <!-- Test Results Summary -->
656
+ <div class="diagnostic-summary" id="diagnostic-summary" style="display: none;">
657
+ <div class="glass-card">
658
+ <h3>Test Results Summary</h3>
659
+ <div class="summary-grid">
660
+ <div class="summary-item">
661
+ <span class="summary-label">Duration:</span>
662
+ <span class="summary-value" id="summary-duration">-</span>
663
+ </div>
664
+ <div class="summary-item">
665
+ <span class="summary-label">Tests Passed:</span>
666
+ <span class="summary-value" id="summary-passed">-</span>
667
+ </div>
668
+ <div class="summary-item">
669
+ <span class="summary-label">Tests Failed:</span>
670
+ <span class="summary-value" id="summary-failed">-</span>
671
+ </div>
672
+ <div class="summary-item">
673
+ <span class="summary-label">Critical Issues:</span>
674
+ <span class="summary-value" id="summary-critical">-</span>
675
+ </div>
676
+ </div>
677
+ <div id="suggested-fixes" style="margin-top: 15px;"></div>
678
+ </div>
679
+ </div>
680
+ </section>
681
  </main>
682
  </div>
683
  </div>