156 lines
3.8 KiB
Markdown
156 lines
3.8 KiB
Markdown
# GroupChat2 Server
|
|
|
|
The server is a Rust/Axum application that provides authentication, room and message APIs, WebSocket chat delivery, AI response orchestration, file uploads, and SQLite-backed persistence for GroupChat2.
|
|
|
|
## Stack
|
|
|
|
- Rust 2021
|
|
- Axum and Tokio
|
|
- SQLx with SQLite
|
|
- JWT auth and Argon2 password hashing
|
|
- OpenRouter for AI completions
|
|
- Tavily or Brave for web search tools
|
|
|
|
## Responsibilities
|
|
|
|
- Register and authenticate users
|
|
- Support Nostr challenge/verify login
|
|
- Manage rooms, members, invites, and profile updates
|
|
- Persist messages, hashes, room settings, and AI metadata
|
|
- Broadcast real-time events over WebSockets
|
|
- Stream AI responses and tool usage events to connected clients
|
|
- Store uploaded avatars and chat images
|
|
- Serve built frontend assets in production
|
|
|
|
## Requirements
|
|
|
|
- Rust toolchain with `cargo`
|
|
- A valid `OPENROUTER_API_KEY`
|
|
- A search provider configured through either Tavily or Brave
|
|
|
|
## Environment
|
|
|
|
Copy `.env.example` to `.env` and fill in the values you need.
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
Important variables:
|
|
|
|
- `BIND_ADDR`: server bind address, default `0.0.0.0:3001`
|
|
- `RUST_LOG`: log level, default `info`
|
|
- `DATABASE_URL`: SQLite connection string, default `sqlite:chat.db?mode=rwc`
|
|
- `JWT_SECRET`: JWT signing secret
|
|
- `OPENROUTER_API_KEY`: required
|
|
- `SEARCH_PROVIDER`: `tavily` or `brave`
|
|
- `TAVILY_API_KEY`: required when `SEARCH_PROVIDER=tavily`
|
|
- `BRAVE_API_KEY`: required when `SEARCH_PROVIDER=brave`
|
|
- `STATIC_DIR`: optional path to built client assets for production serving
|
|
|
|
## Commands
|
|
|
|
Run the backend directly:
|
|
|
|
```bash
|
|
cargo run
|
|
```
|
|
|
|
Build a release binary:
|
|
|
|
```bash
|
|
cargo build --release
|
|
```
|
|
|
|
From the repo root, production build/run is also available through:
|
|
|
|
```bash
|
|
./prod.sh
|
|
```
|
|
|
|
## Startup Behavior
|
|
|
|
On startup the server:
|
|
|
|
- loads environment variables from `.env`
|
|
- validates required AI/search configuration
|
|
- creates a timestamped backup of the SQLite database if it already exists
|
|
- keeps the 10 most recent backups
|
|
- opens the SQLite database
|
|
- applies SQL migrations embedded in the binary
|
|
|
|
## API Surface
|
|
|
|
Main routes exposed by the server:
|
|
|
|
- `/api/auth/register`
|
|
- `/api/auth/login`
|
|
- `/api/auth/me`
|
|
- `/api/auth/profile`
|
|
- `/api/auth/avatar`
|
|
- `/api/auth/nostr/challenge`
|
|
- `/api/auth/nostr/verify`
|
|
- `/api/rooms`
|
|
- `/api/rooms/:room_id`
|
|
- `/api/rooms/:room_id/messages`
|
|
- `/api/rooms/:room_id/join`
|
|
- `/api/rooms/:room_id/clear`
|
|
- `/api/messages/hash/:hash`
|
|
- `/api/models`
|
|
- `/api/invites`
|
|
- `/api/invites/:token/accept`
|
|
- `/api/invites/nostr`
|
|
- `/api/upload`
|
|
- `/ws`
|
|
- `/uploads/*`
|
|
|
|
## Real-Time Flow
|
|
|
|
WebSocket clients connect to `/ws` with a JWT token in the query string.
|
|
|
|
Client messages include:
|
|
|
|
- `join_room`
|
|
- `typing`
|
|
- `send_message`
|
|
|
|
Server events include:
|
|
|
|
- new messages
|
|
- AI typing notifications
|
|
- AI stream chunks and stream end markers
|
|
- AI tool usage updates
|
|
- user typing notifications
|
|
- room deleted and room cleared events
|
|
|
|
## Storage Layout
|
|
|
|
```text
|
|
server/
|
|
|- migrations/ SQL schema and incremental changes
|
|
|- src/ handlers, middleware, models, services
|
|
|- uploads/ avatars and chat images
|
|
|- backups/ automatic database backups
|
|
|- chat.db SQLite database
|
|
```
|
|
|
|
Uploaded file behavior:
|
|
|
|
- avatars are stored under `uploads/avatars/`
|
|
- chat images are stored under `uploads/chat-images/`
|
|
- avatar uploads are limited to 2 MB
|
|
- chat image uploads are limited to 5 MB
|
|
|
|
## AI Behavior
|
|
|
|
When a user mentions the assistant or the room is configured to always respond, the server:
|
|
|
|
- loads recent room history
|
|
- includes image context for human-uploaded images when available
|
|
- calls OpenRouter in streaming mode
|
|
- executes tool calls for search or page fetches
|
|
- broadcasts streaming output to the room
|
|
- stores the final AI response with usage metadata
|
|
|
|
For frontend behavior and local browser setup, see the [Client README](../client/README.md).
|