Menu
popagent
publicLatest change baffb3c2ac834de138dc9ac86330273851896d24 - Move task board to root overview by AkurAI Build
# Chat UI Library: **assistant-ui** (`@assistant-ui/react` primitives). Docs: https://www.assistant-ui.com/ ## Architecture - `useChatRuntime` + `AssistantChatTransport` (`@assistant-ui/react-ai-sdk`) targets `/api/chat`; the selected model, persistent session ID, and repository workspace ID ride in the request. Backend history reconstruction and newest-message policy are defined in [AGENTS_AGENT.md](AGENTS_AGENT.md). - Composed from primitives (`ThreadPrimitive`, `MessagePrimitive`, `ComposerPrimitive`) with our own markup — not the styled `Thread` bundle. - Markdown: `MarkdownTextPrimitive` (`@assistant-ui/react-markdown`) + `remark-gfm`, styled under `.md-content` in `globals.css`. - Tool calls use `MessagePrimitive.Parts` `tools.Fallback`. The global display preference selects compact chips, expanded argument/result details, or timeline-accented cards; each card exposes its current execution status. - Styling: **Tailwind v4** at serve time (`bun-plugin-tailwind`, `bunfig.toml` `[serve.static]`). Semantic theme tokens in `globals.css` support Light, Dark, Dracula, Nord, Tokyo Night, Catppuccin, Gruvbox, and Solarized Light palettes; the Appearance setting persists the selection in browser local storage and initially follows the operating system. Icons come from `lucide-react`. - Shared server/UI wire shapes come from `src/api-types.ts`. Large independent surfaces are split into `ModelPicker.tsx`, `MemoryDrawer.tsx`, `WorkspaceOverview.tsx`, `DocumentationPage.tsx`, `AgentSettingsPage.tsx`, and `AutonomySettingsPanel.tsx`; `Chat.tsx` owns repository-workspace and session orchestration. - Native browser-history routing keeps major locations reloadable and shareable: `/` is the overview, `/workspaces/:workspaceId` is a repository workspace, `/workspaces/:workspaceId/docs/*` is its Markdown documentation workspace, `/chats/:sessionId` is a conversation, and `/settings/:section` is a settings section. Bun serves the application shell for browser routes while unmatched `/api/*` requests remain JSON 404 responses. - `src/ui/api.ts` provides `apiFetch`, attaching the optional localStorage API key and dispatching `popagent:unauthorized` on 401; all UI API calls use it. - Session saves include the current `revision`; a 409 conflict is retried once with the server session revision while retaining local messages. - Tool cards centrally mask arguments and results for retired plaintext secret tools as `[redacted]`. - Failure surfacing: transient errors show in the module-level toast host (`src/ui/toast.ts` + `<Toasts/>` in the Chat root); a failed initial session load renders a retry card instead of a blank screen; a 401 renders an access key gate that stores the key in `localStorage["popagent:api-key"]`. - Message actions use `ActionBarPrimitive`: copy on all messages, regenerate on assistant messages, and trace-linked thumbs up/down plus trace-ID copy when a traced assistant response is available. Actions appear on hover/focus and hide while running. Feedback is recorded once per rendered response through the protected observability API. - Accessibility: an `aria-live=polite` region announces run start/completion; `useFocusTrap` (`src/ui/use-focus-trap.ts`) traps Tab and restores prior focus in MemoryDrawer, AgentSettingsPage, WorkspaceDialog, DeleteDialog, credential edit/delete dialogs, and the ModelPicker popover. - The context meter renders nothing when the catalog has no context window for the selected model, rather than showing a zero denominator. ## Workspace layout Sidebar: branding, a master overview link, repository workspace switcher, one primary `Create new chat` control, title search, active/archived views, and the selected workspace's sessions ordered by activity. Each session can be renamed, archived/restored, or permanently deleted. Permanent deletion confirms that transcript and Mastra thread data are removed while independent long-term memories remain. Main header: a searchable, provider-grouped model picker fed by `GET /api/models`, long-term-memory control, and tool-display settings. Tool display mode (`compact`, `expanded`, or `timeline`) is global and persisted in browser local storage. Main: the default master overview is the operational root. It creates background tasks for a selected repository and renders the live agile task board before repository cards with chat counts, active task counts, and recent activity. The board groups queued, in-progress/cancelling, attention-required (failed, cancelled, or dead-letter), and done work without inventing review or artifact-readiness state. Cards show workspace, latest agent activity, bounded step progress, attempts, retries, recovery, errors, source lineage, timestamps, and collapsible request/output evidence. Root task state refreshes every two seconds; mobile uses horizontal snap lanes instead of compressing four columns. Each repository workspace landing page can permanently delete all of its active and archived chats through a focus-trapped confirmation modal; transcripts and Mastra threads are removed while independent long-term memories remain. The documentation workspace provides a Markdown page tree, editor, GFM preview, semantic search, and index status; its durable contracts live in [AGENTS_DOCUMENTATION.md](AGENTS_DOCUMENTATION.md). A chat view contains its thread viewport, empty-state suggestions, composer with send/stop toggle, thinking indicator, collapsible hook activity, and context-window meter. Specialist `data-agentActivity` parts render inline as live iteration cards beside the supervisor's final response. The meter uses provider `inputTokens` from `message.metadata.custom.usage`; its denominator comes from live 9Router context-window metadata. Desktop keeps session navigation visible. Mobile uses an isolated modal session drawer, a single-row workspace header, 44px touch targets, safe-area-aware composer spacing, and a horizontal settings-section bar above full-width settings content. Settings is a routed full-screen modal workspace reached from session navigation or a direct `/settings/:section` URL. It uses dialog semantics, focuses its close control on open, closes on Escape to the originating route, and restores focus to the opener: - **Agents** presents a compact selectable handoff sequence—Orchestrator → Researcher → Implementer → Reviewer—then edits each agent's PostgreSQL-backed display identity, delegation description, complete role instructions, workspace/browser access, delegation eligibility, and tool membership. Instructions are capped at 32,000 characters and link to their agency-agents source provenance. It also manages database-backed Agent Skills including instructions, references, source provenance, enablement, user invocation, creation, and deletion. Empty identity or instruction fields are rejected. - **Browser** provides a structured AgentBrowser overview plus persisted runtime; security and API boundaries are canonical in [AGENTS_BROWSER.md](AGENTS_BROWSER.md). It includes viewport, isolation, session/idle limits, screencast, recording, capability, host-policy, active-session, and encrypted Playwright storage-profile controls. It lists and closes live sessions and downloads/deletes retained recordings. Headless operation and read-only tool exclusions remain fixed server safety boundaries. - **Secrets** manages write-only credentials through the authenticated metadata-only API. Operators can create, rotate, bind, and delete a credential; values are never rendered or returned. Each usable credential requires one exact HTTPS origin. Create/edit and destructive confirmation use focus-trapped, theme-matched dialogs with explicit loading, empty, error, and busy states. - **Memory** explains Mastra's recent-message → observation → reflection model with an accessible, settings-aware connection graph and exposes persisted operating presets, token thresholds, retention, asynchronous buffering and safety controls, idle/provider-change activation, shared budgets, exact-history recall scope, temporal markers, attachment policy, Observer context optimization, and custom Observer/Reflector guidance. It links to the current Mastra Observational Memory documentation and previews the effective token intervals calculated from the persisted values. - **Runtime** edits the database-backed default model, supervisor/specialist execution limits, delegation bounds and feedback, and background-task concurrency/timing. Changes apply to new turns and tasks; active tasks retain the timeout captured when they started. - Browser, Secrets, Memory, Runtime, and Autonomy controls render only after their API values load; the client has no substitute settings defaults. - **Autonomy** configures persisted self-improvement and contained source self-update enablement, reflection cadence, batch and retry bounds, automatic strategy/skill application, and the internal self-update cron through `GET/PATCH /api/settings/autonomy`. Protected `GET /api/autonomy/signals` and `GET /api/autonomy/revisions` accept only a strict `limit` from 1–200; `POST /api/autonomy/revisions/:id/revert` rejects unknown or non-revertible revisions. While mounted, the section refreshes signal and revision history every two seconds and aborts its in-flight read on unmount; background failures retain the last rendered history without replacing the initial loading, empty, or error states. It shows pending/processing/applied/retried/dead-letter health, signal attempts and redacted errors, and applied or reverted learned overlay/skill contents. Compensating revisions display their explicit `revertsRevisionId` lineage. Reverting an applied revision requires a focus-trapped theme-matched confirmation; it never changes user-managed base instructions, capability membership, workspace/browser access, secrets, hooks, authentication, or execution bounds. - **Observability** follows [AGENTS_OBSERVABILITY.md](AGENTS_OBSERVABILITY.md) and shows last-24-hour run/error/token/latency KPIs, recent traces with expandable span timelines, and correlated warnings/errors. Reads use the server's bounded observability APIs and expose explicit loading, empty, and failure states. - **Schedules** selects a repository workspace before creating recurring work. The editor offers every day, weekdays, or every week; weekly schedules add a day selector, and every option uses a native time input. It does not expose a timezone because schedules use the server computer's configured timezone. Self-update schedules are managed in Autonomy and cannot be paused or deleted from Schedules; user-created schedules retain those controls. Schedule rows show explicit source lineage, a human-readable recurrence, and the local next-run timestamp. Live one-off tasks are intentionally absent from Settings and belong to the master overview. - When a Mastra browser becomes active for the current chat, an authenticated SSE screencast workspace slides in from the right. Desktop keeps transcript and browser side by side; mobile uses a focus-trapped full-screen dialog. The panel shows URL, tabs, access and stream state, remains view-only by default, and requires explicit interactive-session takeover before bounded pointer or keyboard events are accepted. Hiding the panel disables takeover. ## Decisions - No shadcn/ui — Tailwind + primitives cover current needs. - No AI Elements — overlaps with assistant-ui; one chat layer, not two. - Gotcha: `useThread` is not exported by this `@assistant-ui/react` version — use `ThreadPrimitive.If running` for run state and `useAuiState` for message metadata/state selectors. - Visual direction: Mastra Docs density and hierarchy interpreted as a macOS-forward liquid-glass workspace. Use near-black/soft-white neutral fields, restrained green status/accent color, translucent navigation and controls with real backdrop context, fine inner highlights, and compact workhorse typography. Glass is reserved for navigation, controls, overlays, the composer, and user messages; reading content remains visually quiet. - Session creation is single-flight (`src/ui/single-flight.ts`): rapid clicks share one pending `POST /api/sessions`, then creation becomes available again. Keep the primary creation and session-selection accessible names distinct; duplicate `New chat` names make automation and assistive navigation ambiguous. - Initial loading honors the current browser route; `/` opens the master workspace overview and never creates a chat implicitly. A chat is created only after the user selects a repository workspace and activates `New chat`. With no active model selection, creation omits the model so the server uses the current persisted default. - Active and archived lists are disjoint API views. Every session response includes `archivedAt` (`null` while active); verify both views after lifecycle or cleanup changes rather than inferring state from the visible list alone. - Initial session and workspace loading is independent of the live model catalog. If 9Router catalog discovery fails, existing sessions and the master overview still open; the model picker remains empty until a reload. ## Contract checks - UI helper contracts live beside their helpers. - UI verification follows the TDD, browser-lifecycle, console, network, and reporting gates in [AGENTS_RULES.md](AGENTS_RULES.md).