fix(desktop): make owner-only relay agents mentionable by their owner - #4839
fix(desktop): make owner-only relay agents mentionable by their owner#4839TheSeydiCharyyev wants to merge 1 commit into
Conversation
|
Related: our server-hosted agent is in the channel and has a directory card, but Desktop still hides it from @ unless we strip ownership. Please stop treating relay-directory agents as non-mentionable for the owner. +1 |
|
Confirmed, and this PR alone does not cover your case. Adding a second commit here: an owner-only relay agent counts as mentionable for its owner, taking ownership from the profile data this hook already reads. |
relayAgentIsSharedWithUser accepted only `anyone` and `allowlist`, so an owner-only agent was never invocable - not even for the one person it answers to. With a directory entry and channel membership, shouldHideAgentFromMentions then hid it as explicitly not-invocable, which is why dropping ownership worked around it. RelayAgent carries no owner field, so getMentionableAgentPubkeys now takes an owner lookup and useMentions supplies it from the profile metadata the hook already reads for candidate labels. Ownership is matched, never assumed: an unknown owner keeps the agent hidden. Raised on block#4839 by a third deployment hitting the same wall. Signed-off-by: Seydi Charyyev <seydi.charyev@gmail.com>
|
I filed #4776 and I run the same shape of setup: self-hosted relay, six communities on it, 23 agents as containers on my own VM, none of them spawned by the desktop. So this hits me directly and I'm glad someone picked it up. I've been running the equivalent of your part 1 as a local patch for about a week. Same conclusion — the candidate loop builds everything Part 2 is the interesting one for me, because I hit the symptom and never found the cause. All my agents run with On #4833's second half: that's what I ran into. I hand-wrote entries into Two things I can't speak to. I haven't built your branch, so this is a code read, not a test report. And I patch |
|
Same setup on my side: server agents, desktop as the client. Glad part 2 landed; that was the gap I was hitting. Thanks both. |
relayAgentIsSharedWithUser admits `anyone` and `allowlist`, so an owner-only agent fell through to false for everyone - including the one person it answers to. `owner-only` is also the server default, so a relay agent created without an explicit mode is invocable by nobody at all, while the agent settings label that mode "Only me (default)" and promise "Only you and your agents can send instructions". RelayAgent carries no owner field, so the owner comes from profile metadata. getMentionableAgentPubkeys now takes the profile lookup and resolves ownership through mergeOwnedAgentPubkeys, the helper the inbox already uses for the same question. Ownership is matched, never assumed: an agent whose owner cannot be resolved stays hidden, and a caller that passes no profiles keeps today's behaviour. The mention path never reads sharedChannelIds - it only ever asks for the channel or managed-only scope - so useMentions no longer builds or passes it. Reported in block#4776 and block#4833. Signed-off-by: Seydi Charyyev <seydi.charyev@gmail.com>
8378df2 to
94012de
Compare
|
Part 1 is gone from this PR. #4913 landed on 5 Aug and does the same thing, plus exact-channel authorization, fail-closed DMs, cached-row reauthorization and forum coverage. Your local patch and my first commit are both superseded by it. The branch is rebuilt on current On That surface is still not whole, though. It asks for the On the shape of the fix, one thing worth knowing before you read the diff: The keyring problem you described is a separate defect and deserves its own issue. You have the reproduction: hand-written |
What is broken
relayAgentIsSharedWithUserhandles two response modes:anyoneandallowlist. There is a third one.RespondToModeis"owner-only" | "allowlist" | "anyone", andowner-onlyfalls through tofalse. It isfalsefor every viewer, including the one person the agent answers to.This is bigger than it looks, because
owner-onlyis the server default.types.tssays the field omitted means"owner-only"(server default). The agent settings label that mode "Only me (default)" and print "Only you and your agents can send instructions." So the default mode promises the owner can instruct the agent, and the mention picker then hides that agent from the owner.The hole only opens for an agent the desktop does not manage, for example one running as a container elsewhere. Managed agents are admitted by a separate path, so nobody who starts agents from the desktop would ever see this.
The fix
RelayAgenthas no owner field, so the owner has to come from profile metadata.getMentionableAgentPubkeysnow takes the profile lookup and resolves ownership withmergeOwnedAgentPubkeysfromfeatures/agents/knownAgentPubkeys.ts. That helper is already documented as "Agent identities controlled by the current user", and the inbox already uses it for the same question. This path just never asked it.Ownership is matched, never assumed. An agent whose owner cannot be resolved stays hidden. A caller that passes no profiles gets exactly today's behaviour.
Channel exactness does not change. The mention path goes through
relayAgentCanRespondInChannel, which still requires the agent to be in that channel, so the owner reaches the agent only where the agent actually is. DMs and unresolved composer contexts use themanaged-onlyscope and stay fail-closed.Tests
Two new tests in
agentAutocompleteEligibility.test.mjs. Both fail on the current helper and pass after it:# pass 21 / # fail 2before,# pass 23 / # fail 0after.The existing
owner-onlyassertion in that file is untouched and still green. It callsrelayAgentIsSharedWithUserwithout a viewer pubkey and expectsfalse, which is still what happens: no viewer identity, no admission.One removal
useMentionsbuiltsharedChannelIdsand passed it in. That call site only ever asks for thechannelormanaged-onlyscope, and neither one reads that set — onlycommunitydoes. So the parameter is now optional anduseMentionsno longer builds it.useChannelsQuerywent with it, because it fed nothing else in the hook.Relation to #4913
This PR opened with two commits. The first removed a managed-list gate that ran ahead of the policy check. #4913 landed that behaviour and a lot more, so that commit is dropped and the branch is rebuilt on current
main. What is left is theowner-onlygap, which #4913 did not close.Scope
Three other call sites share this helper:
MembersSidebar,useNewMessageRecipientsandProjectsAgentPromptPage. They are unchanged. Owner data is not available at those call sites without adding a profile query, and inProjectsAgentPromptPagethe profile query runs after this set is computed. Becauseprofilesis optional, all three keep today's behaviour.One note on trust, since ownership now decides what the picker shows.
ownerPubkeyis not self-asserted. It comes from the NIP-OAauthtag on the agent's kind:0, andprofile_valid_oa_owner_pubkeyverifies that tag against the owner beforeget_users_batchreturns it, so a forged or stale marker resolves to no owner at all. An agent whose owner does not verify stays hidden, and the relay still enforces the real gate on the way in.Validation
pnpm --dir desktop test— 4389 passedpnpm --dir desktop typecheckpnpm --dir desktop check— biome, file-size ratchet, px-text, pubkey-truncationuseMentions.tsgoes from 1000 lines to 991, so it stays under the ratchetRefs #4776, #4833.