installation state of tool
This commit is contained in:
parent
f5b4366bd8
commit
2007828404
@ -7,7 +7,6 @@ import ActionList from './action-list'
|
|||||||
import ModelList from './model-list'
|
import ModelList from './model-list'
|
||||||
import AgentStrategyList from './agent-strategy-list'
|
import AgentStrategyList from './agent-strategy-list'
|
||||||
import Drawer from '@/app/components/base/drawer'
|
import Drawer from '@/app/components/base/drawer'
|
||||||
import MultipleToolSelector from '@/app/components/plugins/plugin-detail-panel/multiple-tool-selector'
|
|
||||||
import type { PluginDetail } from '@/app/components/plugins/types'
|
import type { PluginDetail } from '@/app/components/plugins/types'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
|
|
||||||
@ -28,12 +27,6 @@ const PluginDetailPanel: FC<Props> = ({
|
|||||||
onUpdate()
|
onUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
const [value, setValue] = React.useState<any>(undefined)
|
|
||||||
const testChange = (val: any) => {
|
|
||||||
console.log('tool change', val)
|
|
||||||
setValue(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!detail)
|
if (!detail)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
@ -59,15 +52,6 @@ const PluginDetailPanel: FC<Props> = ({
|
|||||||
{!!detail.declaration.agent_strategy && <AgentStrategyList detail={detail} />}
|
{!!detail.declaration.agent_strategy && <AgentStrategyList detail={detail} />}
|
||||||
{!!detail.declaration.endpoint && <EndpointList detail={detail} />}
|
{!!detail.declaration.endpoint && <EndpointList detail={detail} />}
|
||||||
{!!detail.declaration.model && <ModelList detail={detail} />}
|
{!!detail.declaration.model && <ModelList detail={detail} />}
|
||||||
{false && (
|
|
||||||
<div className='px-4 py-2'>
|
|
||||||
<MultipleToolSelector
|
|
||||||
value={value || []}
|
|
||||||
label='TOOLS'
|
|
||||||
onChange={testChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
import {
|
||||||
|
usePluginManifestInfo,
|
||||||
|
} from '@/service/use-plugins'
|
||||||
|
|
||||||
|
export const usePluginInstalledCheck = (providerName = '') => {
|
||||||
|
const pluginID = providerName?.split('/').splice(0, 2).join('/')
|
||||||
|
|
||||||
|
const { data: manifest } = usePluginManifestInfo(pluginID)
|
||||||
|
|
||||||
|
return {
|
||||||
|
inMarketPlace: !!manifest,
|
||||||
|
manifest: manifest?.data.plugin,
|
||||||
|
}
|
||||||
|
}
|
@ -32,12 +32,15 @@ import {
|
|||||||
useInvalidateAllBuiltInTools,
|
useInvalidateAllBuiltInTools,
|
||||||
useUpdateProviderCredentials,
|
useUpdateProviderCredentials,
|
||||||
} from '@/service/use-tools'
|
} from '@/service/use-tools'
|
||||||
|
import { useInstallPackageFromMarketPlace } from '@/service/use-plugins'
|
||||||
|
import { usePluginInstalledCheck } from '@/app/components/plugins/plugin-detail-panel/tool-selector/hooks'
|
||||||
import { CollectionType } from '@/app/components/tools/types'
|
import { CollectionType } from '@/app/components/tools/types'
|
||||||
import type { ToolDefaultValue } from '@/app/components/workflow/block-selector/types'
|
import type { ToolDefaultValue } from '@/app/components/workflow/block-selector/types'
|
||||||
import type {
|
import type {
|
||||||
OffsetOptions,
|
OffsetOptions,
|
||||||
Placement,
|
Placement,
|
||||||
} from '@floating-ui/react'
|
} from '@floating-ui/react'
|
||||||
|
import { MARKETPLACE_API_PREFIX } from '@/config'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
|
|
||||||
export type ToolValue = {
|
export type ToolValue = {
|
||||||
@ -92,6 +95,9 @@ const ToolSelector: FC<Props> = ({
|
|||||||
const { data: workflowTools } = useAllWorkflowTools()
|
const { data: workflowTools } = useAllWorkflowTools()
|
||||||
const invalidateAllBuiltinTools = useInvalidateAllBuiltInTools()
|
const invalidateAllBuiltinTools = useInvalidateAllBuiltInTools()
|
||||||
|
|
||||||
|
// plugin info check
|
||||||
|
const { inMarketPlace, manifest } = usePluginInstalledCheck(value?.provider_name)
|
||||||
|
|
||||||
const currentProvider = useMemo(() => {
|
const currentProvider = useMemo(() => {
|
||||||
const mergedTools = [...(buildInTools || []), ...(customTools || []), ...(workflowTools || [])]
|
const mergedTools = [...(buildInTools || []), ...(customTools || []), ...(workflowTools || [])]
|
||||||
return mergedTools.find((toolWithProvider) => {
|
return mergedTools.find((toolWithProvider) => {
|
||||||
@ -164,6 +170,25 @@ const ToolSelector: FC<Props> = ({
|
|||||||
onSuccess: handleCredentialSettingUpdate,
|
onSuccess: handleCredentialSettingUpdate,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// install from marketplace
|
||||||
|
const { mutateAsync: installPackageFromMarketPlace, isPending } = useInstallPackageFromMarketPlace()
|
||||||
|
const manifestIcon = useMemo(() => {
|
||||||
|
if (!manifest)
|
||||||
|
return ''
|
||||||
|
return `${MARKETPLACE_API_PREFIX}/plugins/${(manifest as any).plugin_id}/icon`
|
||||||
|
}, [manifest])
|
||||||
|
const handleInstall = async () => {
|
||||||
|
if (!manifest)
|
||||||
|
return
|
||||||
|
try {
|
||||||
|
await installPackageFromMarketPlace(manifest.latest_package_identifier)
|
||||||
|
invalidateAllBuiltinTools()
|
||||||
|
}
|
||||||
|
catch (e: any) {
|
||||||
|
Toast.notify({ type: 'error', message: `${e.message || e}` })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PortalToFollowElem
|
<PortalToFollowElem
|
||||||
@ -188,7 +213,7 @@ const ToolSelector: FC<Props> = ({
|
|||||||
{!trigger && value?.provider_name && (
|
{!trigger && value?.provider_name && (
|
||||||
<ToolItem
|
<ToolItem
|
||||||
open={isShow}
|
open={isShow}
|
||||||
icon={currentProvider?.icon}
|
icon={currentProvider?.icon || manifestIcon}
|
||||||
providerName={value.provider_name}
|
providerName={value.provider_name}
|
||||||
toolName={value.tool_name}
|
toolName={value.tool_name}
|
||||||
showSwitch={supportEnableSwitch}
|
showSwitch={supportEnableSwitch}
|
||||||
@ -197,13 +222,15 @@ const ToolSelector: FC<Props> = ({
|
|||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
noAuth={currentProvider && !currentProvider.is_team_authorization}
|
noAuth={currentProvider && !currentProvider.is_team_authorization}
|
||||||
onAuth={() => setShowSettingAuth(true)}
|
onAuth={() => setShowSettingAuth(true)}
|
||||||
// uninstalled TODO
|
uninstalled={!currentProvider && inMarketPlace}
|
||||||
// isError TODO
|
isInstalling={isPending}
|
||||||
errorTip={<div className='space-y-1 text-xs'>
|
onInstall={() => handleInstall()}
|
||||||
<h3 className='text-text-primary font-semibold'>{t('workflow.nodes.agent.pluginNotInstalled')}</h3>
|
isError={!currentProvider && !inMarketPlace}
|
||||||
<p className='text-text-secondary tracking-tight'>{t('workflow.nodes.agent.pluginNotInstalledDesc')}</p>
|
errorTip={<div className='space-y-1 max-w-[240px] text-xs'>
|
||||||
|
<h3 className='text-text-primary font-semibold'>{t('plugin.detailPanel.toolSelector.uninstalledTitle')}</h3>
|
||||||
|
<p className='text-text-secondary tracking-tight'>{t('plugin.detailPanel.toolSelector.uninstalledContent')}</p>
|
||||||
<p>
|
<p>
|
||||||
<Link href={'/plugins'} className='text-text-accent tracking-tight'>{t('workflow.nodes.agent.linkToPlugin')}</Link>
|
<Link href={'/plugins'} className='text-text-accent tracking-tight'>{t('plugin.detailPanel.toolSelector.uninstalledLink')}</Link>
|
||||||
</p>
|
</p>
|
||||||
</div>}
|
</div>}
|
||||||
/>
|
/>
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
RiEqualizer2Line,
|
RiEqualizer2Line,
|
||||||
RiErrorWarningFill,
|
RiErrorWarningFill,
|
||||||
} from '@remixicon/react'
|
} from '@remixicon/react'
|
||||||
|
import { Group } from '@/app/components/base/icons/src/vender/other'
|
||||||
import AppIcon from '@/app/components/base/app-icon'
|
import AppIcon from '@/app/components/base/app-icon'
|
||||||
import Switch from '@/app/components/base/switch'
|
import Switch from '@/app/components/base/switch'
|
||||||
import Button from '@/app/components/base/button'
|
import Button from '@/app/components/base/button'
|
||||||
@ -61,10 +62,21 @@ const ToolItem = ({
|
|||||||
open && 'bg-components-panel-on-panel-item-bg-hover shadow-sm',
|
open && 'bg-components-panel-on-panel-item-bg-hover shadow-sm',
|
||||||
isDeleting && 'hover:bg-state-destructive-hover border-state-destructive-border shadow-xs',
|
isDeleting && 'hover:bg-state-destructive-hover border-state-destructive-border shadow-xs',
|
||||||
)}>
|
)}>
|
||||||
<div className={cn('shrink-0', isTransparent && 'opacity-50')}>
|
{icon && (
|
||||||
{typeof icon === 'string' && <div className='w-7 h-7 bg-cover bg-center border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge rounded-lg' style={{ backgroundImage: `url(${icon})` }} />}
|
<div className={cn('shrink-0', isTransparent && 'opacity-50')}>
|
||||||
{typeof icon !== 'string' && <AppIcon className='w-7 h-7 border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge rounded-lg' size='xs' icon={icon?.content} background={icon?.background} />}
|
{typeof icon === 'string' && <div className='w-7 h-7 bg-cover bg-center border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge rounded-lg' style={{ backgroundImage: `url(${icon})` }} />}
|
||||||
</div>
|
{typeof icon !== 'string' && <AppIcon className='w-7 h-7 border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge rounded-lg' size='xs' icon={icon?.content} background={icon?.background} />}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!icon && (
|
||||||
|
<div className={cn(
|
||||||
|
'flex items-center justify-center w-7 h-7 rounded-md border-[0.5px] border-components-panel-border-subtle bg-background-default-subtle',
|
||||||
|
)}>
|
||||||
|
<div className='flex w-5 h-5 items-center justify-center opacity-35'>
|
||||||
|
<Group className='text-text-tertiary' />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className={cn('pl-0.5 grow truncate', isTransparent && 'opacity-50')}>
|
<div className={cn('pl-0.5 grow truncate', isTransparent && 'opacity-50')}>
|
||||||
<div className='text-text-tertiary system-2xs-medium-uppercase'>{providerNameText}</div>
|
<div className='text-text-tertiary system-2xs-medium-uppercase'>{providerNameText}</div>
|
||||||
<div className='text-text-secondary system-xs-medium'>{toolName}</div>
|
<div className='text-text-secondary system-xs-medium'>{toolName}</div>
|
||||||
|
@ -74,6 +74,9 @@ const translation = {
|
|||||||
auth: 'AUTHORIZATION',
|
auth: 'AUTHORIZATION',
|
||||||
settings: 'TOOL SETTINGS',
|
settings: 'TOOL SETTINGS',
|
||||||
empty: 'Click the \'+\' button to add tools. You can add multiple tools.',
|
empty: 'Click the \'+\' button to add tools. You can add multiple tools.',
|
||||||
|
uninstalledTitle: 'Tool not installed',
|
||||||
|
uninstalledContent: 'This plugin is installed from the local/GitHub repository. Please use after installation.',
|
||||||
|
uninstalledLink: 'Manage in Plugins',
|
||||||
},
|
},
|
||||||
configureApp: 'Configure App',
|
configureApp: 'Configure App',
|
||||||
configureModel: 'Configure model',
|
configureModel: 'Configure model',
|
||||||
|
@ -74,6 +74,9 @@ const translation = {
|
|||||||
auth: '授权',
|
auth: '授权',
|
||||||
settings: '工具设置',
|
settings: '工具设置',
|
||||||
empty: '点击 "+" 按钮添加工具。您可以添加多个工具。',
|
empty: '点击 "+" 按钮添加工具。您可以添加多个工具。',
|
||||||
|
uninstalledTitle: '工具未安装',
|
||||||
|
uninstalledContent: '此插件安装自 本地 / GitHub 仓库,请安装后使用。',
|
||||||
|
uninstalledLink: '在插件中管理',
|
||||||
},
|
},
|
||||||
configureApp: '应用设置',
|
configureApp: '应用设置',
|
||||||
configureModel: '模型设置',
|
configureModel: '模型设置',
|
||||||
|
@ -9,6 +9,7 @@ import type {
|
|||||||
Permissions,
|
Permissions,
|
||||||
Plugin,
|
Plugin,
|
||||||
PluginDetail,
|
PluginDetail,
|
||||||
|
PluginInfoFromMarketPlace,
|
||||||
PluginTask,
|
PluginTask,
|
||||||
PluginsFromMarketplaceByInfoResponse,
|
PluginsFromMarketplaceByInfoResponse,
|
||||||
PluginsFromMarketplaceResponse,
|
PluginsFromMarketplaceResponse,
|
||||||
@ -91,6 +92,7 @@ export const useUpdatePackageFromMarketPlace = () => {
|
|||||||
|
|
||||||
export const useVersionListOfPlugin = (pluginID: string) => {
|
export const useVersionListOfPlugin = (pluginID: string) => {
|
||||||
return useQuery<{ data: VersionListResponse }>({
|
return useQuery<{ data: VersionListResponse }>({
|
||||||
|
enabled: !!pluginID,
|
||||||
queryKey: [NAME_SPACE, 'versions', pluginID],
|
queryKey: [NAME_SPACE, 'versions', pluginID],
|
||||||
queryFn: () => getMarketplace<{ data: VersionListResponse }>(`/plugins/${pluginID}/versions`, { params: { page: 1, page_size: 100 } }),
|
queryFn: () => getMarketplace<{ data: VersionListResponse }>(`/plugins/${pluginID}/versions`, { params: { page: 1, page_size: 100 } }),
|
||||||
})
|
})
|
||||||
@ -399,6 +401,15 @@ export const useMutationClearAllTaskPlugin = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const usePluginManifestInfo = (pluginUID: string) => {
|
||||||
|
return useQuery({
|
||||||
|
enabled: !!pluginUID,
|
||||||
|
queryKey: [[NAME_SPACE, 'manifest', pluginUID]],
|
||||||
|
queryFn: () => getMarketplace<{ data: { plugin: PluginInfoFromMarketPlace, version: { version: string } } }>(`/plugins/${pluginUID}`),
|
||||||
|
retry: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export const useDownloadPlugin = (info: { organization: string; pluginName: string; version: string }, needDownload: boolean) => {
|
export const useDownloadPlugin = (info: { organization: string; pluginName: string; version: string }, needDownload: boolean) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: [NAME_SPACE, 'downloadPlugin', info],
|
queryKey: [NAME_SPACE, 'downloadPlugin', info],
|
||||||
|
Loading…
Reference in New Issue
Block a user