Hide non-invocable member agents from @-mention autocomplete#1611
Conversation
Agents you can't invoke (e.g. Fizz, owned by another team) still appeared in the composer's @-mention list when they were added to the channel as members. The existing invocability filter in useMentions only applied to non-member agents, so member agents bypassed it entirely. Extract the decision into a pure helper, shouldHideAgentFromMentions, and apply it to all agent candidates. Option B semantics: hide a member agent only when we have an explicit not-invocable signal — a relay directory (kind:10100) entry that excludes the current user. When invocability is unknown (agent not yet in the directory / still loading), keep showing it so we never hide an agent we can't confirm is non-invocable. This mirrors the backend gate (author_allowed in buzz-acp), so the autocomplete stays consistent with server-side enforcement. Adds unit tests covering every branch, including the two Option B cases and npub/hex pubkey normalization.
wpfleger96
left a comment
There was a problem hiding this comment.
Reviewed and re-verified at source (ran the tests + typecheck myself). Clean, minimal, well-scoped fix.
The extraction of shouldHideAgentFromMentions into a pure helper is the right move, and the branch ordering reads clearly: non-agent → show, invocable → show, non-member non-invocable → hide (preserves prior behavior), member → hide only on an explicit not-invocable directory signal. The "only hide when we can confirm non-invocable" stance on the last row is the correct conservative default — a member agent whose directory profile is still loading stays visible rather than flickering out.
Provenance is consistent: directoryAgentPubkeys and mentionableAgentPubkeys are both derived from relayAgentsQuery.data, so "in the directory but not mentionable" is a real explicit-exclusion signal, not an artifact of two unsynced sources. I also checked the other !candidate.isMember use (extractMentionPubkeys, useMentions.ts:830) — it iterates mentionCandidates, which is already filtered by this helper upstream, so a hidden member agent can't be re-extracted from text there. No missed filter path.
Verified locally: node --test on the eligibility suite → 17/17 pass; tsc --noEmit → clean. One optional note inline; nothing blocking.
…e coupling Address review feedback on block#1611: add a comment on the member branch of shouldHideAgentFromMentions noting it treats directory presence (without mentionability) as an explicit not-invocable signal, which is only sound because both sets derive from the same relayAgentsQuery.data. Flags the premature-hide risk if a future change sources the directory set elsewhere.
Problem
Agents you can't invoke — e.g.
Fizz, owned by another team — still show up in the composer's@-mention autocomplete when they've been added to a channel as members.The autocomplete already has an invocability filter (
useMentions.ts), but it only applied to agents that aren't channel members:Fizz is added to the channel as a member by its owning team, so
!candidate.isMemberis false, the check is skipped, and Fizz always appears — even though the backend (author_allowedinbuzz-acp) would reject a mention of it.Fix
Extract the show/hide decision into a pure, tested helper
shouldHideAgentFromMentions(...)and apply it to all agent candidates, member or not. The "can I invoke this agent" set (getMentionableAgentPubkeys) is unchanged and continues to mirror the backend gate.Semantics (member agents are the new case):
mentionableAgentPubkeys)The last row is deliberate: we only hide a member agent when we have an explicit not-invocable signal (a directory entry that excludes the current user). If the agent's directory profile is missing or still loading, invocability is unknown and we keep showing it — we never hide an agent we can't confirm is non-invocable.
useMentionsbuilds adirectoryAgentPubkeysset fromrelayAgentsQuery.datato supply that signal.Tests
Adds unit tests in
agentAutocompleteEligibility.test.mjscovering every branch, including both member cases (Fizz hidden; unknown-invocability shown) and npub/hex pubkey normalization.node --test→ 17/17 passbiome check(3 changed files) → cleantsc --noEmit→ 0 errors