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
26 changes: 24 additions & 2 deletions desktop/src/testing/e2eBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2370,6 +2370,28 @@ function resetMockRelayAgents(config?: E2eConfig) {
respond_to: seed.respondTo ?? "owner-only",
respond_to_allowlist: seed.respondToAllowlist ?? [],
});

// A relay-agent seed that names real channels represents a bot that is
// an actual member of those channels — e.g. another identity's agent
// added as a bot member of a shared channel — not just a
// relay-directory listing. Mirror resetMockManagedAgents's membership
// push (below) so specs can exercise the cross-owner "bot member of a
// shared channel" case without also declaring the agent as locally
// managed.
for (const channel of channels) {
if (channel.members.some((member) => member.pubkey === seed.pubkey)) {
continue;
}
channel.members.push({
pubkey: seed.pubkey,
role: "bot",
is_agent: true,
joined_at: new Date().toISOString(),
display_name: seed.name,
});
syncMockChannel(channel);
touchMockChannel(channel);
}
}
}

Expand Down Expand Up @@ -3583,7 +3605,7 @@ function initializeMockHuddle(
const openedExternalUrls: string[] = [];
const defaultMockRelayAgents: RawRelayAgent[] = [
{
pubkey: ALICE_PUBKEY,
pubkey: "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a",
name: "alice",
agent_type: "goose",
channels: ["general", "agents"],
Expand All @@ -3597,7 +3619,7 @@ const defaultMockRelayAgents: RawRelayAgent[] = [
respond_to_allowlist: [],
},
{
pubkey: CHARLIE_PUBKEY,
pubkey: "5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c",
name: "charlie",
agent_type: "codex",
channels: ["general"],
Expand Down
63 changes: 63 additions & 0 deletions desktop/tests/e2e/mentions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1933,6 +1933,69 @@ test("shared agents wait for initial directory authorization", async ({
});
});

test("bot agents owned by another identity are mentionable when added to a shared channel", async ({
page,
}) => {
const OTHER_OWNER_BOT_PUBKEY =
"7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b";
await installMockBridge(page, {
relayAgents: [
{
pubkey: OTHER_OWNER_BOT_PUBKEY,
name: "scout",
respondTo: "anyone",
channelNames: ["general"],
},
],
});
await page.goto("/");
await page.getByTestId("channel-general").click();
await expect(page.getByTestId("chat-title")).toHaveText("general");

const input = page.getByTestId("message-input");
await input.fill("@scout");

const dropdown = autocomplete(page);
await expect(dropdown.getByText("scout")).toBeVisible();
await expect(dropdown.getByText("agent")).toBeVisible();

await input.press("Enter");
await page.keyboard.type(" can you help?");
await page.getByTestId("send-message").click();

const mentionChip = page
.getByTestId("message-row")
.last()
.locator("[data-mention].agent-mention-highlight", { hasText: "scout" });
await expect(mentionChip).toBeVisible();
});

test("bot agents owned by another identity stay hidden when not added to a shared channel", async ({
page,
}) => {
const OTHER_OWNER_BOT_PUBKEY =
"8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c";
await installMockBridge(page, {
relayAgents: [
{
pubkey: OTHER_OWNER_BOT_PUBKEY,
name: "ghost",
respondTo: "anyone",
// Deliberately not added to "general" — respondTo=anyone alone must
// not be enough; the fix requires real channel membership too.
},
],
});
await page.goto("/");
await page.getByTestId("channel-general").click();
await expect(page.getByTestId("chat-title")).toHaveText("general");

const input = page.getByTestId("message-input");
await input.fill("@ghost");

await expect(autocomplete(page)).toHaveCount(0);
});

test("mentioning an in-channel stopped managed agent starts it before sending", async ({
page,
}) => {
Expand Down