# Web Dashboard

The Omnius daemon serves a zero-build, self-contained dashboard from the same
origin as the REST API. Start it with `omnius serve`, then open
`http://127.0.0.1:11435/`. The interface uses Omnius's compact NOCLIP-derived
style kit and shared responsive observability-card grids; the route registry in
`packages/cli/src/api/web-ui.ts` is the source of truth for pages and aliases.

## Routes

| Route | Alias | Operational surface |
| --- | --- | --- |
| `/chat` | `/` | Stateful conversations, full history, active plan/context, attachments, files, and steering check-ins |
| `/agent` | - | One-shot agent task contract, persona/profile, isolation controls, run history, and event stream |
| `/voice` | - | Voicechat, exact TTS model selection, model options, ASR setup/activation/test, transcript, and TTS test |
| `/generate` | - | Image/video/audio/music generation, AV analysis, store relocation, model inventory, and global gallery |
| `/projects` | - | Workspace discovery, registration, activation, rename, removal, and current-context inspection |
| `/dashboard` | `/jobs` | System/GPU/resource state, processes, scheduler, services, usage, and update state |
| `/activity` | - | Run, tool, engine, memory, and server-event observability |
| `/discover` | - | Capability-catalog start points, intent search, and exact discovery-entry expansion |
| `/settings` | `/config` | Models, endpoints, voice, runtime behavior, access, keys, appearance, and service configuration |

The browser router and daemon HTML allow-list consume the same route registry,
so a page cannot be added in only one layer without a route test failing.

## Workspace Scope

The active workspace is global daemon state and scopes project preferences,
browser chat organization, TUI session discovery, files, model/theme choices,
and agent forms. The clickable brand at the top of the sidebar opens a searchable
workspace dialog sourced from `GET /v1/projects`. Selecting an entry calls
`POST /v1/projects/switch`; **Manage workspaces** opens `/projects`.

Every normal TUI start registers its working directory. The Projects page can
also call `GET /v1/projects/scan`, explicitly register a root, rename it, make it
current, or unregister it. Per-project preferences are server-managed through
`/v1/projects/preferences`; the client cannot overwrite the preference schema
version or `updatedAt` fields.

## Chats, TUI Sessions, And Agent Runs

Chats and agent runs are intentionally different records:

- A chat is a multi-turn conversation backed by the canonical daemon chat
  store. It may have an active agent subprocess and a reactive partial reply.
- A TUI session is quality-filtered visual history imported from the selected
  workspace. Its public id has a `tui:` prefix.
- An agent run is a one-shot execution record and form snapshot shown on the
  Agent page; it is not inserted into the chat list.

The chat index calls `GET /v1/chat/sessions?root=<workspace>`. By default the
response combines persisted browser chats with importable TUI sessions. The
session-quality layer suppresses exit-only commands such as `/quit` and `/exit`,
manual-save placeholders, empty/noise-only transcripts, and duplicate normalized
TUI histories. Pass `include_tui=0` when an integration needs browser chats only.

Opening a chat calls `GET /v1/chat/sessions/{id}` and hydrates the complete
public message history, source transcript, token/timestamp metadata, and any
in-flight run. While a run is active, the page polls
`GET /v1/chat/sessions/{id}/status?since=<seq>` to restore unseen deltas rather
than rerunning the task. Summaries/titles and ghost-text follow-ups use the
dedicated summarize and suggest endpoints.

Search, pins, folders, folder open-state, and inline display renames are
workspace-scoped browser organization stored in local storage. They do not
rewrite the underlying daemon transcript. The current dashboard **del** and row
delete controls remove the browser-side organization entry only; a canonical
delete must use the admin-scoped `DELETE /v1/chat/sessions/{id}` endpoint. This
distinction prevents documentation from implying that hiding a row destroyed
server history.

During an active chat, typing can become a steering check-in. The raw user input
and its interpreted steering packet are persisted, rendered in the conversation,
and delivered to the runner at a turn boundary through `/v1/chat/check-in`.

## Agent Command Center

The Agent page keeps task definition and runtime observability together. It
contains the task contract, working directory/workspace synchronization,
persona/profile, model and endpoint selection, tool and sandbox controls,
isolation settings, run submission, captured output, and event history. Submit
with `POST /v1/run`, query `/v1/runs` or `/v1/runs/{id}`, read captured output at
`/v1/runs/{id}/output`, and abort with `DELETE /v1/runs/{id}`.

## Voice And ASR

The Voice page exposes the same control plane as the CLI and REST API:

1. Read `/v1/voice/state` and `/v1/voice/models`.
2. Switch an exact TTS model with `/v1/voice/models/switch`; starting or TTS
   synthesis warms the selected engine instead of silently falling back.
3. Read `/v1/asr/engines`, choose an engine/model, run managed setup when its
   runtime or weights are absent, activate it, then upload a real audio sample to
   `/v1/asr/test` with optional names/hotwords/context.
4. Start `/v1/voicechat/ws` for full-duplex browser mic → ASR → agent text → TTS
   audio. Transcript, partial/final state, agent text, synthesis boundaries, and
   errors remain visible in the page.

TTS choices include GLaDOS, Overwatch, the packaged
`luxtts:announcer-testchamber03` reference, and enabled Voicebox models. ASR is
selected independently and includes Whisper, managed `transcribe-cli`, the
currently gated Nemotron adapter, and pinned Microsoft VibeVoice ASR. VibeVoice
is a completed-file backend (up to 60 minutes, with speakers/timestamps/context),
not an incremental PCM backend. On CUDA Jetson/ARM64, managed setup inherits the
host CUDA Torch build and hardware readiness uses `tegrastats` plus Torch CUDA
device properties; it never replaces the host build with generic PyPI Torch.

## Generate And Media Store

Generate lists available model adapters, accepts image/video/audio/music jobs,
shows model and progress state, and reads the project-independent global gallery
under `~/.omnius/media`. It also exposes:

- AV analysis through `POST /v1/media/av/analyze`;
- store inspection/migration through `/v1/media/store` and `/v1/media/migrate`;
- store relocation with a dry-run or background job through
  `/v1/media/relocate`, with progress from `/v1/media/relocate/status`;
- raw media streaming through `/v1/media/file`.

Heavy runtimes and weights remain in the unified Omnius model store; they are
not copied into each workspace or shipped in the npm package.

## Dashboard, Activity, Discovery, And Settings

The Dashboard page combines resource metrics, GPU/VRAM placement, Ollama pool
state, process/run cards, scheduled work, user services, token usage, and update
progress. Activity consumes the SSE event stream and presents run/tool/memory/
engine state. Discover begins from `/v1/discovery/bootstrap`, searches the
machine catalog, and expands exact entries without requiring source inspection.
Settings groups model/endpoint, voice, runtime, access/key, appearance, and
service controls while preserving project scope.

## Verified Updates

The dashboard polls `/v1/system` every 10 seconds. When its semver-safe registry
check reports `latest_version`, the normally hidden update controls become exact
version buttons. Clicking one:

1. preflights the live daemon version;
2. sends `POST /v1/update` with that exact semver;
3. polls `GET /v1/update` every two seconds for the durable operation id, phase,
   live subprocess output, failure remediation, and verification evidence;
4. requires the installed package, resolved executable, restarted daemon,
   installed package hash, daemon boot hash, and target version to agree;
5. reconnects event/model/health views only after verification succeeds.

If the tray was running, the coordinator relaunches and verifies it. A failed or
timed-out update stays visibly failed and includes the update log path; it is not
reported as complete merely because an npm child exited.

## Authentication And Remote Access

Loopback is the default and the safest dashboard deployment. If REST bearer keys
are configured, the browser stores the selected key locally and sends it through
the same scope policy as external clients (`read` < `run` < `admin`). Remote
access should use a tunnel or an authenticated share URL; changing
`/v1/admin/access` is loopback-only even when the current policy is `any`.

Useful diagnostics:

```bash
curl -s http://127.0.0.1:11435/health
curl -s http://127.0.0.1:11435/version
curl -s http://127.0.0.1:11435/v1/routes
curl -s http://127.0.0.1:11435/v1/projects
curl -s http://127.0.0.1:11435/v1/update
```

For the complete supported API use the [REST reference](../reference/rest-api.md),
and for bearer-key behavior use the [authentication map](../reference/auth-map.md).
