mcli-framework 7.3.1__py3-none-any.whl → 7.5.0__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.

Potentially problematic release.


This version of mcli-framework might be problematic. Click here for more details.

Files changed (96) hide show
  1. mcli/app/commands_cmd.py +741 -0
  2. mcli/lib/auth/aws_manager.py +9 -64
  3. mcli/lib/auth/azure_manager.py +9 -64
  4. mcli/lib/auth/credential_manager.py +70 -1
  5. mcli/lib/auth/gcp_manager.py +11 -64
  6. mcli/ml/dashboard/app.py +6 -39
  7. mcli/ml/dashboard/app_integrated.py +288 -117
  8. mcli/ml/dashboard/app_supabase.py +8 -57
  9. mcli/ml/dashboard/app_training.py +10 -12
  10. mcli/ml/dashboard/common.py +167 -0
  11. mcli/ml/dashboard/overview.py +378 -0
  12. mcli/ml/dashboard/pages/cicd.py +4 -4
  13. mcli/ml/dashboard/pages/debug_dependencies.py +406 -0
  14. mcli/ml/dashboard/pages/gravity_viz.py +783 -0
  15. mcli/ml/dashboard/pages/monte_carlo_predictions.py +555 -0
  16. mcli/ml/dashboard/pages/predictions_enhanced.py +4 -2
  17. mcli/ml/dashboard/pages/scrapers_and_logs.py +25 -9
  18. mcli/ml/dashboard/pages/test_portfolio.py +54 -4
  19. mcli/ml/dashboard/pages/trading.py +80 -26
  20. mcli/ml/dashboard/streamlit_extras_utils.py +297 -0
  21. mcli/ml/dashboard/styles.py +55 -0
  22. mcli/ml/dashboard/utils.py +7 -0
  23. mcli/ml/dashboard/warning_suppression.py +34 -0
  24. mcli/ml/database/session.py +169 -16
  25. mcli/ml/predictions/monte_carlo.py +428 -0
  26. mcli/ml/trading/alpaca_client.py +82 -18
  27. mcli/self/self_cmd.py +182 -737
  28. {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/METADATA +2 -3
  29. {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/RECORD +33 -87
  30. mcli/__init__.py +0 -160
  31. mcli/__main__.py +0 -14
  32. mcli/app/__init__.py +0 -23
  33. mcli/app/model/__init__.py +0 -0
  34. mcli/app/video/__init__.py +0 -5
  35. mcli/chat/__init__.py +0 -34
  36. mcli/lib/__init__.py +0 -0
  37. mcli/lib/api/__init__.py +0 -0
  38. mcli/lib/auth/__init__.py +0 -1
  39. mcli/lib/config/__init__.py +0 -1
  40. mcli/lib/erd/__init__.py +0 -25
  41. mcli/lib/files/__init__.py +0 -0
  42. mcli/lib/fs/__init__.py +0 -1
  43. mcli/lib/logger/__init__.py +0 -3
  44. mcli/lib/performance/__init__.py +0 -17
  45. mcli/lib/pickles/__init__.py +0 -1
  46. mcli/lib/shell/__init__.py +0 -0
  47. mcli/lib/toml/__init__.py +0 -1
  48. mcli/lib/watcher/__init__.py +0 -0
  49. mcli/ml/__init__.py +0 -16
  50. mcli/ml/api/__init__.py +0 -30
  51. mcli/ml/api/routers/__init__.py +0 -27
  52. mcli/ml/auth/__init__.py +0 -45
  53. mcli/ml/backtesting/__init__.py +0 -39
  54. mcli/ml/cli/__init__.py +0 -5
  55. mcli/ml/config/__init__.py +0 -33
  56. mcli/ml/configs/__init__.py +0 -16
  57. mcli/ml/dashboard/__init__.py +0 -12
  58. mcli/ml/dashboard/components/__init__.py +0 -7
  59. mcli/ml/dashboard/pages/__init__.py +0 -6
  60. mcli/ml/data_ingestion/__init__.py +0 -39
  61. mcli/ml/database/__init__.py +0 -47
  62. mcli/ml/experimentation/__init__.py +0 -29
  63. mcli/ml/features/__init__.py +0 -39
  64. mcli/ml/mlops/__init__.py +0 -33
  65. mcli/ml/models/__init__.py +0 -94
  66. mcli/ml/monitoring/__init__.py +0 -25
  67. mcli/ml/optimization/__init__.py +0 -27
  68. mcli/ml/predictions/__init__.py +0 -5
  69. mcli/ml/preprocessing/__init__.py +0 -28
  70. mcli/ml/scripts/__init__.py +0 -1
  71. mcli/ml/trading/__init__.py +0 -60
  72. mcli/ml/training/__init__.py +0 -10
  73. mcli/mygroup/__init__.py +0 -3
  74. mcli/public/__init__.py +0 -1
  75. mcli/public/commands/__init__.py +0 -2
  76. mcli/self/__init__.py +0 -3
  77. mcli/workflow/__init__.py +0 -0
  78. mcli/workflow/daemon/__init__.py +0 -15
  79. mcli/workflow/dashboard/__init__.py +0 -5
  80. mcli/workflow/docker/__init__.py +0 -0
  81. mcli/workflow/file/__init__.py +0 -0
  82. mcli/workflow/gcloud/__init__.py +0 -1
  83. mcli/workflow/git_commit/__init__.py +0 -0
  84. mcli/workflow/interview/__init__.py +0 -0
  85. mcli/workflow/politician_trading/__init__.py +0 -4
  86. mcli/workflow/registry/__init__.py +0 -0
  87. mcli/workflow/repo/__init__.py +0 -0
  88. mcli/workflow/scheduler/__init__.py +0 -25
  89. mcli/workflow/search/__init__.py +0 -0
  90. mcli/workflow/sync/__init__.py +0 -5
  91. mcli/workflow/videos/__init__.py +0 -1
  92. mcli/workflow/wakatime/__init__.py +0 -80
  93. {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/WHEEL +0 -0
  94. {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/entry_points.txt +0 -0
  95. {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/licenses/LICENSE +0 -0
  96. {mcli_framework-7.3.1.dist-info → mcli_framework-7.5.0.dist-info}/top_level.txt +0 -0
@@ -12,18 +12,51 @@ from typing import List
12
12
 
13
13
  import numpy as np
14
14
 
15
+ # Suppress warnings before other imports
16
+ from mcli.ml.dashboard.common import suppress_streamlit_warnings
17
+
18
+ suppress_streamlit_warnings()
19
+
15
20
  logger = logging.getLogger(__name__)
21
+
16
22
  import pandas as pd
17
23
  import plotly.express as px
18
24
  import plotly.graph_objects as go
19
25
  import requests
20
26
  import streamlit as st
21
- from dotenv import load_dotenv
22
27
  from plotly.subplots import make_subplots
23
- from supabase import Client, create_client
28
+ from supabase import Client
29
+
30
+ # Import common dashboard utilities
31
+ from mcli.ml.dashboard.common import (
32
+ get_supabase_client,
33
+ load_environment_variables,
34
+ setup_page_config,
35
+ )
36
+ from mcli.ml.dashboard.styles import apply_dashboard_styles
24
37
 
25
- # Load environment variables from .env file
26
- load_dotenv()
38
+ # Load environment variables
39
+ load_environment_variables()
40
+
41
+ # Import streamlit-extras utilities
42
+ try:
43
+ from mcli.ml.dashboard.streamlit_extras_utils import (
44
+ enhanced_metrics,
45
+ section_header,
46
+ vertical_space,
47
+ data_quality_indicators,
48
+ trading_status_card,
49
+ )
50
+ HAS_STREAMLIT_EXTRAS = True
51
+ except (ImportError, KeyError, ModuleNotFoundError) as e:
52
+ HAS_STREAMLIT_EXTRAS = False
53
+ enhanced_metrics = None
54
+ section_header = None
55
+ vertical_space = None
56
+ data_quality_indicators = None
57
+ trading_status_card = None
58
+ # Suppress warning for now - this is handled gracefully
59
+ # st.warning(f"Streamlit-extras utilities not available: {e}")
27
60
 
28
61
  # Add ML pipeline imports
29
62
  try:
@@ -46,45 +79,146 @@ except ImportError:
46
79
  PoliticianTradingPredictor = None
47
80
 
48
81
  # Add new dashboard pages
82
+ HAS_OVERVIEW_PAGE = False
83
+ HAS_PREDICTIONS_ENHANCED = False
84
+ HAS_SCRAPERS_PAGE = False
85
+ HAS_TRADING_PAGES = False
86
+ HAS_MONTE_CARLO_PAGE = False
87
+ HAS_CICD_PAGE = False
88
+ HAS_WORKFLOWS_PAGE = False
89
+ HAS_DEBUG_PAGE = False
90
+
91
+ show_overview = None
92
+ show_cicd_dashboard = None
93
+ show_workflows_dashboard = None
94
+ show_predictions_enhanced = None
95
+ show_scrapers_and_logs = None
96
+ show_trading_dashboard = None
97
+ show_test_portfolio = None
98
+ show_monte_carlo_predictions = None
99
+ show_debug_dependencies = None
100
+
101
+ # Import Overview page
102
+ try:
103
+ from mcli.ml.dashboard.overview import show_overview
104
+ HAS_OVERVIEW_PAGE = True
105
+ except (ImportError, KeyError, ModuleNotFoundError) as e:
106
+ st.warning(f"Overview page not available: {e}")
107
+
49
108
  try:
50
- from mcli.ml.dashboard.pages.cicd import show_cicd_dashboard
51
- from mcli.ml.dashboard.pages.workflows import show_workflows_dashboard
52
109
  from mcli.ml.dashboard.pages.predictions_enhanced import show_predictions_enhanced
110
+ HAS_PREDICTIONS_ENHANCED = True
111
+ except (ImportError, KeyError, ModuleNotFoundError) as e:
112
+ st.warning(f"Predictions Enhanced page not available: {e}")
113
+
114
+ try:
53
115
  from mcli.ml.dashboard.pages.scrapers_and_logs import show_scrapers_and_logs
116
+ HAS_SCRAPERS_PAGE = True
117
+ except (ImportError, KeyError, ModuleNotFoundError) as e:
118
+ st.warning(f"Scrapers & Logs page not available: {e}")
119
+
120
+ try:
121
+ import sys
122
+ import traceback
123
+
124
+ # Verbose logging for alpaca-py debugging
125
+ st.info("🔍 Attempting to import trading pages (alpaca-py dependent)...")
126
+
127
+ # First, try importing alpaca directly to see the specific error
128
+ try:
129
+ import alpaca
130
+ st.success(f"✅ alpaca module imported successfully")
131
+ if hasattr(alpaca, "__version__"):
132
+ st.info(f"Alpaca version: {alpaca.__version__}")
133
+ if hasattr(alpaca, "__file__"):
134
+ st.caption(f"Alpaca location: {alpaca.__file__}")
135
+ except ImportError as alpaca_error:
136
+ st.error(f"❌ Failed to import alpaca module: {alpaca_error}")
137
+ with st.expander("🔬 Detailed alpaca import error"):
138
+ st.code(traceback.format_exc())
139
+
140
+ # Try to provide diagnostic info
141
+ st.warning("💡 Troubleshooting tips:")
142
+ st.markdown("""
143
+ - Check that `alpaca-py>=0.20.0` is in requirements.txt
144
+ - Verify Python version is 3.8+ (current: {}.{})
145
+ - Check Streamlit Cloud deployment logs for installation errors
146
+ - Visit the **Debug Dependencies** page for detailed diagnostics
147
+ """.format(sys.version_info.major, sys.version_info.minor))
148
+
149
+ # Now try importing the trading pages
54
150
  from mcli.ml.dashboard.pages.trading import show_trading_dashboard
55
151
  from mcli.ml.dashboard.pages.test_portfolio import show_test_portfolio
152
+ HAS_TRADING_PAGES = True
153
+ st.success("✅ Trading pages imported successfully!")
56
154
 
57
- HAS_EXTENDED_PAGES = True
58
- HAS_SCRAPERS_PAGE = True
59
- except ImportError as e:
60
- print(f"Import error: {e}") # Debug print
61
- HAS_EXTENDED_PAGES = False
62
- HAS_SCRAPERS_PAGE = False
63
- show_cicd_dashboard = None
64
- show_workflows_dashboard = None
65
- show_predictions_enhanced = None
66
- show_scrapers_and_logs = None
67
- show_trading_dashboard = None
68
- show_test_portfolio = None
69
-
70
- # Page config
71
- st.set_page_config(
72
- page_title="MCLI ML Dashboard - Integrated",
73
- page_icon="📊",
74
- layout="wide",
75
- initial_sidebar_state="expanded",
155
+ except (ImportError, KeyError, ModuleNotFoundError) as e:
156
+ st.error(f"❌ Trading pages not available: {e}")
157
+ with st.expander("📋 Full error traceback"):
158
+ st.code(traceback.format_exc())
159
+
160
+ # Show installed packages related to alpaca
161
+ try:
162
+ import subprocess
163
+ result = subprocess.run(
164
+ ["pip", "list"],
165
+ capture_output=True,
166
+ text=True,
167
+ timeout=5
168
+ )
169
+ alpaca_packages = [line for line in result.stdout.split("\n") if "alpaca" in line.lower()]
170
+ if alpaca_packages:
171
+ st.info("📦 Found alpaca-related packages:")
172
+ for pkg in alpaca_packages:
173
+ st.code(pkg)
174
+ else:
175
+ st.warning("⚠️ No alpaca-related packages found in pip list")
176
+
177
+ # Show full pip list for debugging
178
+ with st.expander("🔍 Full pip list (for debugging)"):
179
+ st.code(result.stdout, language="text")
180
+ except Exception as pip_error:
181
+ st.caption(f"Could not check installed packages: {pip_error}")
182
+
183
+ try:
184
+ from mcli.ml.dashboard.pages.monte_carlo_predictions import show_monte_carlo_predictions
185
+ HAS_MONTE_CARLO_PAGE = True
186
+ except (ImportError, KeyError, ModuleNotFoundError) as e:
187
+ HAS_MONTE_CARLO_PAGE = False
188
+
189
+ # Import CI/CD and Workflows pages
190
+ try:
191
+ from mcli.ml.dashboard.pages.cicd import show_cicd_dashboard
192
+ HAS_CICD_PAGE = True
193
+ except (ImportError, KeyError, ModuleNotFoundError) as e:
194
+ st.warning(f"CI/CD page not available: {e}")
195
+
196
+ try:
197
+ from mcli.ml.dashboard.pages.workflows import show_workflows_dashboard
198
+ HAS_WORKFLOWS_PAGE = True
199
+ except (ImportError, KeyError, ModuleNotFoundError) as e:
200
+ st.warning(f"Workflows page not available: {e}")
201
+
202
+ # Import Debug Dependencies page (always available for troubleshooting)
203
+ try:
204
+ from mcli.ml.dashboard.pages.debug_dependencies import show_debug_dependencies
205
+ HAS_DEBUG_PAGE = True
206
+ except (ImportError, KeyError, ModuleNotFoundError) as e:
207
+ st.warning(f"Debug Dependencies page not available: {e}")
208
+
209
+ # Page config - must be before other st commands
210
+ setup_page_config(
211
+ page_title="Politician Trading Tracker - MCLI",
212
+ page_icon="📊"
76
213
  )
77
214
 
78
- # Custom CSS
215
+ # Apply standard dashboard styles (includes metric-card, alert boxes)
216
+ apply_dashboard_styles()
217
+
218
+ # Add integrated dashboard-specific CSS
79
219
  st.markdown(
80
220
  """
81
221
  <style>
82
- .metric-card {
83
- background-color: #f0f2f6;
84
- padding: 1rem;
85
- border-radius: 0.5rem;
86
- border-left: 4px solid #1f77b4;
87
- }
88
222
  .success-box {
89
223
  background-color: #d4edda;
90
224
  border: 1px solid #c3e6cb;
@@ -104,69 +238,7 @@ st.markdown(
104
238
  unsafe_allow_html=True,
105
239
  )
106
240
 
107
-
108
- @st.cache_resource
109
- def get_supabase_client() -> Client:
110
- """Get Supabase client with Streamlit Cloud secrets support"""
111
- # Try Streamlit secrets first (for Streamlit Cloud), then fall back to environment variables (for local dev)
112
- try:
113
- url = st.secrets.get("SUPABASE_URL", "")
114
- key = st.secrets.get("SUPABASE_KEY", "") or st.secrets.get("SUPABASE_SERVICE_ROLE_KEY", "")
115
- except (AttributeError, FileNotFoundError):
116
- # Secrets not available, try environment variables
117
- url = os.getenv("SUPABASE_URL", "")
118
- key = os.getenv("SUPABASE_KEY", "") or os.getenv("SUPABASE_SERVICE_ROLE_KEY", "")
119
-
120
- if not url or not key:
121
- st.error(
122
- "❌ Supabase credentials not configured"
123
- )
124
- with st.expander("🔧 Configuration Required"):
125
- st.markdown("""
126
- **Missing Supabase credentials:**
127
- - `SUPABASE_URL`: {}
128
- - `SUPABASE_KEY`: {}
129
-
130
- **For Streamlit Cloud:**
131
- 1. Go to https://share.streamlit.io
132
- 2. Select your app → Settings → Secrets
133
- 3. Add:
134
- ```toml
135
- SUPABASE_URL = "https://your-project.supabase.co"
136
- SUPABASE_KEY = "your-anon-key"
137
- ```
138
-
139
- **For local development:**
140
- 1. Create `.streamlit/secrets.toml` file
141
- 2. Add the same credentials as above
142
- 3. Restart the dashboard
143
-
144
- **Using demo data** until configured.
145
- """.format(
146
- "✅ Set" if url else "❌ Missing",
147
- "✅ Set" if key else "❌ Missing"
148
- ))
149
- return None
150
-
151
- try:
152
- client = create_client(url, key)
153
- # Test connection with a simple query
154
- try:
155
- test_result = client.table("politicians").select("id").limit(1).execute()
156
- logger.info(f"✅ Supabase connection successful (URL: {url[:30]}...)")
157
- return client
158
- except Exception as conn_error:
159
- st.error(f"❌ Supabase connection failed: {conn_error}")
160
- with st.expander("🔍 Connection Details"):
161
- st.write(f"**URL:** {url[:30]}...")
162
- st.write(f"**Error:** {str(conn_error)}")
163
- st.write("**Using demo data** until connection is restored.")
164
- logger.error(f"Supabase connection test failed: {conn_error}")
165
- return None
166
- except Exception as e:
167
- st.error(f"❌ Failed to create Supabase client: {e}")
168
- logger.error(f"Failed to create Supabase client: {e}")
169
- return None
241
+ # Note: get_supabase_client is now imported from common.py
170
242
 
171
243
 
172
244
  @st.cache_data(ttl=300) # Cache for 5 minutes
@@ -811,15 +883,37 @@ def get_model_metrics():
811
883
 
812
884
  def main():
813
885
  """Main dashboard function"""
886
+
887
+ # Clear any problematic session state that might cause media file errors
888
+ try:
889
+ # Remove any file-related session state that might be causing issues
890
+ keys_to_remove = []
891
+ for key in st.session_state.keys():
892
+ if 'file' in key.lower() or 'download' in key.lower() or 'media' in key.lower():
893
+ keys_to_remove.append(key)
894
+
895
+ for key in keys_to_remove:
896
+ if key in st.session_state:
897
+ del st.session_state[key]
898
+ except Exception:
899
+ # Ignore errors when clearing session state
900
+ pass
814
901
 
815
902
  # Title and header
816
- st.title("🤖 MCLI ML System Dashboard - Integrated")
817
- st.markdown("Real-time ML pipeline monitoring with LSH daemon integration")
903
+ st.title("📊 Politician Trading Tracker")
904
+ st.markdown("Track, Analyze & Replicate Congressional Trading Patterns")
818
905
 
819
906
  # Sidebar
820
907
  st.sidebar.title("Navigation")
821
908
  # Build page list
822
- pages = [
909
+ pages = []
910
+
911
+ # Add Overview as first page if available
912
+ if HAS_OVERVIEW_PAGE:
913
+ pages.append("Overview")
914
+
915
+ # Add other pages
916
+ pages.extend([
823
917
  "Pipeline Overview",
824
918
  "ML Processing",
825
919
  "Model Performance",
@@ -829,24 +923,37 @@ def main():
829
923
  "Test Portfolio",
830
924
  "LSH Jobs",
831
925
  "System Health",
832
- ]
926
+ ])
833
927
 
834
928
  # Add scrapers and logs page
835
929
  if HAS_SCRAPERS_PAGE:
836
930
  pages.append("Scrapers & Logs")
837
931
 
838
- # Add extended pages if available
839
- if HAS_EXTENDED_PAGES:
840
- pages.extend(["CI/CD Pipelines", "Workflows"])
841
-
932
+ # Add Monte Carlo predictions page
933
+ if HAS_MONTE_CARLO_PAGE:
934
+ pages.append("Monte Carlo Predictions")
935
+
936
+ # Add CI/CD page if available
937
+ if HAS_CICD_PAGE:
938
+ pages.append("CI/CD Pipelines")
939
+
940
+ # Add Workflows page if available
941
+ if HAS_WORKFLOWS_PAGE:
942
+ pages.append("Workflows")
943
+
944
+ # Add Debug Dependencies page (always useful for troubleshooting)
945
+ if HAS_DEBUG_PAGE:
946
+ pages.append("Debug Dependencies")
947
+
842
948
  page = st.sidebar.selectbox(
843
949
  "Choose a page",
844
950
  pages,
845
951
  index=0, # Default to Pipeline Overview
952
+ key="main_page_selector"
846
953
  )
847
954
 
848
955
  # Auto-refresh toggle (default off to prevent blocking)
849
- auto_refresh = st.sidebar.checkbox("Auto-refresh (30s)", value=False)
956
+ auto_refresh = st.sidebar.checkbox("Auto-refresh (30s)", value=True)
850
957
  if auto_refresh:
851
958
  try:
852
959
  from streamlit_autorefresh import st_autorefresh
@@ -873,7 +980,12 @@ def main():
873
980
 
874
981
  # Main content with error handling
875
982
  try:
876
- if page == "Pipeline Overview":
983
+ if page == "Overview":
984
+ if HAS_OVERVIEW_PAGE and show_overview:
985
+ show_overview()
986
+ else:
987
+ st.error("Overview page not available")
988
+ elif page == "Pipeline Overview":
877
989
  show_pipeline_overview()
878
990
  elif page == "ML Processing":
879
991
  show_ml_processing()
@@ -883,30 +995,82 @@ def main():
883
995
  show_model_training_evaluation()
884
996
  elif page == "Predictions":
885
997
  # Use enhanced predictions page if available, otherwise fallback
886
- if HAS_EXTENDED_PAGES and show_predictions_enhanced:
998
+ if HAS_PREDICTIONS_ENHANCED and show_predictions_enhanced:
887
999
  show_predictions_enhanced()
888
1000
  else:
889
1001
  show_predictions()
890
1002
  elif page == "Trading Dashboard":
891
- if HAS_EXTENDED_PAGES and show_trading_dashboard:
892
- show_trading_dashboard()
1003
+ if HAS_TRADING_PAGES and show_trading_dashboard:
1004
+ try:
1005
+ show_trading_dashboard()
1006
+ except Exception as e:
1007
+ st.error(f"❌ Error in Trading Dashboard page: {e}")
1008
+ import traceback
1009
+ st.code(traceback.format_exc())
893
1010
  else:
894
1011
  st.warning("Trading dashboard not available")
895
1012
  elif page == "Test Portfolio":
896
- if HAS_EXTENDED_PAGES and show_test_portfolio:
897
- show_test_portfolio()
1013
+ if HAS_TRADING_PAGES and show_test_portfolio:
1014
+ try:
1015
+ show_test_portfolio()
1016
+ except Exception as e:
1017
+ st.error(f"❌ Error in Test Portfolio page: {e}")
1018
+ import traceback
1019
+ st.code(traceback.format_exc())
898
1020
  else:
899
1021
  st.warning("Test portfolio not available")
1022
+ elif page == "Monte Carlo Predictions":
1023
+ if HAS_MONTE_CARLO_PAGE and show_monte_carlo_predictions:
1024
+ try:
1025
+ show_monte_carlo_predictions()
1026
+ except Exception as e:
1027
+ st.error(f"❌ Error in Monte Carlo Predictions page: {e}")
1028
+ import traceback
1029
+ st.code(traceback.format_exc())
1030
+ else:
1031
+ st.warning("Monte Carlo predictions not available")
900
1032
  elif page == "LSH Jobs":
901
1033
  show_lsh_jobs()
902
1034
  elif page == "System Health":
903
1035
  show_system_health()
904
1036
  elif page == "Scrapers & Logs" and HAS_SCRAPERS_PAGE:
905
- show_scrapers_and_logs()
906
- elif page == "CI/CD Pipelines" and HAS_EXTENDED_PAGES:
907
- show_cicd_dashboard()
908
- elif page == "Workflows" and HAS_EXTENDED_PAGES:
909
- show_workflows_dashboard()
1037
+ try:
1038
+ show_scrapers_and_logs()
1039
+ except Exception as e:
1040
+ st.error(f"❌ Error in Scrapers & Logs page: {e}")
1041
+ import traceback
1042
+ st.code(traceback.format_exc())
1043
+ elif page == "CI/CD Pipelines":
1044
+ if show_cicd_dashboard is not None:
1045
+ try:
1046
+ show_cicd_dashboard()
1047
+ except Exception as e:
1048
+ st.error(f"❌ Error in CI/CD Pipelines page: {e}")
1049
+ import traceback
1050
+ st.code(traceback.format_exc())
1051
+ else:
1052
+ st.warning("CI/CD Pipelines page is not available. This page requires additional dependencies.")
1053
+ elif page == "Workflows":
1054
+ if show_workflows_dashboard is not None:
1055
+ try:
1056
+ show_workflows_dashboard()
1057
+ except Exception as e:
1058
+ st.error(f"❌ Error in Workflows page: {e}")
1059
+ import traceback
1060
+ st.code(traceback.format_exc())
1061
+ else:
1062
+ st.warning("Workflows page is not available. This page requires additional dependencies.")
1063
+
1064
+ elif page == "Debug Dependencies":
1065
+ if show_debug_dependencies is not None:
1066
+ try:
1067
+ show_debug_dependencies()
1068
+ except Exception as e:
1069
+ st.error(f"❌ Error in Debug Dependencies page: {e}")
1070
+ import traceback
1071
+ st.code(traceback.format_exc())
1072
+ else:
1073
+ st.warning("Debug Dependencies page is not available.")
910
1074
  except Exception as e:
911
1075
  st.error(f"❌ Error loading page '{page}': {e}")
912
1076
  import traceback
@@ -2804,5 +2968,12 @@ def show_system_health():
2804
2968
  st.plotly_chart(fig, width="stretch", config={"responsive": True})
2805
2969
 
2806
2970
 
2807
- # Run the main dashboard function
2808
- main()
2971
+ # Run the main dashboard function with error handling
2972
+ try:
2973
+ main()
2974
+ except Exception as e:
2975
+ st.error(f"❌ Dashboard error: {e}")
2976
+ st.info("🔄 Please refresh the page to try again")
2977
+ import traceback
2978
+ with st.expander("Error details"):
2979
+ st.code(traceback.format_exc())
@@ -1,75 +1,26 @@
1
1
  """Streamlit dashboard for ML system monitoring - Supabase version"""
2
2
 
3
3
  import asyncio
4
- import os
5
4
  from datetime import datetime, timedelta
6
- from pathlib import Path
7
5
 
8
6
  import numpy as np
9
7
  import pandas as pd
10
8
  import plotly.express as px
11
9
  import plotly.graph_objects as go
12
10
  import streamlit as st
13
- from dotenv import load_dotenv
14
11
  from plotly.subplots import make_subplots
15
- from supabase import Client, create_client
12
+
13
+ from mcli.ml.dashboard.common import get_supabase_client, load_environment_variables, setup_page_config
14
+ from mcli.ml.dashboard.styles import apply_dashboard_styles
16
15
 
17
16
  # Page config must come first
18
- st.set_page_config(
19
- page_title="MCLI ML Dashboard", page_icon="📊", layout="wide", initial_sidebar_state="expanded"
20
- )
21
-
22
- # Load environment variables from supabase/.env.local
23
- env_path = Path(__file__).parent.parent.parent.parent.parent / "supabase" / ".env.local"
24
- if env_path.exists():
25
- load_dotenv(env_path)
26
-
27
- # Custom CSS
28
- st.markdown(
29
- """
30
- <style>
31
- .metric-card {
32
- background-color: #f0f2f6;
33
- padding: 1rem;
34
- border-radius: 0.5rem;
35
- border-left: 4px solid #1f77b4;
36
- }
37
- </style>
38
- """,
39
- unsafe_allow_html=True,
40
- )
17
+ setup_page_config(page_title="MCLI ML Dashboard")
41
18
 
19
+ # Load environment variables
20
+ load_environment_variables()
42
21
 
43
- @st.cache_resource
44
- def get_supabase_client() -> Client:
45
- """Get Supabase client with Streamlit Cloud secrets support"""
46
- # Try Streamlit secrets first (for Streamlit Cloud), then fall back to environment variables (for local dev)
47
- try:
48
- url = st.secrets.get("SUPABASE_URL", "")
49
- key = st.secrets.get("SUPABASE_KEY", "") or st.secrets.get("SUPABASE_SERVICE_ROLE_KEY", "")
50
- except (AttributeError, FileNotFoundError):
51
- # Secrets not available, try environment variables
52
- url = os.getenv("SUPABASE_URL", "")
53
- key = os.getenv("SUPABASE_KEY", "") or os.getenv("SUPABASE_SERVICE_ROLE_KEY", "")
54
-
55
- if not url or not key:
56
- st.warning(
57
- "⚠️ Supabase credentials not found. Configure SUPABASE_URL and SUPABASE_KEY in Streamlit Cloud secrets or environment variables."
58
- )
59
- return None
60
-
61
- try:
62
- client = create_client(url, key)
63
- # Test connection
64
- try:
65
- client.table("politicians").select("id").limit(1).execute()
66
- return client
67
- except Exception as e:
68
- st.error(f"❌ Supabase connection test failed: {e}")
69
- return None
70
- except Exception as e:
71
- st.error(f"❌ Failed to create Supabase client: {e}")
72
- return None
22
+ # Apply standard dashboard styles
23
+ apply_dashboard_styles()
73
24
 
74
25
 
75
26
  @st.cache_data(ttl=30)
@@ -12,24 +12,22 @@ from scipy import stats
12
12
 
13
13
  from mcli.ml.database.models import Experiment, Model, ModelStatus
14
14
  from mcli.ml.database.session import SessionLocal
15
+ from mcli.ml.dashboard.common import setup_page_config
16
+ from mcli.ml.dashboard.styles import apply_dashboard_styles
15
17
 
16
- st.set_page_config(
18
+ # Page config - must be first
19
+ setup_page_config(
17
20
  page_title="MCLI Training Dashboard",
18
- page_icon="🔬",
19
- layout="wide",
20
- initial_sidebar_state="expanded",
21
+ page_icon="🔬"
21
22
  )
22
23
 
23
- # Custom CSS
24
+ # Apply standard dashboard styles (includes metric-card)
25
+ apply_dashboard_styles()
26
+
27
+ # Add training-specific CSS
24
28
  st.markdown(
25
29
  """
26
30
  <style>
27
- .metric-card {
28
- background-color: #f0f2f6;
29
- padding: 1rem;
30
- border-radius: 0.5rem;
31
- border-left: 4px solid #1f77b4;
32
- }
33
31
  .model-card {
34
32
  background-color: #ffffff;
35
33
  padding: 1.5rem;
@@ -594,7 +592,7 @@ def main():
594
592
  )
595
593
 
596
594
  # Auto-refresh toggle
597
- auto_refresh = st.sidebar.checkbox("Auto-refresh (60s)", value=False)
595
+ auto_refresh = st.sidebar.checkbox("Auto-refresh (60s)", value=True)
598
596
  if auto_refresh:
599
597
  import time
600
598