fix(desktop): hide message action for inaccessible agents (#1883)

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
Wes
2026-07-14 17:21:54 -07:00
committed by GitHub
co-authored by Pinky
parent 54f4165942
commit 8ce9e79145
3 changed files with 93 additions and 39 deletions
@@ -241,6 +241,11 @@ export function UserProfilePopover({
const selfProfileQuery = useProfileQuery(open && showProfileActions);
const isCurrentUserOwner = ownsAuthorAgent(profile, currentPubkey);
const viewerIsOwner = isCurrentUserOwner || isOwner === true;
const showMessageAction =
showProfileActions &&
!isAgentClassificationPending &&
(!isBotProfile || viewerIsOwner);
const showAnyProfileActions = showHumanProfileActions || showMessageAction;
const canViewActivity =
isBotProfile && viewerIsOwner && canOpenAgentActivity(pubkey);
const presenceStatus = presenceQuery.data?.[pubkey.toLowerCase()];
@@ -298,7 +303,7 @@ export function UserProfilePopover({
);
const handleMessage = React.useCallback(async () => {
if (!showProfileActions || pendingAction !== null) return;
if (!showMessageAction || pendingAction !== null) return;
clearHoverTimer();
setPendingAction("message");
@@ -326,7 +331,7 @@ export function UserProfilePopover({
openDmMutation,
pendingAction,
pubkey,
showProfileActions,
showMessageAction,
]);
const handleHuddle = React.useCallback(async () => {
@@ -615,7 +620,7 @@ export function UserProfilePopover({
</button>
) : null}
{hasUserStatus || showProfileActions ? (
{hasUserStatus || showAnyProfileActions ? (
<>
<div
aria-hidden="true"
@@ -634,7 +639,7 @@ export function UserProfilePopover({
) : null}
</StatusLine>
) : null}
{showProfileActions ? (
{showAnyProfileActions ? (
<div className="flex gap-2">
{showHumanProfileActions ? (
<Button
@@ -666,29 +671,31 @@ export function UserProfilePopover({
)}
</Button>
) : null}
<Button
className="min-w-0 flex-1"
data-testid={`user-profile-popover-message-${pubkey}`}
disabled={
pendingAction !== null || openDmMutation.isPending
}
onClick={() => {
void handleMessage();
}}
size="sm"
type="button"
variant="outline"
>
{pendingAction === "message" ? (
<Spinner
aria-hidden="true"
className="h-3.5 w-3.5 border-2"
/>
) : (
<MessageSquare />
)}
Message
</Button>
{showMessageAction ? (
<Button
className="min-w-0 flex-1"
data-testid={`user-profile-popover-message-${pubkey}`}
disabled={
pendingAction !== null || openDmMutation.isPending
}
onClick={() => {
void handleMessage();
}}
size="sm"
type="button"
variant="outline"
>
{pendingAction === "message" ? (
<Spinner
aria-hidden="true"
className="h-3.5 w-3.5 border-2"
/>
) : (
<MessageSquare />
)}
Message
</Button>
) : null}
{showHumanProfileActions ? (
<Button
className="min-w-0 flex-1"
+55 -10
View File
@@ -168,6 +168,21 @@ async function expectAgentProfileMessageOnly(
).toHaveCount(0);
}
async function expectAgentProfileActionsHidden(
profilePopover: import("@playwright/test").Locator,
pubkey: string,
) {
await expect(
profilePopover.getByTestId(`user-profile-popover-message-${pubkey}`),
).toHaveCount(0);
await expect(
profilePopover.getByTestId(`user-profile-popover-wave-${pubkey}`),
).toHaveCount(0);
await expect(
profilePopover.getByTestId(`user-profile-popover-huddle-${pubkey}`),
).toHaveCount(0);
}
test("@ trigger prioritizes channel members before runnable personas and other agents", async ({
page,
}) => {
@@ -1273,7 +1288,7 @@ test("system agent avatar only exposes message action", async ({ page }) => {
);
});
test("profile-only agent author popover only exposes message action", async ({
test("profile-only agent author hides actions without agent access", async ({
page,
}) => {
await installMockBridge(page, {
@@ -1305,7 +1320,7 @@ test("profile-only agent author popover only exposes message action", async ({
'[data-testid="user-profile-popover"][data-state="open"]',
);
await expect(profilePopover).toBeVisible();
await expectAgentProfileMessageOnly(
await expectAgentProfileActionsHidden(
profilePopover,
PROFILE_ONLY_AGENT_PUBKEY,
);
@@ -1684,7 +1699,16 @@ test("clicking a mention chip in a forum post opens the profile panel", async ({
);
});
test("bot profile only exposes message action", async ({ page }) => {
test("owned bot profile only exposes message action", async ({ page }) => {
await installMockBridge(page, {
managedAgents: [
{
pubkey: TEST_IDENTITIES.charlie.pubkey,
name: "charlie",
status: "online",
},
],
});
await page.goto("/");
await page.getByTestId("channel-agents").click();
await expect(page.getByTestId("chat-title")).toHaveText("agents");
@@ -1699,14 +1723,24 @@ test("bot profile only exposes message action", async ({ page }) => {
'[data-testid="user-profile-popover"][data-state="open"]',
);
await expect(profilePopover).toBeVisible();
await expect(profilePopover.getByText("Codex")).toBeVisible();
await expectAgentProfileMessageOnly(
profilePopover,
TEST_IDENTITIES.charlie.pubkey,
);
});
test("agent mention profile only exposes message action", async ({ page }) => {
test("owned agent mention profile only exposes message action", async ({
page,
}) => {
await installMockBridge(page, {
managedAgents: [
{
pubkey: TEST_IDENTITIES.charlie.pubkey,
name: "charlie",
status: "online",
},
],
});
await page.goto("/");
await page.getByTestId("channel-general").click();
await expect(page.getByTestId("chat-title")).toHaveText("general");
@@ -1813,7 +1847,7 @@ test("profile popover wave sends a direct message for a human profile", async ({
);
});
test("delayed agent profile keeps wave and huddle hidden while classifying", async ({
test("delayed inaccessible agent profile keeps all actions hidden", async ({
page,
}) => {
await installMockBridge(page, {
@@ -1853,8 +1887,19 @@ test("delayed agent profile keeps wave and huddle hidden while classifying", asy
'[data-testid="user-profile-popover"][data-state="open"]',
);
await expect(profilePopover).toBeVisible();
await expectAgentProfileMessageOnly(
profilePopover,
DELAYED_RELAY_AGENT_PUBKEY,
);
await expect(
profilePopover.getByTestId(
`user-profile-popover-message-${DELAYED_RELAY_AGENT_PUBKEY}`,
),
).toHaveCount(0);
await expect(
profilePopover.getByTestId(
`user-profile-popover-wave-${DELAYED_RELAY_AGENT_PUBKEY}`,
),
).toHaveCount(0);
await expect(
profilePopover.getByTestId(
`user-profile-popover-huddle-${DELAYED_RELAY_AGENT_PUBKEY}`,
),
).toHaveCount(0);
});
+4 -2
View File
@@ -224,7 +224,9 @@ test("inbox feed shows channel and agent activity sections", async ({
);
});
test("inbox agent hover only exposes message action", async ({ page }) => {
test("inbox agent hover hides actions without agent access", async ({
page,
}) => {
await page.goto("/");
await selectHomeInboxFilter(page, "Agents");
@@ -242,7 +244,7 @@ test("inbox agent hover only exposes message action", async ({ page }) => {
profilePopover.getByTestId(
`user-profile-popover-message-${DEFAULT_AGENT_ACTIVITY_PUBKEY}`,
),
).toBeVisible();
).toHaveCount(0);
await expect(
profilePopover.getByTestId(
`user-profile-popover-wave-${DEFAULT_AGENT_ACTIVITY_PUBKEY}`,