This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/README.md
2026-02-19 15:03:20 +00:00

193 lines
6.3 KiB
Markdown

# 🔀 Chat Switchboard
**Multi-Model AI Chat Platform — Self-Hosted, Extensible, Fast**
A self-hosted AI chat interface that routes conversations across multiple LLM providers. Built with a Go backend for performance and a clean vanilla JS frontend inspired by Open WebUI.
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Go Version](https://img.shields.io/badge/Go-1.22+-00ADD8?logo=go)](https://go.dev/)
---
## What It Does
- **Multi-provider routing** — Connect OpenAI, Anthropic, Venice.ai, Ollama, or any OpenAI-compatible API. Switch models per-conversation.
- **Streaming responses** — SSE-based streaming with stop button, thinking block display, and full markdown rendering.
- **Per-user API keys** — Each user manages their own provider keys. Admins can set global keys shared across the instance.
- **Admin panel** — User management, global provider config, model visibility, registration toggle, usage stats.
- **Self-hosted** — Single Docker image, PostgreSQL backend. No external dependencies at runtime.
---
## Quick Start
### Docker (Recommended)
```bash
git clone https://git.gobha.me/xcaliber/chat-switchboard.git
cd chat-switchboard
cp server/.env.example server/.env
# Edit .env: set DATABASE_URL, JWT_SECRET, etc.
docker-compose up -d
```
Access at `http://localhost:3000`. First registered user becomes admin.
### Manual
```bash
# Backend
cd server
cp .env.example .env
go build -o switchboard .
./switchboard
# Frontend — serve src/ with any HTTP server
cd ../src
python3 -m http.server 8080
```
Point the frontend at the backend by setting the API base URL (defaults to same-origin).
---
## Architecture
```
┌──────────────────────────┐
│ Frontend (Vanilla JS) │
│ 4 files + vendor libs │
│ No build step required │
└───────────┬──────────────┘
│ REST + SSE
┌──────────────────────────┐
│ Go Backend │
│ ├── Auth (JWT + refresh)│
│ ├── Chat CRUD │
│ ├── Completion proxy │
│ ├── Provider management │
│ ├── Admin endpoints │
│ └── Static file server │
└───────────┬──────────────┘
PostgreSQL
```
### Frontend (src/)
| File | Size | Purpose |
|------|------|---------|
| `api.js` | 240 lines | HTTP client, token management, auto-refresh on 401 |
| `app.js` | 490 lines | State, init flow, auth, chat CRUD, event wiring |
| `ui.js` | 510 lines | DOM rendering, streaming, modals, formatting |
| `debug.js` | 550 lines | Console/network intercept, state inspector (Ctrl+Shift+L) |
| `vendor/` | 62KB | marked.js + DOMPurify (local, CDN fallback) |
No framework. No build step. No node_modules. Works in disconnected (SCIF) environments with vendor libs baked in.
### Backend (server/)
Go 1.22, ~26 source files. Key packages:
- `handlers/` — Auth, chats, messages, completions, API configs, admin
- `middleware/` — JWT auth, admin role check, rate limiting, error handling, logging
- `providers/` — OpenAI and Anthropic adapters with streaming support
- `models/` — Database models
- `database/` — PostgreSQL connection + migration runner
- `config/` — Environment-based configuration
### API Surface
| Route | Method | Auth | Description |
|-------|--------|------|-------------|
| `/health` | GET | — | Health check + version |
| `/api/v1/auth/register` | POST | — | Create account |
| `/api/v1/auth/login` | POST | — | Get JWT tokens |
| `/api/v1/auth/refresh` | POST | — | Rotate access token |
| `/api/v1/chats` | GET/POST | ✓ | List / create chats |
| `/api/v1/chats/:id` | GET/PUT/DELETE | ✓ | Chat CRUD |
| `/api/v1/chats/:id/messages` | GET | ✓ | Message history |
| `/api/v1/chat/completions` | POST | ✓ | Streaming SSE or sync JSON |
| `/api/v1/models/enabled` | GET | ✓ | Available models |
| `/api/v1/api-configs` | GET/POST/DELETE | ✓ | User provider management |
| `/api/v1/profile` | GET/PUT | ✓ | User profile |
| `/api/v1/settings` | GET/PUT | ✓ | User settings (persisted) |
| `/api/v1/admin/*` | various | admin | User/provider/model/settings management |
---
## Configuration
All via environment variables (see `server/.env.example`):
| Variable | Default | Description |
|----------|---------|-------------|
| `PORT` | `8080` | Backend listen port |
| `DATABASE_URL` | — | PostgreSQL connection string |
| `JWT_SECRET` | — | Token signing key |
| `JWT_EXPIRY` | `15m` | Access token TTL |
| `REFRESH_EXPIRY` | `7d` | Refresh token TTL |
| `CORS_ORIGINS` | `*` | Allowed origins |
| `REGISTRATION_ENABLED` | `true` | Allow new signups |
---
## Deployment
### Docker Compose (unified)
The provided `Dockerfile` is a 3-stage build:
1. `golang:1.22-bookworm` — compiles Go backend
2. `node:20-alpine` — downloads vendor JS libs via `npm pack`
3. `nginx:1-alpine` — serves frontend, proxies `/api/` to Go backend
Vendor libs are baked into the image at build time — no CDN access needed at runtime (SCIF-safe).
### Reverse Proxy
If running behind nginx/Caddy, proxy `/api/` and `/health` to the Go backend. Serve `src/` as static files.
---
## Development
```bash
# Backend (hot reload with air)
cd server
go install github.com/air-verse/air@latest
air
# Frontend — just edit files, hard-refresh browser
# Debug: Ctrl+Shift+L opens debug modal
```
### Database Migrations
Migrations in `migrations/` run automatically on startup. Current schema:
- `001_full_schema.sql` — users, chats, messages, api_configs
- `002_refresh_tokens.sql` — token rotation
- `003_global_settings.sql` — admin settings table
- `004_model_configs.sql` — per-model enable/disable
---
## Roadmap
See [ROADMAP.md](ROADMAP.md) for the full plan. Next up:
1. **WebSocket hub** — real-time message delivery, typing indicators
2. **Channels** — multi-user + AI chat rooms with @mentions
3. **Plugin system** — Go-native extensions, installable via admin UI
4. **Notes & Knowledge Base** — markdown notes, document upload, RAG via pgvector
---
## License
MIT — build anything, including commercial products.
---
**Repository:** https://git.gobha.me/xcaliber/chat-switchboard