Add /api/messages/hash/:hash endpoint that resolves a message hash to
its room ID (with membership check). The client now handles both
#roomId/hash and #hash formats - the latter calls the API to find
which room the message belongs to, then loads it and scrolls.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a hash column to messages table computed from SHA-256(created_at + content)
to ensure message integrity. Existing messages get backfilled during migration.
All messages now show copy and permalink buttons on hover, with hash-based
URL fragments that auto-scroll and highlight the target message.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add automatic SQLite database backup before migrations on every server
start. Backups are timestamped and stored in backups/, with WAL/SHM
files included. Old backups are pruned to keep only the 10 most recent.
Update dev.sh to use separate ports and database from production so both
can run simultaneously on the same machine:
- Production: server :3001, DB chat.db
- Development: server :3002, Vite :3003, DB chat-dev.db
Make Vite config dynamic via VITE_PORT and VITE_API_PORT env vars.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add user profile page with custom avatar upload (crop/resize to 256px),
avatar display throughout the app, and MD5-based Gravatar fallback.
Add image paste/attach support in chat with vision model detection via
OpenRouter API. Images can be pasted from clipboard or selected via file
picker, uploaded to the server, and sent alongside messages. The AI
receives images as base64 data URLs for multimodal models. Models with
vision support are indicated with a badge in the model picker.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add dev.sh for running server + client in parallel on macOS, and prod.sh
for building and deploying in production. The Rust server now serves
static client files with SPA fallback, eliminating the need for Vite in
production. Also adds missing BRAVE_API_KEY to .env.example.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add avatar_hash (MD5 of email) to MessagePayload for server-side hash computation
- Create avatar.js with Gravatar URL generation and client-side MD5 implementation
- Show sender names and unique avatars on all messages including own messages
- Use monsterid fallback for users without Gravatar, robot icons reserved for AI
- LEFT JOIN users table in message history queries for avatar hash lookup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add clickable member count in room header that shows a dropdown with
all room members (AI agent + humans) with role badges
- Give each room's AI agent a random name from 10 options (Nova, Atlas,
Sage, etc.), editable when creating the room
- Replace AI text avatar with a robot SVG icon across all components
- Fix broken invite system: add client-side URL routing for /invite/:token,
handle post-login invite acceptance via sessionStorage, and return
room_id from accept_invite endpoint for auto-navigation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces batch AI responses with real-time SSE streaming from OpenRouter.
Tokens are buffered client-side and drained via requestAnimationFrame for
a smooth typing effect instead of choppy chunk dumps.
Backend:
- Rewrite openrouter service for SSE streaming with incremental tool call accumulation
- Add AiStreamChunk/AiStreamEnd WebSocket event types
- Stream content deltas to clients during all tool call rounds
- Increase broadcast channel capacity (256 -> 4096) and handle Lagged errors gracefully
Frontend:
- Add StreamBuffer utility with adaptive rAF-based character draining
- Show streaming message-bubble with blinking cursor during generation
- Clean up buffer on room switch and final message replacement
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full-stack real-time group chat with Rust/Axum backend and Riot.js frontend.
Features:
- Auth (register/login/JWT), rooms, invites, WebSocket messaging
- AI responses via OpenRouter with tool calling (Brave Search + web fetch)
- Real-time tool usage indicators (searching/reading page)
- Collapsible tool results in message bubbles
- AI stats bar (model, tokens, speed, response time) persisted to DB
- Room soft-delete, /clear command, dynamic model fetching
- Markdown rendering with code highlighting and copy buttons
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>