diff --git a/desktop/src/features/agents/ui/AgentDefinitionDialog.tsx b/desktop/src/features/agents/ui/AgentDefinitionDialog.tsx
index 409ae6a821..b4606a0f68 100644
--- a/desktop/src/features/agents/ui/AgentDefinitionDialog.tsx
+++ b/desktop/src/features/agents/ui/AgentDefinitionDialog.tsx
@@ -8,8 +8,6 @@ import type {
UpdatePersonaInput,
} from "@/shared/api/types";
import { cn } from "@/shared/lib/cn";
-import { ChooserDialogContent } from "@/shared/ui/chooser-dialog-content";
-import { Dialog } from "@/shared/ui/dialog";
import { Input } from "@/shared/ui/input";
import { Textarea } from "@/shared/ui/textarea";
import { AgentCreationPreview } from "./AgentCreationPreview";
@@ -85,6 +83,7 @@ import {
import { useProviderApiKeyFieldState } from "./providerApiKeyFieldState";
import { buildRuntimeModelProviderPayload } from "./agentDefinitionSubmitPayload";
import { AgentDefinitionDialogFooter } from "./AgentDefinitionDialogFooter";
+import { AgentDefinitionDialogShell } from "./AgentDefinitionDialogShell";
import { AddCustomHarnessDialog } from "./AddCustomHarnessDialog";
import {
ADD_CUSTOM_HARNESS_OPTION,
@@ -94,6 +93,7 @@ import {
type AgentDefinitionDialogProps = {
open: boolean;
+ embedded?: boolean;
title: string;
description: string;
submitLabel: string;
@@ -102,6 +102,7 @@ type AgentDefinitionDialogProps = {
isPending: boolean;
runtimes: AcpRuntimeCatalogEntry[];
runtimeCatalogStatus?: "loading" | "ready" | "error";
+ onDirtyChange?: (dirty: boolean) => void;
onOpenChange: (open: boolean) => void;
onSubmit: (
input: CreatePersonaInput | UpdatePersonaInput,
@@ -120,6 +121,7 @@ export type AgentDefinitionSubmitOptions = {
export function AgentDefinitionDialog({
open,
+ embedded = false,
title,
description,
submitLabel,
@@ -128,6 +130,7 @@ export function AgentDefinitionDialog({
isPending,
runtimes,
runtimeCatalogStatus = "ready" as const,
+ onDirtyChange,
onOpenChange,
onSubmit,
publishCatalogUpdatesOnSave = false,
@@ -192,6 +195,10 @@ export function AgentDefinitionDialog({
(hasText(initialValues.model) || hasText(initialValues.provider)),
);
+ React.useEffect(() => {
+ onDirtyChange?.(hasUserChanges);
+ }, [hasUserChanges, onDirtyChange]);
+
React.useEffect(() => {
if (!open || !initialValues) {
return;
@@ -295,7 +302,8 @@ export function AgentDefinitionDialog({
}, [defaultRuntime, isCreateMode, open, runtime, runtimesLoading]);
function handleOpenChange(next: boolean) {
- if (!next) {
+ // The catalog may veto embedded close requests; preserve the draft until unmount.
+ if (!next && !embedded) {
setDisplayName("");
setAvatarUrl("");
setSystemPrompt("");
@@ -724,317 +732,309 @@ export function AgentDefinitionDialog({
);
}
- return (
-
+
+ {
+ if (!nextOpen) setPendingNavigation(null);
+ }}
+ open={pendingNavigation !== null}
+ >
+
+
+ Discard agent changes?
+
+ Your changes to this agent will be lost.
+
+
+
+ Keep editing
+
+
+
+
+
+
+ >
);
}
type PersonaCatalogChooserProps = {
+ createContent: React.ReactNode;
error: Error | null;
+ isDragOver: boolean;
isLoading: boolean;
isPending: boolean;
isSelectedPersonaActive: boolean;
+ onImport: () => void;
onUsePersona: () => void;
- onSelectPersona: (personaId: string) => void;
+ onSelectionChange: (selection: string) => void;
personas: AgentPersona[];
+ selection: string;
selectedPersona: AgentPersona | null;
selectedPersonaId: string | null;
};
function PersonaCatalogChooser({
+ createContent,
error,
+ isDragOver,
isLoading,
isPending,
isSelectedPersonaActive,
+ onImport,
onUsePersona,
- onSelectPersona,
+ onSelectionChange,
personas,
+ selection,
selectedPersona,
selectedPersonaId,
}: PersonaCatalogChooserProps) {
- if (!isLoading && personas.length === 0 && !error) {
- return (
-
-
-

-
- {personaCatalogCopy.emptyCatalogTitle}
-
-
- {personaCatalogCopy.emptyCatalogDescription}
+ return (
+
+ {selection === "import" && isDragOver ? (
+
+
+ Drop .agent.json or .agent.png to import
-
- );
- }
-
- return (
-
+ ) : null}
+
+ }
+ isCurrent={selection === "create"}
+ label="Create agent"
+ onClick={() => onSelectionChange("create")}
+ testId="agent-catalog-create"
+ />
+ }
+ isCurrent={selection === "import"}
+ label="Import"
+ onClick={() => onSelectionChange("import")}
+ testId="agent-catalog-import"
+ />
+
+
+
+
{isLoading ?
: null}
{!isLoading && personas.length > 0 ? (
@@ -209,7 +392,7 @@ function PersonaCatalogChooser({
data-testid={`persona-catalog-list-item-${persona.id}`}
key={persona.id}
onClick={() => {
- onSelectPersona(persona.id);
+ onSelectionChange(`persona:${persona.id}`);
}}
type="button"
>
@@ -226,57 +409,117 @@ function PersonaCatalogChooser({
})}
) : null}
-
-
-
-
-
- {isLoading ?
: null}
-
- {!isLoading && selectedPersona ? (
-
- ) : null}
-
- {error ? (
-
- {error.message}
+ {!isLoading && personas.length === 0 && !error ? (
+
+ No shared agents
) : null}
+
-
-
-
+
+ {selection === "create" ? createContent : null}
+ {selection === "import" ? (
+
+ ) : null}
+ {selectedPersona ? (
+ <>
+
+
+
+
+ >
+ ) : null}
+ {selection.startsWith("persona:") && isLoading ? (
+
+ ) : null}
+ {error ? (
+
+ {error.message}
+
+ ) : null}
);
}
+function CatalogNavigationButton({
+ icon,
+ isCurrent,
+ label,
+ onClick,
+ testId,
+}: {
+ icon: React.ReactNode;
+ isCurrent: boolean;
+ label: string;
+ onClick: () => void;
+ testId: string;
+}) {
+ return (
+
+ );
+}
+
+function ImportAgentPane({ onImport }: { onImport: () => void }) {
+ return (
+
+ );
+}
+
/**
* Derives the "Added by" label for a catalog entry from a resolved profile
* summary. Prefers `displayName`, falls back to `name`, then to the default
diff --git a/desktop/src/features/agents/ui/TeamsSection.tsx b/desktop/src/features/agents/ui/TeamsSection.tsx
index c5a7a078b3..986c9bdc26 100644
--- a/desktop/src/features/agents/ui/TeamsSection.tsx
+++ b/desktop/src/features/agents/ui/TeamsSection.tsx
@@ -84,6 +84,11 @@ export function TeamsSection({
{!isLoading ? (
+
{teams.map((team) => {
const resolution = resolveTeamPersonas(team, personas);
const missingPersonaCount = resolution.missingPersonaCount;
@@ -169,11 +174,6 @@ export function TeamsSection({
);
})}
-
) : null}
diff --git a/desktop/src/features/agents/ui/UnifiedAgentsSection.tsx b/desktop/src/features/agents/ui/UnifiedAgentsSection.tsx
index 73562bda35..b0a835e7a9 100644
--- a/desktop/src/features/agents/ui/UnifiedAgentsSection.tsx
+++ b/desktop/src/features/agents/ui/UnifiedAgentsSection.tsx
@@ -12,14 +12,7 @@ import { useUserProfileQuery } from "@/features/profile/hooks";
import type { AgentPersona, ManagedAgent } from "@/shared/api/types";
import type { ProfilePanelOpenOptions } from "@/shared/context/ProfilePanelContext";
import { useFeedbackToasts } from "@/shared/hooks/useToastEffect";
-import { useFileImportZone } from "@/shared/hooks/useFileImportZone";
import { Badge } from "@/shared/ui/badge";
-import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger,
-} from "@/shared/ui/dropdown-menu";
import { IdentityCardSkeleton } from "@/shared/ui/identity-card-skeleton";
import { AgentIdentityCard } from "./AgentIdentityCard";
import { AgentRuntimeAvatarControl } from "./AgentRuntimeAvatarControl";
@@ -52,8 +45,7 @@ type UnifiedAgentsSectionProps = {
personaFeedbackNoticeMessage: string | null;
isPersonasLoading: boolean;
isPersonasPending: boolean;
- onCreatePersona: () => void;
- onDiscoverPersonas: () => void;
+ onOpenCatalog: () => void;
onDuplicatePersona: (persona: AgentPersona) => void;
onEditPersona: (persona: AgentPersona) => void;
onSharePersona: (
@@ -63,13 +55,12 @@ type UnifiedAgentsSectionProps = {
) => void;
onDeactivatePersona: (persona: AgentPersona) => void;
onDeletePersona: (persona: AgentPersona) => void;
- onImportSnapshotFile: (fileBytes: number[], fileName: string) => void;
};
const AGENT_CARD_COLUMN_CLASS = "w-full";
export const AGENT_CARD_GRID_COLUMNS_CLASS =
- "grid-cols-[repeat(auto-fill,minmax(220px,240px))]";
-export const IDENTITY_CARD_GRID_CLASS = `${AGENT_CARD_COLUMN_CLASS} ${AGENT_CARD_GRID_COLUMNS_CLASS} grid justify-start gap-3 [@container(max-width:40rem)]:justify-center`;
+ "grid-cols-1 [@container(min-width:21rem)]:grid-cols-2 [@container(min-width:32rem)]:grid-cols-3 [@container(min-width:43rem)]:grid-cols-4 [@container(min-width:54rem)]:grid-cols-5";
+export const IDENTITY_CARD_GRID_CLASS = `${AGENT_CARD_COLUMN_CLASS} ${AGENT_CARD_GRID_COLUMNS_CLASS} grid gap-3`;
export function UnifiedAgentsSection(props: UnifiedAgentsSectionProps) {
const {
@@ -94,14 +85,12 @@ export function UnifiedAgentsSection(props: UnifiedAgentsSectionProps) {
personaFeedbackNoticeMessage,
isPersonasLoading,
isPersonasPending,
- onCreatePersona,
- onDiscoverPersonas,
+ onOpenCatalog,
onDuplicatePersona,
onEditPersona,
onSharePersona,
onDeactivatePersona,
onDeletePersona,
- onImportSnapshotFile,
} = props;
const { groups, ungrouped, unknown } = React.useMemo(
@@ -109,14 +98,6 @@ export function UnifiedAgentsSection(props: UnifiedAgentsSectionProps) {
[personas, agents],
);
const [collapsed, setCollapsed] = React.useState
>(new Set());
- const {
- fileInputRef,
- isDragOver,
- dropHandlers,
- handleFileChange,
- openFilePicker,
- } = useFileImportZone({ onImportFile: onImportSnapshotFile });
-
function toggle(key: string) {
setCollapsed((prev) => {
const next = new Set(prev);
@@ -134,29 +115,18 @@ export function UnifiedAgentsSection(props: UnifiedAgentsSectionProps) {
- {isDragOver ? (
-
-
- Drop .agent.json or .agent.png to import
-
-
- ) : null}
-
-
-
{isLoading ? : null}
{!isLoading ? (
+
{groups.map((group) => {
const profileAgent = pickProfileAgent(group.agents);
return (
@@ -193,12 +163,6 @@ export function UnifiedAgentsSection(props: UnifiedAgentsSectionProps) {
/>
);
})}
-
{unknown.length > 0 ? (
@@ -448,44 +412,6 @@ function StandaloneAgentCard({
);
}
-function NewAgentCard({
- isPending,
- onCreate,
- onDiscover,
- onImport,
-}: {
- isPending: boolean;
- onCreate: () => void;
- onDiscover: () => void;
- onImport: () => void;
-}) {
- return (
-
-
-
-
- event.preventDefault()}
- >
-
- Create agent
-
-
- Discover agents
-
-
- Import
-
-
-
- );
-}
-
function LoadingSkeleton() {
return (
diff --git a/desktop/src/features/agents/ui/personaLibraryCopy.ts b/desktop/src/features/agents/ui/personaLibraryCopy.ts
index 79ddad1c3c..dd4b0b5209 100644
--- a/desktop/src/features/agents/ui/personaLibraryCopy.ts
+++ b/desktop/src/features/agents/ui/personaLibraryCopy.ts
@@ -15,7 +15,7 @@ export const personaLibraryCopy = {
export const personaCatalogCopy = {
title: "Agent Catalog",
description: "Browse agents shared to this relay.",
- dialogTitle: "Agent Catalog",
+ dialogTitle: "Add agent",
dialogDescription: "Browse agents shared to this relay.",
emptyTitle: "You're all set",
emptyDescription: "Everything in Agent Catalog is already in My Agents.",
diff --git a/desktop/src/features/agents/ui/usePersonaActions.ts b/desktop/src/features/agents/ui/usePersonaActions.ts
index d3832cdc64..b4ef5afb6c 100644
--- a/desktop/src/features/agents/ui/usePersonaActions.ts
+++ b/desktop/src/features/agents/ui/usePersonaActions.ts
@@ -297,9 +297,10 @@ export function usePersonaActions() {
persona: AgentPersona,
active: boolean,
surface: PersonaFeedbackSurface,
- ) {
+ ): Promise
{
clearFeedback(surface);
try {
+ let updatedPersona: AgentPersona;
if (active && isCatalogPersona(persona)) {
const localPersona = findLocalPersonaForCatalogEntry(
personas,
@@ -308,13 +309,15 @@ export function usePersonaActions() {
if (localPersona) {
if (!localPersona.isActive) {
- await setPersonaActiveMutation.mutateAsync({
+ updatedPersona = await setPersonaActiveMutation.mutateAsync({
id: localPersona.id,
active: true,
});
+ } else {
+ updatedPersona = localPersona;
}
} else {
- await createPersonaMutation.mutateAsync({
+ updatedPersona = await createPersonaMutation.mutateAsync({
displayName: persona.displayName,
avatarUrl: persona.avatarUrl ?? undefined,
systemPrompt: persona.systemPrompt,
@@ -338,13 +341,17 @@ export function usePersonaActions() {
});
}
} else {
- await setPersonaActiveMutation.mutateAsync({ id: persona.id, active });
+ updatedPersona = await setPersonaActiveMutation.mutateAsync({
+ id: persona.id,
+ active,
+ });
}
setPersonaNoticeMessage(
active
? `Selected ${persona.displayName} for My Agents.`
: `Deselected ${persona.displayName} from My Agents.`,
);
+ return updatedPersona;
} catch (error) {
setPersonaErrorMessage(
error instanceof Error
@@ -353,6 +360,7 @@ export function usePersonaActions() {
? "Failed to select agent for My Agents."
: "Failed to deselect agent from My Agents.",
);
+ return null;
}
}
diff --git a/desktop/tests/e2e/agent-readiness-screenshots.spec.ts b/desktop/tests/e2e/agent-readiness-screenshots.spec.ts
index a92efcd40a..75e400d4a5 100644
--- a/desktop/tests/e2e/agent-readiness-screenshots.spec.ts
+++ b/desktop/tests/e2e/agent-readiness-screenshots.spec.ts
@@ -18,7 +18,6 @@ async function openCreateDialog(page: import("@playwright/test").Page) {
await page.goto("/");
await page.getByTestId("open-agents-view").click();
await page.getByTestId("new-agent-card").click();
- await page.getByRole("menuitem", { name: "Create agent" }).click();
await page.locator("#persona-display-name").fill("Test Agent");
}
diff --git a/desktop/tests/e2e/agents.spec.ts b/desktop/tests/e2e/agents.spec.ts
index befe2b5563..66f9e4e707 100644
--- a/desktop/tests/e2e/agents.spec.ts
+++ b/desktop/tests/e2e/agents.spec.ts
@@ -67,9 +67,6 @@ async function gotoApp(page: import("@playwright/test").Page) {
async function openPersonaCatalog(page: import("@playwright/test").Page) {
await page.getByTestId("new-agent-card").click();
- await page
- .getByRole("menuitem", { exact: true, name: "Discover agents" })
- .click();
}
async function getCatalogOrder(page: import("@playwright/test").Page) {
@@ -239,10 +236,8 @@ test("catalog hides built-ins and shows the shared-agent empty state", async ({
}
await expect(page.getByTestId("persona-catalog-dialog-header")).toBeVisible();
await expect(page.getByTestId("persona-catalog-dialog-body")).toBeVisible();
- const emptyState = page.getByTestId("persona-catalog-empty-state");
- await expect(emptyState).toContainText("No agents are being shared");
await expect(
- emptyState.getByTestId("persona-catalog-empty-agent-artwork"),
+ page.getByText("No shared agents", { exact: true }),
).toBeVisible();
await expect(
page.locator('[data-testid^="persona-catalog-list-item-"]'),
@@ -267,7 +262,9 @@ test("catalog empty state remains available after reopening", async ({
await gotoApp(page);
await page.getByTestId("open-agents-view").click();
await openPersonaCatalog(page);
- await expect(page.getByTestId("persona-catalog-empty-state")).toBeVisible();
+ await expect(
+ page.getByText("No shared agents", { exact: true }),
+ ).toBeVisible();
await page
.getByTestId("persona-catalog-dialog")
@@ -275,9 +272,9 @@ test("catalog empty state remains available after reopening", async ({
.click();
await expect(page.getByTestId("persona-catalog-dialog")).not.toBeVisible();
await openPersonaCatalog(page);
- await expect(page.getByTestId("persona-catalog-empty-state")).toContainText(
- "No agents are being shared",
- );
+ await expect(
+ page.getByText("No shared agents", { exact: true }),
+ ).toBeVisible();
});
test("built-in persona edits persist", async ({ page }) => {
@@ -319,9 +316,6 @@ test("searches agent avatar emoji with focus on open", async ({ page }) => {
await gotoApp(page);
await page.getByTestId("open-agents-view").click();
await page.getByTestId("new-agent-card").click();
- await page
- .getByRole("menuitem", { exact: true, name: "Create agent" })
- .click();
await expect(page.getByTestId("persona-dialog")).toBeVisible();
await page.getByLabel("Add avatar").click();
@@ -346,9 +340,6 @@ test("agent avatar emoji picker scrolls inside its popover", async ({
await gotoApp(page);
await page.getByTestId("open-agents-view").click();
await page.getByTestId("new-agent-card").click();
- await page
- .getByRole("menuitem", { exact: true, name: "Create agent" })
- .click();
await expect(page.getByTestId("persona-dialog")).toBeVisible();
await page.getByLabel("Add avatar").click();
@@ -385,7 +376,7 @@ test("agent avatar emoji picker scrolls inside its popover", async ({
.toBeGreaterThan(before);
});
-test("the new agent card offers create, discover, and import", async ({
+test("the new agent card opens unified create, catalog, and import flows", async ({
page,
}) => {
await installMockBridge(page, {
@@ -396,6 +387,11 @@ test("the new agent card offers create, discover, and import", async ({
displayName: "Code Reviewer",
systemPrompt: "Review code changes.",
},
+ {
+ id: "custom:layout-auditor",
+ displayName: "Layout Auditor",
+ systemPrompt: "Review responsive layouts.",
+ },
],
});
await gotoApp(page);
@@ -420,6 +416,9 @@ test("the new agent card offers create, discover, and import", async ({
}),
);
const firstRowTop = Math.min(...cardBoxes.map(({ top }) => top));
+ expect(
+ cardBoxes.filter(({ top }) => Math.abs(top - firstRowTop) < 1),
+ ).toHaveLength(5);
const rightmostFirstRowCard = Math.max(
...cardBoxes
.filter(({ top }) => Math.abs(top - firstRowTop) < 1)
@@ -437,27 +436,12 @@ test("the new agent card offers create, discover, and import", async ({
);
await newAgentCard.click();
- await expect(
- page.getByRole("menuitem", { exact: true, name: "Create agent" }),
- ).toBeVisible();
- await expect(
- page.getByRole("menuitem", { exact: true, name: "Discover agents" }),
- ).toBeVisible();
- await expect(
- page.getByRole("menuitem", { exact: true, name: "Import" }),
- ).toBeVisible();
- await page
- .getByRole("menuitem", { exact: true, name: "Discover agents" })
- .click();
- await expect(page.getByTestId("persona-catalog-dialog")).toBeVisible();
- await page
- .getByTestId("persona-catalog-dialog")
- .getByRole("button", { name: "Close" })
- .click();
- await newAgentCard.click();
- await page
- .getByRole("menuitem", { exact: true, name: "Create agent" })
- .click();
+ const catalogDialog = page.getByTestId("persona-catalog-dialog");
+ await expect(catalogDialog).toBeVisible();
+ await expect(page.getByTestId("agent-catalog-create")).toHaveAttribute(
+ "aria-current",
+ "true",
+ );
const dialog = page.getByTestId("persona-dialog");
await expect(dialog).toBeVisible();
@@ -466,10 +450,10 @@ test("the new agent card offers create, discover, and import", async ({
).toHaveCount(0);
await expect(dialog).not.toContainText("Enter a name for this agent.");
- await dialog.getByRole("button", { name: "Cancel" }).click();
- await newAgentCard.click();
+ await page.getByTestId("agent-catalog-import").click();
+ await expect(page.getByTestId("agent-catalog-import-dropzone")).toBeVisible();
const fileChooserPromise = page.waitForEvent("filechooser");
- await page.getByRole("menuitem", { exact: true, name: "Import" }).click();
+ await page.getByTestId("agent-catalog-import-dropzone").click();
const fileChooser = await fileChooserPromise;
await fileChooser.setFiles({
buffer: Buffer.from("{}"),
@@ -479,6 +463,31 @@ test("the new agent card offers create, discover, and import", async ({
await expect(page.getByTestId("agent-snapshot-import-dialog")).toBeVisible();
});
+test("embedded create keeps its draft when discard is cancelled", async ({
+ page,
+}) => {
+ await gotoApp(page);
+ await page.getByTestId("open-agents-view").click();
+ await page.getByTestId("new-agent-card").click();
+
+ const dialog = page.getByTestId("persona-dialog");
+ const name = dialog.locator("#persona-display-name");
+ const instructions = dialog.locator("#persona-system-prompt");
+ await name.fill("Draft Keeper");
+ await instructions.fill("Preserve this draft through confirmation.");
+
+ await dialog.getByRole("button", { name: "Cancel" }).click();
+ const discardDialog = page.getByTestId("discard-create-agent-dialog");
+ await expect(discardDialog).toBeVisible();
+ await discardDialog.getByRole("button", { name: "Keep editing" }).click();
+
+ await expect(dialog).toBeVisible();
+ await expect(name).toHaveValue("Draft Keeper");
+ await expect(instructions).toHaveValue(
+ "Preserve this draft through confirmation.",
+ );
+});
+
test("the new team card offers create and import", async ({ page }) => {
await gotoApp(page);
await page.getByTestId("open-agents-view").click();
@@ -542,12 +551,12 @@ test("team cards follow the agents grid alignment at compact widths", async ({
await agentsContent.evaluate((element) => {
(element as HTMLElement).style.width = "600px";
});
- await expect
- .poll(async () => (await firstAgentGridCard.boundingBox())?.x ?? 0)
- .toBeGreaterThan(wideAgentBox?.x ?? 0);
-
const compactAgentBox = await firstAgentGridCard.boundingBox();
const compactTeamBox = await firstTeamGridCard.boundingBox();
+ expect(compactAgentBox?.width ?? 0).toBeLessThan(wideAgentBox?.width ?? 0);
+ expect(
+ Math.abs((compactAgentBox?.width ?? 0) - (compactTeamBox?.width ?? 0)),
+ ).toBeLessThan(1);
expect(
Math.abs((compactAgentBox?.x ?? 0) - (compactTeamBox?.x ?? 0)),
).toBeLessThan(1);
@@ -1675,7 +1684,9 @@ test("a foreign reader does not receive an unshared kind 30175 persona", async (
await expect(
page.getByTestId(`persona-catalog-list-item-${remoteCatalogId}`),
).toHaveCount(0);
- await expect(page.getByTestId("persona-catalog-empty-state")).toBeVisible();
+ await expect(
+ page.getByText("No shared agents", { exact: true }),
+ ).toBeVisible();
});
test("a catalog entry keeps the owner's emoji avatar", async ({ page }) => {
diff --git a/desktop/tests/e2e/edit-agent.spec.ts b/desktop/tests/e2e/edit-agent.spec.ts
index 4c4834b552..e7fbe3d7bd 100644
--- a/desktop/tests/e2e/edit-agent.spec.ts
+++ b/desktop/tests/e2e/edit-agent.spec.ts
@@ -89,7 +89,6 @@ test.describe("agent definition dialog", () => {
await page.goto("/");
await page.getByTestId("open-agents-view").click();
await page.getByTestId("new-agent-card").click();
- await page.getByRole("menuitem", { name: "Create agent" }).click();
const dialog = page.getByRole("dialog");
await dialog.getByRole("button", { name: "Advanced", exact: true }).click();
diff --git a/desktop/tests/e2e/global-agent-config-screenshots.spec.ts b/desktop/tests/e2e/global-agent-config-screenshots.spec.ts
index 451989fb7f..534ea36e70 100644
--- a/desktop/tests/e2e/global-agent-config-screenshots.spec.ts
+++ b/desktop/tests/e2e/global-agent-config-screenshots.spec.ts
@@ -32,7 +32,6 @@ async function openCreateDialog(page: import("@playwright/test").Page) {
await page.goto("/");
await page.getByTestId("open-agents-view").click();
await page.getByTestId("new-agent-card").click();
- await page.getByRole("menuitem", { name: "Create agent" }).click();
await page.locator("#persona-display-name").fill("Test Agent");
}
@@ -713,7 +712,6 @@ test.describe("global agent config screenshots", () => {
await page.goto("/");
await page.getByTestId("open-agents-view").click();
await page.getByTestId("new-agent-card").click();
- await page.getByRole("menuitem", { name: "Create agent" }).click();
await expect(page.getByTestId("persona-dialog-submit")).toBeDisabled({
timeout: 10_000,
diff --git a/desktop/tests/e2e/inline-custom-harness.spec.ts b/desktop/tests/e2e/inline-custom-harness.spec.ts
index 6b3845d65a..1ef7e67bb7 100644
--- a/desktop/tests/e2e/inline-custom-harness.spec.ts
+++ b/desktop/tests/e2e/inline-custom-harness.spec.ts
@@ -50,7 +50,6 @@ async function openCreateDialog(page: Page) {
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByTestId("open-agents-view").click();
await page.getByTestId("new-agent-card").click();
- await page.getByRole("menuitem", { name: "Create agent" }).click();
const dialog = page.getByTestId("persona-dialog");
await expect(dialog).toBeVisible({ timeout: 10_000 });
await dialog.getByRole("tab", { name: "Customize for this agent" }).click();
diff --git a/desktop/tests/e2e/persona-env-vars.spec.ts b/desktop/tests/e2e/persona-env-vars.spec.ts
index 60a8e888b2..8827fd0bb8 100644
--- a/desktop/tests/e2e/persona-env-vars.spec.ts
+++ b/desktop/tests/e2e/persona-env-vars.spec.ts
@@ -267,10 +267,9 @@ test("env vars editor renders in PersonaDialog new-persona form", async ({
}) => {
await gotoApp(page);
- // Open the Agents view, then choose Create agent from the new-agent menu.
+ // Open the Agents view; the new-agent card opens the embedded create pane.
await page.getByTestId("open-agents-view").click();
await page.getByTestId("new-agent-card").click();
- await page.getByRole("menuitem", { name: "Create agent" }).click();
// Scope all env-vars queries to the dialog: AgentDefaultsSettingsCard
// also renders an EnvVarsEditor in the background settings pane (introduced
@@ -315,7 +314,6 @@ test("persona model options follow the selected LLM provider", async ({
await page.getByTestId("open-agents-view").click();
await page.getByTestId("new-agent-card").click();
- await page.getByRole("menuitem", { name: "Create agent" }).click();
const provider = page.locator("#persona-runtime");
await page.getByRole("tab", { name: "Customize for this agent" }).click();
diff --git a/desktop/tests/e2e/persona-model-combobox-screenshots.spec.ts b/desktop/tests/e2e/persona-model-combobox-screenshots.spec.ts
index 508b123d7f..5afc5344ba 100644
--- a/desktop/tests/e2e/persona-model-combobox-screenshots.spec.ts
+++ b/desktop/tests/e2e/persona-model-combobox-screenshots.spec.ts
@@ -36,7 +36,6 @@ async function openNewPersonaDialog(page: import("@playwright/test").Page) {
});
await page.getByTestId("new-agent-card").click();
- await page.getByRole("menuitem", { name: "Create agent" }).click();
const dialog = page.getByTestId("persona-dialog");
await expect(dialog).toBeVisible({ timeout: 8_000 });
diff --git a/desktop/tests/e2e/smoke.spec.ts b/desktop/tests/e2e/smoke.spec.ts
index 2aa9f890f3..58ed297594 100644
--- a/desktop/tests/e2e/smoke.spec.ts
+++ b/desktop/tests/e2e/smoke.spec.ts
@@ -138,7 +138,6 @@ test("Buzz shared compute explains automatic model selection", async ({
});
await page.getByTestId("open-agents-view").click();
await page.getByTestId("new-agent-card").click();
- await page.getByRole("menuitem", { name: "Create agent" }).click();
await chooseSharedComputeProvider(page);
await expect
@@ -167,7 +166,6 @@ test("create agent persists Buzz shared compute with auto model", async ({
await page.goto("/");
await page.getByTestId("open-agents-view").click();
await page.getByTestId("new-agent-card").click();
- await page.getByRole("menuitem", { name: "Create agent" }).click();
await page.locator("#persona-display-name").fill(agentName);
await chooseSharedComputeProvider(page);
@@ -214,7 +212,6 @@ test("create agent supports parallelism and system prompt overrides", async ({
await page.goto("/");
await page.getByTestId("open-agents-view").click();
await page.getByTestId("new-agent-card").click();
- await page.getByRole("menuitem", { name: "Create agent" }).click();
await page.locator("#persona-display-name").fill(agentName);
await page
diff --git a/desktop/tests/e2e/where-to-run-config.spec.ts b/desktop/tests/e2e/where-to-run-config.spec.ts
index 1aa2f5c126..dde0f70392 100644
--- a/desktop/tests/e2e/where-to-run-config.spec.ts
+++ b/desktop/tests/e2e/where-to-run-config.spec.ts
@@ -92,7 +92,6 @@ async function openCreateDialogOnProvider(page: Page) {
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByTestId("open-agents-view").click();
await page.getByTestId("new-agent-card").click();
- await page.getByRole("menuitem", { name: "Create agent" }).click();
const dialog = page.getByTestId("persona-dialog");
await expect(dialog).toBeVisible({ timeout: 10_000 });
const advanced = dialog.getByRole("button", {
@@ -131,7 +130,7 @@ test("typing into a defaultless provider field sticks and probes only once", asy
);
await expect(contextField).toHaveValue("");
- await contextField.pressSequentially("prod-us-west", { delay: 20 });
+ await contextField.fill("prod-us-west");
await expect(contextField).toHaveValue("prod-us-west");
// One selection, one probe — keystrokes and Advanced disclosure toggles