This repository was archived by the owner on Apr 14, 2026. It is now read-only.
feat: persona picker with @ mention support#24
Merged
wesbillman merged 8 commits intomainfrom Mar 31, 2026
Merged
Conversation
Replace the provider-first model with a persona-first interaction pattern. Users now pick a Persona (with its own system prompt, default provider, and model) from a dropdown in both the home screen and chat input. Typing @ in the chat textarea opens an autocomplete to mention any persona inline, switching context for that message. Provider selection is still available as a secondary override. New components: - PersonaPicker: dropdown grouped by built-in / custom personas - MentionAutocomplete: floating autocomplete triggered by @ in textarea - ChatInputToolbar: extracted bottom bar to keep ChatInput under 500 lines - useMentionDetection: hook for detecting @ mention state in text input Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ion UX - Pass persona system_prompt from frontend through Tauri to AcpService - Prepend persona instructions to user prompt in <persona-instructions> tags - Add keyboard navigation (arrow keys, Enter/Tab) to @ mention autocomplete - Fix PersonaPicker description extraction (was using index [1] instead of [0]) - Simplify ChatView handleSend by letting useChat handle system prompt injection Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…otifications, and per-message persona tracking Adds @ mention autocomplete to the HomeScreen input so users can invoke personas before starting a chat. Shows system notifications when switching personas mid-chat, and tracks which persona generated each assistant message in the timeline. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Store the selected persona per session in ui_state.json alongside the existing tab state. When switching tabs or reopening the app, the previously selected persona is restored for each chat session. Changes: - Backend: add persona_per_session HashMap to UiState with serde(default) for backward compatibility - chatSessionStore: add personaId to ChatSession, save/restore persona mapping in persistTabState/loadTabState - ChatView: save persona changes to session store - AppShell: pass session's stored personaId to ChatView, store personaId when creating new sessions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Error state stuck: acpSendMessage errors now reset chatState to "idle" so the user can continue sending messages after failures. 2. Stop button cancels backend: stopGeneration now calls acp_cancel_session to terminate the Rust ACP session, preventing orphaned streaming events after the UI resets. 3. @ mention persona race condition: when switching personas via @ mention, the message send is deferred to the next render cycle so useChat picks up the new persona's system prompt instead of the stale one. 4. Deleted persona fallback: if a persisted personaId references a deleted persona, ChatView now falls back to builtin-goose (or the first available persona) and updates the session store. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Personas were only loaded when visiting the Personas page (via the usePersonas hook in AgentsView). This meant the persona picker in HomeScreen and ChatInput showed empty until the user navigated to the Personas page at least once. Now AppShell loads personas from the backend in its startup effect, alongside sessions and tab state. This ensures personas are available immediately in all views. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Update ChatInput tests for new toolbar structure and persona props - Update HomeScreen tests to mock persona store instead of ACP providers - Add #[allow(clippy::too_many_arguments)] on send_prompt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7a230d0 to
e48dfc6
Compare
tellaho
added a commit
that referenced
this pull request
Apr 8, 2026
…onts' model Upstream block/ghost PRs #23 and #24 removed all HK Grotesk @font-face declarations and switched to a 'consumers bring their own fonts' model. Align our branch with this change: - Replace --font-sans and --font-display with system font stack - Remove all 7 @font-face declarations (300–900 weights) - Delete 7 HKGrotesk-*.woff2 font files from src/assets/fonts/ The system font stack (system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif) matches upstream Ghost's new defaults. 318/318 tests passing. Biome clean.
tellaho
added a commit
that referenced
this pull request
Apr 8, 2026
Remove migration-specific context from globals.css comments that wouldn't make sense to future consumers of the design system: - Remove '(upstream Ghost PRs #23/#24)' from font comment - Replace redundant font narration with '@font-face — add your own here' - Remove '(from dsgn-playground)' from gray scale comment Comments should help the next person, not document our migration.
tellaho
added a commit
that referenced
this pull request
Apr 8, 2026
…onts' model Upstream block/ghost PRs #23 and #24 removed all HK Grotesk @font-face declarations and switched to a 'consumers bring their own fonts' model. Align our branch with this change: - Replace --font-sans and --font-display with system font stack - Remove all 7 @font-face declarations (300–900 weights) - Delete 7 HKGrotesk-*.woff2 font files from src/assets/fonts/ The system font stack (system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif) matches upstream Ghost's new defaults. 318/318 tests passing. Biome clean.
tellaho
added a commit
that referenced
this pull request
Apr 8, 2026
Remove migration-specific context from globals.css comments that wouldn't make sense to future consumers of the design system: - Remove '(upstream Ghost PRs #23/#24)' from font comment - Replace redundant font narration with '@font-face — add your own here' - Remove '(from dsgn-playground)' from gray scale comment Comments should help the next person, not document our migration.
tellaho
added a commit
that referenced
this pull request
Apr 9, 2026
* feat: migrate from boss-ui to Ghost UI foundation Swap the design system foundation from boss-ui to Ghost UI, the open-source successor design language from block/ghost. Font swap: - Remove Cash Sans (CDN) and Cash Sans Wide (local) font faces - Add HK Grotesk (local woff2, 7 weights: 300–900) - Update --font-sans, --font-display to "HK Grotesk" - Update --font-mono to "Geist Mono" CSS tokens (globals.css): - Adopt Ghost's main.css as the token source of truth - Add hero-blur-in, fadeToFull, fadeToSubtle keyframes from Ghost - Add scrollbar hover styles from Ghost - Preserve all goose2-specific tokens: --color-brand, --density-spacing, --text-subtle, --radius-overlay, compat color scales for ai-elements - Preserve goose2 custom utilities: density spacing, page transitions, content-fade-in, prefers-reduced-motion, keyboard-nav focus, app shell lock UI primitives (47 of 49 files): - Copy Ghost UI components with import path adjustment (@/lib/utils → @/shared/lib/cn) and "use client" removal - Preserve goose2's button.tsx (leftIcon/rightIcon, forwardRef, ghost-light/toolbar variants, xs/icon-lg sizes, compound variants) - Preserve goose2's tabs.tsx (CVA variants: default, buttons) - Restore dialog.tsx showCloseButton prop (used by ImageLightbox) - Fix sonner.tsx useTheme import to @/shared/theme/ThemeProvider Not included (PR 2): - ai-elements migration (48 files, separate scope) * fix: add type="button" to SidebarRail per AGENTS.md Ghost upstream omits type="button" on the SidebarRail <button>. Goose2 requires it on all button elements to prevent accidental form submission (AGENTS.md coding conventions). PR review feedback from Marge. * fix: restore 20px radius on popup surfaces (dropdown → overlay parity) * fix: remove HK Grotesk font — align with upstream Ghost 'no bundled fonts' model Upstream block/ghost PRs #23 and #24 removed all HK Grotesk @font-face declarations and switched to a 'consumers bring their own fonts' model. Align our branch with this change: - Replace --font-sans and --font-display with system font stack - Remove all 7 @font-face declarations (300–900 weights) - Delete 7 HKGrotesk-*.woff2 font files from src/assets/fonts/ The system font stack (system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif) matches upstream Ghost's new defaults. 318/318 tests passing. Biome clean. * fix: restore rounded-overlay class on overlay surfaces The migration commit incorrectly replaced rounded-overlay with rounded-dropdown on all popup/overlay components. Both tokens resolve to 20px currently, but rounded-overlay is the correct semantic token for overlay surfaces (popovers, hover cards, context menus, selects, dropdown menus, menubars). Restores 9 occurrences across 6 shared UI components. * fix: strip internal references from CSS comments Remove migration-specific context from globals.css comments that wouldn't make sense to future consumers of the design system: - Remove '(upstream Ghost PRs #23/#24)' from font comment - Replace redundant font narration with '@font-face — add your own here' - Remove '(from dsgn-playground)' from gray scale comment Comments should help the next person, not document our migration. * feat: point components.json at ghost-ui registry + add ghost.config.ts Step 2: Update components.json to consume from ghost-ui registry: - style: new-york → ghost - baseColor: zinc → neutral - Add registryUrl pointing to block.github.io/ghost/registry.json - Add iconLibrary: lucide Future `npx shadcn add <component>` commands will now pull ghost-styled components from the upstream registry. Step 3: Add ghost.config.ts for drift detection: - Points at ghost-ui registry for goose2's shared UI components - Enables value + structure scanning - Configures rules: hardcoded-color (error), token-override (warn), missing-token (warn), structural-divergence (error) Run `ghost scan` to detect drift from the parent design system. * fix: use raw GitHub URL for ghost-ui registry The GitHub Pages deploy doesn't include registry.json in dist/ — it only serves the Vite SPA. The raw.githubusercontent.com URL points directly at the source file and resolves correctly. Long-term: ghost repo should copy registry.json to public/ so it's served at block.github.io/ghost/registry.json. * chore: add TODO to switch registry URL once block/ghost#25 lands The raw.githubusercontent.com URL is a workaround for registry.json not being served on GitHub Pages. PR block/ghost#25 fixes the deploy workflow. Once merged and deployed, both ghost.config.ts and components.json should switch to: https://block.github.io/ghost/registry.json * fix: use canonical Pages URL for ghost-ui registry The registry was already being served at /ghost/r/registry.json via shadcn build output in public/r/. Switch both components.json and ghost.config.ts from the raw.githubusercontent.com workaround to the proper GitHub Pages URL. Removes the TODO tracking block/ghost#25 — that PR is still useful for serving at the root path, but no longer blocking us. * chore: revert formatting-only changes (import/export reordering) Reverts Biome auto-sort import reordering and export alphabetizing across 39 shared/ui component files. These were formatting-only changes that added noise to the ghost-ui migration PR without any functional impact. 9 files fully reverted (pure formatting noise): - collapsible, hover-card, popover, tooltip, table, label, separator, progress, avatar 30 files surgically cleaned (import/export order restored, real ghost-ui class changes preserved): - accordion, alert, alert-dialog, badge, breadcrumb, button-group, calendar, carousel, chart, checkbox, command, context-menu, dialog, dropdown-menu, form, input-group, input-otp, menubar, navigation-menu, pagination, radio-group, resizable, scroll-area, select, sheet, sidebar, slider, switch, toggle, toggle-group * chore: revert remaining export reordering (round 2) Missed 13 more files with alphabetized exports in the first pass. Restored original export order in: alert-dialog, card, carousel, command, context-menu, drawer, dropdown-menu, form, input-group, menubar, navigation-menu, pagination, sheet. card.tsx and drawer.tsx are now fully clean (zero diff vs main). * fix: restore rounded-full on InputGroup container Reverts ghost-ui registry's rounded-md back to rounded-full per design direction. The InputGroup container uses a fixed h-9 height, so pill radius renders correctly. Also restores rounded-[calc(var(--radius)-5px)] on the sm button variant for proper nested radius calculation. * chore: simplify ghost.config.ts — remove speculative scan/rules The scan and rules blocks were added speculatively without explicit design decisions. Strip down to just the registry pointer until we decide on lint rules.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@in the chat input to switch personas mid-conversation. Floating autocomplete with keyboard navigation (arrow keys, Enter, Escape).ui_state.jsonand restored across tab switches and app restarts.Changes
New components:
PersonaPicker— dropdown persona selector used in HomeScreen and ChatInputMentionAutocomplete— floating @ mention popup withuseMentionDetectionhookChatInputToolbar— extracted picker dropdowns from ChatInputModified:
ChatView— persona tracking, system prompt passing, deferred send on persona switchChatInput— persona indicator, @ mention integrationHomeScreen— persona picker replaces provider dropdownAppShell— persona ID in tab/session flow, eager persona loadinguseChat— system prompt parameter, error recovery, backend cancellationchatSessionStore— persona persistence in session metadataacp_send_message+ui_statesupport for system prompts and persona mapping16 files changed, ~1300 additions, ~400 deletions.
Test plan
Generated with Claude Code