petter2025's picture
Update ui/styles.py
409be37 verified
raw
history blame
15.9 kB
"""
Configuration management for ARF Demo
Updated with REAL ARF installation detection - FIXED ENUM ERROR
"""
from typing import Optional, Dict, Any, List
from enum import Enum
import os
import logging
logger = logging.getLogger(__name__)
# Try to import from pydantic-settings, fallback to pydantic
try:
from pydantic_settings import BaseSettings
from pydantic import Field, validator
PYDANTIC_V2 = True
logger.info("Using pydantic-settings for BaseSettings")
except ImportError:
try:
from pydantic import BaseSettings, Field, validator
PYDANTIC_V2 = False
logger.info("Using pydantic.BaseSettings (older version)")
except ImportError as e:
logger.error(f"Failed to import pydantic: {e}")
# Create minimal fallback
class BaseSettings:
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
class Field:
@staticmethod
def default(value):
return value
def validator(*args, **kwargs):
def decorator(func):
return func
return decorator
PYDANTIC_V2 = False
class ARFMode(str, Enum):
"""ARF operation modes"""
DEMO = "demo"
OSS = "oss"
ENTERPRISE = "enterprise"
class SafetyMode(str, Enum):
"""Safety modes for execution"""
ADVISORY = "advisory"
APPROVAL = "approval"
AUTONOMOUS = "autonomous"
class InstallationStatus(str, Enum):
"""ARF package installation status"""
NOT_INSTALLED = "not_installed"
OSS_ONLY = "oss_only"
ENTERPRISE = "enterprise"
BOTH = "both"
class Settings(BaseSettings):
"""
Application settings with environment variable support
"""
# ===== System Mode =====
arf_mode: str = Field(
default="demo", # Changed from ARFMode to string to avoid enum issues
description="ARF operation mode: demo, oss, enterprise"
)
use_true_arf: bool = Field(
default=True,
description="Use true ARF integration when available"
)
# ===== Installation Status (Auto-detected) =====
arf_oss_installed: bool = Field(
default=False,
description="ARF OSS package installed"
)
arf_enterprise_installed: bool = Field(
default=False,
description="ARF Enterprise package installed"
)
arf_oss_version: Optional[str] = Field(
default=None,
description="ARF OSS version if installed"
)
arf_enterprise_version: Optional[str] = Field(
default=None,
description="ARF Enterprise version if installed"
)
# ===== ARF Configuration =====
arf_api_key: Optional[str] = Field(
default=None,
description="ARF API key for real integration"
)
arf_base_url: str = Field(
default="https://api.arf.dev",
description="ARF API base URL"
)
# ===== Business Configuration =====
engineer_hourly_rate: float = Field(
default=150.0,
description="Engineer hourly rate in USD"
)
engineer_annual_cost: float = Field(
default=125000.0,
description="Engineer annual cost in USD"
)
default_savings_rate: float = Field(
default=0.82,
description="Default savings rate with ARF"
)
# ===== UI Configuration =====
auto_refresh_seconds: int = Field(
default=30,
description="Auto-refresh interval in seconds"
)
max_history_items: int = Field(
default=100,
description="Maximum history items to display"
)
# ===== Demo Configuration =====
default_scenario: str = Field(
default="Cache Miss Storm",
description="Default incident scenario"
)
scenario_config_path: str = Field(
default="config/scenarios",
description="Path to scenario configuration files"
)
# ===== Safety Configuration =====
default_safety_mode: str = Field(
default="advisory", # Changed from SafetyMode to string
description="Default safety mode: advisory, approval, autonomous"
)
require_approval: bool = Field(
default=True,
description="Require human approval for execution"
)
# ===== Validation =====
@validator("arf_api_key")
def validate_api_key(cls, v: Optional[str], values: Dict[str, Any]) -> Optional[str]:
if values.get("arf_mode") == "enterprise" and not v:
raise ValueError("ARF API key required for Enterprise mode")
return v
@validator("use_true_arf")
def validate_true_arf(cls, v: bool, values: Dict[str, Any]) -> bool:
if v and not values.get("arf_oss_installed"):
logger.warning("True ARF requested but OSS package not installed. Using mock mode.")
return False
return v
# ===== Installation Detection =====
@classmethod
def detect_installation(cls):
"""Detect ARF package installation"""
results = {
"oss_installed": False,
"enterprise_installed": False,
"oss_version": None,
"enterprise_version": None
}
# Check OSS package
try:
import agentic_reliability_framework as arf_oss
results["oss_installed"] = True
results["oss_version"] = getattr(arf_oss, '__version__', '3.3.7')
logger.info(f"✅ ARF OSS v{results['oss_version']} detected")
except ImportError:
logger.info("⚠️ ARF OSS not installed - will use mock mode")
# Check Enterprise package
try:
import arf_enterprise
results["enterprise_installed"] = True
results["enterprise_version"] = getattr(arf_enterprise, '__version__', '1.0.2')
logger.info(f"✅ ARF Enterprise v{results['enterprise_version']} detected")
except ImportError:
logger.info("⚠️ ARF Enterprise not installed - will use simulation")
return results
def get_installation_status(self) -> InstallationStatus:
"""Get current installation status"""
if self.arf_oss_installed and self.arf_enterprise_installed:
return InstallationStatus.BOTH
elif self.arf_enterprise_installed:
return InstallationStatus.ENTERPRISE
elif self.arf_oss_installed:
return InstallationStatus.OSS_ONLY
else:
return InstallationStatus.NOT_INSTALLED
def get_installation_badges(self) -> Dict[str, Any]:
"""Get badge information for UI display"""
if self.arf_oss_installed:
oss_badge = {
"text": f"✅ ARF OSS v{self.arf_oss_version}",
"color": "#10b981",
"icon": "✅"
}
else:
oss_badge = {
"text": "⚠️ Mock ARF",
"color": "#f59e0b",
"icon": "⚠️"
}
if self.arf_enterprise_installed:
enterprise_badge = {
"text": f"🚀 Enterprise v{self.arf_enterprise_version}",
"color": "#8b5cf6",
"icon": "🚀"
}
else:
enterprise_badge = {
"text": "🔒 Enterprise Required",
"color": "#64748b",
"icon": "🔒"
}
return {
"oss": oss_badge,
"enterprise": enterprise_badge
}
def get_installation_recommendations(self) -> List[str]:
"""Get installation recommendations"""
recommendations = []
if not self.arf_oss_installed:
recommendations.append(
"Install real ARF OSS: `pip install agentic-reliability-framework==3.3.7`"
)
if not self.arf_enterprise_installed:
recommendations.append(
"Install ARF Enterprise: `pip install agentic-reliability-enterprise` (requires license)"
)
return recommendations
class Config:
env_file = ".env"
env_file_encoding = "utf-8"
case_sensitive = False
# Global settings instance with installation detection
try:
# First detect installation
installation_info = Settings.detect_installation()
# Create settings with installation info
settings = Settings(
arf_oss_installed=installation_info["oss_installed"],
arf_enterprise_installed=installation_info["enterprise_installed"],
arf_oss_version=installation_info["oss_version"],
arf_enterprise_version=installation_info["enterprise_version"],
)
# Log installation status
status = settings.get_installation_status()
logger.info(f"ARF Installation Status: {status.value}")
if status == InstallationStatus.NOT_INSTALLED:
logger.warning("No ARF packages installed. Demo will use mock mode.")
logger.warning("For real ARF experience, install: pip install agentic-reliability-framework==3.3.7")
except Exception as e:
logger.warning(f"Failed to load settings: {e}, using defaults")
settings = Settings(
arf_mode="demo",
use_true_arf=False,
arf_oss_installed=False,
arf_enterprise_installed=False,
engineer_hourly_rate=150.0,
engineer_annual_cost=125000.0,
default_savings_rate=0.82,
auto_refresh_seconds=30,
max_history_items=100,
default_scenario="Cache Miss Storm",
scenario_config_path="config/scenarios",
default_safety_mode="advisory",
require_approval=True
)
def get_settings() -> Settings:
"""Get settings instance (singleton pattern)"""
return settings
def print_installation_status():
"""Print installation status to console - SAFE VERSION"""
try:
s = get_settings()
print("=" * 70)
print("🚀 ARF Ultimate Investor Demo - Installation Status")
print("=" * 70)
print(f"📦 ARF OSS: {'✅ v' + s.arf_oss_version if s.arf_oss_installed else '⚠️ Not installed'}")
print(f"🏢 Enterprise: {'✅ v' + s.arf_enterprise_version if s.arf_enterprise_installed else '⚠️ Not installed'}")
# Safe string access
print(f"🎯 Mode: {s.arf_mode.upper()}")
print(f"🤖 Using True ARF: {'✅ Yes' if s.use_true_arf else '⚠️ Mock mode'}")
recommendations = s.get_installation_recommendations()
if recommendations:
print("\n💡 Recommendations:")
for rec in recommendations:
print(f" • {rec}")
print("=" * 70)
except Exception as e:
print(f"⚠️ Could not print installation status: {e}")
def get_styles() -> str:
"""Return CSS styles for ARF demo - ADDED THIS FUNCTION"""
return """
/* ARF Demo Styles - Professional Dark Theme */
:root {
--primary: #3b82f6;
--primary-dark: #1d4ed8;
--success: #10b981;
--danger: #ef4444;
--warning: #f59e0b;
--dark-bg: #0f172a;
--dark-card: #1e293b;
--dark-border: #334155;
--dark-text: #f8fafc;
--dark-muted: #94a3b8;
}
/* Modern Glass Effect */
.glass {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
/* Professional Card Styling */
.arf-card {
border: 1px solid var(--dark-border);
border-radius: 14px;
padding: 20px;
background: var(--dark-card);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.arf-card:hover {
transform: translateY(-2px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.4);
}
/* Tab Navigation */
.tab-nav {
background: var(--dark-bg);
border-bottom: 2px solid var(--dark-border);
}
.tab-nav .tab {
padding: 12px 24px;
font-weight: 600;
border-radius: 8px 8px 0 0;
border: 2px solid transparent;
border-bottom: none;
transition: all 0.2s ease;
}
.tab-nav .tab.selected {
background: var(--dark-card);
border-color: var(--dark-border);
color: var(--primary);
}
/* Button Styling */
button {
border-radius: 10px !important;
font-weight: 600 !important;
transition: all 0.2s ease !important;
}
button.primary {
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%) !important;
border: none !important;
color: white !important;
}
button.secondary {
background: var(--dark-card) !important;
border: 2px solid var(--dark-border) !important;
color: var(--dark-text) !important;
}
button:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3) !important;
}
/* Header Gradient */
.header-gradient {
background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 100%);
border-radius: 16px;
box-shadow: 0 8px 32px rgba(59, 130, 246, 0.15);
}
/* Status Indicators */
.status-success {
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
color: white;
padding: 4px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: bold;
display: inline-flex;
align-items: center;
gap: 6px;
}
.status-warning {
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
color: white;
padding: 4px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: bold;
display: inline-flex;
align-items: center;
gap: 6px;
}
.status-danger {
background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
color: white;
padding: 4px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: bold;
display: inline-flex;
align-items: center;
gap: 6px;
}
/* Metric Cards */
.metric-card {
border-left: 4px solid var(--primary);
border-radius: 12px;
padding: 18px;
background: var(--dark-card);
margin: 8px;
text-align: center;
flex: 1;
min-width: 140px;
}
.metric-value {
font-size: 28px;
font-weight: bold;
color: var(--primary);
margin: 8px 0;
}
/* Agent Cards */
.agent-card {
border: 2px solid var(--dark-border);
border-radius: 14px;
padding: 18px;
background: var(--dark-card);
text-align: center;
min-height: 180px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.agent-card.active {
border-color: var(--success);
background: rgba(16, 185, 129, 0.1);
}
/* Responsive Design */
@media (max-width: 768px) {
.arf-card {
padding: 15px;
}
.metric-card {
min-width: 100%;
}
}
/* Custom Scrollbar */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: var(--dark-bg);
}
::-webkit-scrollbar-thumb {
background: var(--dark-border);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--dark-muted);
}
"""