diff --git a/web/src/app/home/agents/components/AgentCreateContent.tsx b/web/src/app/home/agents/components/AgentCreateContent.tsx
index 9e6e8a972..66d7cd613 100644
--- a/web/src/app/home/agents/components/AgentCreateContent.tsx
+++ b/web/src/app/home/agents/components/AgentCreateContent.tsx
@@ -1,16 +1,14 @@
import { useState } from 'react';
-import type React from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
-import { Bot, CheckCircle2, Workflow } from 'lucide-react';
+import { Bot, Workflow } from 'lucide-react';
import { httpClient } from '@/app/infra/http/HttpClient';
import { AgentKind } from '@/app/infra/entities/api';
-import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
-import { Badge } from '@/components/ui/badge';
+import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
import {
Card,
CardContent,
@@ -79,26 +77,18 @@ export default function AgentCreateContent({
});
}
- const typeOptions: Array<{
- kind: AgentKind;
- icon: React.ElementType;
- title: string;
- description: string;
- badge: string;
- }> = [
+ const typeOptions = [
{
- kind: 'agent',
+ kind: 'agent' as const,
icon: Bot,
title: t('agents.agentType'),
- description: t('agents.agentTypeDescription'),
- badge: t('agents.allEvents'),
+ helper: t('agents.allEvents'),
},
{
- kind: 'pipeline',
+ kind: 'pipeline' as const,
icon: Workflow,
title: t('agents.pipelineType'),
- description: t('agents.pipelineTypeDescription'),
- badge: t('agents.messageEventsOnly'),
+ helper: t('agents.messageEventsOnly'),
},
];
@@ -131,63 +121,41 @@ export default function AgentCreateContent({
-
+ {
+ if (value) handleKindChange(value as AgentKind);
+ }}
+ variant="outline"
+ spacing={3}
+ className="grid w-full gap-3 sm:grid-cols-2 lg:grid-cols-1"
+ >
{typeOptions.map((option) => {
const Icon = option.icon;
- const selected = kind === option.kind;
return (
-
-
-
-
-
+
+
+
+
+
+ {option.title}
+
+
+ {option.helper}
+
+
+
);
})}
-
+
diff --git a/web/tests/e2e/crud-smoke.spec.ts b/web/tests/e2e/crud-smoke.spec.ts
index 5b1495d48..201ecec72 100644
--- a/web/tests/e2e/crud-smoke.spec.ts
+++ b/web/tests/e2e/crud-smoke.spec.ts
@@ -97,7 +97,7 @@ test.describe('frontend CRUD smoke flows', () => {
await expect(page).toHaveURL(/\/home\/bots\?id=bot-1$/);
await page.goto('/home/agents?id=new');
- await page.getByRole('button', { name: /^Pipeline/ }).click();
+ await page.getByRole('radio', { name: /^Pipeline/ }).click();
await page.locator('input[name="name"]').fill('Viewer Pipeline');
await page
.locator('input[name="description"]')
@@ -173,18 +173,20 @@ test.describe('frontend CRUD smoke flows', () => {
await page.goto('/home/agents?id=new');
const agentTypeCard = page.locator('[data-processor-kind="agent"]');
const pipelineTypeCard = page.locator('[data-processor-kind="pipeline"]');
- await expect(agentTypeCard).toHaveAttribute('data-slot', 'card');
- await expect(pipelineTypeCard).toHaveAttribute('data-slot', 'card');
- await expect(
- agentTypeCard.getByRole('button', { name: /^Agent/ }),
- ).toHaveAttribute('aria-pressed', 'true');
+ await expect(agentTypeCard).toHaveAttribute(
+ 'data-slot',
+ 'toggle-group-item',
+ );
+ await expect(pipelineTypeCard).toHaveAttribute(
+ 'data-slot',
+ 'toggle-group-item',
+ );
+ await expect(agentTypeCard).toHaveAttribute('aria-checked', 'true');
await expect(page.getByTestId('agent-diagram')).toBeVisible();
await expect(page.getByTestId('pipeline-diagram')).toHaveCount(0);
- await page.getByRole('button', { name: /^Pipeline/ }).click();
- await expect(
- pipelineTypeCard.getByRole('button', { name: /^Pipeline/ }),
- ).toHaveAttribute('aria-pressed', 'true');
+ await page.getByRole('radio', { name: /^Pipeline/ }).click();
+ await expect(pipelineTypeCard).toHaveAttribute('aria-checked', 'true');
await expect(page.getByTestId('pipeline-diagram')).toBeVisible();
await expect(page.getByTestId('agent-diagram')).toHaveCount(0);
@@ -734,7 +736,7 @@ test.describe('pipeline advanced flows', () => {
// Create a pipeline
await page.goto('/home/agents?id=new');
- await page.getByRole('button', { name: /^Pipeline/ }).click();
+ await page.getByRole('radio', { name: /^Pipeline/ }).click();
await page.locator('input[name="name"]').fill('Tab Test Pipeline');
await submit(page);
@@ -765,7 +767,7 @@ test.describe('pipeline advanced flows', () => {
// Create a pipeline
await page.goto('/home/agents?id=new');
- await page.getByRole('button', { name: /^Pipeline/ }).click();
+ await page.getByRole('radio', { name: /^Pipeline/ }).click();
await page.locator('input[name="name"]').fill('Dirty Form Pipeline');
await submit(page);
@@ -787,7 +789,7 @@ test.describe('pipeline advanced flows', () => {
await installLangBotApiMocks(page, { authenticated: true });
await page.goto('/home/agents?id=new');
- await page.getByRole('button', { name: /^Pipeline/ }).click();
+ await page.getByRole('radio', { name: /^Pipeline/ }).click();
// Submit without filling name
await submit(page);
@@ -1038,7 +1040,7 @@ test.describe('cross-resource flows', () => {
// Create a pipeline first
await page.goto('/home/agents?id=new');
- await page.getByRole('button', { name: /^Pipeline/ }).click();
+ await page.getByRole('radio', { name: /^Pipeline/ }).click();
await page.locator('input[name="name"]').fill('Production Pipeline');
await submit(page);
await expect(page).toHaveURL(/\/home\/agents\?id=pipeline-1$/);