Files
nexusAI/docs/services/chat-client.md
2026-04-06 05:00:12 -07:00

4.7 KiB

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

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.