chore: rebrand project to GopherGate
Updated all naming from LLM Proxy to GopherGate. Implemented new CSS-based branding and updated Go module/binary naming.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# LLM Proxy Gateway Configuration Example
|
||||
# GopherGate Configuration Example
|
||||
# Copy this file to .env and fill in your values
|
||||
|
||||
# ==============================================================================
|
||||
|
||||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -46,4 +46,4 @@ jobs:
|
||||
go-version: '1.22'
|
||||
cache: true
|
||||
- name: Build
|
||||
run: go build -v -o llm-proxy ./cmd/llm-proxy
|
||||
run: go build -v -o gophergate ./cmd/gophergate
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Backend Architecture (Go)
|
||||
|
||||
The LLM Proxy backend is implemented in Go, focusing on high performance, clear concurrency patterns, and maintainability.
|
||||
The GopherGate backend is implemented in Go, focusing on high performance, clear concurrency patterns, and maintainability.
|
||||
|
||||
## Core Technologies
|
||||
|
||||
@@ -15,7 +15,7 @@ The LLM Proxy backend is implemented in Go, focusing on high performance, clear
|
||||
|
||||
```text
|
||||
├── cmd/
|
||||
│ └── llm-proxy/ # Entry point (main.go)
|
||||
│ └── gophergate/ # Entry point (main.go)
|
||||
├── internal/
|
||||
│ ├── config/ # Configuration loading and validation
|
||||
│ ├── db/ # Database schema, migrations, and models
|
||||
|
||||
@@ -11,7 +11,7 @@ RUN go mod download
|
||||
COPY . .
|
||||
|
||||
# Build the application
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -o llm-proxy ./cmd/llm-proxy
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -o gophergate ./cmd/gophergate
|
||||
|
||||
# Final stage
|
||||
FROM alpine:latest
|
||||
@@ -21,7 +21,7 @@ RUN apk --no-cache add ca-certificates tzdata
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the binary from the builder stage
|
||||
COPY --from=builder /app/llm-proxy .
|
||||
COPY --from=builder /app/gophergate .
|
||||
COPY --from=builder /app/static ./static
|
||||
|
||||
# Create data directory
|
||||
@@ -31,4 +31,4 @@ RUN mkdir -p /app/data
|
||||
EXPOSE 8080
|
||||
|
||||
# Run the application
|
||||
CMD ["./llm-proxy"]
|
||||
CMD ["./gophergate"]
|
||||
|
||||
16
README.md
16
README.md
@@ -1,4 +1,4 @@
|
||||
# LLM Proxy Gateway
|
||||
# GopherGate
|
||||
|
||||
A unified, high-performance LLM proxy gateway built in Go. It provides a single OpenAI-compatible API to access multiple providers (OpenAI, Gemini, DeepSeek, Grok, Ollama) with built-in token tracking, real-time cost calculation, multi-user authentication, and a management dashboard.
|
||||
|
||||
@@ -27,7 +27,7 @@ A unified, high-performance LLM proxy gateway built in Go. It provides a single
|
||||
|
||||
## Security
|
||||
|
||||
LLM Proxy is designed with security in mind:
|
||||
GopherGate is designed with security in mind:
|
||||
|
||||
- **Signed Session Tokens:** Management dashboard sessions are secured using HMAC-SHA256 signed tokens.
|
||||
- **Encrypted Storage:** Support for encrypted provider API keys in the database.
|
||||
@@ -55,8 +55,8 @@ LLM Proxy is designed with security in mind:
|
||||
1. Clone and build:
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd llm-proxy
|
||||
go build -o llm-proxy ./cmd/llm-proxy
|
||||
cd gophergate
|
||||
go build -o gophergate ./cmd/gophergate
|
||||
```
|
||||
|
||||
2. Configure environment:
|
||||
@@ -70,7 +70,7 @@ LLM Proxy is designed with security in mind:
|
||||
|
||||
3. Run the proxy:
|
||||
```bash
|
||||
./llm-proxy
|
||||
./gophergate
|
||||
```
|
||||
|
||||
The server starts on `http://0.0.0.0:8080` by default.
|
||||
@@ -79,13 +79,13 @@ The server starts on `http://0.0.0.0:8080` by default.
|
||||
|
||||
```bash
|
||||
# Build the container
|
||||
docker build -t llm-proxy .
|
||||
docker build -t gophergate .
|
||||
|
||||
# Run the container
|
||||
docker run -p 8080:8080 \
|
||||
-e LLM_PROXY__ENCRYPTION_KEY=your-secure-key \
|
||||
-v ./data:/app/data \
|
||||
llm-proxy
|
||||
gophergate
|
||||
```
|
||||
|
||||
## Management Dashboard
|
||||
@@ -107,7 +107,7 @@ Access the dashboard at `http://localhost:8080`.
|
||||
**Forgot Password?**
|
||||
You can reset the admin password to default by running:
|
||||
```bash
|
||||
./llm-proxy -reset-admin
|
||||
./gophergate -reset-admin
|
||||
```
|
||||
|
||||
## API Usage
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"llm-proxy/internal/config"
|
||||
"llm-proxy/internal/db"
|
||||
"llm-proxy/internal/server"
|
||||
"gophergate/internal/config"
|
||||
"gophergate/internal/db"
|
||||
"gophergate/internal/server"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
@@ -48,7 +48,7 @@ func main() {
|
||||
s := server.NewServer(cfg, database)
|
||||
|
||||
// Run server
|
||||
log.Printf("Starting LLM Proxy on %s:%d", cfg.Server.Host, cfg.Server.Port)
|
||||
log.Printf("Starting GopherGate on %s:%d", cfg.Server.Host, cfg.Server.Port)
|
||||
if err := s.Run(); err != nil {
|
||||
log.Fatalf("Server failed: %v", err)
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
# Deployment Guide (Go)
|
||||
|
||||
This guide covers deploying the Go-based LLM Proxy Gateway.
|
||||
This guide covers deploying the Go-based GopherGate.
|
||||
|
||||
## Environment Setup
|
||||
|
||||
@@ -18,12 +18,12 @@ This guide covers deploying the Go-based LLM Proxy Gateway.
|
||||
|
||||
### 1. Build
|
||||
```bash
|
||||
go build -o llm-proxy ./cmd/llm-proxy
|
||||
go build -o gophergate ./cmd/gophergate
|
||||
```
|
||||
|
||||
### 2. Run
|
||||
```bash
|
||||
./llm-proxy
|
||||
./gophergate
|
||||
```
|
||||
|
||||
## Docker Deployment
|
||||
@@ -32,17 +32,17 @@ The project includes a multi-stage `Dockerfile` for minimal image size.
|
||||
|
||||
### 1. Build Image
|
||||
```bash
|
||||
docker build -t llm-proxy .
|
||||
docker build -t gophergate .
|
||||
```
|
||||
|
||||
### 2. Run Container
|
||||
```bash
|
||||
docker run -d \
|
||||
--name llm-proxy \
|
||||
--name gophergate \
|
||||
-p 8080:8080 \
|
||||
-v $(pwd)/data:/app/data \
|
||||
--env-file .env \
|
||||
llm-proxy
|
||||
gophergate
|
||||
```
|
||||
|
||||
## Production Considerations
|
||||
|
||||
4
go.mod
4
go.mod
@@ -1,4 +1,4 @@
|
||||
module llm-proxy
|
||||
module gophergate
|
||||
|
||||
go 1.26.1
|
||||
|
||||
@@ -9,6 +9,7 @@ require (
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/jmoiron/sqlx v1.4.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/shirou/gopsutil/v3 v3.24.5
|
||||
github.com/spf13/viper v1.21.0
|
||||
golang.org/x/crypto v0.48.0
|
||||
modernc.org/sqlite v1.47.0
|
||||
@@ -44,7 +45,6 @@ require (
|
||||
github.com/quic-go/quic-go v0.59.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
|
||||
2
go.sum
2
go.sum
@@ -104,6 +104,8 @@ github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/i
|
||||
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
|
||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||
|
||||
BIN
gophergate
Executable file
BIN
gophergate
Executable file
Binary file not shown.
@@ -4,8 +4,8 @@ import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"llm-proxy/internal/db"
|
||||
"llm-proxy/internal/models"
|
||||
"gophergate/internal/db"
|
||||
"gophergate/internal/models"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"llm-proxy/internal/config"
|
||||
"llm-proxy/internal/models"
|
||||
"gophergate/internal/config"
|
||||
"gophergate/internal/models"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"llm-proxy/internal/config"
|
||||
"llm-proxy/internal/models"
|
||||
"gophergate/internal/config"
|
||||
"gophergate/internal/models"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"llm-proxy/internal/config"
|
||||
"llm-proxy/internal/models"
|
||||
"gophergate/internal/config"
|
||||
"gophergate/internal/models"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"llm-proxy/internal/models"
|
||||
"gophergate/internal/models"
|
||||
)
|
||||
|
||||
// MessagesToOpenAIJSON converts unified messages to OpenAI-compatible JSON, including tools and images.
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"llm-proxy/internal/config"
|
||||
"llm-proxy/internal/models"
|
||||
"gophergate/internal/config"
|
||||
"gophergate/internal/models"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package providers
|
||||
import (
|
||||
"context"
|
||||
|
||||
"llm-proxy/internal/models"
|
||||
"gophergate/internal/models"
|
||||
)
|
||||
|
||||
type Provider interface {
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"llm-proxy/internal/db"
|
||||
"llm-proxy/internal/models"
|
||||
"gophergate/internal/db"
|
||||
"gophergate/internal/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"llm-proxy/internal/db"
|
||||
"gophergate/internal/db"
|
||||
)
|
||||
|
||||
type RequestLog struct {
|
||||
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"llm-proxy/internal/config"
|
||||
"llm-proxy/internal/db"
|
||||
"llm-proxy/internal/middleware"
|
||||
"llm-proxy/internal/models"
|
||||
"llm-proxy/internal/providers"
|
||||
"llm-proxy/internal/utils"
|
||||
"gophergate/internal/config"
|
||||
"gophergate/internal/db"
|
||||
"gophergate/internal/middleware"
|
||||
"gophergate/internal/models"
|
||||
"gophergate/internal/providers"
|
||||
"gophergate/internal/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -90,7 +90,7 @@ func (s *Server) handleWebSocket(c *gin.Context) {
|
||||
// Initial message
|
||||
conn.WriteJSON(gin.H{
|
||||
"type": "connected",
|
||||
"message": "Connected to LLM Proxy Dashboard",
|
||||
"message": "Connected to GopherGate Dashboard",
|
||||
})
|
||||
|
||||
for {
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"llm-proxy/internal/models"
|
||||
"gophergate/internal/models"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
|
||||
@@ -148,22 +148,54 @@ body {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin: 0 auto 1.25rem;
|
||||
border-radius: 16px;
|
||||
background: var(--bg2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--orange);
|
||||
font-size: 2rem;
|
||||
background: rgba(254, 128, 25, 0.15);
|
||||
color: var(--primary);
|
||||
border-radius: 12px;
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
/* GopherGate Logo Icon */
|
||||
.logo-icon-container {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: var(--blue-light);
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: var(--shadow);
|
||||
border: 2px solid var(--fg1);
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.logo-icon-container.small {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 6px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.logo-icon-text {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-weight: 700;
|
||||
color: var(--bg0);
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.logo-icon-container.small .logo-icon-text {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.login-header h1 {
|
||||
font-size: 1.75rem;
|
||||
font-size: 2rem;
|
||||
font-weight: 800;
|
||||
color: var(--fg0);
|
||||
color: var(--primary-light);
|
||||
margin-bottom: 0.5rem;
|
||||
letter-spacing: -0.025em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.login-subtitle {
|
||||
|
||||
@@ -3,50 +3,38 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>LLM Proxy Gateway - Admin Dashboard</title>
|
||||
<title>GopherGate - Admin Dashboard</title>
|
||||
<link rel="stylesheet" href="/css/dashboard.css?v=11">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<link rel="icon" href="img/logo-icon.png" type="image/png" sizes="any">
|
||||
<link rel="apple-touch-icon" href="img/logo-icon.png">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/luxon@3.4.4/build/global/luxon.min.js"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Login Screen -->
|
||||
<div id="login-screen" class="login-container">
|
||||
<div class="login-card">
|
||||
<div class="login-header">
|
||||
<i class="fas fa-terminal login-logo-fallback"></i>
|
||||
<h1>LLM Proxy Gateway</h1>
|
||||
<p class="login-subtitle">Admin Dashboard</p>
|
||||
<body class="gruvbox-dark">
|
||||
<!-- Auth Page -->
|
||||
<div id="auth-page" class="auth-container">
|
||||
<div class="auth-card">
|
||||
<div class="auth-header">
|
||||
<div class="auth-logo">
|
||||
<div class="logo-icon-container">
|
||||
<span class="logo-icon-text">GG</span>
|
||||
</div>
|
||||
</div>
|
||||
<h1>GopherGate</h1>
|
||||
<p>Secure LLM Gateway & Management</p>
|
||||
</div>
|
||||
<form id="login-form" class="login-form" onsubmit="event.preventDefault();">
|
||||
<div class="form-group">
|
||||
<input type="text" id="username" name="username" placeholder=" " required>
|
||||
<label for="username">
|
||||
<i class="fas fa-user"></i> Username
|
||||
</label>
|
||||
<form id="login-form">
|
||||
<div class="form-control">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" id="username" name="username" required autocomplete="username">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="password" id="password" name="password" placeholder=" " required>
|
||||
<label for="password">
|
||||
<i class="fas fa-lock"></i> Password
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="login-btn">
|
||||
<i class="fas fa-sign-in-alt"></i> Sign In
|
||||
</button>
|
||||
</div>
|
||||
<div class="login-footer">
|
||||
<p>Default: <code>admin</code> / <code>admin</code> (change in Settings > Security)</p>
|
||||
<div class="form-control">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" name="password" required autocomplete="current-password">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-block">Sign In</button>
|
||||
</form>
|
||||
<div id="login-error" class="error-message" style="display: none;">
|
||||
<i class="fas fa-exclamation-circle"></i>
|
||||
<span>Invalid credentials. Please try again.</span>
|
||||
</div>
|
||||
<div id="login-error" class="error-message" style="display: none;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -56,9 +44,10 @@
|
||||
<nav class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<div class="logo">
|
||||
<img src="img/logo-icon.png" alt="LLM Proxy" class="sidebar-logo" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline-block';">
|
||||
<i class="fas fa-shield-alt logo-fallback" style="display: none;"></i>
|
||||
<span>LLM Proxy</span>
|
||||
<div class="logo-icon-container small">
|
||||
<span class="logo-icon-text">GG</span>
|
||||
</div>
|
||||
<span>GopherGate</span>
|
||||
</div>
|
||||
<button class="sidebar-toggle" id="sidebar-toggle">
|
||||
<i class="fas fa-bars"></i>
|
||||
@@ -68,68 +57,74 @@
|
||||
<div class="sidebar-menu">
|
||||
<div class="menu-section">
|
||||
<h3 class="menu-title">MAIN</h3>
|
||||
<a href="#overview" class="menu-item active" data-page="overview" data-tooltip="Dashboard Overview">
|
||||
<i class="fas fa-th-large"></i>
|
||||
<span>Overview</span>
|
||||
</a>
|
||||
<a href="#analytics" class="menu-item" data-page="analytics" data-tooltip="Usage Analytics">
|
||||
<i class="fas fa-chart-line"></i>
|
||||
<span>Analytics</span>
|
||||
</a>
|
||||
<a href="#costs" class="menu-item" data-page="costs" data-tooltip="Cost Tracking">
|
||||
<i class="fas fa-dollar-sign"></i>
|
||||
<span>Cost Management</span>
|
||||
</a>
|
||||
<ul class="menu-list">
|
||||
<li class="menu-item active" data-page="overview">
|
||||
<i class="fas fa-th-large"></i>
|
||||
<span>Overview</span>
|
||||
</li>
|
||||
<li class="menu-item" data-page="analytics">
|
||||
<i class="fas fa-chart-bar"></i>
|
||||
<span>Analytics</span>
|
||||
</li>
|
||||
<li class="menu-item" data-page="costs">
|
||||
<i class="fas fa-dollar-sign"></i>
|
||||
<span>Costs & Billing</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="menu-section">
|
||||
<h3 class="menu-title">MANAGEMENT</h3>
|
||||
<a href="#clients" class="menu-item" data-page="clients" data-tooltip="API Clients">
|
||||
<i class="fas fa-users"></i>
|
||||
<span>Client Management</span>
|
||||
</a>
|
||||
<a href="#providers" class="menu-item" data-page="providers" data-tooltip="Model Providers">
|
||||
<i class="fas fa-server"></i>
|
||||
<span>Providers</span>
|
||||
</a>
|
||||
<a href="#models" class="menu-item" data-page="models" data-tooltip="Manage Models">
|
||||
<i class="fas fa-cube"></i>
|
||||
<span>Models</span>
|
||||
</a>
|
||||
<a href="#monitoring" class="menu-item" data-page="monitoring" data-tooltip="Live Monitoring">
|
||||
<i class="fas fa-heartbeat"></i>
|
||||
<span>Real-time Monitoring</span>
|
||||
</a>
|
||||
<ul class="menu-list">
|
||||
<li class="menu-item" data-page="clients">
|
||||
<i class="fas fa-users"></i>
|
||||
<span>Clients</span>
|
||||
</li>
|
||||
<li class="menu-item" data-page="providers">
|
||||
<i class="fas fa-server"></i>
|
||||
<span>Providers</span>
|
||||
</li>
|
||||
<li class="menu-item" data-page="models">
|
||||
<i class="fas fa-brain"></i>
|
||||
<span>Models</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="menu-section">
|
||||
<h3 class="menu-title">SYSTEM</h3>
|
||||
<a href="#users" class="menu-item admin-only" data-page="users" data-tooltip="User Accounts">
|
||||
<i class="fas fa-user-shield"></i>
|
||||
<span>User Management</span>
|
||||
</a>
|
||||
<a href="#settings" class="menu-item admin-only" data-page="settings" data-tooltip="System Settings">
|
||||
<i class="fas fa-cog"></i>
|
||||
<span>Settings</span>
|
||||
</a>
|
||||
<a href="#logs" class="menu-item" data-page="logs" data-tooltip="System Logs">
|
||||
<i class="fas fa-list-alt"></i>
|
||||
<span>System Logs</span>
|
||||
</a>
|
||||
<ul class="menu-list">
|
||||
<li class="menu-item" data-page="monitoring">
|
||||
<i class="fas fa-activity"></i>
|
||||
<span>Live Monitoring</span>
|
||||
</li>
|
||||
<li class="menu-item" data-page="logs">
|
||||
<i class="fas fa-list-alt"></i>
|
||||
<span>Logs</span>
|
||||
</li>
|
||||
<li class="menu-item" data-page="users">
|
||||
<i class="fas fa-user-shield"></i>
|
||||
<span>Admin Users</span>
|
||||
</li>
|
||||
<li class="menu-item" data-page="settings">
|
||||
<i class="fas fa-cog"></i>
|
||||
<span>Settings</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="sidebar-footer">
|
||||
<div class="user-info">
|
||||
<div class="user-avatar">
|
||||
<i class="fas fa-user-circle"></i>
|
||||
<i class="fas fa-user"></i>
|
||||
</div>
|
||||
<div class="user-details">
|
||||
<span class="user-name">Loading...</span>
|
||||
<span class="user-role">...</span>
|
||||
<div class="user-name" id="display-username">Admin</div>
|
||||
<div class="user-role" id="display-role">Administrator</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="logout-btn" id="logout-btn" title="Logout">
|
||||
<button id="logout-btn" class="btn-icon" title="Logout">
|
||||
<i class="fas fa-sign-out-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
@@ -137,43 +132,40 @@
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content">
|
||||
<!-- Top Navigation -->
|
||||
<header class="top-nav">
|
||||
<div class="nav-left">
|
||||
<h1 class="page-title" id="page-title">Dashboard Overview</h1>
|
||||
<header class="top-bar">
|
||||
<div class="page-title">
|
||||
<h2 id="current-page-title">Overview</h2>
|
||||
</div>
|
||||
<div class="nav-right">
|
||||
<div class="nav-item" id="ws-status-nav" title="WebSocket Connection Status">
|
||||
<div class="ws-dot"></div>
|
||||
<span class="ws-text">Connecting...</span>
|
||||
<div class="top-bar-actions">
|
||||
<div id="connection-status" class="status-indicator">
|
||||
<span class="status-dot"></span>
|
||||
<span class="status-text">Disconnected</span>
|
||||
</div>
|
||||
<div class="nav-item" title="Refresh Current Page">
|
||||
<i class="fas fa-sync-alt" id="refresh-btn"></i>
|
||||
</div>
|
||||
<div class="nav-item">
|
||||
<span id="current-time">Loading...</span>
|
||||
<div class="theme-toggle" id="theme-toggle">
|
||||
<i class="fas fa-moon"></i>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Page Content -->
|
||||
<div class="page-content" id="page-content">
|
||||
<!-- Dynamic content container -->
|
||||
</div>
|
||||
|
||||
<!-- Global Spinner -->
|
||||
<div class="spinner-container">
|
||||
<div class="spinner"></div>
|
||||
<div id="page-content" class="content-body">
|
||||
<!-- Content will be loaded dynamically -->
|
||||
<div class="loader-container">
|
||||
<div class="loader"></div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- Scripts (cache-busted with version query params) -->
|
||||
<!-- Scripts -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/luxon@3.3.0/build/global/luxon.min.js"></script>
|
||||
<script src="/js/api.js?v=7"></script>
|
||||
<script src="/js/auth.js?v=7"></script>
|
||||
<script src="/js/dashboard.js?v=7"></script>
|
||||
<script src="/js/websocket.js?v=7"></script>
|
||||
<script src="/js/charts.js?v=7"></script>
|
||||
<script src="/js/websocket.js?v=7"></script>
|
||||
<script src="/js/dashboard.js?v=7"></script>
|
||||
|
||||
<!-- Page Modules -->
|
||||
<script src="/js/pages/overview.js?v=7"></script>
|
||||
<script src="/js/pages/analytics.js?v=7"></script>
|
||||
<script src="/js/pages/costs.js?v=7"></script>
|
||||
@@ -185,4 +177,4 @@
|
||||
<script src="/js/pages/logs.js?v=7"></script>
|
||||
<script src="/js/pages/users.js?v=7"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Authentication Module for LLM Proxy Dashboard
|
||||
// Authentication Module for GopherGate Dashboard
|
||||
|
||||
class AuthManager {
|
||||
constructor() {
|
||||
|
||||
Reference in New Issue
Block a user