diff --git a/client/src/components/SidePanel/Agents/AgentConfig.tsx b/client/src/components/SidePanel/Agents/AgentConfig.tsx index 5d6c9a7cf5..886fba3785 100644 --- a/client/src/components/SidePanel/Agents/AgentConfig.tsx +++ b/client/src/components/SidePanel/Agents/AgentConfig.tsx @@ -8,6 +8,7 @@ import { processAgentOption, getEndpointField, defaultTextProps, + validateEmail, getIconKey, cn, } from '~/utils'; @@ -445,10 +446,8 @@ export default function AgentConfig({ createMutation }: Pick + validateEmail(value ?? '', localize('com_ui_support_contact_email_invalid')), }} render={({ field, fieldState: { error } }) => ( <> diff --git a/client/src/components/SidePanel/Agents/AgentPanel.tsx b/client/src/components/SidePanel/Agents/AgentPanel.tsx index 6d9d643ba3..96fc43d27e 100644 --- a/client/src/components/SidePanel/Agents/AgentPanel.tsx +++ b/client/src/components/SidePanel/Agents/AgentPanel.tsx @@ -72,6 +72,7 @@ export default function AgentPanel() { const models = useMemo(() => modelsQuery.data ?? {}, [modelsQuery.data]); const methods = useForm({ defaultValues: getDefaultAgentFormValues(), + mode: 'onChange', }); const { control, handleSubmit, reset } = methods; diff --git a/client/src/components/SidePanel/Agents/MCPPanel.tsx b/client/src/components/SidePanel/Agents/MCPPanel.tsx index 6e793f13f6..e207a15300 100644 --- a/client/src/components/SidePanel/Agents/MCPPanel.tsx +++ b/client/src/components/SidePanel/Agents/MCPPanel.tsx @@ -65,6 +65,7 @@ export default function MCPPanel() { const methods = useForm({ defaultValues: defaultMCPFormValues, + mode: 'onChange', }); const { reset } = methods; diff --git a/client/src/utils/email.ts b/client/src/utils/email.ts new file mode 100644 index 0000000000..b1ad6d7d1c --- /dev/null +++ b/client/src/utils/email.ts @@ -0,0 +1,28 @@ +import { z } from 'zod'; + +/** + * Zod email validation schema + * Uses Zod's built-in email validation which is more robust than simple regex + * Based on: https://zod.dev/api?id=emails + */ +export const emailSchema = z.string().email(); + +/** + * Validates an email address using Zod + * @param email - The email address to validate + * @param errorMessage - Optional custom error message (defaults to Zod's message) + * @returns true if valid, error message if invalid + */ +export const validateEmail = (email: string, errorMessage?: string): true | string => { + if (!email || email.trim() === '') { + return true; + } + + const result = emailSchema.safeParse(email); + return ( + result.success || + errorMessage || + result.error.errors[0]?.message || + 'Please enter a valid email address' + ); +}; diff --git a/client/src/utils/index.ts b/client/src/utils/index.ts index 6fc179f560..07a1caecb1 100644 --- a/client/src/utils/index.ts +++ b/client/src/utils/index.ts @@ -18,6 +18,7 @@ export * from './resources'; export * from './roles'; export * from './localStorage'; export * from './promptGroups'; +export * from './email'; export { default as cn } from './cn'; export { default as logger } from './logger'; export { default as buildTree } from './buildTree';