Menu
popagent
publicLatest change aae5334a8232931db2dad7a987306d228e7e8de6 - Add live task Kanban board 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 shows repository cards with chat counts, active task counts, and recent activity. 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. - **Tasks** selects a repository workspace before creating background prompts or recurring schedules. A live agile board is the primary task surface: queued, in-progress/cancelling, attention-required (failed, cancelled, or dead-letter), and done lanes retain the server's explicit execution states without inventing a review or artifact-readiness state. Cards show the latest agent activity, bounded step progress, attempts, retries, recovery, errors, source lineage, timestamps, and collapsible request/output evidence. The board refreshes every two seconds while visible; mobile uses horizontal snap lanes instead of compressing four columns. The schedule 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. Task and schedule rows display their explicit `source` lineage. Self-update schedules are managed in Autonomy and cannot be paused or deleted from Tasks; user-created schedules retain those controls. Schedule rows show a human-readable recurrence and local next-run timestamp. - 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).