mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Fix wave agent target classification
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user