fix(desktop): let channel-member agents be mentioned - #5
Merged
Merged
Conversation
The mention picker ran two agent gates in sequence, and the first made
the second's intent unreachable:
if (!isAgentIdentityInAllowedList(candidate, mentionable)) return;
if (shouldHideAgentFromMentions({...})) return;
`isAgentIdentityInAllowedList` rejects every candidate flagged `isAgent`
that is not already in `mentionableAgentPubkeys`. `shouldHideAgentFromMentions`
is a strict superset of that check except for exactly one case, which it
handles deliberately and documents at length: a channel-member agent with
no kind:10100 directory entry is *shown*, because unknown invocability is
not evidence of exclusion.
That branch never ran. Any agent owned by someone else was dropped by the
first gate before it could apply.
The practical effect is total: `mentionableAgentPubkeys` admits a relay
agent only via `channel_ids` / `respond_to` / `respond_to_allowlist` read
from its kind:10100 profile — and nothing in this repo publishes that
event. The only writer is `buzz channels set-add-policy`, whose content is
just `{"channel_add_policy": …}`; since kind 10100 is replaceable, that
write also erases any profile that did exist. So the directory is empty in
practice, no other-owner agent can enter the allowed set, and every one of
them was hidden — even when its owner had explicitly allowlisted the
mentioning user.
Gate on `shouldHideAgentFromMentions` alone. Non-member agents are still
hidden, and a directory entry that excludes the viewer still hides
(`return directoryAgentPubkeys.has(...)`), so the only behavior change is
the case the hide rule always meant to allow.
MembersSidebar keeps the stricter predicate — deciding whether to ADD an
agent to a channel is a different question from whether to mention one
already in it.
Verified: desktop tests 4553 passed (1 new, pinning the disagreement
between the two predicates so the gate is not reinstated), tsc clean,
pnpm check clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Junchao Yan <yjc801@gmail.com>
Review finding (P2, useMentions.ts:257): this PR admits a channel-member agent with no kind:10100 directory entry into the mention picker, but `knownAgentPubkeys` stayed exactly `mentionableAgentPubkeys`, so `isAgentPubkey` returned false for that same identity. After selection the send flow therefore dropped it from `explicitAgentPubkeys` and `preparedAgentPubkeys` — with "Keep addressed agents active" on, the agent vanished from the composer after the first thread send and was omitted from `sync_agents_to_active_huddle`. The picker's member branch and the send path's classification are now one gate: `getAdmittedMemberAgentPubkeys` lives beside `shouldHideAgentFromMentions`, so the two cannot drift apart. `useMentionAgentPubkeys` derives the three sets the mention surface needs — invocable, member-agent, and known (invocable plus admitted member agents) — and `memberAgentPubkeys` becomes the single source for the candidate loop's `isAgent` instead of a repeated inline expression. It is a separate module because `useMentions.ts` already sat at the 1000-line ratchet; the guard says split, not bump. Replaces the smoke test that asserted this agent stays hidden. It passed only by checking for zero rows before member and profile data settled, so it could not see the regression. The new test drives picker selection through a thread send and asserts the mention is retained, promoted into the thread's stored audience, and enrolled in the Huddle sync; it fails on the pre-fix classification with an empty composer. Signed-off-by: Junchao Yan <yjc801@gmail.com>
yjc801
added a commit
that referenced
this pull request
Aug 21, 2026
Resolves the desktop agent-mention conflicts from upstream block#6338 ("Fix cross-owner relay agent mentions in owner-only builds"), which removed the owner-only gate from mention admission that this fork had also been carrying. - agentAutocompleteEligibility: take upstream's removal of the ownerOnly/isManagedAgent/ownerPubkey gate; keep the fork's lenient channel-member branch (#5) and its directoryAgentPubkeys input, which upstream's change does not cover. - agentMentionRevalidation: same — drop the owner-profile proof fetch, keep the roster fetch that the member branch depends on. - useMentions: keep the fork's per-community relay URL (#4), drop the owner-only query. - MembersSidebar: keep the fork's MembersSidebarAddMemberRows split and delete upstream's duplicate AddMemberSearchResultRow.tsx. - relayReconnectReplay.test.mjs: upstream's new coupling guard reads the drift literal from ingest.rs; this fork hoists it into buzz-core for buzz-waker, so point the guard at the real definition. Validated: desktop tsc, 5438 desktop tests, biome, px/file-size guards, cargo fmt, cargo check (workspace + Tauri, all targets), 2781 Tauri lib tests. Signed-off-by: Junchao Yan <yjc801@gmail.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.
Summary
An agent owned by someone else could never be mentioned, even when its owner had explicitly allowlisted the mentioning user. Found while investigating why an agent that was a
bot-role member of a channel, with permission granted, simply did not appear in the@picker.The mention picker ran two agent gates in sequence, and the first made the second's intent unreachable:
isAgentIdentityInAllowedListrejects every candidate flaggedisAgentthat isn't already inmentionableAgentPubkeys.shouldHideAgentFromMentionsis a strict superset of that check except for exactly one case, which it handles deliberately and documents at length:That branch never ran. The first gate dropped the candidate before it could apply.
Why the effect is total, not marginal. A relay agent enters
mentionableAgentPubkeysonly viachannel_ids/respond_to/respond_to_allowlist, read from its kind:10100 profile. Nothing in this repo publishes that event. The only writer isbuzz channels set-add-policy, whose content is just{"channel_add_policy": …}— and since kind 10100 is replaceable (asserted at compile time inbuzz-core/src/kind.rs), that write also erases any profile that did exist. So the directory is empty in practice, no other-owner agent can enter the allowed set, and all of them were hidden.The fix: gate on
shouldHideAgentFromMentionsalone.Reviewer notes
if (!isMember) return true), and a directory entry that excludes the viewer still hides (return directoryAgentPubkeys.has(...)). The only behavior change is the case the hide rule always intended to allow.MembersSidebardeliberately keeps the stricter predicate. Deciding whether to add an agent to a channel is a different question from whether to mention one already in it.isAgentIdentityInAllowedListas the obvious guard.useMentionsis a hook with a dozen queries and the repo has no hook-testing harness, so the protection here is a pinned-contract test plus a comment at the call site — documentation-grade, not enforcement.set-add-policyerases agent profiles, and that kind:10100 has no producer at all, are both upstream (block/buzz) problems. This PR only stops the desktop from hiding agents because of them.Related issue
None found (fork).
Testing
pnpm test: 4553 passed (1 new — assertsshouldHideAgentFromMentionsshows a channel-member agent with no directory entry, whileisAgentIdentityInAllowedListrejects the same input).pnpm exec tsc --noEmit: clean.pnpm check(biome + file-size + px-text + pubkey-truncation): clean, only the two known pre-existing infos.--no-sign) and ran it against a real relay: an agent owned by another user, holdingbotrole in the channel and permitted by its owner, now appears in the@picker. It was absent onmainunder identical conditions.No screenshots — the change is the presence of a row in an autocomplete that requires a specific multi-user setup to reproduce.
🤖 Generated with Claude Code