From dfac2934236665dec81576566dc1c0a662fc3fa1 Mon Sep 17 00:00:00 2001 From: iroiro147 Date: Sat, 1 Aug 2026 10:04:14 +0530 Subject: [PATCH] fix(desktop): coalesce persona defs with running instances in @ picker (#3947) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Buzz Desktop, the mention picker could offer account-synced persona-definition rows as 'not in channel' while omitting the actual locally managed running instances that are channel members. Two candidate-assembly defects: 1. Persona-definition records in managed-agents.json can carry an empty pubkey (their running instance carries the real one). addCandidate admitted them as agent candidates, so phantom rows rendered and could shadow the real instance. Skip any candidate whose normalized pubkey is blank. 2. Running instances were not enriched with their linked persona's displayName — the instance's own (often null) name won, so the picker showed an unnamed instance and the persona row as a separate 'managed by you' duplicate. When agent.personaId links to an active persona, prefer the persona's displayName for presentation; membership and delivery stay keyed by the instance pubkey (join: instance.persona_id == persona.id). Verified: pnpm typecheck clean, biome check clean. Fixes block/buzz#3947 Signed-off-by: iroiro147 --- .../src/features/messages/lib/useMentions.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/desktop/src/features/messages/lib/useMentions.ts b/desktop/src/features/messages/lib/useMentions.ts index 0c73b75339..573c771247 100644 --- a/desktop/src/features/messages/lib/useMentions.ts +++ b/desktop/src/features/messages/lib/useMentions.ts @@ -243,6 +243,13 @@ export function useMentions( const addCandidate = (candidate: MentionCandidate & { pubkey: string }) => { const pubkey = normalizePubkey(candidate.pubkey); + if (!pubkey) { + // Persona-definition rows in managed-agents.json can carry an empty + // pubkey (their running instance carries the real one). They are not + // mentionable identities — skip so they never render as phantom + // candidates or shadow the real instance (#3947). + return; + } if (isArchivedDiscovery(pubkey)) { return; } @@ -347,16 +354,23 @@ export function useMentions( } for (const agent of managedAgentsQuery.data ?? []) { + const linkedPersonaName = agent.personaId + ? (activePersonaById.get(agent.personaId)?.displayName ?? null) + : null; addCandidate({ kind: "identity", pubkey: agent.pubkey, - displayName: agent.name, + // Prefer the linked persona's display name for presentation; the + // instance's own `name` may be null on running instances (#3947). + displayName: agent.name || linkedPersonaName || null, isMember: false, isAgent: true, isManagedAgent: true, personaId: agent.personaId ?? undefined, personaName: - personaNameByPubkey.get(normalizePubkey(agent.pubkey)) ?? null, + personaNameByPubkey.get(normalizePubkey(agent.pubkey)) ?? + linkedPersonaName ?? + null, ownerPubkey: currentPubkey, }); }