fix(agents): make agents mentionable by non-owners (desktop eligibility gate + kind:10100 directory) - #4713
Open
dexsynccom wants to merge 2 commits into
Open
fix(agents): make agents mentionable by non-owners (desktop eligibility gate + kind:10100 directory)#4713dexsynccom wants to merge 2 commits into
dexsynccom wants to merge 2 commits into
Conversation
isAgentIdentityInManagedList (block#2149) dropped every agent-flagged mention candidate not present in the local managed-agents list. Only the agent's owner has it there, so for everyone else the candidate vanished from both the autocomplete picker and the send-time p-tag extraction: typed @mentions went out as plain text, the harness's require_mention #p subscription never matched, and the agent silently ignored the message. Members could reach agents from mobile (which has no such gate) but not from desktop. Scope the gate to what block#2149 actually wanted to hide — stale incarnations of the current user's own agents — by comparing the candidate's verified NIP-OA ownerPubkey with the current user. Foreign- or unknown-owned agents now fall through to shouldHideAgentFromMentions, whose member/directory policy applies again: member agents with unknown invocability are shown; non-member, non-invocable agents stay hidden. Moving formatSearchUserDisplayName, formatSearchUserSecondaryLabel and appendUniqueName into mentionCandidates.ts keeps useMentions.ts under the 1000-line ratchet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: dexsynccom <rifai@dexsync.com>
Clients already consume kind:10100 for mention eligibility (desktop list_relay_agents, mobile agentDirectoryProvider) and the relay ingests it with a users-table side effect, but nothing ever published it — so an agent's respond_to/allowlist policy and channel set were invisible to other users' clients, and respond_to=anyone had no effect on who could see the agent in mention autocomplete. Publish the profile at the presence-online readiness boundary and republish whenever a membership notification changes the subscribed channel set. Content carries the cross-client contract fields: respond_to, respond_to_allowlist, channel_ids, channel_add_policy. Discovery metadata only — the author gate (author_allowed) remains the enforcement point. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: dexsynccom <rifai@dexsync.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On a multi-user deployment, only an agent's creator could interact with it from the desktop app. Other channel members typed
@Agent …and got silence — the message posted normally, the relay accepted it, and the agent stayed healthy and kept answering its owner. The same members could reach the agent from the mobile app.Root cause
Desktop mention
ptags are only produced for identities present in the composer'smentionCandidateslist — both the autocomplete picker and the send-time text matcher (extractMentionPubkeys) draw from it.isAgentIdentityInManagedList(#2149) drops every agent-flagged candidate not present in the local managed-agents list, and only the owner's machine has the agent there. Every feed into the candidate list flags such an agent (role == "bot"from kind:39002 membership; client-side NIP-OA owner verification on kind:0 for profile and search rows), so for non-owners the candidate is dropped on every path. Typing@Agentstays plain text, the event carries noptag — and since the harness's Mentions mode subscribes with#p=[agent]in its REQ, the relay never even delivers the message to the agent. Nothing errors anywhere; mobile was unaffected because its member candidates have no such gate.Compounding it, nothing anywhere published kind:10100 agent-directory profiles, so the respond_to-aware eligibility both clients already implement (
relayAgentIsSharedWithUser/ mobileagentIsSharedWithUser) had no data —respond_to=anyonewas invisible to other users' clients.Changes
fix(desktop): let non-owners @-mention channel-member agents
isAgentIdentityInManagedListto agents owned by the current user (compared via the verified NIP-OAownerPubkey), preserving fix(desktop): prefer live agent mentions #2149's stale-incarnation dedupe while letting foreign/unknown-owned agents fall through toshouldHideAgentFromMentions— whose member/directory policy applies again (member agents with unknown invocability are shown; non-member, non-invocable agents stay hidden).currentPubkeyat both call sites (useMentions,MembersSidebaradd-member search).useMentions.tsintomentionCandidates.tsto stay under the 1000-line file ratchet.feat(acp): publish kind:10100 agent directory profile
publish_agent_profilepublishes/refreshes the replaceable kind:10100 at the presence-online readiness boundary and republishes when membership notifications change the subscribed channel set.respond_to,respond_to_allowlist,channel_ids,channel_add_policy— already parsed by desktopagents_from_events, mobileAgentDirectoryEntry.fromEvent, and required by the relay's ingest side effect.author_allowed) remains the enforcement point.respond_tostrings clients compare.Testing
just cigreen end-to-end (fmt, clippy, desktop check/build/unit tests, Tauri fmt/check/tests, mobile analyze/tests).mentions.spec.ts: foreign-owned non-member agents still hidden; own profile-only agents still hidden).events/event_mentions) showed every non-owner message missing the agentptag while the owner's carried it, with the same user succeeding from mobile and failing from desktop.🤖 Generated with Claude Code