116 lines
4.7 KiB
Markdown
116 lines
4.7 KiB
Markdown
# Chat Client
|
|
|
|
**Package:** `@nexusai/chat-client`
|
|
**Location:** `packages/chat-client`
|
|
**Deployed on:** Mini PC 2 (192.168.0.205)
|
|
**URL:** `https://nexus.jellystorm.com` (behind Authelia SSO)
|
|
|
|
## Purpose
|
|
|
|
Browser-based chat interface for NexusAI. Communicates exclusively with
|
|
the orchestration service — no direct access to memory, embedding, or
|
|
inference services. Served as static files by Caddy on Mini PC 2.
|
|
|
|
## Dependencies
|
|
|
|
- `react` + `react-dom` — UI framework
|
|
- `uuid` — session ID generation
|
|
- `vite` + `@vitejs/plugin-react` — build tooling
|
|
|
|
## Build
|
|
```bash
|
|
cd packages/chat-client
|
|
npm run build # outputs to dist/
|
|
npm run dev # local dev server on port 5173
|
|
```
|
|
|
|
Vite bakes environment variables into the bundle at build time. The `.env`
|
|
file is only needed on the machine running the build, not where files are served.
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Required | Default | Description |
|
|
|---|---|---|---|
|
|
| VITE_ORCHESTRATION_URL | No | `''` (empty) | Orchestration base URL. Empty string uses Vite proxy in dev, Caddy proxy in production. |
|
|
|
|
## Internal Structure
|
|
```
|
|
src/
|
|
├── api/
|
|
│ └── orchestration.js # All fetch calls to the orchestration service
|
|
├── hooks/
|
|
│ ├── useSession.js # Session list, history loading, active session state
|
|
│ └── useChat.js # Message sending, SSE streaming, message state
|
|
├── components/
|
|
│ ├── App.jsx # Root component — layout and shared state
|
|
│ ├── SessionList.jsx # Left sidebar — session list and new chat button
|
|
│ ├── ChatWindow.jsx # Centre panel — message thread and input bar
|
|
│ ├── MessageBubble.jsx # Individual message bubble (user or assistant)
|
|
│ └── InfoPanel.jsx # Right panel — model selector and session metadata
|
|
├── index.css # Global reset and CSS variables
|
|
└── main.jsx # React entry point
|
|
```
|
|
|
|
## Layout
|
|
|
|
Three-panel layout with collapsible sidebars:
|
|
┌─────────────────┬──────────────────────────┬─────────────┐
|
|
│ Session List │ Chat Window │ Info Panel │
|
|
│ (collapsible) │ │ (collapsible)│
|
|
│ │ [message thread] │ │
|
|
│ + New Chat │ │ Model │
|
|
│ │ │ Session ID │
|
|
│ Session 1 │ │ Token count │
|
|
│ Session 2 │ │ │
|
|
│ │ [input bar] │ │
|
|
└─────────────────┴──────────────────────────┴─────────────┘
|
|
|
|
On mobile, sidebars collapse to a 56px icon rail. The centre chat window
|
|
always fills the remaining space.
|
|
|
|
## API Layer
|
|
|
|
All orchestration calls are centralised in `src/api/orchestration.js`:
|
|
|
|
| Function | Method | Path | Description |
|
|
|---|---|---|---|
|
|
| `fetchSessions` | GET | /sessions | Load session list for sidebar |
|
|
| `fetchSessionHistory` | GET | /sessions/:id/history | Load episode history on session select |
|
|
| `sendMessage` | POST | /chat | Send message, await full response |
|
|
| `streamMessage` | POST | /chat/stream | Send message, receive SSE token stream |
|
|
|
|
`streamMessage` returns an abort function — call it to cancel a stream mid-flight.
|
|
It uses a buffer pattern to handle SSE chunks that may span multiple network packets.
|
|
|
|
## Streaming
|
|
|
|
The chat input sends messages via `POST /chat/stream`. Tokens arrive as SSE events:
|
|
data: {"text":"Hello"}
|
|
data: {"text":" Tim"}
|
|
data: {"done":true}
|
|
|
|
An empty assistant bubble is appended immediately when the stream opens, then
|
|
updated token by token using `updateLastMessage`. The blinking cursor in
|
|
`MessageBubble` is shown while `message.streaming === true` and disappears
|
|
when `done` is received.
|
|
|
|
## Model Selector
|
|
|
|
Available models are defined in `InfoPanel.jsx`:
|
|
|
|
| Label | Value |
|
|
|---|---|
|
|
| Companion | `companion:latest` |
|
|
| Mistral Nemo | `mistral-nemo:latest` |
|
|
| Coder | `coder:latest` |
|
|
| Qwen 2.5 Coder 14B | `qwen2.5-coder:14b` |
|
|
|
|
The selected model is passed with every chat request. To add a new model,
|
|
update the `MODELS` array in `InfoPanel.jsx`.
|
|
|
|
## Session Management
|
|
|
|
Sessions are identified by a `external_id` — a human-readable string or UUID
|
|
generated client-side. New sessions are created locally with `uuid` and auto-registered
|
|
in the memory service on the first message. The session list refreshes after each
|
|
completed response to surface newly created sessions. |