Skip to content

feat: quick-add agent popover with two entry points#626

Draft
tellaho wants to merge 3 commits into
mainfrom
tho/quick-add-agent-popover
Draft

feat: quick-add agent popover with two entry points#626
tellaho wants to merge 3 commits into
mainfrom
tho/quick-add-agent-popover

Conversation

@tellaho
Copy link
Copy Markdown
Collaborator

@tellaho tellaho commented May 20, 2026

Summary

Replace the "click + → full dialog" flow with a lightweight quick-add popover that makes adding an agent to a channel a one-click action. The full dialog stays as an advanced escape hatch via "More options…".

What changed

New: QuickAddAgentPopover component

  • Lightweight Radix popover (dropdown-menu energy)
  • Shows agents sorted by state: running (not in channel) → running (already here, muted) → available personas
  • One-click to attach a running agent or spin up a persona
  • "More options…" at the bottom opens the existing AddChannelBotDialog
  • Arrow-key navigation via roving focus
  • Valid ARIA: role="listbox" scoped to item list only

Two trigger points, same popover

  • The + button in ChannelMembersBar now opens the popover (not the dialog directly)
  • New "Add agent" ghost button at the bottom of the sidebar's Bots section

Dialog ownership lifted

  • Single AddChannelBotDialog instance owned by ChannelScreen
  • Both trigger points share it via props — no duplicate dialog risk

Extracted utilities

  • sortProviders — shared "goose first" provider sort
  • safeBotName — defensive pickBotName wrapper with fallback chain

E2E tests updated

  • Tests now click through popover → "More options…" before asserting on the full dialog

Key decisions

  • Uses useBotRecents for smart ordering (recents float to top)
  • Running agents use useAttachManagedAgentToChannelMutation
  • Personas use useCreateChannelManagedAgentMutation (leverages existing reuse logic from PR fix: prevent agent proliferation when adding bots to channels #621)
  • Force-new-instance stays buried in the full dialog — not in the popover
  • Null channelId guard: popover renders children-only, handlers early-return
  • Discriminated union types enforce valid item states at compile time

tellaho added 3 commits May 19, 2026 22:01
Replace the direct + → full dialog flow with a lightweight Radix popover
that shows available agents sorted by state (running > configured > catalog).
One click to add. The full AddChannelBotDialog is still accessible via
'More options…' at the bottom of the popover.

Two trigger points:
- The existing + button in ChannelMembersBar now opens the popover
- A new 'Add agent' button at the bottom of the sidebar Bots section

The sidebar already had People/Bots section headers — the inline add
affordance lives at the bottom of the Bots section.

Actions:
- Running agent not in channel → useAttachManagedAgentToChannelMutation
- Persona without running agent → useCreateChannelManagedAgentMutation
  (leverages existing reuse logic from agentReuse.ts)

The popover uses useBotRecents for smart ordering and pickBotName for
instance naming. Force-new-instance stays buried in the full dialog.
Critical fixes:
1. Null channelId guard — popover renders children-only (no popover
   content) when channelId is null. Action handlers also early-return.
2. pickBotName fallback — safeBotName() wraps pickBotName with a
   defensive fallback to persona.displayName or 'Agent'.
3. E2E test updates — tests now click through the quick-add popover's
   'More options…' button before asserting on the full dialog.
4. Duplicate AddChannelBotDialog — removed the sidebar's own dialog
   instance. Dialog state is now lifted to ChannelScreen and passed
   down via props. Only one dialog instance exists (in ChannelMembersBar).

Medium fixes:
5. Discriminated union types — QuickAddAgentItem is now a proper
   tagged union (RunningAvailableItem | RunningInChannelItem | PersonaItem).
   No more optional agent?/persona? fields.
6. Extracted sortProviders utility — shared between ChannelMembersBar
   and any future consumer. Single source of truth for provider ordering.
7. Emerald colors kept — matches existing presence pattern (bg-emerald-500)
   used throughout the codebase. No design token exists for 'running' status.
8. Keyboard navigation — added arrow-key roving focus via onKeyDown handler
   on the popover container, targeting [data-quick-add-item] buttons.
9. Eager queries — channel members query already gated by popover open state.
   Other queries (agents, personas, providers) are globally cached by
   ChannelMembersBar which is always mounted — no extra network cost.
The 'More options…' button is not a listbox option, so the listbox
role belongs on the inner div that contains only the agent option items.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant