Fix wave agent target classification

This commit is contained in:
klopez4212
2026-06-30 13:55:22 +01:00
parent 97a3962352
commit 07b8f35de4
7 changed files with 56 additions and 29 deletions
@@ -16,10 +16,7 @@ import {
type AgentConversationMarker,
} from "@/features/agents/agentConversations";
import { buildDirectMessageIntro } from "@/features/channels/lib/dmParticipantDisplay";
import {
getDmHuddleMemberPubkeys,
hasOtherDmParticipant,
} from "@/features/channels/lib/dmHuddleMembers";
import { getDmHuddleMemberPubkeys } from "@/features/channels/lib/dmHuddleMembers";
import {
buildVideoReviewCommentsByRootId,
buildVideoReviewContextForMessage,
@@ -176,8 +173,7 @@ export const ChannelPane = React.memo(function ChannelPane({
() => getDmHuddleMemberPubkeys(activeChannel, agentPubkeys, currentPubkey),
[activeChannel, agentPubkeys, currentPubkey],
);
const huddleMemberPubkeysPending =
agentPubkeysPending && hasOtherDmParticipant(activeChannel, currentPubkey);
const huddleMemberPubkeysPending = agentPubkeysPending;
const isActiveWelcomeChannel =
activeChannel !== null && isWelcomeChannel(activeChannel);
React.useEffect(() => {
@@ -375,8 +375,7 @@ export function ChannelScreen({
(messageProfilesQuery.isPending ||
messageProfilesQuery.isFetching ||
messageProfilesQuery.isPlaceholderData));
const agentPubkeysPending =
activeChannel?.channelType === "dm" && agentLookupPending;
const agentPubkeysPending = agentLookupPending;
const {
agentSessionCandidates,
botTypingEntries,
@@ -13,6 +13,7 @@ import {
getThreadReference,
isBroadcastReply,
} from "@/features/messages/lib/threading";
import { collectWaveTargetPubkeys } from "@/features/messages/lib/waveMessage";
import {
resolveUserLabel,
type UserProfileLookup,
@@ -488,7 +489,7 @@ export function collectMessageAuthorPubkeys(events: RelayEvent[]) {
}
export function collectMessageMentionPubkeys(
events: Array<{ tags?: string[][] }>,
events: Array<{ tags?: string[][]; content?: string }>,
) {
const pubkeys = new Set<string>();
@@ -500,6 +501,9 @@ export function collectMessageMentionPubkeys(
}
}
}
for (const pubkey of collectWaveTargetPubkeys(events)) {
pubkeys.add(pubkey);
}
return [...pubkeys];
}
@@ -57,3 +57,18 @@ export function parseWaveMessageContent(
targetIsAgent,
};
}
export function collectWaveTargetPubkeys(
events: Array<{ content?: string }>,
): string[] {
const pubkeys = new Set<string>();
for (const event of events) {
const waveMessage = parseWaveMessageContent(event.content ?? "");
if (waveMessage?.targetPubkey) {
pubkeys.add(waveMessage.targetPubkey);
}
}
return [...pubkeys];
}
@@ -56,11 +56,11 @@ export function WaveMessageAttachment({
const targetAgentLookupPending =
targetIsAgent &&
normalizedTargetPubkey !== null &&
(huddleMemberPubkeysPending ||
(targetAgentPubkey === null &&
!resolvedHuddleMemberPubkeys.some(
(pubkey) => normalizePubkey(pubkey) === normalizedTargetPubkey,
)));
huddleMemberPubkeysPending &&
targetAgentPubkey === null &&
!resolvedHuddleMemberPubkeys.some(
(pubkey) => normalizePubkey(pubkey) === normalizedTargetPubkey,
);
const startHuddleDisabled =
!channelId || isStarting || targetAgentLookupPending;
@@ -212,8 +212,7 @@ export function UserProfilePopover({
const isAgentByProfile = Boolean(
usersBatchQuery.data?.profiles[normalizePubkey(pubkey)]?.isAgent,
);
const isAgentTarget =
isBotProfile || isAgentByProfile || isAgentClassificationPending;
const isAgentTarget = isBotProfile || isAgentByProfile;
const displayName = profile?.displayName ?? truncatePubkey(pubkey);
// Owner signal mirrors UserProfilePanel: a declared NIP-OA owner whose agent
// runs elsewhere holds no local seckey, so key custody (`isOwner`) alone
@@ -368,7 +367,13 @@ export function UserProfilePopover({
]);
const handleWave = React.useCallback(async () => {
if (!showProfileActions || pendingAction !== null) return;
if (
!showProfileActions ||
pendingAction !== null ||
isAgentClassificationPending
) {
return;
}
clearHoverTimer();
setPendingAction("wave");
@@ -453,6 +458,7 @@ export function UserProfilePopover({
currentPubkey,
goChannel,
identityQuery.data,
isAgentClassificationPending,
isAgentTarget,
openDmMutation,
pendingAction,
@@ -614,7 +620,9 @@ export function UserProfilePopover({
className="buzz-wave-hover-trigger shrink-0 px-3"
data-testid={`user-profile-popover-wave-${pubkey}`}
disabled={
pendingAction !== null || openDmMutation.isPending
pendingAction !== null ||
openDmMutation.isPending ||
isAgentClassificationPending
}
onClick={() => {
void handleWave();
+16 -11
View File
@@ -1445,9 +1445,11 @@ test("wave attachment huddle passes the bot DM pubkey", async ({ page }) => {
);
await expect(profilePopover).toBeVisible();
await expect(profilePopover.getByText("Codex")).toBeVisible();
await profilePopover
.getByTestId(`user-profile-popover-wave-${TEST_IDENTITIES.charlie.pubkey}`)
.click();
const charlieWaveButton = profilePopover.getByTestId(
`user-profile-popover-wave-${TEST_IDENTITIES.charlie.pubkey}`,
);
await expect(charlieWaveButton).toBeEnabled();
await charlieWaveButton.click();
await expect(page.getByTestId("message-wave-attachment")).toBeVisible();
await page
@@ -1505,14 +1507,15 @@ test("wave attachment huddle waits for placeholder profile-only bot data", async
'[data-testid="user-profile-popover"][data-state="open"]',
);
await expect(profilePopover).toBeVisible();
await profilePopover
.getByTestId(`user-profile-popover-wave-${PROFILE_ONLY_AGENT_PUBKEY}`)
.click();
const miraWaveButton = profilePopover.getByTestId(
`user-profile-popover-wave-${PROFILE_ONLY_AGENT_PUBKEY}`,
);
await expect(miraWaveButton).toBeEnabled({ timeout: 5_000 });
await miraWaveButton.click();
const startHuddleButton = page
.getByTestId("message-wave-attachment")
.getByRole("button", { name: "Start huddle" });
await expect(startHuddleButton).toBeDisabled();
await expect(startHuddleButton).toBeEnabled({ timeout: 5_000 });
await startHuddleButton.click();
@@ -1561,14 +1564,16 @@ test("wave attachment huddle waits for delayed bot DM pubkey", async ({
'[data-testid="user-profile-popover"][data-state="open"]',
);
await expect(profilePopover).toBeVisible();
await profilePopover
.getByTestId(`user-profile-popover-wave-${DELAYED_RELAY_AGENT_PUBKEY}`)
.click();
const orbitWaveButton = profilePopover.getByTestId(
`user-profile-popover-wave-${DELAYED_RELAY_AGENT_PUBKEY}`,
);
await expect(orbitWaveButton).toBeDisabled();
await expect(orbitWaveButton).toBeEnabled({ timeout: 7_000 });
await orbitWaveButton.click();
const startHuddleButton = page
.getByTestId("message-wave-attachment")
.getByRole("button", { name: "Start huddle" });
await expect(startHuddleButton).toBeDisabled();
await expect(startHuddleButton).toBeEnabled({ timeout: 7_000 });
await startHuddleButton.click();