UI

Agency’s product UI is a schema-driven SPA: Django (and host apps) describe what the interface means; agency-ui (Vue 3 / Vite) decides how it renders.

Operators use the Agency desktop at / (after /login/). The desktop is an installable PWA: offline it waits for the server, and a backend restart reloads the shell. Staff admin sites remain under /admin/, /system/, /custom/. Mission Control is the Agents / Missions / Executions app on that desktop (Mission Control).

Three-repo split

Repo

Role

agency-ui

Vue source — schema types, renderer, desktop + Mission Control components

agency-django

Domain + REST + Channels; ships published static/agency/ui/

agency-server

Compose, nginx, collectstatic

Publish flow:

agency-ui  ──npm run build:django──►  agency-django/static/agency/ui/
                                            │
                                            ▼ collectstatic
                                     nginx  /static/ + Django  /

Do not hand-edit agency-django/.../static/agency/ui/.

Core principle

Django sends semantic nodes, never Vuetify tags:

{ "type": "progress", "props": { "value": 42, "label": "Indexing" } }

The renderer maps progress → a Vue/Vuetify component. Adding a screen means a new schema node type + registry entry, not a one-off Django template.

Component catalogue: Frontend components (agency-ui). Envelope and node contracts: UI Schema. Reactive event routing: Agency Bus. Bootstrap / observe from Python: Python: serving the SPA. Useful URLs: Sites.

User preferences & Desktop

Authenticated users have UserPreferences (workspace, UI, operator, system voice), exposed as GET/PATCH /api/me/prefs/ and injected in bootstrap as prefs.

  • UI — light/dark, language (en/es), IANA timezone. Change language in the user window; the page reloads. Timezone is used by get_datetime when a secretary run is bound.

  • RAG — active corpus workspace (Documentos / Buscar). Explorers have no workspace dropdown.

  • Preferences — active operator agent, system voice (grave OS lines and speaking on behalf of the user). Each Agent has its own Voice (TTS provider + key); agent chat / mission TTS uses that, falling back to the system voice.

  • Desktop snapshot — open windows, minimized / maximized flags, geometry x/y/w/h, chrome pose, projection (flat / perspective), and optional child props for ephemeral restore. Debounced PATCH after move / resize / open / close.

Window addresses

Stable ids for dedupe, the Windows drawer, and Desktop persistence:

  • Singleton (schema app): agents, documents, system, media, map, …

  • Instance: kind.ref — e.g. extraction.<uuid>, agent.<uuid>, user.me, execution.<uuid>.

Dot present ⇒ instance window. kind is a window kind (view), not always a Django model name. Helpers: agency-ui/src/desktop/windowAddress.ts and openAddress.ts. Legacy win-* ids normalize to this grammar.

Window manager (operator UX)

RuntimeShell drawer: profile header (48px avatar + name) then tabs Menu · Windows · Inbox. App bar (right): one System icon (channel / two PCs while idle; REST or telemetry glyph during recent activity — click opens System). Theme toggle only while windows are floating. On mobile, and when a desktop window is maximized, the active window’s minimize / close replace the theme button and the title moves into the app bar (Agency / {window}). Desktop maximized also shows restore. The app bar is always flat (no elevation). Mobile has no restore — minimize is the way back.

  • Profile — click avatar/name in drawer → user.me window (User · Options · Sites). Options is grouped UI / RAG / Preferences; Sites lists external admin/docs links.

  • Menu — open catalog / tool windows (Agents, Missions, System, …).

  • Windows — all open windows (desktop and mobile). Click to focus or restore; close button on each row. Badge shows open count.

  • Inbox — pending HITL questions (agent + text); click opens the reply dialog.

Internationalization

Shell strings use Django gettext (same catalogs as admin). build_bootstrap activates the user language and embeds locale + messages in #agency-bootstrap. Preference UserPreferences.language (me/prefs/); changing language in the user window PATCHes prefs and reloads the page. Catalog source: agency.ui.i18n; Spanish: agency/locale/es/LC_MESSAGES/django.po. Vue keeps agency-ui/src/i18n/*.ts only as a Vite dev fallback when bootstrap has no messages.

Desktop: floating windows over the wallpaper; icons that are not in the drawer Menu (active-agent face, Chat, Tests). Catalog apps open from Menu. Mobile (and desktop maximize): one full-screen window at a time (same store, no floating chrome); title and min/close live in the app bar. Desktop maximize also exposes restore so the window returns to floating geometry; the app bar drops its shadow while that chrome is up.

Window controls: floating title bar has minimize / maximize / close. Mosaic lives in the drawer tools row. Maximize uses the same chrome as mobile. Wheel over maximize scales the window’s CSS 3D pose.scale 5% about the cursor (persisted). Mosaic tiles every open window — 2D shelf / 3D carousel included — in a CCTV grid (2 = split, 4 = 2×2, 5 = 1+4, up to 16); the active window takes the featured pane. Minimize from that chrome returns to the desktop (or the next window). Restore from the app bar (desktop only) does the same without hiding the window. Double-click the floating title bar toggles maximize unless noFull / noMax is set.

Staff can inspect or reset a user’s Desktop snapshot from Django admin User preferences (/admin/ and /system/).

Desktop vs Mission Control

/ is the Agency desktop (icons, windows, drawer). Other apps on the same shell: Help, Camera, Documents, Displays, Photos, Media, Map, System, …

Mission Control (Menu → Dispatch) is only Agents, Missions, Executions, and the APIs that drive them. Flows: Mission Control. Execution lifecycle: Execution Runtime. WebSockets: Connections.

Development & publish

Task

Where

Edit Vue source

agency-ui

Publish dist

npm run build:django or umbrella ./dev ui (Workspace)

Commit dist

agency-django/src/agency/static/agency/ui/

Collect static

agency-server — collectstatic in Docker

See DEVELOPMENT.md in each repo. Node ≥ 20.19 for Vite 8.