Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions desktop/src/features/messages/ui/NonMemberMentionDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@ export function NonMemberMentionDialog({
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>
Mention people outside this channel?
Mention someone outside this channel?
</AlertDialogTitle>
<AlertDialogDescription>
{names.join(", ")} {names.length === 1 ? "is" : "are"} not in this
channel. Invite them to the channel, or send without inviting them.
channel. Invite them (this re-adds previously removed members), or
send without inviting them.
</AlertDialogDescription>
</AlertDialogHeader>
{error ? (
Expand Down
59 changes: 33 additions & 26 deletions desktop/src/features/messages/ui/useMentionSendFlow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,14 @@ export function useMentionSendFlow({
await startAgentMutation.mutateAsync(agent.pubkey);
}
} else {
await attachAgentMutation.mutateAsync({
channelId: capturedChannelId,
agent,
role: "bot",
});
// Never silently re-attach a non-member agent on mention.
// Channel membership changes go through the invite confirmation
// (handleInviteNonMembers) so a prior Remove cannot be undone by
// typing @Name (#3577).
errors.push(
`${agent.name}: not in this channel — invite them before mentioning.`,
);
continue;
}
pubkeys.push(pubkey);
} catch (error) {
Expand All @@ -294,7 +297,6 @@ export function useMentionSendFlow({
};
},
[
attachAgentMutation,
getManagedAgentsByPubkey,
mentions.memberPubkeys,
startAgentMutation,
Expand Down Expand Up @@ -713,23 +715,10 @@ export function useMentionSendFlow({
buildCustomEmojiTags(finalContent, customEmoji),
);
const nonMemberPubkeys = getNonMemberMentionPubkeys(pubkeys);
let promptNonMemberPubkeys = nonMemberPubkeys.filter(
(pubkey) =>
!mentions.isManagedAgentPubkey(pubkey) &&
!createdPersonaAgentPubkeySet.has(normalizePubkey(pubkey)),
);

if (promptNonMemberPubkeys.length > 0) {
try {
const managedAgentsByPubkey = await getManagedAgentsByPubkey();
promptNonMemberPubkeys = promptNonMemberPubkeys.filter(
(pubkey) => !managedAgentsByPubkey.has(normalizePubkey(pubkey)),
);
} catch {
// Keep the hook-based managed-agent filtering even if the query
// fallback misses; ordinary non-members still get prompted.
}
}
// Include managed agents that aren't channel members so a mention
// cannot silently re-attach a previously removed agent (#3577).
// First-time adds go through the same invite confirmation.
const promptNonMemberPubkeys = nonMemberPubkeys;

const pendingDraft: PendingNonMemberMentionSend = {
capturedChannelId: effectiveChannelId,
Expand Down Expand Up @@ -769,12 +758,10 @@ export function useMentionSendFlow({
channelType,
createMentionedPersonaAgents,
customEmoji,
getManagedAgentsByPubkey,
getNonMemberMentionPubkeys,
getDmThreadAgentMentionError,
mentions.extractMentionPubkeys,
mentions.isAgentPubkey,
mentions.isManagedAgentPubkey,
onPrepareSendChannel,
],
);
Expand Down Expand Up @@ -827,11 +814,14 @@ export function useMentionSendFlow({
const managedAgentsByPubkey = await getManagedAgentsByPubkey();
const peoplePubkeys: string[] = [];
const relayAgentPubkeys: string[] = [];
const managedAgentsToAttach: ManagedAgent[] = [];

for (const pubkey of uniqueNormalizedPubkeys(
pendingNonMemberSend.nonMemberPubkeys,
)) {
if (managedAgentsByPubkey.has(pubkey)) {
const managed = managedAgentsByPubkey.get(pubkey);
if (managed) {
managedAgentsToAttach.push(managed);
continue;
}

Expand Down Expand Up @@ -861,6 +851,22 @@ export function useMentionSendFlow({
errors.push(...result.errors.map((error) => error.error));
}

for (const agent of managedAgentsToAttach) {
try {
await attachAgentMutation.mutateAsync({
channelId: pendingNonMemberSend.capturedChannelId ?? "",
agent,
role: "bot",
});
} catch (error) {
errors.push(
`${agent.name}: ${
error instanceof Error ? error.message : "Could not invite agent."
}`,
);
}
}

if (errors.length > 0) {
setNonMemberPromptError(errors.join("; "));
return;
Expand All @@ -882,6 +888,7 @@ export function useMentionSendFlow({
});
}, [
addMembersMutation,
attachAgentMutation,
completeSend,
getManagedAgentsByPubkey,
mentions.isAgentPubkey,
Expand Down