forked from cardosofelipe/fast-next-template
feat(agents): add frontend types and validation for category fields
Frontend changes to support new AgentType category and display fields: Types (agentTypes.ts): - Add AgentTypeCategory union type with 8 categories - Add CATEGORY_METADATA constant with labels, descriptions, colors - Update all interfaces with new fields (category, icon, color, etc.) - Add AgentTypeGroupedResponse type Validation (agentType.ts): - Add AGENT_TYPE_CATEGORIES constant with metadata - Add AVAILABLE_ICONS constant for icon picker - Add COLOR_PALETTE constant for color selection - Update agentTypeFormSchema with new field validators - Update defaultAgentTypeValues with new fields Form updates: - Transform function now maps category and display fields from API Test updates: - Add new fields to mock AgentTypeResponse objects 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -96,6 +96,13 @@ function transformAgentTypeToFormValues(
|
||||
mcp_servers: agentType.mcp_servers,
|
||||
tool_permissions: agentType.tool_permissions,
|
||||
is_active: agentType.is_active,
|
||||
// Category and display fields
|
||||
category: agentType.category,
|
||||
icon: agentType.icon,
|
||||
color: agentType.color,
|
||||
sort_order: agentType.sort_order ?? 0,
|
||||
typical_tasks: agentType.typical_tasks ?? [],
|
||||
collaboration_hints: agentType.collaboration_hints ?? [],
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -5,6 +5,68 @@
|
||||
* Used for type-safe API communication with the agent-types endpoints.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Category classification for agent types
|
||||
*/
|
||||
export type AgentTypeCategory =
|
||||
| 'development'
|
||||
| 'design'
|
||||
| 'quality'
|
||||
| 'operations'
|
||||
| 'ai_ml'
|
||||
| 'data'
|
||||
| 'leadership'
|
||||
| 'domain_expert';
|
||||
|
||||
/**
|
||||
* Metadata for each category including display label and description
|
||||
*/
|
||||
export const CATEGORY_METADATA: Record<
|
||||
AgentTypeCategory,
|
||||
{ label: string; description: string; color: string }
|
||||
> = {
|
||||
development: {
|
||||
label: 'Development',
|
||||
description: 'Product, project, and engineering roles',
|
||||
color: '#3B82F6',
|
||||
},
|
||||
design: {
|
||||
label: 'Design',
|
||||
description: 'UI/UX and design research',
|
||||
color: '#EC4899',
|
||||
},
|
||||
quality: {
|
||||
label: 'Quality',
|
||||
description: 'QA and security assurance',
|
||||
color: '#10B981',
|
||||
},
|
||||
operations: {
|
||||
label: 'Operations',
|
||||
description: 'DevOps and MLOps engineering',
|
||||
color: '#F59E0B',
|
||||
},
|
||||
ai_ml: {
|
||||
label: 'AI & ML',
|
||||
description: 'Machine learning specialists',
|
||||
color: '#8B5CF6',
|
||||
},
|
||||
data: {
|
||||
label: 'Data',
|
||||
description: 'Data science and engineering',
|
||||
color: '#06B6D4',
|
||||
},
|
||||
leadership: {
|
||||
label: 'Leadership',
|
||||
description: 'Technical leadership and facilitation',
|
||||
color: '#F97316',
|
||||
},
|
||||
domain_expert: {
|
||||
label: 'Domain Experts',
|
||||
description: 'Industry and domain specialists',
|
||||
color: '#84CC16',
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Base agent type fields shared across create, update, and response schemas
|
||||
*/
|
||||
@@ -20,6 +82,13 @@ export interface AgentTypeBase {
|
||||
mcp_servers: string[];
|
||||
tool_permissions: Record<string, unknown>;
|
||||
is_active: boolean;
|
||||
// Category and display fields
|
||||
category?: AgentTypeCategory | null;
|
||||
icon?: string | null;
|
||||
color?: string | null;
|
||||
sort_order: number;
|
||||
typical_tasks: string[];
|
||||
collaboration_hints: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,6 +106,13 @@ export interface AgentTypeCreate {
|
||||
mcp_servers?: string[];
|
||||
tool_permissions?: Record<string, unknown>;
|
||||
is_active?: boolean;
|
||||
// Category and display fields
|
||||
category?: AgentTypeCategory | null;
|
||||
icon?: string | null;
|
||||
color?: string | null;
|
||||
sort_order?: number;
|
||||
typical_tasks?: string[];
|
||||
collaboration_hints?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,6 +130,13 @@ export interface AgentTypeUpdate {
|
||||
mcp_servers?: string[] | null;
|
||||
tool_permissions?: Record<string, unknown> | null;
|
||||
is_active?: boolean | null;
|
||||
// Category and display fields
|
||||
category?: AgentTypeCategory | null;
|
||||
icon?: string | null;
|
||||
color?: string | null;
|
||||
sort_order?: number | null;
|
||||
typical_tasks?: string[] | null;
|
||||
collaboration_hints?: string[] | null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,6 +155,13 @@ export interface AgentTypeResponse {
|
||||
mcp_servers: string[];
|
||||
tool_permissions: Record<string, unknown>;
|
||||
is_active: boolean;
|
||||
// Category and display fields
|
||||
category: AgentTypeCategory | null;
|
||||
icon: string | null;
|
||||
color: string | null;
|
||||
sort_order: number;
|
||||
typical_tasks: string[];
|
||||
collaboration_hints: string[];
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
instance_count: number;
|
||||
@@ -104,9 +194,15 @@ export interface AgentTypeListParams {
|
||||
page?: number;
|
||||
limit?: number;
|
||||
is_active?: boolean;
|
||||
category?: AgentTypeCategory;
|
||||
search?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response type for grouped agent types by category
|
||||
*/
|
||||
export type AgentTypeGroupedResponse = Record<string, AgentTypeResponse[]>;
|
||||
|
||||
/**
|
||||
* Model parameter configuration with typed fields
|
||||
*/
|
||||
|
||||
@@ -6,12 +6,18 @@
|
||||
*/
|
||||
|
||||
import { z } from 'zod';
|
||||
import type { AgentTypeCategory } from '@/lib/api/types/agentTypes';
|
||||
|
||||
/**
|
||||
* Slug validation regex: lowercase letters, numbers, and hyphens only
|
||||
*/
|
||||
const slugRegex = /^[a-z0-9-]+$/;
|
||||
|
||||
/**
|
||||
* Hex color validation regex
|
||||
*/
|
||||
const hexColorRegex = /^#[0-9A-Fa-f]{6}$/;
|
||||
|
||||
/**
|
||||
* Available AI models for agent types
|
||||
*/
|
||||
@@ -43,6 +49,84 @@ export const AGENT_TYPE_STATUS = [
|
||||
{ value: false, label: 'Inactive' },
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Agent type categories for organizing agents
|
||||
*/
|
||||
/* istanbul ignore next -- constant declaration */
|
||||
export const AGENT_TYPE_CATEGORIES: {
|
||||
value: AgentTypeCategory;
|
||||
label: string;
|
||||
description: string;
|
||||
}[] = [
|
||||
{ value: 'development', label: 'Development', description: 'Product, project, and engineering' },
|
||||
{ value: 'design', label: 'Design', description: 'UI/UX and design research' },
|
||||
{ value: 'quality', label: 'Quality', description: 'QA and security assurance' },
|
||||
{ value: 'operations', label: 'Operations', description: 'DevOps and MLOps engineering' },
|
||||
{ value: 'ai_ml', label: 'AI & ML', description: 'Machine learning specialists' },
|
||||
{ value: 'data', label: 'Data', description: 'Data science and engineering' },
|
||||
{ value: 'leadership', label: 'Leadership', description: 'Technical leadership' },
|
||||
{ value: 'domain_expert', label: 'Domain Experts', description: 'Industry specialists' },
|
||||
];
|
||||
|
||||
/**
|
||||
* Available Lucide icons for agent types
|
||||
*/
|
||||
/* istanbul ignore next -- constant declaration */
|
||||
export const AVAILABLE_ICONS = [
|
||||
// Development
|
||||
{ value: 'clipboard-check', label: 'Clipboard Check', category: 'development' },
|
||||
{ value: 'briefcase', label: 'Briefcase', category: 'development' },
|
||||
{ value: 'file-text', label: 'File Text', category: 'development' },
|
||||
{ value: 'git-branch', label: 'Git Branch', category: 'development' },
|
||||
{ value: 'code', label: 'Code', category: 'development' },
|
||||
{ value: 'server', label: 'Server', category: 'development' },
|
||||
{ value: 'layout', label: 'Layout', category: 'development' },
|
||||
{ value: 'smartphone', label: 'Smartphone', category: 'development' },
|
||||
// Design
|
||||
{ value: 'palette', label: 'Palette', category: 'design' },
|
||||
{ value: 'search', label: 'Search', category: 'design' },
|
||||
// Quality
|
||||
{ value: 'shield', label: 'Shield', category: 'quality' },
|
||||
{ value: 'shield-check', label: 'Shield Check', category: 'quality' },
|
||||
// Operations
|
||||
{ value: 'settings', label: 'Settings', category: 'operations' },
|
||||
{ value: 'settings-2', label: 'Settings 2', category: 'operations' },
|
||||
// AI/ML
|
||||
{ value: 'brain', label: 'Brain', category: 'ai_ml' },
|
||||
{ value: 'microscope', label: 'Microscope', category: 'ai_ml' },
|
||||
{ value: 'eye', label: 'Eye', category: 'ai_ml' },
|
||||
{ value: 'message-square', label: 'Message Square', category: 'ai_ml' },
|
||||
// Data
|
||||
{ value: 'bar-chart', label: 'Bar Chart', category: 'data' },
|
||||
{ value: 'database', label: 'Database', category: 'data' },
|
||||
// Leadership
|
||||
{ value: 'users', label: 'Users', category: 'leadership' },
|
||||
{ value: 'target', label: 'Target', category: 'leadership' },
|
||||
// Domain Expert
|
||||
{ value: 'calculator', label: 'Calculator', category: 'domain_expert' },
|
||||
{ value: 'heart-pulse', label: 'Heart Pulse', category: 'domain_expert' },
|
||||
{ value: 'flask-conical', label: 'Flask', category: 'domain_expert' },
|
||||
{ value: 'lightbulb', label: 'Lightbulb', category: 'domain_expert' },
|
||||
{ value: 'book-open', label: 'Book Open', category: 'domain_expert' },
|
||||
// Generic
|
||||
{ value: 'bot', label: 'Bot', category: 'generic' },
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Color palette for agent type visual distinction
|
||||
*/
|
||||
/* istanbul ignore next -- constant declaration */
|
||||
export const COLOR_PALETTE = [
|
||||
{ value: '#3B82F6', label: 'Blue', category: 'development' },
|
||||
{ value: '#EC4899', label: 'Pink', category: 'design' },
|
||||
{ value: '#10B981', label: 'Green', category: 'quality' },
|
||||
{ value: '#F59E0B', label: 'Amber', category: 'operations' },
|
||||
{ value: '#8B5CF6', label: 'Purple', category: 'ai_ml' },
|
||||
{ value: '#06B6D4', label: 'Cyan', category: 'data' },
|
||||
{ value: '#F97316', label: 'Orange', category: 'leadership' },
|
||||
{ value: '#84CC16', label: 'Lime', category: 'domain_expert' },
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Model params schema
|
||||
*/
|
||||
@@ -52,6 +136,20 @@ const modelParamsSchema = z.object({
|
||||
top_p: z.number().min(0).max(1),
|
||||
});
|
||||
|
||||
/**
|
||||
* Agent type category enum values
|
||||
*/
|
||||
const agentTypeCategoryValues = [
|
||||
'development',
|
||||
'design',
|
||||
'quality',
|
||||
'operations',
|
||||
'ai_ml',
|
||||
'data',
|
||||
'leadership',
|
||||
'domain_expert',
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Schema for agent type form fields
|
||||
*/
|
||||
@@ -96,6 +194,23 @@ export const agentTypeFormSchema = z.object({
|
||||
tool_permissions: z.record(z.string(), z.unknown()),
|
||||
|
||||
is_active: z.boolean(),
|
||||
|
||||
// Category and display fields
|
||||
category: z.enum(agentTypeCategoryValues).nullable().optional(),
|
||||
|
||||
icon: z.string().max(50, 'Icon must be less than 50 characters').nullable().optional(),
|
||||
|
||||
color: z
|
||||
.string()
|
||||
.regex(hexColorRegex, 'Color must be a valid hex code (e.g., #3B82F6)')
|
||||
.nullable()
|
||||
.optional(),
|
||||
|
||||
sort_order: z.number().int().min(0).max(1000),
|
||||
|
||||
typical_tasks: z.array(z.string()),
|
||||
|
||||
collaboration_hints: z.array(z.string()),
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -138,6 +253,13 @@ export const defaultAgentTypeValues: AgentTypeCreateFormValues = {
|
||||
mcp_servers: [],
|
||||
tool_permissions: {},
|
||||
is_active: false, // Start as draft
|
||||
// Category and display fields
|
||||
category: null,
|
||||
icon: 'bot',
|
||||
color: '#3B82F6',
|
||||
sort_order: 0,
|
||||
typical_tasks: [],
|
||||
collaboration_hints: [],
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,13 @@ Your approach is:
|
||||
mcp_servers: ['gitea', 'knowledge', 'filesystem'],
|
||||
tool_permissions: {},
|
||||
is_active: true,
|
||||
// Category and display fields
|
||||
category: 'development',
|
||||
icon: 'git-branch',
|
||||
color: '#3B82F6',
|
||||
sort_order: 40,
|
||||
typical_tasks: ['Design system architecture', 'Create ADRs'],
|
||||
collaboration_hints: ['backend-engineer', 'frontend-engineer'],
|
||||
created_at: '2025-01-10T00:00:00Z',
|
||||
updated_at: '2025-01-18T00:00:00Z',
|
||||
instance_count: 2,
|
||||
|
||||
@@ -16,6 +16,13 @@ const mockAgentType: AgentTypeResponse = {
|
||||
mcp_servers: ['gitea'],
|
||||
tool_permissions: {},
|
||||
is_active: true,
|
||||
// Category and display fields
|
||||
category: 'development',
|
||||
icon: 'git-branch',
|
||||
color: '#3B82F6',
|
||||
sort_order: 40,
|
||||
typical_tasks: ['Design system architecture'],
|
||||
collaboration_hints: ['backend-engineer'],
|
||||
created_at: '2025-01-10T00:00:00Z',
|
||||
updated_at: '2025-01-18T00:00:00Z',
|
||||
instance_count: 2,
|
||||
|
||||
@@ -17,6 +17,13 @@ const mockAgentTypes: AgentTypeResponse[] = [
|
||||
mcp_servers: ['gitea', 'knowledge'],
|
||||
tool_permissions: {},
|
||||
is_active: true,
|
||||
// Category and display fields
|
||||
category: 'development',
|
||||
icon: 'clipboard-check',
|
||||
color: '#3B82F6',
|
||||
sort_order: 10,
|
||||
typical_tasks: ['Manage backlog', 'Write user stories'],
|
||||
collaboration_hints: ['business-analyst', 'scrum-master'],
|
||||
created_at: '2025-01-15T00:00:00Z',
|
||||
updated_at: '2025-01-20T00:00:00Z',
|
||||
instance_count: 3,
|
||||
@@ -34,6 +41,13 @@ const mockAgentTypes: AgentTypeResponse[] = [
|
||||
mcp_servers: ['gitea'],
|
||||
tool_permissions: {},
|
||||
is_active: false,
|
||||
// Category and display fields
|
||||
category: 'development',
|
||||
icon: 'git-branch',
|
||||
color: '#3B82F6',
|
||||
sort_order: 40,
|
||||
typical_tasks: ['Design architecture', 'Create ADRs'],
|
||||
collaboration_hints: ['backend-engineer', 'devops-engineer'],
|
||||
created_at: '2025-01-10T00:00:00Z',
|
||||
updated_at: '2025-01-18T00:00:00Z',
|
||||
instance_count: 0,
|
||||
|
||||
Reference in New Issue
Block a user