feat: install plugin button
This commit is contained in:
parent
5fb356fd33
commit
5ba0b85738
@ -83,7 +83,7 @@ export const AgentStrategySelector = memo((props: AgentStrategySelectorProps) =>
|
|||||||
if (!list) return []
|
if (!list) return []
|
||||||
return list.filter(tool => tool.name.toLowerCase().includes(query.toLowerCase()))
|
return list.filter(tool => tool.name.toLowerCase().includes(query.toLowerCase()))
|
||||||
}, [query, list])
|
}, [query, list])
|
||||||
const isShowError = (['plugin-not-found', 'strategy-not-found'] as Array<undefined | StrategyStatus>).includes(strategyStatus)
|
const showError = (['plugin-not-found', 'strategy-not-found'] as Array<undefined | StrategyStatus>).includes(strategyStatus)
|
||||||
const icon = list?.find(
|
const icon = list?.find(
|
||||||
coll => coll.tools?.find(tool => tool.name === value?.agent_strategy_name),
|
coll => coll.tools?.find(tool => tool.name === value?.agent_strategy_name),
|
||||||
)?.icon as string | undefined
|
)?.icon as string | undefined
|
||||||
@ -105,8 +105,8 @@ export const AgentStrategySelector = memo((props: AgentStrategySelectorProps) =>
|
|||||||
{value?.agent_strategy_label || t('workflow.nodes.agent.strategy.selectTip')}
|
{value?.agent_strategy_label || t('workflow.nodes.agent.strategy.selectTip')}
|
||||||
</p>
|
</p>
|
||||||
{value && <div className='ml-auto flex items-center gap-1'>
|
{value && <div className='ml-auto flex items-center gap-1'>
|
||||||
{strategyStatus === 'plugin-not-found' && <InstallPluginButton onClick={e => e.stopPropagation()} size={'small'} />}
|
{strategyStatus === 'plugin-not-found' && <InstallPluginButton onClick={e => e.stopPropagation()} size={'small'} uniqueIdentifier={value.plugin_unique_identifier} />}
|
||||||
{isShowError ? <ExternalNotInstallWarn /> : <RiArrowDownSLine className='size-4 text-text-tertiary' />}
|
{showError ? <ExternalNotInstallWarn /> : <RiArrowDownSLine className='size-4 text-text-tertiary' />}
|
||||||
</div>}
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
</PortalToFollowElemTrigger>
|
</PortalToFollowElemTrigger>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Button from '@/app/components/base/button'
|
import Button from '@/app/components/base/button'
|
||||||
import { RiInstallLine, RiLoader2Line } from '@remixicon/react'
|
import { RiInstallLine, RiLoader2Line } from '@remixicon/react'
|
||||||
import type { ComponentProps } from 'react'
|
import type { ComponentProps, MouseEventHandler } from 'react'
|
||||||
import classNames from '@/utils/classnames'
|
import classNames from '@/utils/classnames'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useCheckInstalled, useInstallPackageFromMarketPlace } from '@/service/use-plugins'
|
import { useCheckInstalled, useInstallPackageFromMarketPlace } from '@/service/use-plugins'
|
||||||
@ -21,13 +21,21 @@ export const InstallPluginButton = (props: InstallPluginButtonProps) => {
|
|||||||
manifest.refetch()
|
manifest.refetch()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const handleInstall = () => {
|
const handleInstall: MouseEventHandler = (e) => {
|
||||||
|
e.stopPropagation()
|
||||||
install.mutate(uniqueIdentifier)
|
install.mutate(uniqueIdentifier)
|
||||||
}
|
}
|
||||||
|
const isLoading = manifest.isLoading || install.isPending
|
||||||
if (!manifest.data) return null
|
if (!manifest.data) return null
|
||||||
if (manifest.data.plugins.some(plugin => plugin.id === uniqueIdentifier)) return null
|
if (manifest.data.plugins.some(plugin => plugin.id === uniqueIdentifier)) return null
|
||||||
return <Button variant={'secondary'} disabled={install.isPending} {...rest} onClick={handleInstall} className={classNames('flex items-center', className)} >
|
return <Button
|
||||||
{install.isPending ? t('workflow.nodes.agent.pluginInstaller.install') : t('workflow.nodes.agent.pluginInstaller.installing')}
|
variant={'secondary'}
|
||||||
{!install.isPending ? <RiInstallLine className='size-4 ml-1' /> : <RiLoader2Line className='size-4 ml-1 animate-spin' />}
|
disabled={isLoading}
|
||||||
|
{...rest}
|
||||||
|
onClick={handleInstall}
|
||||||
|
className={classNames('flex items-center', className)}
|
||||||
|
>
|
||||||
|
{!isLoading ? t('workflow.nodes.agent.pluginInstaller.install') : t('workflow.nodes.agent.pluginInstaller.installing')}
|
||||||
|
{!isLoading ? <RiInstallLine className='size-4 ml-1' /> : <RiLoader2Line className='size-4 ml-1 animate-spin' />}
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,12 @@ import {
|
|||||||
} from '@/app/components/workflow/hooks'
|
} from '@/app/components/workflow/hooks'
|
||||||
import { useCallback, useMemo } from 'react'
|
import { useCallback, useMemo } from 'react'
|
||||||
import { type ToolVarInputs, VarType } from '../tool/types'
|
import { type ToolVarInputs, VarType } from '../tool/types'
|
||||||
import { useCheckInstalled } from '@/service/use-plugins'
|
import { useCheckInstalled, useFetchPluginsInMarketPlaceByIds } from '@/service/use-plugins'
|
||||||
import type { Var } from '../../types'
|
import type { Var } from '../../types'
|
||||||
import { VarType as VarKindType } from '../../types'
|
import { VarType as VarKindType } from '../../types'
|
||||||
import useAvailableVarList from '../_base/hooks/use-available-var-list'
|
import useAvailableVarList from '../_base/hooks/use-available-var-list'
|
||||||
|
|
||||||
export type StrategyStatus = 'loading' | 'plugin-not-found' | 'strategy-not-found' | 'success'
|
export type StrategyStatus = 'loading' | 'plugin-not-found' | 'plugin-not-found-and-not-in-marketplace' | 'strategy-not-found' | 'success'
|
||||||
|
|
||||||
const useConfig = (id: string, payload: AgentNodeType) => {
|
const useConfig = (id: string, payload: AgentNodeType) => {
|
||||||
const { nodesReadOnly: readOnly } = useNodesReadOnly()
|
const { nodesReadOnly: readOnly } = useNodesReadOnly()
|
||||||
@ -25,16 +25,26 @@ const useConfig = (id: string, payload: AgentNodeType) => {
|
|||||||
})
|
})
|
||||||
const strategyProvider = useStrategyProviderDetail(
|
const strategyProvider = useStrategyProviderDetail(
|
||||||
inputs.agent_strategy_provider_name || '',
|
inputs.agent_strategy_provider_name || '',
|
||||||
|
{ retry: false },
|
||||||
)
|
)
|
||||||
const currentStrategy = strategyProvider.data?.declaration.strategies.find(
|
const currentStrategy = strategyProvider.data?.declaration.strategies.find(
|
||||||
str => str.identity.name === inputs.agent_strategy_name,
|
str => str.identity.name === inputs.agent_strategy_name,
|
||||||
)
|
)
|
||||||
|
const marketplace = useFetchPluginsInMarketPlaceByIds([inputs.agent_strategy_provider_name!], {
|
||||||
|
retry: false,
|
||||||
|
})
|
||||||
const currentStrategyStatus: StrategyStatus = useMemo(() => {
|
const currentStrategyStatus: StrategyStatus = useMemo(() => {
|
||||||
if (strategyProvider.isLoading) return 'loading'
|
if (strategyProvider.isLoading || marketplace.isLoading) return 'loading'
|
||||||
if (strategyProvider.isError) return 'plugin-not-found'
|
if (strategyProvider.isError) {
|
||||||
|
if (marketplace.data && marketplace.data.data.plugins.length === 0)
|
||||||
|
return 'plugin-not-found-and-not-in-marketplace'
|
||||||
|
|
||||||
|
return 'plugin-not-found'
|
||||||
|
}
|
||||||
if (!currentStrategy) return 'strategy-not-found'
|
if (!currentStrategy) return 'strategy-not-found'
|
||||||
return 'success'
|
return 'success'
|
||||||
}, [currentStrategy, strategyProvider])
|
}, [currentStrategy, marketplace, strategyProvider.isError, strategyProvider.isLoading])
|
||||||
|
console.log('currentStrategyStatus', currentStrategyStatus)
|
||||||
const pluginId = inputs.agent_strategy_provider_name?.split('/').splice(0, 2).join('/')
|
const pluginId = inputs.agent_strategy_provider_name?.split('/').splice(0, 2).join('/')
|
||||||
const pluginDetail = useCheckInstalled({
|
const pluginDetail = useCheckInstalled({
|
||||||
pluginIds: [pluginId || ''],
|
pluginIds: [pluginId || ''],
|
||||||
|
@ -22,7 +22,7 @@ import type {
|
|||||||
PluginsSearchParams,
|
PluginsSearchParams,
|
||||||
} from '@/app/components/plugins/marketplace/types'
|
} from '@/app/components/plugins/marketplace/types'
|
||||||
import { get, getMarketplace, post, postMarketplace } from './base'
|
import { get, getMarketplace, post, postMarketplace } from './base'
|
||||||
import type { MutateOptions } from '@tanstack/react-query'
|
import type { MutateOptions, QueryOptions } from '@tanstack/react-query'
|
||||||
import {
|
import {
|
||||||
useMutation,
|
useMutation,
|
||||||
useQuery,
|
useQuery,
|
||||||
@ -321,8 +321,9 @@ export const useMutationPluginsFromMarketplace = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useFetchPluginsInMarketPlaceByIds = (unique_identifiers: string[]) => {
|
export const useFetchPluginsInMarketPlaceByIds = (unique_identifiers: string[], options?: QueryOptions<{ data: PluginsFromMarketplaceResponse }>) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
|
...options,
|
||||||
queryKey: [NAME_SPACE, 'fetchPluginsInMarketPlaceByIds', unique_identifiers],
|
queryKey: [NAME_SPACE, 'fetchPluginsInMarketPlaceByIds', unique_identifiers],
|
||||||
queryFn: () => postMarketplace<{ data: PluginsFromMarketplaceResponse }>('/plugins/identifier/batch', {
|
queryFn: () => postMarketplace<{ data: PluginsFromMarketplaceResponse }>('/plugins/identifier/batch', {
|
||||||
body: {
|
body: {
|
||||||
|
@ -2,6 +2,7 @@ import type {
|
|||||||
StrategyPluginDetail,
|
StrategyPluginDetail,
|
||||||
} from '@/app/components/plugins/types'
|
} from '@/app/components/plugins/types'
|
||||||
import { useInvalid } from './use-base'
|
import { useInvalid } from './use-base'
|
||||||
|
import type { QueryOptions } from '@tanstack/react-query'
|
||||||
import {
|
import {
|
||||||
useQuery,
|
useQuery,
|
||||||
} from '@tanstack/react-query'
|
} from '@tanstack/react-query'
|
||||||
@ -21,8 +22,9 @@ export const useInvalidateStrategyProviders = () => {
|
|||||||
return useInvalid(useStrategyListKey)
|
return useInvalid(useStrategyListKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useStrategyProviderDetail = (agentProvider: string) => {
|
export const useStrategyProviderDetail = (agentProvider: string, options?: QueryOptions<StrategyPluginDetail>) => {
|
||||||
return useQuery<StrategyPluginDetail>({
|
return useQuery<StrategyPluginDetail>({
|
||||||
|
...options,
|
||||||
queryKey: [NAME_SPACE, 'detail', agentProvider],
|
queryKey: [NAME_SPACE, 'detail', agentProvider],
|
||||||
queryFn: () => fetchStrategyDetail(agentProvider),
|
queryFn: () => fetchStrategyDetail(agentProvider),
|
||||||
enabled: !!agentProvider,
|
enabled: !!agentProvider,
|
||||||
|
Loading…
Reference in New Issue
Block a user