Keep huddle actions pending for bot hints

This commit is contained in:
klopez4212
2026-06-29 14:34:09 +01:00
parent 81e110df66
commit 7f1a47d3d9
3 changed files with 100 additions and 10 deletions

View File

@@ -285,9 +285,7 @@ export const ChannelPane = React.memo(function ChannelPane({
[activeChannel, agentPubkeys, currentPubkey],
);
const huddleMemberPubkeysPending =
agentPubkeysPending &&
huddleMemberPubkeys.length === 0 &&
hasOtherDmParticipant(activeChannel, currentPubkey);
agentPubkeysPending && hasOtherDmParticipant(activeChannel, currentPubkey);
const isActiveWelcomeChannel =
activeChannel !== null && isWelcomeChannel(activeChannel);
useComposerHeightPadding(

View File

@@ -67,6 +67,24 @@ function resolveDisplayLabel(
return resolveLabel(pubkey, currentPubkey, profiles);
}
function isKnownAgentPubkey(
pubkey: string | undefined,
profiles: UserProfileLookup | undefined,
personaLookup?: Map<string, string>,
agentPubkeys?: ReadonlySet<string>,
) {
if (!pubkey) {
return false;
}
const normalizedPubkey = normalizePubkey(pubkey);
return (
agentPubkeys?.has(normalizedPubkey) === true ||
profiles?.[normalizedPubkey]?.isAgent === true ||
personaLookup?.has(normalizedPubkey) === true
);
}
function ProfileName({
children,
highlight = false,
@@ -118,12 +136,16 @@ function ProfileName({
function SystemMessageAvatar({
actorPubkey,
agentPubkeys,
currentPubkey,
personaLookup,
profiles,
targetPubkey,
}: {
actorPubkey: string | undefined;
agentPubkeys?: ReadonlySet<string>;
currentPubkey: string | undefined;
personaLookup?: Map<string, string>;
profiles: UserProfileLookup | undefined;
targetPubkey: string | undefined;
}) {
@@ -141,6 +163,12 @@ function SystemMessageAvatar({
const singlePubkey = actorPubkey ?? targetPubkey;
if (!hasActorAndTarget) {
const isSingleAgent = isKnownAgentPubkey(
singlePubkey,
profiles,
personaLookup,
agentPubkeys,
);
const avatar = (
<UserAvatar
avatarUrl={resolveAvatarUrl(singlePubkey, profiles)}
@@ -152,9 +180,14 @@ function SystemMessageAvatar({
if (singlePubkey) {
return (
<UserProfilePopover pubkey={singlePubkey}>
<UserProfilePopover
botIdenticonValue={isSingleAgent ? actorLabel : undefined}
pubkey={singlePubkey}
role={isSingleAgent ? "bot" : undefined}
>
<button
className="shrink-0 rounded-full focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
data-testid="system-message-avatar"
type="button"
>
{avatar}
@@ -166,6 +199,12 @@ function SystemMessageAvatar({
return avatar;
}
const isActorAgent = isKnownAgentPubkey(
actorPubkey,
profiles,
personaLookup,
agentPubkeys,
);
const targetLabel = resolveUserLabel({
pubkey: targetPubkey,
currentPubkey,
@@ -192,7 +231,11 @@ function SystemMessageAvatar({
);
return (
<UserProfilePopover pubkey={actorPubkey}>
<UserProfilePopover
botIdenticonValue={isActorAgent ? actorLabel : undefined}
pubkey={actorPubkey}
role={isActorAgent ? "bot" : undefined}
>
<button
className="shrink-0 rounded-full focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
type="button"
@@ -210,11 +253,12 @@ function describeSystemEvent(
personaLookup?: Map<string, string>,
agentPubkeys?: ReadonlySet<string>,
): SystemMessageDescription | null {
const isTargetAgent =
payload.target !== undefined &&
(agentPubkeys?.has(normalizePubkey(payload.target)) === true ||
profiles?.[normalizePubkey(payload.target)]?.isAgent === true ||
personaLookup?.has(normalizePubkey(payload.target)) === true);
const isTargetAgent = isKnownAgentPubkey(
payload.target,
profiles,
personaLookup,
agentPubkeys,
);
const actorLabel = resolveDisplayLabel(
payload.actor,
currentPubkey,
@@ -350,7 +394,9 @@ export const SystemMessageRow = React.memo(function SystemMessageRow({
<div className="flex items-start gap-2.5">
<SystemMessageAvatar
actorPubkey={payload.actor}
agentPubkeys={agentPubkeys}
currentPubkey={currentPubkey}
personaLookup={personaLookup}
profiles={profiles}
targetPubkey={payload.target}
/>

View File

@@ -967,6 +967,52 @@ test("system agent profile huddle passes profile-only bot pubkey", async ({
.toEqual(expect.arrayContaining([PROFILE_ONLY_AGENT_PUBKEY]));
});
test("system agent avatar huddle passes profile-only bot pubkey", async ({
page,
}) => {
await page.goto("/");
await page.getByTestId("channel-general").click();
await expect(page.getByTestId("chat-title")).toHaveText("general");
await waitForMockLiveSubscription(page, "general", SYSTEM_MESSAGE_KIND);
await page.evaluate(
({ kind, targetPubkey }) => {
window.__BUZZ_E2E_EMIT_MOCK_MESSAGE__?.({
channelName: "general",
content: JSON.stringify({
type: "member_joined",
actor: targetPubkey,
target: targetPubkey,
}),
kind,
});
},
{
kind: SYSTEM_MESSAGE_KIND,
targetPubkey: PROFILE_ONLY_AGENT_PUBKEY,
},
);
await waitForTimelineSettled(page);
const joinedRow = page
.getByTestId("system-message-row")
.filter({ hasText: "mira" })
.filter({ hasText: "joined the channel" });
await joinedRow.getByTestId("system-message-avatar").hover();
const profilePopover = page.locator(
'[data-testid="user-profile-popover"][data-state="open"]',
);
await expect(profilePopover).toBeVisible();
await profilePopover
.getByTestId(`user-profile-popover-huddle-${PROFILE_ONLY_AGENT_PUBKEY}`)
.click();
await expect
.poll(() => readStartHuddleMemberPubkeys(page))
.toEqual(expect.arrayContaining([PROFILE_ONLY_AGENT_PUBKEY]));
});
test("system member-joined rows render the joined person as a mention chip", async ({
page,
}) => {