Really-amin commited on
Commit
7afcafb
·
verified ·
1 Parent(s): 0cefe26

Upload 47 files

Browse files
Files changed (3) hide show
  1. api_server_extended.py +16 -0
  2. static/css/main.css +21 -8
  3. static/js/app.js +72 -23
api_server_extended.py CHANGED
@@ -902,14 +902,30 @@ async def get_status():
902
  except Exception:
903
  pass
904
 
 
 
 
 
 
 
 
 
 
 
905
  return {
906
  "status": "ok",
 
907
  "timestamp": datetime.now().isoformat(),
 
908
  "providers": {
909
  "total": len(providers),
910
  "free": free_count,
911
  "paid": paid_count
912
  },
 
 
 
 
913
  "resources": resources_data,
914
  "models": {
915
  "total": model_count
 
902
  except Exception:
903
  pass
904
 
905
+ # Get system health metrics
906
+ online_count = 0
907
+ degraded_count = 0
908
+ offline_count = 0
909
+ response_times = []
910
+
911
+ # Try to get health status from providers if available
912
+ # This is a simplified version - in production you'd check actual provider health
913
+ system_health = "ok" if len(providers) > 0 else "unknown"
914
+
915
  return {
916
  "status": "ok",
917
+ "system_health": system_health,
918
  "timestamp": datetime.now().isoformat(),
919
+ "last_update": datetime.now().isoformat(),
920
  "providers": {
921
  "total": len(providers),
922
  "free": free_count,
923
  "paid": paid_count
924
  },
925
+ "online": online_count,
926
+ "degraded": degraded_count,
927
+ "offline": offline_count,
928
+ "avg_response_time_ms": round(sum(response_times) / len(response_times), 2) if response_times else 0,
929
  "resources": resources_data,
930
  "models": {
931
  "total": model_count
static/css/main.css CHANGED
@@ -470,23 +470,36 @@ body::before {
470
  /* Stats Grid */
471
  .stats-grid {
472
  display: grid;
473
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
474
  gap: 20px;
475
  margin-bottom: 30px;
476
  }
477
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  .stat-card {
479
  background: linear-gradient(135deg, rgba(17, 24, 39, 0.8), rgba(31, 41, 55, 0.6));
480
  border: 1px solid var(--border);
481
  border-radius: 16px;
482
- padding: 25px;
483
  display: flex;
484
  align-items: center;
485
- gap: 20px;
486
  transition: all var(--transition-normal);
487
  backdrop-filter: blur(10px);
488
  position: relative;
489
  overflow: hidden;
 
490
  }
491
 
492
  .stat-card::before {
@@ -527,13 +540,13 @@ body::before {
527
  }
528
 
529
  .stat-icon {
530
- width: 70px;
531
- height: 70px;
532
- border-radius: 16px;
533
  display: flex;
534
  align-items: center;
535
  justify-content: center;
536
- font-size: 32px;
537
  flex-shrink: 0;
538
  }
539
 
@@ -566,7 +579,7 @@ body::before {
566
  }
567
 
568
  .stat-value {
569
- font-size: 36px;
570
  font-weight: 800;
571
  color: var(--primary);
572
  margin-bottom: 5px;
 
470
  /* Stats Grid */
471
  .stats-grid {
472
  display: grid;
473
+ grid-template-columns: repeat(4, 1fr);
474
  gap: 20px;
475
  margin-bottom: 30px;
476
  }
477
 
478
+ @media (max-width: 1400px) {
479
+ .stats-grid {
480
+ grid-template-columns: repeat(2, 1fr);
481
+ }
482
+ }
483
+
484
+ @media (max-width: 768px) {
485
+ .stats-grid {
486
+ grid-template-columns: 1fr;
487
+ }
488
+ }
489
+
490
  .stat-card {
491
  background: linear-gradient(135deg, rgba(17, 24, 39, 0.8), rgba(31, 41, 55, 0.6));
492
  border: 1px solid var(--border);
493
  border-radius: 16px;
494
+ padding: 20px;
495
  display: flex;
496
  align-items: center;
497
+ gap: 15px;
498
  transition: all var(--transition-normal);
499
  backdrop-filter: blur(10px);
500
  position: relative;
501
  overflow: hidden;
502
+ min-height: 120px;
503
  }
504
 
505
  .stat-card::before {
 
540
  }
541
 
542
  .stat-icon {
543
+ width: 60px;
544
+ height: 60px;
545
+ border-radius: 14px;
546
  display: flex;
547
  align-items: center;
548
  justify-content: center;
549
+ font-size: 28px;
550
  flex-shrink: 0;
551
  }
552
 
 
579
  }
580
 
581
  .stat-value {
582
+ font-size: 32px;
583
  font-weight: 800;
584
  color: var(--primary);
585
  margin-bottom: 5px;
static/js/app.js CHANGED
@@ -463,22 +463,51 @@ async function loadDashboard() {
463
  providersEl.textContent = providers;
464
  }
465
 
466
- // Display system status
467
  const systemStatusDiv = document.getElementById('system-status');
468
- const healthStatus = statusData.system_health || 'unknown';
469
- const healthClass = healthStatus === 'healthy' ? 'alert-success' :
470
- healthStatus === 'degraded' ? 'alert-warning' : 'alert-error';
471
-
472
- systemStatusDiv.innerHTML = `
473
- <div class="alert ${healthClass}">
474
- <strong>System Status:</strong> ${healthStatus}<br>
475
- <strong>Online APIs:</strong> ${statusData.online || 0}<br>
476
- <strong>Degraded APIs:</strong> ${statusData.degraded || 0}<br>
477
- <strong>Offline APIs:</strong> ${statusData.offline || 0}<br>
478
- <strong>Avg Response Time:</strong> ${statusData.avg_response_time_ms || 0}ms<br>
479
- <strong>Last Update:</strong> ${new Date(statusData.last_update || Date.now()).toLocaleString('en-US')}
480
- </div>
481
- `;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
482
  } else {
483
  throw new Error('Status endpoint not available');
484
  }
@@ -904,14 +933,16 @@ async function loadModels() {
904
  </div>
905
  `;
906
 
907
- // Update stat-models in dashboard and sidebar
908
  const modelsStatEl = document.getElementById('stat-models');
909
  const sidebarModelsEl = document.getElementById('sidebar-models');
 
 
910
  if (modelsStatEl) {
911
- modelsStatEl.textContent = modelsCount;
912
  }
913
  if (sidebarModelsEl) {
914
- sidebarModelsEl.textContent = modelsCount;
915
  }
916
  } else {
917
  throw new Error('Models status endpoint not available');
@@ -988,6 +1019,11 @@ async function loadModels() {
988
  async function initializeModels() {
989
  ToastManager.info('Initializing models... This may take a moment.');
990
 
 
 
 
 
 
991
  try {
992
  const response = await fetch('/api/models/initialize', { method: 'POST' });
993
  if (!response.ok) {
@@ -996,15 +1032,28 @@ async function initializeModels() {
996
 
997
  const data = await response.json();
998
 
999
- if (data.status === 'ok') {
1000
- ToastManager.success('Models initialized successfully!');
1001
- loadModels(); // Reload models list
 
 
 
 
 
 
1002
  } else {
1003
- ToastManager.warning('Models partially initialized');
1004
  }
 
 
 
1005
  } catch (error) {
1006
  console.error('Error initializing models:', error);
1007
- ToastManager.error('Failed to initialize models');
 
 
 
 
1008
  }
1009
  }
1010
 
 
463
  providersEl.textContent = providers;
464
  }
465
 
466
+ // Display system status - handle different response formats
467
  const systemStatusDiv = document.getElementById('system-status');
468
+ if (systemStatusDiv) {
469
+ // Try to get health status from different possible fields
470
+ const healthStatus = statusData.system_health || statusData.status || 'ok';
471
+ const healthClass = healthStatus === 'healthy' || healthStatus === 'ok' ? 'alert-success' :
472
+ healthStatus === 'degraded' ? 'alert-warning' : 'alert-error';
473
+
474
+ // Get provider counts
475
+ const providers = statusData.providers || {};
476
+ const totalProviders = providers.total || statusData.total_apis || 0;
477
+ const onlineProviders = statusData.online || 0;
478
+ const degradedProviders = statusData.degraded || 0;
479
+ const offlineProviders = statusData.offline || 0;
480
+ const avgResponseTime = statusData.avg_response_time_ms || 0;
481
+ const lastUpdate = statusData.last_update || statusData.timestamp || new Date().toISOString();
482
+
483
+ // Format last update time
484
+ let formattedTime = 'N/A';
485
+ try {
486
+ const updateDate = new Date(lastUpdate);
487
+ formattedTime = updateDate.toLocaleString('en-US', {
488
+ year: 'numeric',
489
+ month: '2-digit',
490
+ day: '2-digit',
491
+ hour: '2-digit',
492
+ minute: '2-digit',
493
+ second: '2-digit'
494
+ });
495
+ } catch (e) {
496
+ formattedTime = lastUpdate;
497
+ }
498
+
499
+ systemStatusDiv.innerHTML = `
500
+ <div class="alert ${healthClass}">
501
+ <strong>System Status:</strong> ${healthStatus === 'ok' ? 'Healthy' : healthStatus}<br>
502
+ <strong>Total Providers:</strong> ${totalProviders}<br>
503
+ <strong>Online APIs:</strong> ${onlineProviders}<br>
504
+ <strong>Degraded APIs:</strong> ${degradedProviders}<br>
505
+ <strong>Offline APIs:</strong> ${offlineProviders}<br>
506
+ <strong>Avg Response Time:</strong> ${avgResponseTime}ms<br>
507
+ <strong>Last Update:</strong> ${formattedTime}
508
+ </div>
509
+ `;
510
+ }
511
  } else {
512
  throw new Error('Status endpoint not available');
513
  }
 
933
  </div>
934
  `;
935
 
936
+ // Update stat-models in dashboard and sidebar with actual loaded count
937
  const modelsStatEl = document.getElementById('stat-models');
938
  const sidebarModelsEl = document.getElementById('sidebar-models');
939
+ // Use pipelines_loaded if available, otherwise use modelsCount
940
+ const displayCount = pipelinesLoaded > 0 ? pipelinesLoaded : modelsCount;
941
  if (modelsStatEl) {
942
+ modelsStatEl.textContent = displayCount;
943
  }
944
  if (sidebarModelsEl) {
945
+ sidebarModelsEl.textContent = displayCount;
946
  }
947
  } else {
948
  throw new Error('Models status endpoint not available');
 
1019
  async function initializeModels() {
1020
  ToastManager.info('Initializing models... This may take a moment.');
1021
 
1022
+ const modelsStatusDiv = document.getElementById('models-status');
1023
+ if (modelsStatusDiv) {
1024
+ modelsStatusDiv.innerHTML = '<div class="loading"><div class="spinner"></div> Initializing models...</div>';
1025
+ }
1026
+
1027
  try {
1028
  const response = await fetch('/api/models/initialize', { method: 'POST' });
1029
  if (!response.ok) {
 
1032
 
1033
  const data = await response.json();
1034
 
1035
+ // Handle different response formats
1036
+ const isOk = data.status === 'ok' || data.ok === true || (data.models_loaded && data.models_loaded > 0);
1037
+ const modelsLoaded = data.models_loaded || data.pipelines_loaded || 0;
1038
+ const modelsFailed = data.models_failed || data.pipelines_failed || 0;
1039
+
1040
+ if (isOk) {
1041
+ ToastManager.success(`Models initialized successfully! ${modelsLoaded} model(s) loaded.`);
1042
+ } else if (modelsLoaded > 0) {
1043
+ ToastManager.warning(`Models partially initialized: ${modelsLoaded} loaded, ${modelsFailed} failed`);
1044
  } else {
1045
+ ToastManager.warning('No models loaded. Using fallback mode.');
1046
  }
1047
+
1048
+ // Reload models list and status
1049
+ await loadModels();
1050
  } catch (error) {
1051
  console.error('Error initializing models:', error);
1052
+ ToastManager.error('Failed to initialize models: ' + error.message);
1053
+
1054
+ if (modelsStatusDiv) {
1055
+ modelsStatusDiv.innerHTML = `<div class="alert alert-error">Error initializing models: ${error.message}</div>`;
1056
+ }
1057
  }
1058
  }
1059