From 702612e3f9189e6502c80d4d383c35920c6621f1 Mon Sep 17 00:00:00 2001 From: icarus Date: Sun, 14 Sep 2025 03:59:21 +0800 Subject: [PATCH] feat(agent): implement AddAgentPopup - Add isAgentType function to validate agent type strings - Update i18n files with new agent type validation messages - Add common validation error messages and success notifications --- .../src/components/Popups/AddAgentPopup.tsx | 240 +++++++++++++----- src/renderer/src/i18n/locales/en-us.json | 19 ++ src/renderer/src/i18n/locales/zh-cn.json | 20 +- src/renderer/src/types/agent.ts | 4 + 4 files changed, 221 insertions(+), 62 deletions(-) diff --git a/src/renderer/src/components/Popups/AddAgentPopup.tsx b/src/renderer/src/components/Popups/AddAgentPopup.tsx index ee930f77f5..2cb11b731c 100644 --- a/src/renderer/src/components/Popups/AddAgentPopup.tsx +++ b/src/renderer/src/components/Popups/AddAgentPopup.tsx @@ -2,6 +2,7 @@ import { Avatar, Button, Form, + Input, Modal, ModalBody, ModalContent, @@ -10,26 +11,47 @@ import { Select, SelectedItemProps, SelectedItems, - SelectItem + SelectItem, + Textarea } from '@heroui/react' -import ClaudeCodeIcon from '@renderer/assets/images/models/claude.png' +import { loggerService } from '@logger' +import ClaudeIcon from '@renderer/assets/images/models/claude.png' import { TopView } from '@renderer/components/TopView' import { useAgents } from '@renderer/hooks/useAgents' import { useTimer } from '@renderer/hooks/useTimer' import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' -import { AgentEntity } from '@renderer/types' +import { AgentEntity, isAgentType } from '@renderer/types' import { uuid } from '@renderer/utils' -import { useCallback, useMemo, useRef, useState } from 'react' +import { ChangeEvent, FormEvent, useCallback, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' +import { ErrorBoundary } from '../ErrorBoundary' + +const logger = loggerService.withContext('AddAgentPopup') interface Props { resolve: (value: AgentEntity | undefined) => void } -type AgentTypeOption = { +interface Option { + key: string + label: string + // img src + avatar: string +} + +interface AgentTypeOption extends Option { key: AgentEntity['type'] name: AgentEntity['name'] - avatar: AgentEntity['avatar'] +} + +type ModelOption = Option + +type AgentForm = { + type: AgentEntity['type'] + name: AgentEntity['name'] + description?: AgentEntity['description'] + instructions?: AgentEntity['instructions'] + model?: AgentEntity['model'] } const PopupContainer: React.FC = ({ resolve }) => { @@ -37,10 +59,17 @@ const PopupContainer: React.FC = ({ resolve }) => { const { t } = useTranslation() const loadingRef = useRef(false) const { setTimeoutTimer } = useTimer() + // eslint-disable-next-line @typescript-eslint/no-unused-vars const { addAgent } = useAgents() + // default values. may change to undefined. + const [form, setForm] = useState({ + type: 'claude-code', + name: 'Claude Code', + model: 'claude-4-sonnet' + }) const Option = useCallback( - ({ option }: { option?: AgentTypeOption | null }) => { + ({ option }: { option?: Option | null }) => { if (!option) { return (
@@ -52,31 +81,29 @@ const PopupContainer: React.FC = ({ resolve }) => { return (
- {option.name} + {option.label}
) }, [t] ) - const Item = useCallback( - ({ item }: { item: SelectedItemProps }) =>