'use client' import type { AgentPublicationCountsResponse } from '@dify/contracts/api/console/agent/types.gen' import type { AgentRosterListState } from './components/agent-roster-list' import { ScrollArea, ScrollAreaContent, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport, } from '@langgenius/dify-ui/scroll-area' import { keepPreviousData, useInfiniteQuery } from '@tanstack/react-query' import { useDebounce } from 'ahooks' import { useQueryState } from 'nuqs' import { useId } from 'react' import { useTranslation } from 'react-i18next' import { useDocLink } from '@/context/i18n' import useDocumentTitle from '@/hooks/use-document-title' import { consoleQuery } from '@/service/client' import { AgentRosterList } from './components/agent-roster-list' import { RosterToolbar } from './components/roster-toolbar' import { rosterCreatedByMeQueryParser, rosterFilterQueryParser, rosterKeywordQueryParser, rosterQueryParamNames, rosterSortByQueryParser, } from './query-params' const ROSTER_PAGE_SIZE = 30 const EMPTY_PUBLICATION_COUNTS: AgentPublicationCountsResponse = { drafts: 0, published: 0, } export default function RosterPage() { const { t } = useTranslation('agentV2') const docLink = useDocLink() const [keyword] = useQueryState(rosterQueryParamNames.keyword, rosterKeywordQueryParser) const [rosterFilter] = useQueryState(rosterQueryParamNames.filter, rosterFilterQueryParser) const [createdByMe] = useQueryState( rosterQueryParamNames.createdByMe, rosterCreatedByMeQueryParser, ) const [sortBy] = useQueryState(rosterQueryParamNames.sortBy, rosterSortByQueryParser) const debouncedKeyword = useDebounce(keyword.trim(), { wait: 300 }) const rosterQueryInput = { limit: ROSTER_PAGE_SIZE, sort_by: sortBy, ...(debouncedKeyword ? { name: debouncedKeyword } : {}), ...(createdByMe ? { is_created_by_me: true } : {}), ...(rosterFilter !== 'all' ? { publication_status: rosterFilter } : {}), } const { data: rosterPages, isPending, isFetching, isFetchingNextPage, isFetchNextPageError, fetchNextPage, hasNextPage, isLoadingError, isRefetchError, refetch, } = useInfiniteQuery({ ...consoleQuery.agent.get.infiniteOptions({ input: (pageParam) => ({ query: { ...rosterQueryInput, page: Number(pageParam), }, }), getNextPageParam: (lastPage) => (lastPage.has_more ? lastPage.page + 1 : undefined), initialPageParam: 1, }), placeholderData: keepPreviousData, }) const rosterItems = rosterPages?.pages.flatMap((page) => page.data) ?? [] const publicationCounts = rosterPages?.pages[0]?.publication_counts ?? EMPTY_PUBLICATION_COUNTS const pageTitle = t(($) => $['roster.title']) const pageTitleId = useId() const listState: AgentRosterListState = isLoadingError ? { status: 'error', onRetry: () => void refetch() } : isPending ? { status: 'pending' } : { status: 'ready', agents: rosterItems, emptyState: debouncedKeyword || rosterFilter !== 'all' || createdByMe ? 'filtered' : 'roster', footer: isFetchNextPageError ? { status: 'error', onRetry: () => void fetchNextPage() } : isRefetchError ? { status: 'error', onRetry: () => void refetch() } : hasNextPage ? { status: 'load-more', isLoading: isFetchingNextPage, onLoadMore: () => void fetchNextPage(), } : { status: 'none' }, isFetching, } useDocumentTitle(pageTitle) return (