Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <meta http-equiv="refresh" content="10"> | |
| <title>Claude Code Proxy - Admin Dashboard</title> | |
| <style> | |
| * { box-sizing: border-box; } | |
| body { | |
| background-color: #0d1117; | |
| color: #c9d1d9; | |
| font-family: 'SF Mono', 'Cascadia Code', 'Fira Code', monospace; | |
| font-size: 13px; | |
| line-height: 1.5; | |
| margin: 0; | |
| padding: 20px; | |
| } | |
| .container { max-width: 1200px; margin: 0 auto; } | |
| .header { | |
| color: #58a6ff; | |
| font-size: 18px; | |
| font-weight: bold; | |
| margin-bottom: 20px; | |
| } | |
| .summary { | |
| background: #161b22; | |
| border: 1px solid #30363d; | |
| border-radius: 6px; | |
| padding: 12px 16px; | |
| margin-bottom: 20px; | |
| font-size: 14px; | |
| } | |
| .summary-line { | |
| color: #8b949e; | |
| } | |
| .summary-line span { | |
| color: #58a6ff; | |
| font-weight: bold; | |
| } | |
| .section { | |
| background: #161b22; | |
| border: 1px solid #30363d; | |
| border-radius: 6px; | |
| padding: 12px 16px; | |
| margin-bottom: 20px; | |
| } | |
| .section-title { | |
| color: #58a6ff; | |
| font-weight: bold; | |
| margin-bottom: 12px; | |
| font-size: 14px; | |
| } | |
| .divider { | |
| color: #30363d; | |
| margin: 8px 0; | |
| } | |
| table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| } | |
| th { | |
| text-align: left; | |
| color: #8b949e; | |
| font-weight: normal; | |
| padding: 6px 8px; | |
| border-bottom: 1px solid #30363d; | |
| font-size: 12px; | |
| } | |
| td { | |
| padding: 6px 8px; | |
| border-bottom: 1px solid #21262d; | |
| } | |
| tr:last-child td { | |
| border-bottom: none; | |
| } | |
| .session-id { | |
| color: #f0883e; | |
| font-family: monospace; | |
| } | |
| .provider-badge { | |
| display: inline-block; | |
| background: #1f6feb; | |
| color: #ffffff; | |
| padding: 2px 6px; | |
| border-radius: 3px; | |
| font-size: 11px; | |
| margin-right: 4px; | |
| } | |
| .status-healthy { | |
| color: #3fb950; | |
| } | |
| .status-limited { | |
| color: #f85149; | |
| } | |
| .status-active { | |
| color: #3fb950; | |
| } | |
| .status-idle { | |
| color: #8b949e; | |
| } | |
| .empty { | |
| color: #8b949e; | |
| font-style: italic; | |
| } | |
| .footer { | |
| color: #8b949e; | |
| font-size: 11px; | |
| text-align: center; | |
| margin-top: 20px; | |
| } | |
| .footer a { | |
| color: #58a6ff; | |
| text-decoration: none; | |
| } | |
| .footer a:hover { | |
| text-decoration: underline; | |
| } | |
| .number { | |
| color: #79c0ff; | |
| font-weight: bold; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="header">Claude Code Proxy - Admin Dashboard</div> | |
| <div class="summary"> | |
| <div class="summary-line"> | |
| Active Sessions: <span>{{ summary.active_sessions }}</span> | | |
| Total Requests: <span>{{ summary.total_requests }}</span> | | |
| Providers: <span>{{ summary.providers }}</span> | |
| </div> | |
| </div> | |
| <div class="section"> | |
| <div class="section-title">Sessions</div> | |
| {% if sessions %} | |
| <div class="divider">βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ</div> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Session ID</th> | |
| <th>Requests</th> | |
| <th>Providers</th> | |
| <th>Last Active</th> | |
| <th>Req/Min</th> | |
| <th>Status</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {% for session in sessions %} | |
| <tr> | |
| <td class="session-id">{{ session.session_id[:12] }}...</td> | |
| <td class="number">{{ session.total_requests }}</td> | |
| <td> | |
| {% for provider in session.providers %} | |
| <span class="provider-badge">{{ provider }}</span> | |
| {% endfor %} | |
| </td> | |
| <td>{{ session.last_activity_display }}</td> | |
| <td class="number">{{ session.requests_per_minute }}</td> | |
| <td class="{{ session.status_class }}">{{ session.status }}</td> | |
| </tr> | |
| {% endfor %} | |
| </tbody> | |
| </table> | |
| {% else %} | |
| <p class="empty">No active sessions</p> | |
| {% endif %} | |
| </div> | |
| <div class="section"> | |
| <div class="section-title">Provider Load</div> | |
| {% if providers %} | |
| <div class="divider">βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ</div> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Provider</th> | |
| <th>Active</th> | |
| <th>Sessions</th> | |
| <th>Req/Min</th> | |
| <th>Status</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {% for provider in providers %} | |
| <tr> | |
| <td class="session-id">{{ provider.provider_id }}</td> | |
| <td class="number">{{ provider.active_requests }}</td> | |
| <td class="number">{{ provider.sessions_count }}</td> | |
| <td class="number">{{ provider.requests_per_minute }}</td> | |
| <td> | |
| {% if provider.is_healthy %} | |
| <span class="status-healthy">✓ {{ provider.status }}</span> | |
| {% else %} | |
| <span class="status-limited">⚠ {{ provider.status }}</span> | |
| {% endif %} | |
| </td> | |
| </tr> | |
| {% endfor %} | |
| </tbody> | |
| </table> | |
| {% else %} | |
| <p class="empty">No provider data</p> | |
| {% endif %} | |
| </div> | |
| <div class="footer"> | |
| Auto-refreshes every 10 seconds • <a href="/api/admin/sessions">JSON API</a> | |
| </div> | |
| </div> | |
| </body> | |
| </html> |