import type { AgentInviteOptionResponse } from '@dify/contracts/api/console/agent/types.gen' import type { ComboboxChangeEventDetails } from '@langgenius/dify-ui/combobox' import type { NodeDefault } from '../types' import type { AgentRosterNodeData } from './types' import { cn } from '@langgenius/dify-ui/cn' import { Combobox, ComboboxInput, ComboboxInputGroup, ComboboxItem, ComboboxItemText, ComboboxList, ComboboxStatus, } from '@langgenius/dify-ui/combobox' import { Popover, PopoverContent, PopoverTitle, PopoverTrigger } from '@langgenius/dify-ui/popover' import { toast } from '@langgenius/dify-ui/toast' import { useQuery } from '@tanstack/react-query' import { useDebounce } from 'ahooks' import { useState } from 'react' import { useTranslation } from 'react-i18next' import AppIcon from '@/app/components/base/app-icon' import Badge from '@/app/components/base/badge' import { useHooksStore } from '@/app/components/workflow/hooks-store' import Link from '@/next/link' import { consoleQuery } from '@/service/client' import BlockIcon from '../block-icon' const AGENT_SELECTOR_PAGE_SIZE = 8 type AgentSelectorOption = AgentInviteOptionResponse | AgentSelectorActionOption type AgentSelectorActionOption = 'start-from-scratch' | 'manage-in-agent-console' export function AgentSelectorContent({ open, onOpenChange, onSelect, onStartFromScratch, }: { open: boolean onOpenChange: (open: boolean) => void onSelect: (agent: AgentRosterNodeData) => void onStartFromScratch?: () => void }) { const { t } = useTranslation(['agentV2', 'common', 'workflow']) const appId = useHooksStore((s) => s.configsMap?.flowId) const [searchText, setSearchText] = useState('') const debouncedSearchText = useDebounce(searchText.trim(), { wait: 300 }) const agentsQuery = useQuery({ ...consoleQuery.agent.inviteOptions.get.queryOptions({ input: { query: { limit: AGENT_SELECTOR_PAGE_SIZE, page: 1, ...(appId ? { app_id: appId } : {}), ...(debouncedSearchText ? { keyword: debouncedSearchText } : {}), }, }, }), staleTime: 0, }) const agents = agentsQuery.data?.data ?? [] const actionOptions: AgentSelectorActionOption[] = onStartFromScratch ? ['start-from-scratch', 'manage-in-agent-console'] : ['manage-in-agent-console'] const options: AgentSelectorOption[] = [...agents, ...actionOptions] const getOptionLabel = (option: AgentSelectorOption) => { if (isAgentSelectorActionOption(option)) { if (option === 'start-from-scratch') return t(($) => $['roster.nodeSelector.startFromScratch'], { ns: 'agentV2' }) return t(($) => $['roster.nodeSelector.manageInAgentConsole'], { ns: 'agentV2' }) } return option.name } const handleInputValueChange = (nextSearchText: string, details: ComboboxChangeEventDetails) => { if (details.reason !== 'item-press') setSearchText(nextSearchText) } const handleValueChange = (option: AgentSelectorOption | null) => { if (!option) return if (isAgentSelectorActionOption(option)) { if (option === 'start-from-scratch') onStartFromScratch?.() return } if (!option.active_config_snapshot_id) { toast.error(t(($) => $['nodes.agent.modelNotSelected'], { ns: 'workflow' })) return } onSelect(toAgentRosterNodeData(option)) } const handleOpenChange = (nextOpen: boolean) => { if (!nextOpen) onOpenChange(false) } const isLoading = agentsQuery.isPending return (