update documentation

This commit is contained in:
Storme-bit
2026-04-17 03:46:17 -07:00
parent 27e3c98304
commit 5145b9a7db
13 changed files with 822 additions and 794 deletions

View File

@@ -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`.