Skip to content

fix(desktop): mention autocomplete drops every relay-directory agent before eligibility runs - #3292

Open
TNovs1 wants to merge 1 commit into
block:mainfrom
TNovs1:fix-desktop-relay-agent-mentions
Open

fix(desktop): mention autocomplete drops every relay-directory agent before eligibility runs#3292
TNovs1 wants to merge 1 commit into
block:mainfrom
TNovs1:fix-desktop-relay-agent-mentions

Conversation

@TNovs1

@TNovs1 TNovs1 commented Jul 28, 2026

Copy link
Copy Markdown

Problem

useMentions gates every autocomplete candidate through isAgentIdentityInManagedList against only the local managed-agent set. Any candidate flagged isAgent: true that is not managed by this desktop is dropped before shouldHideAgentFromMentions runs — so relayAgentIsSharedWithUser, the respond_to allowlist, and channel membership are never consulted for it. The entire relay-agent branch of agentAutocompleteEligibility is unreachable from the mention picker.

Net effect: an agent hosted anywhere other than the local desktop (registered in the relay agent directory via kind:10100, attested via NIP-OA, or both) can never be @-mentioned, even when its directory entry explicitly allowlists the current user.

Reproduction

  1. Register a server-hosted agent in the relay directory: kind:10100 with respond_to: "allowlist" including your pubkey.
  2. Add it to a channel you are in. It appears in the member list.
  3. Type @ — the agent is never offered.
  4. Delete its kind:10100 (NIP-09) — the identity is offered again, because with no directory entry it isn't flagged as an agent at all. Publishing the metadata the eligibility module wants to read is exactly what makes the agent invisible to it.

Fix

Gate the candidate loop on mergeKnownAgentPubkeys(managedAgentsQuery.data, relayAgentsQuery.data) — the same managed ∪ relay-directory union the app already treats as "known agents" elsewhere (useKnownAgentPubkeys). Identity decides who is known; the eligibility rules (shouldHideAgentFromMentionsrelayAgentIsSharedWithUser) keep deciding who is invocable — a directory agent whose entry excludes the viewer is still hidden, as before.

One line of behavior change plus a memoized union; no new API surface.

…ng every hosted agent

`isAgentIdentityInManagedList` is called with `managedAgentPubkeys` — agents this
installation runs locally. Any other agent arrives with isAgent=true and is
dropped there, BEFORE `shouldHideAgentFromMentions`, so `relayAgentIsSharedWithUser`,
the respond_to allowlist and channel membership are never consulted for it.

That makes an entire branch of the eligibility module unreachable: an agent hosted
elsewhere cannot be @-mentioned no matter what it publishes, even when it is a
member of the channel, is in the user's own respond_to allowlist, and appears in
the relay directory — and the relay-agent candidate loop a few lines below, which
exists to offer exactly those agents, can never produce a visible suggestion.

The trigger is ordinary NIP-OA attestation: the relay sets users.agent_owner_pubkey
(write-once), the members/profiles API returns is_agent, and the candidate is
flagged an agent. So attesting an agent — the thing that earns it the bot badge and
"managed by <org>" — is also what makes it unmentionable. Reproduced against a
hosted 8-agent fleet: all eight were channel members with the user in their
allowlist and complete kind:10100 profiles, and none could be @-mentioned; three
locally-managed agents in the same channel could.

Gate on managed ∪ relay directory instead, via the same `mergeKnownAgentPubkeys`
helper `useKnownAgentPubkeys` already uses app-wide, restoring the intended
layering: identity/ownership decides who is KNOWN, the eligibility rules decide
who is INVOCABLE. `shouldHideAgentFromMentions` still applies, so a directory
agent that excludes this user is still hidden.
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