groupchat/server/README.md

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).