update documentation
This commit is contained in:
@@ -55,10 +55,6 @@ VITE_ORCHESTRATION_URL=https://nexus.jellystorm.com
|
||||
during local development, bypassing Caddy and Authelia entirely:
|
||||
|
||||
```js
|
||||
// vite.config.js
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
server: {
|
||||
@@ -72,7 +68,8 @@ export default defineConfig({
|
||||
});
|
||||
```
|
||||
|
||||
If new routes are added to the orchestration service, add them here too.
|
||||
When adding new top-level routes to the orchestration service, add a matching
|
||||
entry here too.
|
||||
|
||||
## Internal Structure
|
||||
|
||||
@@ -93,12 +90,13 @@ src/
|
||||
│ ├── Sidebar.jsx # Left sidebar — projects, recent chats, navigation
|
||||
│ ├── 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
|
||||
│ ├── SessionModal.jsx # Modal for session rename and delete confirmation
|
||||
│ ├── ProjectModal.jsx # Modal for project create, edit, and delete confirmation
|
||||
│ ├── InfoPanel.jsx # Right panel — model selector and session metadata (slide-in)
|
||||
│ ├── SessionModal.jsx # Modal for session rename, project assignment, delete
|
||||
│ ├── ProjectModal.jsx # Modal for project create, edit, delete
|
||||
│ ├── AllChatsView.jsx # Full paginated session list with multi-select bulk delete
|
||||
│ ├── AllProjectsView.jsx # Project tile grid with create/edit/delete
|
||||
│ └── SettingsView.jsx # Settings placeholder (sections: Appearance, Memory, Models, About)
|
||||
│ ├── ProjectView.jsx # Individual project — session list, new chat button
|
||||
│ └── SettingsView.jsx # Settings placeholder (Appearance, Memory, Models, About)
|
||||
├── index.css # Global reset, CSS variables, utility classes
|
||||
└── main.jsx # React entry point
|
||||
```
|
||||
@@ -107,9 +105,9 @@ src/
|
||||
|
||||
## Layout
|
||||
|
||||
The app uses a view-based layout. `App.jsx` manages a `view` state
|
||||
(`'chat' | 'all-chats' | 'all-projects' | 'settings'`) that controls which
|
||||
main panel is rendered. The left sidebar and right info panel are always present.
|
||||
The app uses a view-based layout. `App.jsx` manages a `view` state string
|
||||
that controls which main panel is rendered. The left sidebar and right info
|
||||
panel are persistent across all views.
|
||||
|
||||
```
|
||||
┌──────────────────┬──────────────────────────────┐
|
||||
@@ -117,9 +115,9 @@ main panel is rendered. The left sidebar and right info panel are always present
|
||||
│ (collapsible) │ │
|
||||
│ │ chat → ChatWindow │
|
||||
│ + New Chat │ all-chats → AllChatsView │
|
||||
│ ⊞ New Project │ all-projects → AllProjectsView│
|
||||
│ │ settings → SettingsView │
|
||||
│ PROJECTS ▾ │ │
|
||||
│ ⊞ View Projects │ all-projects → AllProjectsView│
|
||||
│ │ project → ProjectView │
|
||||
│ PROJECTS ▾ │ settings → SettingsView │
|
||||
│ [tile] [tile] │ │
|
||||
│ All Projects → │ │
|
||||
│ │ │
|
||||
@@ -132,10 +130,22 @@ main panel is rendered. The left sidebar and right info panel are always present
|
||||
└──────────────────┴──────────────────────────────┘
|
||||
```
|
||||
|
||||
The sidebar collapses to a 48px icon rail. The right info panel (`InfoPanel`)
|
||||
slides in from the right over the main area using `transform: translateX()` —
|
||||
it is hidden by default (`rightOpen` starts `false`) and toggled via a button
|
||||
in the `ChatWindow` header.
|
||||
The sidebar collapses to a 48px icon rail. The right `InfoPanel` slides in
|
||||
from the right using `transform: translateX()` — hidden by default, toggled
|
||||
via the `⊹` button in the `ChatWindow` header.
|
||||
|
||||
## View Routing
|
||||
|
||||
| View | Component | Trigger |
|
||||
|---|---|---|
|
||||
| `'chat'` | `ChatWindow` | Default; selecting a session; new chat |
|
||||
| `'all-chats'` | `AllChatsView` | "All Chats →" or ☰ icon in collapsed rail |
|
||||
| `'all-projects'` | `AllProjectsView` | "View Projects" button or ⊞ icon |
|
||||
| `'project'` | `ProjectView` | Clicking a project tile in the sidebar |
|
||||
| `'settings'` | `SettingsView` | Settings button or ⚙ icon |
|
||||
|
||||
`activeProject` state in `App.jsx` tracks which project `ProjectView` is
|
||||
displaying. Set via `onSelectProject` before navigating to `'project'`.
|
||||
|
||||
## CSS Architecture
|
||||
|
||||
@@ -181,91 +191,47 @@ rules, inline styles for dynamic prop-driven values.
|
||||
| `.label-upper` | Uppercase section label style |
|
||||
| `.truncate` | Text overflow ellipsis |
|
||||
|
||||
## 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 |
|
||||
| `fetchModels` | GET | /models | Load available models from manifest |
|
||||
| `renameSession` | PATCH | /sessions/:id | Rename a session |
|
||||
| `deleteSession` | DELETE | /sessions/:id | Delete a session |
|
||||
| `fetchProjects` | GET | /projects | Load project list |
|
||||
| `createProject` | POST | /projects | Create a new project |
|
||||
| `updateProject` | PATCH | /projects/:id | Update a project |
|
||||
| `deleteProject` | DELETE | /projects/:id | Delete a project |
|
||||
|
||||
`streamMessage` returns an abort function — call it to cancel a stream mid-flight.
|
||||
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:
|
||||
Messages are sent via `POST /chat/stream`. Tokens arrive as SSE events and
|
||||
are written into the active assistant bubble token by token via
|
||||
`updateLastMessage`. The blinking cursor in `MessageBubble` is shown while
|
||||
`message.streaming === true`.
|
||||
|
||||
```
|
||||
data: {"text":"Hello"}
|
||||
data: {"text":" Tim"}
|
||||
data: {"done":true,"model":"gemma-4-26B-A4B-Claude-Distill-APEX-I-Mini.gguf","tokenCount":87}
|
||||
```
|
||||
|
||||
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 the done event is received. Model name and token count from the done
|
||||
event are stored in `useChat` state and displayed in the InfoPanel.
|
||||
|
||||
## Dynamic Model Selector
|
||||
|
||||
Available models are fetched from `GET /models` on mount via the `useModels` hook.
|
||||
The hook initialises with `FALLBACK_MODELS` from `constants.js` and replaces them
|
||||
with the server response on success. If the fetch fails, the fallback list is used
|
||||
silently — a warning is logged to the console.
|
||||
|
||||
To add a model, update `models.json` on the main PC — no client rebuild needed.
|
||||
|
||||
`FALLBACK_MODELS` in `constants.js` should be kept in sync with `models.json`
|
||||
as a reasonable last-resort list in case the endpoint is unreachable.
|
||||
`useChat` accepts an optional `projectId` parameter in `sendMessage`. After
|
||||
the first message completes in a new session, if `projectId` is set,
|
||||
`updateSession` is called to write the project assignment to the backend.
|
||||
|
||||
## Session Management
|
||||
|
||||
Sessions are identified by `external_id` — a UUID generated client-side via the
|
||||
`uuid` package. New sessions are created locally and auto-registered in the memory
|
||||
service on the first message. The session list refreshes after each completed
|
||||
response to surface newly created sessions.
|
||||
Sessions are identified by `external_id` — a UUID generated client-side via
|
||||
the `uuid` package. New sessions are created locally and auto-registered in
|
||||
the memory service on the first message. The session list refreshes after
|
||||
each completed response to surface newly created sessions.
|
||||
|
||||
### Session Name Display
|
||||
### Auto-naming
|
||||
|
||||
The chat header and session rows both display `session.name` if set, falling back
|
||||
to `session.external_id` if no name has been assigned:
|
||||
After the first exchange completes, orchestration fires a secondary inference
|
||||
call with a short naming prompt (max 20 tokens, temperature 0.3). The result
|
||||
is written back as `session.name`. The client fires a second `refreshSessions`
|
||||
after a 3-second delay to pick up the name once written.
|
||||
|
||||
```js
|
||||
activeSession.name || activeSession.external_id
|
||||
```
|
||||
Manually renamed sessions are never overwritten — the `!session.name` guard
|
||||
in `chat/index.js` prevents this.
|
||||
|
||||
### Session Actions
|
||||
|
||||
Session rows in the sidebar support rename and delete via two entry points:
|
||||
Session rows support rename, project assignment, and delete via:
|
||||
- **Hover** — reveals ✎ and ✕ icon buttons alongside the row
|
||||
- **Right-click** — context menu with the same actions
|
||||
|
||||
- **Hover** — reveals ✎ (rename) and ✕ (delete) icon buttons alongside the row
|
||||
- **Right-click** — opens a context menu with the same actions
|
||||
|
||||
Both trigger `SessionModal` — a shared modal component with two modes:
|
||||
|
||||
| Mode | Trigger | Behaviour |
|
||||
|---|---|---|
|
||||
| `settings` | Rename button / context menu rename | Shows name input, saves on Enter or Save button |
|
||||
| `confirm-delete` | Delete button / context menu delete | Shows confirmation dialog, requires explicit Delete click |
|
||||
|
||||
Actions are disabled on unsaved (new) sessions that haven't had a first message sent yet.
|
||||
`SessionModal` handles rename and project assignment together in `settings`
|
||||
mode, and delete confirmation in `confirm-delete` mode.
|
||||
|
||||
### Active Session Clearing on Delete
|
||||
|
||||
When the deleted session is the currently active one, `App.jsx` detects the match
|
||||
and calls `selectSession(null)` to clear the chat window before refreshing the list:
|
||||
When the deleted session is the currently active one, `App.jsx` clears the
|
||||
chat window before refreshing the list:
|
||||
|
||||
```js
|
||||
function handleSessionsChange(deletedSession) {
|
||||
@@ -276,53 +242,23 @@ function handleSessionsChange(deletedSession) {
|
||||
}
|
||||
```
|
||||
|
||||
### Context Menu
|
||||
### Key Patterns
|
||||
|
||||
Implemented via `useContextMenu` hook — tracks `{ x, y, session }` state and
|
||||
attaches a `window` click listener to dismiss on any outside click. Rendered
|
||||
outside the sidebar div via a React fragment to avoid being clipped by
|
||||
`overflow: hidden`.
|
||||
|
||||
### Button Nesting
|
||||
|
||||
Session row action icons (✎ ✕) are rendered as siblings of the session
|
||||
`<button>`, not children — HTML does not allow `<button>` inside `<button>`.
|
||||
The outer `<div>` owns hover state and context menu; the inner `<button>` handles
|
||||
session selection; action icon buttons sit alongside it in the same flex row.
|
||||
- Button nesting: action icons are siblings of row buttons, not children — HTML forbids `<button>` inside `<button>`
|
||||
- Context menu rendered outside sidebar via React fragment to avoid `overflow: hidden` clipping
|
||||
- `useContextMenu` dismisses on a `window` click listener
|
||||
- Dynamic `updateSession` SQL builds `SET` clause from only the fields passed — prevents accidental overwrites
|
||||
|
||||
## Project Management
|
||||
|
||||
Projects are a first-class concept in the UI. The `useProjects` hook fetches
|
||||
the project list from `GET /projects` on mount and exposes a `refreshProjects`
|
||||
callback for keeping the sidebar in sync after mutations.
|
||||
`useProjects` fetches the project list from `GET /projects` on mount and
|
||||
exposes `refreshProjects` for keeping the sidebar in sync after mutations.
|
||||
|
||||
### Project Actions
|
||||
`ProjectModal` handles create, edit, and delete confirmation. Fields: name
|
||||
(required), description (optional), colour picker, isolated toggle.
|
||||
|
||||
Projects are managed from `AllProjectsView` via `ProjectModal`:
|
||||
`ProjectView` shows the project's name, description, isolated badge (if set),
|
||||
and a filtered session list. The "+ New Chat" button creates a new session,
|
||||
navigates to `'chat'`, and writes the project assignment after the first message.
|
||||
|
||||
| Mode | Behaviour |
|
||||
|---|---|
|
||||
| `create` | Name (required), description (optional), colour picker |
|
||||
| `edit` | Same fields as create, pre-populated |
|
||||
| `confirm-delete` | Confirmation dialog — sessions in the project are not deleted |
|
||||
|
||||
The sidebar Projects section shows up to 6 project tiles as coloured badge buttons.
|
||||
Clicking any tile navigates to `AllProjectsView`. The "All Projects →" link is
|
||||
always shown below the tiles.
|
||||
|
||||
After any create, edit, or delete in `AllProjectsView`, `onProjectsChange` is called
|
||||
to trigger `refreshProjects` in `App.jsx`, keeping the sidebar tiles in sync.
|
||||
|
||||
## View Routing
|
||||
|
||||
`App.jsx` manages a `view` state string that controls which main panel renders:
|
||||
|
||||
| View | Component | Trigger |
|
||||
|---|---|---|
|
||||
| `'chat'` | `ChatWindow` | Default; selecting a session from sidebar or AllChatsView |
|
||||
| `'all-chats'` | `AllChatsView` | "All Chats →" link or ☰ icon in collapsed rail |
|
||||
| `'all-projects'` | `AllProjectsView` | "All Projects →" link, ⊞ icon, or New Project button |
|
||||
| `'settings'` | `SettingsView` | Settings button or ⚙ icon in collapsed rail |
|
||||
|
||||
`AllChatsView` navigates back to `'chat'` on session row click, passing the selected
|
||||
session to `selectSession` so history loads immediately.
|
||||
For memory isolation behaviour, see `memory-isolation.md`.
|
||||
Reference in New Issue
Block a user