githubnext/chopinPublic

Let's compose rich plans together

[Design] Replace the composer @ mention picker with assistant-ui mentions

enhancement
LA

## Problem

The chat composer's `@` picker (`apps/web/src/chat/mention-picker.tsx`, `mentions.ts`) is a hand-rolled listbox over a plain textarea: - It has no categories. - Mentions stay raw `@login` text, with no chips. - The `/research` trigger runs through separate code.

#150 shows the current experience confuses people: tagging Chopin hides the tagged user, and there's no feedback while the turn runs.

## Proposal

Replace the picker with [assistant-ui's mention system](https://www.assistant-ui.com/docs/guides/mentions): - `ComposerPrimitive.TriggerPopover` with a `TriggerAdapter` exposing categories: **People** (channel members and authors), **Chopin** (the Planner) and, possibly, **References**. - The pre-built [Composer Trigger Popover](https://www.assistant-ui.com/elements/composer-trigger-popover) and [Directive Text](https://www.assistant-ui.com/elements/directive-text) components, installed with the shadcn CLI the same way #306 installs AI Elements. - Possibly [slash commands](https://www.assistant-ui.com/docs/guides/slash-commands) on the same architecture for `/research`.

These constraints must hold: - **Protocol stays authoritative.** `@chopin` must still map to `Chat.Send.to = "planner"` (`packages/protocol/address.ts`), and the server's `instruction()` must still strip the mention. Use a custom `DirectiveFormatter` that serializes to `@login` / `@chopin`, not assistant-ui's default `:type[label]{name=id}`, unless the protocol is changed deliberately. - **Composer only.** Chopin's transcript, WebSocket and persistence stay as they are. assistant-ui would be bridged in through `ExternalStoreRuntime` for the composer only.

## Update: the standalone lane removes most of the risk

assistant-ui Elements ships a standalone [Mentions](https://www.assistant-ui.com/elements/composer-mentions) composer element (the registry item `elements-composer`, which depends only on `lucide-react` and the shared element surfaces). It filters with `useMentionMatches(value, people)` and inserts **plain `@name` text** with `applyMention`. That matches Chopin's existing `@login` / `@chopin` addressing exactly. The preferred path is therefore: - the standalone `ComposerMenu` / `ComposerPersonItem` over Chopin's existing textarea and send path; - no `@assistant-ui/react` runtime, no `ExternalStoreRuntime`, no directive formatter and no Lexical upgrade.

Inline chips stay out of scope unless they're wanted later. The spike below is only needed if standalone falls short.

## Risks (only if the runtime lane is needed)

1. **Runtime:** `ComposerPrimitive` needs an `AssistantRuntimeProvider`. Check that a composer-only `useExternalStoreRuntime` bridge works with Chopin's existing send path without taking over the transcript, and measure the dependency and bundle cost of `@assistant-ui/react` (zustand, zod, radix-ui, assistant-stream, assistant-cloud). 2. **Lexical version:** inline chips need `@assistant-ui/react-lexical`, which requires `lexical >=0.51` and a single Lexical version across the app. Chopin pins `lexical 0.48.0` through `@mdxeditor/editor 4.1.0`. Check whether MDXEditor and Lexical can move to >=0.51 without editor or collaboration regressions (`registry.test.ts`, the editor E2E tests). Textarea mode without chips would show raw directives, which is worse than today.

## Acceptance criteria

- [ ] The `@` picker uses assistant-ui's standalone Mentions element: people and Chopin (agent role) with keyboard navigation and filtering. It inserts plain `@login` / `@chopin` and sends the same wire payload as today (`to`, mention text). - [ ] No `@assistant-ui/react` runtime dependency. Components install with the shadcn CLI into the same generated directory #306 uses. - [ ] #150 behaviour is fixed: mentioning Chopin doesn't hide another tagged user. - [ ] Existing mention, destination-cue and reference-picker tests are kept or ported. `bun test`, `bun run types`, `bun run ci` and the composer E2E tests pass.

## Related

- #150: tagging Chopin hides the tagged user. - #161: composer redesign. - #306: assistant-ui Elements adoption, which sets up the shadcn `components.json` and the generated directory. - #307: run card on assistant-ui Elements.

Assistant-workflow: inline Assistant-duration: unmeasured Assistant-verification: code inspection passed: read mention-picker.tsx and mentions.ts, the assistant-ui mentions guide, and npm metadata for @assistant-ui/react 0.15.23 and @assistant-ui/react-lexical 0.2.15 (lexical >=0.51 peer) against Chopin's lexical 0.48.0

  1. lavaman131added label enhancementlast month on GitHub

  2. lavaman131assigned lavaman131last month on GitHub

  3. lavaman131referenced this in [Design] Rebuild the workflow run card with assistant-ui Elements #307last month on GitHub

  4. LA
    Author

    Closing to avoid overlapping the in-flight design work: Maggie owns the chat, composer, decisions and research UI (#296, #278, #294, #285, #302, the [Design] issues #160-#164) and Krzysztof owns the research offers (#304). Any UI library choice belongs in that track.

    Assistant-workflow: inline

  5. lavaman131closedlast month on GitHub

  6. lavaman131renamed Replace the composer @ mention picker with assistant-ui mentions to [Design] Replace the composer @ mention picker with assistant-ui mentionslast month on GitHub