Skip to content

Hide non-invocable member agents from @-mention autocomplete#1611

Merged
tlongwell-block merged 2 commits into
block:mainfrom
atishpatel:fix/hide-noninvocable-member-agents-from-mentions
Jul 8, 2026
Merged

Hide non-invocable member agents from @-mention autocomplete#1611
tlongwell-block merged 2 commits into
block:mainfrom
atishpatel:fix/hide-noninvocable-member-agents-from-mentions

Conversation

@atishpatel

Copy link
Copy Markdown
Contributor

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:

if (candidate.isAgent && !candidate.isMember && !mentionableAgentPubkeys.has(pubkey)) return;

Fizz is added to the channel as a member by its owning team, so !candidate.isMember is false, the check is skipped, and Fizz always appears — even though the backend (author_allowed in buzz-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):

candidate result
not an agent show
invocable (in mentionableAgentPubkeys) show
non-member & not invocable hide (unchanged prior behavior)
member & not invocable & in relay directory (kind:10100) hide (this is Fizz)
member & not invocable & not in directory (unknown / still loading) show

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. useMentions builds a directoryAgentPubkeys set from relayAgentsQuery.data to supply that signal.

Tests

Adds unit tests in agentAutocompleteEligibility.test.mjs covering every branch, including both member cases (Fizz hidden; unknown-invocability shown) and npub/hex pubkey normalization.

  • node --test → 17/17 pass
  • biome check (3 changed files) → clean
  • tsc --noEmit → 0 errors

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 wpfleger96 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread desktop/src/features/agents/lib/agentAutocompleteEligibility.ts
…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.
@tlongwell-block tlongwell-block merged commit f929aa0 into block:main Jul 8, 2026
45 of 47 checks passed
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.

3 participants