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,
|
mcp_servers: agentType.mcp_servers,
|
||||||
tool_permissions: agentType.tool_permissions,
|
tool_permissions: agentType.tool_permissions,
|
||||||
is_active: agentType.is_active,
|
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 {
|
return {
|
||||||
|
|||||||
@@ -5,6 +5,68 @@
|
|||||||
* Used for type-safe API communication with the agent-types endpoints.
|
* 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
|
* Base agent type fields shared across create, update, and response schemas
|
||||||
*/
|
*/
|
||||||
@@ -20,6 +82,13 @@ export interface AgentTypeBase {
|
|||||||
mcp_servers: string[];
|
mcp_servers: string[];
|
||||||
tool_permissions: Record<string, unknown>;
|
tool_permissions: Record<string, unknown>;
|
||||||
is_active: boolean;
|
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[];
|
mcp_servers?: string[];
|
||||||
tool_permissions?: Record<string, unknown>;
|
tool_permissions?: Record<string, unknown>;
|
||||||
is_active?: boolean;
|
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;
|
mcp_servers?: string[] | null;
|
||||||
tool_permissions?: Record<string, unknown> | null;
|
tool_permissions?: Record<string, unknown> | null;
|
||||||
is_active?: boolean | 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[];
|
mcp_servers: string[];
|
||||||
tool_permissions: Record<string, unknown>;
|
tool_permissions: Record<string, unknown>;
|
||||||
is_active: boolean;
|
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;
|
created_at: string;
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
instance_count: number;
|
instance_count: number;
|
||||||
@@ -104,9 +194,15 @@ export interface AgentTypeListParams {
|
|||||||
page?: number;
|
page?: number;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
is_active?: boolean;
|
is_active?: boolean;
|
||||||
|
category?: AgentTypeCategory;
|
||||||
search?: string;
|
search?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response type for grouped agent types by category
|
||||||
|
*/
|
||||||
|
export type AgentTypeGroupedResponse = Record<string, AgentTypeResponse[]>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model parameter configuration with typed fields
|
* Model parameter configuration with typed fields
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,12 +6,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
import type { AgentTypeCategory } from '@/lib/api/types/agentTypes';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Slug validation regex: lowercase letters, numbers, and hyphens only
|
* Slug validation regex: lowercase letters, numbers, and hyphens only
|
||||||
*/
|
*/
|
||||||
const slugRegex = /^[a-z0-9-]+$/;
|
const slugRegex = /^[a-z0-9-]+$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hex color validation regex
|
||||||
|
*/
|
||||||
|
const hexColorRegex = /^#[0-9A-Fa-f]{6}$/;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Available AI models for agent types
|
* Available AI models for agent types
|
||||||
*/
|
*/
|
||||||
@@ -43,6 +49,84 @@ export const AGENT_TYPE_STATUS = [
|
|||||||
{ value: false, label: 'Inactive' },
|
{ value: false, label: 'Inactive' },
|
||||||
] as const;
|
] 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
|
* Model params schema
|
||||||
*/
|
*/
|
||||||
@@ -52,6 +136,20 @@ const modelParamsSchema = z.object({
|
|||||||
top_p: z.number().min(0).max(1),
|
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
|
* Schema for agent type form fields
|
||||||
*/
|
*/
|
||||||
@@ -96,6 +194,23 @@ export const agentTypeFormSchema = z.object({
|
|||||||
tool_permissions: z.record(z.string(), z.unknown()),
|
tool_permissions: z.record(z.string(), z.unknown()),
|
||||||
|
|
||||||
is_active: z.boolean(),
|
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: [],
|
mcp_servers: [],
|
||||||
tool_permissions: {},
|
tool_permissions: {},
|
||||||
is_active: false, // Start as draft
|
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'],
|
mcp_servers: ['gitea', 'knowledge', 'filesystem'],
|
||||||
tool_permissions: {},
|
tool_permissions: {},
|
||||||
is_active: true,
|
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',
|
created_at: '2025-01-10T00:00:00Z',
|
||||||
updated_at: '2025-01-18T00:00:00Z',
|
updated_at: '2025-01-18T00:00:00Z',
|
||||||
instance_count: 2,
|
instance_count: 2,
|
||||||
|
|||||||
@@ -16,6 +16,13 @@ const mockAgentType: AgentTypeResponse = {
|
|||||||
mcp_servers: ['gitea'],
|
mcp_servers: ['gitea'],
|
||||||
tool_permissions: {},
|
tool_permissions: {},
|
||||||
is_active: true,
|
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',
|
created_at: '2025-01-10T00:00:00Z',
|
||||||
updated_at: '2025-01-18T00:00:00Z',
|
updated_at: '2025-01-18T00:00:00Z',
|
||||||
instance_count: 2,
|
instance_count: 2,
|
||||||
|
|||||||
@@ -17,6 +17,13 @@ const mockAgentTypes: AgentTypeResponse[] = [
|
|||||||
mcp_servers: ['gitea', 'knowledge'],
|
mcp_servers: ['gitea', 'knowledge'],
|
||||||
tool_permissions: {},
|
tool_permissions: {},
|
||||||
is_active: true,
|
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',
|
created_at: '2025-01-15T00:00:00Z',
|
||||||
updated_at: '2025-01-20T00:00:00Z',
|
updated_at: '2025-01-20T00:00:00Z',
|
||||||
instance_count: 3,
|
instance_count: 3,
|
||||||
@@ -34,6 +41,13 @@ const mockAgentTypes: AgentTypeResponse[] = [
|
|||||||
mcp_servers: ['gitea'],
|
mcp_servers: ['gitea'],
|
||||||
tool_permissions: {},
|
tool_permissions: {},
|
||||||
is_active: false,
|
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',
|
created_at: '2025-01-10T00:00:00Z',
|
||||||
updated_at: '2025-01-18T00:00:00Z',
|
updated_at: '2025-01-18T00:00:00Z',
|
||||||
instance_count: 0,
|
instance_count: 0,
|
||||||
|
|||||||
Reference in New Issue
Block a user