+
+
+
+
+ {isSearch ? t('roster.emptySearch') : t('roster.empty')}
+
+
+ {isSearch ? t('roster.emptySearchDescription') : t('roster.emptyDescription')}
+
+
+ )
+}
+
+function AgentRosterItem({
+ agent,
+}: {
+ agent: AgentRosterResponse
+}) {
+ const { t: tAgentV2 } = useTranslation('agentV2')
+ const version = agent.active_config_snapshot?.version
+
+ return (
+
+
+
+ {agent.icon_type === 'emoji' && agent.icon
+ ? {agent.icon}
+ : }
+
+
+
+
+ {agent.name}
+
+ {version != null && (
+
+ {version}
+
+ )}
+
+ {agent.description && (
+
+ {agent.description}
+
+ )}
+
+
+
+
+ {tAgentV2(getSourceLabelKey(agent.source))}
+
+
+
+
+ {tAgentV2(`roster.status.${agent.status}`)}
+
+ {agent.updated_at &&
{agent.updated_at}
}
+
+
+
+
+ )
+}
+
+export function AgentRosterList({
+ agents,
+ hasMore,
+ isEmptySearch,
+ isError,
+ isFetching,
+ isFetchingNextPage,
+ isPending,
+ onLoadMore,
+}: AgentRosterListProps) {
+ const { t } = useTranslation('agentV2')
+
+ return (
+
+ {isPending &&
}
+ {!isPending && isError && (
+
+
{t('roster.loadingError')}
+
+ )}
+ {!isPending && !isError && agents.length === 0 && (
+
+ )}
+ {!isPending && !isError && agents.map(agent => (
+
+ ))}
+ {!isPending && !isError && hasMore && (
+
+
+
+ )}
+
+ )
+}
diff --git a/web/features/agent-v2/roster/components/archive-agent-button.tsx b/web/features/agent-v2/roster/components/archive-agent-button.tsx
new file mode 100644
index 00000000000..18ce1560581
--- /dev/null
+++ b/web/features/agent-v2/roster/components/archive-agent-button.tsx
@@ -0,0 +1,92 @@
+'use client'
+
+import {
+ AlertDialog,
+ AlertDialogActions,
+ AlertDialogCancelButton,
+ AlertDialogConfirmButton,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from '@langgenius/dify-ui/alert-dialog'
+import { Button } from '@langgenius/dify-ui/button'
+import { toast } from '@langgenius/dify-ui/toast'
+import { useMutation } from '@tanstack/react-query'
+import { useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import { consoleQuery } from '@/service/client'
+
+type ArchiveAgentButtonProps = {
+ agentId: string
+ agentName: string
+}
+
+export function ArchiveAgentButton({
+ agentId,
+ agentName,
+}: ArchiveAgentButtonProps) {
+ const { t } = useTranslation()
+ const { t: tAgentV2 } = useTranslation('agentV2')
+ const [open, setOpen] = useState(false)
+ const archiveAgentMutation = useMutation(consoleQuery.agents.byAgentId.delete.mutationOptions())
+
+ const handleArchive = () => {
+ if (archiveAgentMutation.isPending)
+ return
+
+ archiveAgentMutation.mutate({
+ params: {
+ agent_id: agentId,
+ },
+ }, {
+ onSuccess: () => {
+ toast.success(tAgentV2('roster.archiveSuccess'))
+ setOpen(false)
+ },
+ onError: () => {
+ toast.error(tAgentV2('roster.archiveFailed'))
+ },
+ })
+ }
+
+ return (
+