mirror of https://github.com/langgenius/dify.git
Merge branch 'feat/plugins' into dev/plugin-deploy
This commit is contained in:
commit
730d33176e
|
|
@ -0,0 +1,22 @@
|
|||
import type { FC, PropsWithChildren, ReactNode } from 'react'
|
||||
|
||||
export type ToolTipContentProps = {
|
||||
title?: ReactNode
|
||||
action?: ReactNode
|
||||
} & PropsWithChildren
|
||||
|
||||
export const ToolTipContent: FC<ToolTipContentProps> = ({
|
||||
title,
|
||||
action,
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<div className='w-[180px]'>
|
||||
{title && (
|
||||
<div className='mb-1.5 text-text-secondary font-semibold'>{title}</div>
|
||||
)}
|
||||
<div className='mb-1.5 text-text-tertiary'>{children}</div>
|
||||
{action && <div className='text-text-accent cursor-pointer'>{action}</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -24,16 +24,12 @@ import {
|
|||
useDefaultModel,
|
||||
useMarketplaceAllPlugins,
|
||||
useModelModalHandler,
|
||||
useUpdateModelList,
|
||||
useUpdateModelProviders,
|
||||
} from './hooks'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import ProviderCard from '@/app/components/plugins/provider-card'
|
||||
import List from '@/app/components/plugins/marketplace/list'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useModalContextSelector } from '@/context/modal-context'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import type { Plugin } from '@/app/components/plugins/types'
|
||||
import { MARKETPLACE_URL_PREFIX } from '@/config'
|
||||
import cn from '@/utils/classnames'
|
||||
|
|
@ -46,16 +42,12 @@ type Props = {
|
|||
const ModelProviderPage = ({ searchText }: Props) => {
|
||||
const debouncedSearchText = useDebounce(searchText, { wait: 500 })
|
||||
const { t } = useTranslation()
|
||||
const { eventEmitter } = useEventEmitterContextContext()
|
||||
const updateModelProviders = useUpdateModelProviders()
|
||||
const updateModelList = useUpdateModelList()
|
||||
const { data: textGenerationDefaultModel } = useDefaultModel(ModelTypeEnum.textGeneration)
|
||||
const { data: embeddingsDefaultModel } = useDefaultModel(ModelTypeEnum.textEmbedding)
|
||||
const { data: rerankDefaultModel } = useDefaultModel(ModelTypeEnum.rerank)
|
||||
const { data: speech2textDefaultModel } = useDefaultModel(ModelTypeEnum.speech2text)
|
||||
const { data: ttsDefaultModel } = useDefaultModel(ModelTypeEnum.tts)
|
||||
const { modelProviders: providers } = useProviderContext()
|
||||
const setShowModelModal = useModalContextSelector(state => state.setShowModelModal)
|
||||
const defaultModelNotConfigured = !textGenerationDefaultModel && !embeddingsDefaultModel && !speech2textDefaultModel && !rerankDefaultModel && !ttsDefaultModel
|
||||
const [configuredProviders, notConfiguredProviders] = useMemo(() => {
|
||||
const configuredProviders: ModelProvider[] = []
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@ const ModelIcon: FC<ModelIconProps> = ({
|
|||
|
||||
if (provider?.icon_small) {
|
||||
return (
|
||||
<div className={`flex items-center justify-center ${isDeprecated ? 'opacity-50' : ''}`}>
|
||||
<div className={`flex items-center justify-center w-5 h-5 ${isDeprecated ? 'opacity-50' : ''}`}>
|
||||
<img
|
||||
alt='model-icon'
|
||||
src={`${provider.icon_small[language] || provider.icon_small.en_US}`}
|
||||
className={cn('w-5 h-5', className)}
|
||||
className={cn('w-4.5 h-4.5', className)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@ import { InstallPluginButton } from '@/app/components/workflow/nodes/_base/compo
|
|||
import StatusIndicators from './status-indicators'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useModalContextSelector } from '@/context/modal-context'
|
||||
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||
import { RiEqualizer2Line } from '@remixicon/react'
|
||||
import { fetchPluginInfoFromMarketPlace } from '@/service/plugins'
|
||||
|
||||
|
|
@ -51,10 +49,8 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
|
|||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { modelProviders } = useProviderContext()
|
||||
const setShowModelModal = useModalContextSelector(state => state.setShowModelModal)
|
||||
const updateModelProviders = useUpdateModelProviders()
|
||||
const updateModelList = useUpdateModelList()
|
||||
const { eventEmitter } = useEventEmitterContextContext()
|
||||
const { modelProvider, needsConfiguration } = useMemo(() => {
|
||||
const modelProvider = modelProviders.find(item => item.provider === providerName)
|
||||
const needsConfiguration = modelProvider?.custom_configuration.status === CustomConfigurationStatusEnum.noConfigure && !(
|
||||
|
|
@ -107,7 +103,7 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
|
|||
{modelId ? (
|
||||
<>
|
||||
<ModelIcon
|
||||
className="m-0.5"
|
||||
className='p-0.5'
|
||||
provider={currentProvider || modelProvider}
|
||||
modelName={currentModel?.model || modelId}
|
||||
isDeprecated={hasDeprecated}
|
||||
|
|
|
|||
|
|
@ -34,20 +34,18 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'group flex items-center p-1 gap-0.5 rounded-lg bg-components-input-bg-normal',
|
||||
'group flex items-center p-1 h-8 gap-0.5 rounded-lg bg-components-input-bg-normal',
|
||||
!readonly && 'hover:bg-components-input-bg-hover cursor-pointer',
|
||||
open && 'bg-components-input-bg-hover',
|
||||
model.status !== ModelStatusEnum.active && 'bg-components-input-bg-disabled hover:bg-components-input-bg-disabled',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div className='flex items-center justify-center w-6 h-6'>
|
||||
<ModelIcon
|
||||
className='w-5 h-5 m-0.5'
|
||||
provider={provider}
|
||||
modelName={model.model}
|
||||
/>
|
||||
</div>
|
||||
<ModelIcon
|
||||
className='p-0.5'
|
||||
provider={provider}
|
||||
modelName={model.model}
|
||||
/>
|
||||
<div className='flex px-1 py-[3px] items-center gap-1 grow truncate'>
|
||||
<ModelName
|
||||
className='grow'
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import Placeholder from './base/placeholder'
|
|||
import cn from '@/utils/classnames'
|
||||
import { useGetLanguage } from '@/context/i18n'
|
||||
import { getLanguage } from '@/i18n/language'
|
||||
import { useCategories } from '../hooks'
|
||||
import { useSingleCategories } from '../hooks'
|
||||
import { renderI18nObject } from '@/hooks/use-i18n'
|
||||
|
||||
export type Props = {
|
||||
|
|
@ -43,7 +43,7 @@ const Card = ({
|
|||
}: Props) => {
|
||||
const defaultLocale = useGetLanguage()
|
||||
const locale = localeFromProps ? getLanguage(localeFromProps) : defaultLocale
|
||||
const { categoriesMap } = useCategories()
|
||||
const { categoriesMap } = useSingleCategories()
|
||||
const { category, type, name, org, label, brief, icon, verified } = payload
|
||||
const isBundle = !['plugin', 'model', 'tool', 'extension', 'agent_strategy'].includes(type)
|
||||
const cornerMark = isBundle ? categoriesMap.bundle?.label : categoriesMap[category]?.label
|
||||
|
|
|
|||
|
|
@ -64,3 +64,31 @@ export const useCategories = (translateFromOut?: TFunction) => {
|
|||
categoriesMap,
|
||||
}
|
||||
}
|
||||
|
||||
export const useSingleCategories = (translateFromOut?: TFunction) => {
|
||||
const { t: translation } = useTranslation()
|
||||
const t = translateFromOut || translation
|
||||
|
||||
const categories = categoryKeys.map((category) => {
|
||||
if (category === 'agent') {
|
||||
return {
|
||||
name: 'agent_strategy',
|
||||
label: t(`plugin.categorySingle.${category}`),
|
||||
}
|
||||
}
|
||||
return {
|
||||
name: category,
|
||||
label: t(`plugin.categorySingle.${category}`),
|
||||
}
|
||||
})
|
||||
|
||||
const categoriesMap = categories.reduce((acc, category) => {
|
||||
acc[category.name] = category
|
||||
return acc
|
||||
}, {} as Record<string, Category>)
|
||||
|
||||
return {
|
||||
categories,
|
||||
categoriesMap,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useProviderContext } from '@/context/provider-context'
|
|||
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||
import { useInvalidateAllBuiltInTools, useInvalidateAllToolProviders } from '@/service/use-tools'
|
||||
import { useInvalidateStrategyProviders } from '@/service/use-strategy'
|
||||
import type { Plugin, PluginManifestInMarket } from '../../types'
|
||||
import type { Plugin, PluginDeclaration, PluginManifestInMarket } from '../../types'
|
||||
import { PluginType } from '../../types'
|
||||
|
||||
const useRefreshPluginList = () => {
|
||||
|
|
@ -16,25 +16,27 @@ const useRefreshPluginList = () => {
|
|||
|
||||
const invalidateStrategyProviders = useInvalidateStrategyProviders()
|
||||
return {
|
||||
refreshPluginList: (manifest: PluginManifestInMarket | Plugin) => {
|
||||
refreshPluginList: (manifest?: PluginManifestInMarket | Plugin | PluginDeclaration | null, refreshAllType?: boolean) => {
|
||||
// installed list
|
||||
invalidateInstalledPluginList()
|
||||
|
||||
if (!manifest) return
|
||||
|
||||
// tool page, tool select
|
||||
if (PluginType.tool.includes(manifest.category)) {
|
||||
if (PluginType.tool.includes(manifest.category) || refreshAllType) {
|
||||
invalidateAllToolProviders()
|
||||
invalidateAllBuiltInTools()
|
||||
// TODO: update suggested tools. It's a function in hook useMarketplacePlugins,handleUpdatePlugins
|
||||
}
|
||||
|
||||
// model select
|
||||
if (PluginType.model.includes(manifest.category)) {
|
||||
if (PluginType.model.includes(manifest.category) || refreshAllType) {
|
||||
updateModelProviders()
|
||||
refreshModelProviders()
|
||||
}
|
||||
|
||||
// agent select
|
||||
if (PluginType.agent.includes(manifest.category))
|
||||
if (PluginType.agent.includes(manifest.category) || refreshAllType)
|
||||
invalidateStrategyProviders()
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { RiLoader2Line } from '@remixicon/react'
|
|||
import { useTranslation } from 'react-i18next'
|
||||
import InstallMulti from './install-multi'
|
||||
import { useInstallOrUpdate } from '@/service/use-plugins'
|
||||
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||
import useRefreshPluginList from '../../hooks/use-refresh-plugin-list'
|
||||
const i18nPrefix = 'plugin.installModal'
|
||||
|
||||
type Props = {
|
||||
|
|
@ -29,7 +29,7 @@ const Install: FC<Props> = ({
|
|||
const [selectedPlugins, setSelectedPlugins] = React.useState<Plugin[]>([])
|
||||
const [selectedIndexes, setSelectedIndexes] = React.useState<number[]>([])
|
||||
const selectedPluginsNum = selectedPlugins.length
|
||||
const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
|
||||
const { refreshPluginList } = useRefreshPluginList()
|
||||
const handleSelect = (plugin: Plugin, selectedIndex: number) => {
|
||||
const isSelected = !!selectedPlugins.find(p => p.plugin_id === plugin.plugin_id)
|
||||
let nextSelectedPlugins
|
||||
|
|
@ -61,7 +61,7 @@ const Install: FC<Props> = ({
|
|||
}))
|
||||
const hasInstallSuccess = res.some(r => r.success)
|
||||
if (hasInstallSuccess)
|
||||
invalidateInstalledPluginList()
|
||||
refreshPluginList(undefined, true)
|
||||
},
|
||||
})
|
||||
const handleInstall = () => {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import type { InstallState } from '@/app/components/plugins/types'
|
|||
import { useGitHubReleases } from '../hooks'
|
||||
import { convertRepoToUrl, parseGitHubUrl } from '../utils'
|
||||
import type { PluginDeclaration, UpdateFromGitHubPayload } from '../../types'
|
||||
import { InstallStepFromGitHub, PluginType } from '../../types'
|
||||
import { InstallStepFromGitHub } from '../../types'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import SetURL from './steps/setURL'
|
||||
import SelectPackage from './steps/selectPackage'
|
||||
|
|
@ -15,8 +15,7 @@ import Installed from '../base/installed'
|
|||
import Loaded from './steps/loaded'
|
||||
import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useUpdateModelProviders } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import { useInvalidateAllToolProviders } from '@/service/use-tools'
|
||||
import useRefreshPluginList from '../hooks/use-refresh-plugin-list'
|
||||
|
||||
const i18nPrefix = 'plugin.installFromGitHub'
|
||||
|
||||
|
|
@ -30,8 +29,8 @@ const InstallFromGitHub: React.FC<InstallFromGitHubProps> = ({ updatePayload, on
|
|||
const { t } = useTranslation()
|
||||
const { getIconUrl } = useGetIcon()
|
||||
const { fetchReleases } = useGitHubReleases()
|
||||
const updateModelProviders = useUpdateModelProviders()
|
||||
const invalidateAllToolProviders = useInvalidateAllToolProviders()
|
||||
const { refreshPluginList } = useRefreshPluginList()
|
||||
|
||||
const [state, setState] = useState<InstallState>({
|
||||
step: updatePayload ? InstallStepFromGitHub.selectPackage : InstallStepFromGitHub.setUrl,
|
||||
repoUrl: updatePayload?.originalPackageInfo?.repo
|
||||
|
|
@ -115,14 +114,9 @@ const InstallFromGitHub: React.FC<InstallFromGitHubProps> = ({ updatePayload, on
|
|||
|
||||
const handleInstalled = useCallback(() => {
|
||||
setState(prevState => ({ ...prevState, step: InstallStepFromGitHub.installed }))
|
||||
if (!manifest)
|
||||
return
|
||||
if (PluginType.model.includes(manifest.category))
|
||||
updateModelProviders()
|
||||
if (PluginType.tool.includes(manifest.category))
|
||||
invalidateAllToolProviders()
|
||||
refreshPluginList(manifest)
|
||||
onSuccess()
|
||||
}, [invalidateAllToolProviders, manifest, onSuccess, updateModelProviders])
|
||||
}, [manifest, onSuccess, refreshPluginList])
|
||||
|
||||
const handleFailed = useCallback((errorMsg?: string) => {
|
||||
setState(prevState => ({ ...prevState, step: InstallStepFromGitHub.installFailed }))
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
import type { FC } from 'react'
|
||||
import React, { useCallback } from 'react'
|
||||
import type { PluginDeclaration } from '../../types'
|
||||
import { InstallStep, PluginType } from '../../types'
|
||||
import { InstallStep } from '../../types'
|
||||
import Install from './steps/install'
|
||||
import Installed from '../base/installed'
|
||||
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||
import { useUpdateModelProviders } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import { useInvalidateAllToolProviders } from '@/service/use-tools'
|
||||
import useRefreshPluginList from '../hooks/use-refresh-plugin-list'
|
||||
|
||||
type Props = {
|
||||
step: InstallStep
|
||||
onStepChange: (step: InstallStep) => void,
|
||||
|
|
@ -27,20 +26,12 @@ const ReadyToInstall: FC<Props> = ({
|
|||
errorMsg,
|
||||
onError,
|
||||
}) => {
|
||||
const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
|
||||
const updateModelProviders = useUpdateModelProviders()
|
||||
const invalidateAllToolProviders = useInvalidateAllToolProviders()
|
||||
const { refreshPluginList } = useRefreshPluginList()
|
||||
|
||||
const handleInstalled = useCallback(() => {
|
||||
onStepChange(InstallStep.installed)
|
||||
invalidateInstalledPluginList()
|
||||
if (!manifest)
|
||||
return
|
||||
if (PluginType.model.includes(manifest.category))
|
||||
updateModelProviders()
|
||||
if (PluginType.tool.includes(manifest.category))
|
||||
invalidateAllToolProviders()
|
||||
}, [invalidateAllToolProviders, invalidateInstalledPluginList, manifest, onStepChange, updateModelProviders])
|
||||
refreshPluginList(manifest)
|
||||
}, [manifest, onStepChange, refreshPluginList])
|
||||
|
||||
const handleFailed = useCallback((errorMsg?: string) => {
|
||||
onStepChange(InstallStep.installFailed)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import AgentStrategyList from './agent-strategy-list'
|
|||
import Drawer from '@/app/components/base/drawer'
|
||||
import type { PluginDetail } from '@/app/components/plugins/types'
|
||||
import cn from '@/utils/classnames'
|
||||
import ToolSelector from '@/app/components/plugins/plugin-detail-panel/tool-selector'
|
||||
|
||||
type Props = {
|
||||
detail?: PluginDetail
|
||||
|
|
@ -28,16 +27,6 @@ const PluginDetailPanel: FC<Props> = ({
|
|||
onUpdate()
|
||||
}
|
||||
|
||||
const [value, setValue] = React.useState({
|
||||
provider_name: 'langgenius/google/google',
|
||||
tool_name: 'google_search',
|
||||
})
|
||||
|
||||
const testHandle = (item: any) => {
|
||||
console.log(item)
|
||||
setValue(item)
|
||||
}
|
||||
|
||||
if (!detail)
|
||||
return null
|
||||
|
||||
|
|
@ -63,17 +52,6 @@ const PluginDetailPanel: FC<Props> = ({
|
|||
{!!detail.declaration.agent_strategy && <AgentStrategyList detail={detail} />}
|
||||
{!!detail.declaration.endpoint && <EndpointList detail={detail} />}
|
||||
{!!detail.declaration.model && <ModelList detail={detail} />}
|
||||
{false && (
|
||||
<div className='px-4'>
|
||||
<ToolSelector
|
||||
scope={'all'}
|
||||
value={value}
|
||||
onSelect={item => testHandle(item)}
|
||||
onDelete={() => testHandle(null)}
|
||||
supportEnableSwitch
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ const ToolSelector: FC<Props> = ({
|
|||
const currentProvider = useMemo(() => {
|
||||
const mergedTools = [...(buildInTools || []), ...(customTools || []), ...(workflowTools || [])]
|
||||
return mergedTools.find((toolWithProvider) => {
|
||||
return toolWithProvider.id === value?.provider_name && toolWithProvider.tools.some(tool => tool.name === value?.tool_name)
|
||||
return toolWithProvider.id === value?.provider_name
|
||||
})
|
||||
}, [value, buildInTools, customTools, workflowTools])
|
||||
|
||||
|
|
@ -172,7 +172,9 @@ const ToolSelector: FC<Props> = ({
|
|||
})
|
||||
|
||||
// install from marketplace
|
||||
|
||||
const currentTool = useMemo(() => {
|
||||
return currentProvider?.tools.find(tool => tool.name === value?.tool_name)
|
||||
}, [currentProvider?.tools, value?.tool_name])
|
||||
const manifestIcon = useMemo(() => {
|
||||
if (!manifest)
|
||||
return ''
|
||||
|
|
@ -193,7 +195,10 @@ const ToolSelector: FC<Props> = ({
|
|||
>
|
||||
<PortalToFollowElemTrigger
|
||||
className='w-full'
|
||||
onClick={handleTriggerClick}
|
||||
onClick={() => {
|
||||
if (!currentProvider || !currentTool) return
|
||||
handleTriggerClick()
|
||||
}}
|
||||
>
|
||||
{trigger}
|
||||
{!trigger && !value?.provider_name && (
|
||||
|
|
@ -214,19 +219,22 @@ const ToolSelector: FC<Props> = ({
|
|||
switchValue={value.enabled}
|
||||
onSwitchChange={handleEnabledChange}
|
||||
onDelete={onDelete}
|
||||
noAuth={currentProvider && !currentProvider.is_team_authorization}
|
||||
noAuth={currentProvider && currentTool && !currentProvider.is_team_authorization}
|
||||
onAuth={() => setShowSettingAuth(true)}
|
||||
uninstalled={!currentProvider && inMarketPlace}
|
||||
versionMismatch={currentProvider && inMarketPlace && !currentTool}
|
||||
installInfo={manifest?.latest_package_identifier}
|
||||
onInstall={() => handleInstall()}
|
||||
isError={!currentProvider && !inMarketPlace}
|
||||
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>
|
||||
<Link href={'/plugins'} className='text-text-accent tracking-tight'>{t('plugin.detailPanel.toolSelector.uninstalledLink')}</Link>
|
||||
</p>
|
||||
</div>}
|
||||
isError={(!currentProvider || !currentTool) && !inMarketPlace}
|
||||
errorTip={
|
||||
<div className='space-y-1 max-w-[240px] text-xs'>
|
||||
<h3 className='text-text-primary font-semibold'>{currentTool ? t('plugin.detailPanel.toolSelector.uninstalledTitle') : t('plugin.detailPanel.toolSelector.unsupportedTitle')}</h3>
|
||||
<p className='text-text-secondary tracking-tight'>{currentTool ? t('plugin.detailPanel.toolSelector.uninstalledContent') : t('plugin.detailPanel.toolSelector.unsupportedContent')}</p>
|
||||
<p>
|
||||
<Link href={'/plugins'} className='text-text-accent tracking-tight'>{t('plugin.detailPanel.toolSelector.uninstalledLink')}</Link>
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</PortalToFollowElemTrigger>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ import Button from '@/app/components/base/button'
|
|||
import Indicator from '@/app/components/header/indicator'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { ToolTipContent } from '@/app/components/base/tooltip/content'
|
||||
import { InstallPluginButton } from '@/app/components/workflow/nodes/_base/components/install-plugin-button'
|
||||
import { SwitchPluginVersion } from '@/app/components/workflow/nodes/_base/components/switch-plugin-version'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type Props = {
|
||||
|
|
@ -31,6 +33,7 @@ type Props = {
|
|||
uninstalled?: boolean
|
||||
installInfo?: string
|
||||
onInstall?: () => void
|
||||
versionMismatch?: boolean
|
||||
open: boolean
|
||||
}
|
||||
|
||||
|
|
@ -50,10 +53,11 @@ const ToolItem = ({
|
|||
onInstall,
|
||||
isError,
|
||||
errorTip,
|
||||
versionMismatch,
|
||||
}: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const providerNameText = providerName?.split('/').pop()
|
||||
const isTransparent = uninstalled || isError
|
||||
const isTransparent = uninstalled || versionMismatch || isError
|
||||
const [isDeleting, setIsDeleting] = useState(false)
|
||||
|
||||
return (
|
||||
|
|
@ -82,7 +86,7 @@ const ToolItem = ({
|
|||
<div className='text-text-secondary system-xs-medium'>{toolName}</div>
|
||||
</div>
|
||||
<div className='hidden group-hover:flex items-center gap-1'>
|
||||
{!noAuth && !isError && !uninstalled && (
|
||||
{!noAuth && !isError && !uninstalled && !versionMismatch && (
|
||||
<ActionButton>
|
||||
<RiEqualizer2Line className='w-4 h-4' />
|
||||
</ActionButton>
|
||||
|
|
@ -99,7 +103,7 @@ const ToolItem = ({
|
|||
<RiDeleteBinLine className='w-4 h-4' />
|
||||
</div>
|
||||
</div>
|
||||
{!isError && !uninstalled && !noAuth && showSwitch && (
|
||||
{!isError && !uninstalled && !noAuth && !versionMismatch && showSwitch && (
|
||||
<div className='mr-1' onClick={e => e.stopPropagation()}>
|
||||
<Switch
|
||||
size='md'
|
||||
|
|
@ -108,12 +112,30 @@ const ToolItem = ({
|
|||
/>
|
||||
</div>
|
||||
)}
|
||||
{!isError && !uninstalled && noAuth && (
|
||||
{!isError && !uninstalled && !versionMismatch && noAuth && (
|
||||
<Button variant='secondary' size='small' onClick={onAuth}>
|
||||
{t('tools.notAuthorized')}
|
||||
<Indicator className='ml-2' color='orange' />
|
||||
</Button>
|
||||
)}
|
||||
{!isError && !uninstalled && versionMismatch && installInfo && (
|
||||
<div onClick={e => e.stopPropagation()}>
|
||||
<SwitchPluginVersion
|
||||
className='-mt-1'
|
||||
uniqueIdentifier={installInfo}
|
||||
tooltip={
|
||||
<ToolTipContent
|
||||
title={t('plugin.detailPanel.toolSelector.unsupportedTitle')}
|
||||
>
|
||||
{`${t('plugin.detailPanel.toolSelector.unsupportedContent')} ${t('plugin.detailPanel.toolSelector.unsupportedContent2')}`}
|
||||
</ToolTipContent>
|
||||
}
|
||||
onChange={() => {
|
||||
onInstall?.()
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{!isError && uninstalled && installInfo && (
|
||||
<InstallPluginButton
|
||||
onClick={e => e.stopPropagation()}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import cn from '@/utils/classnames'
|
|||
import { API_PREFIX, MARKETPLACE_URL_PREFIX } from '@/config'
|
||||
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||
import { useInvalidateAllBuiltInTools, useInvalidateAllToolProviders } from '@/service/use-tools'
|
||||
import { useCategories } from '../hooks'
|
||||
import { useSingleCategories } from '../hooks'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ const PluginItem: FC<Props> = ({
|
|||
plugin,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { categoriesMap } = useCategories()
|
||||
const { categoriesMap } = useSingleCategories()
|
||||
const currentPluginID = usePluginPageContext(v => v.currentPluginID)
|
||||
const setCurrentPluginID = usePluginPageContext(v => v.setCurrentPluginID)
|
||||
const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
import type { FC, ReactNode } from 'react'
|
||||
import React, { memo } from 'react'
|
||||
import Card from '@/app/components/plugins/card'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import Button from '@/app/components/base/button'
|
||||
import type { Plugin } from '../types'
|
||||
import type { UseMutationResult } from '@tanstack/react-query'
|
||||
|
||||
type Props = {
|
||||
plugin: Plugin
|
||||
onSave: () => void
|
||||
onCancel: () => void
|
||||
mutation: UseMutationResult
|
||||
confirmButtonText: ReactNode
|
||||
cancelButtonText: ReactNode
|
||||
modelTitle: ReactNode
|
||||
description: ReactNode
|
||||
cardTitleLeft: ReactNode
|
||||
}
|
||||
|
||||
const PluginMutationModal: FC<Props> = ({
|
||||
plugin,
|
||||
onCancel,
|
||||
mutation,
|
||||
confirmButtonText,
|
||||
cancelButtonText,
|
||||
modelTitle,
|
||||
description,
|
||||
cardTitleLeft,
|
||||
}: Props) => {
|
||||
return (
|
||||
<Modal
|
||||
isShow={true}
|
||||
onClose={onCancel}
|
||||
className='min-w-[560px]'
|
||||
closable
|
||||
title={modelTitle}
|
||||
>
|
||||
<div className='mt-3 mb-2 text-text-secondary system-md-regular'>
|
||||
{description}
|
||||
</div>
|
||||
<div className='flex p-2 items-start content-start gap-1 self-stretch flex-wrap rounded-2xl bg-background-section-burn'>
|
||||
<Card
|
||||
installed={mutation.isSuccess}
|
||||
payload={plugin}
|
||||
className='w-full'
|
||||
titleLeft={cardTitleLeft}
|
||||
/>
|
||||
</div>
|
||||
<div className='flex pt-5 justify-end items-center gap-2 self-stretch'>
|
||||
{mutation.isPending && (
|
||||
<Button onClick={onCancel}>
|
||||
{cancelButtonText}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant='primary'
|
||||
loading={mutation.isPending}
|
||||
onClick={mutation.mutate}
|
||||
disabled={mutation.isPending}
|
||||
>
|
||||
{confirmButtonText}
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
PluginMutationModal.displayName = 'PluginMutationModal'
|
||||
|
||||
export default memo(PluginMutationModal)
|
||||
|
|
@ -8,7 +8,7 @@ import { usePluginPageContext } from '../context'
|
|||
import { Group } from '@/app/components/base/icons/src/vender/other'
|
||||
import { useSelector as useAppContextSelector } from '@/context/app-context'
|
||||
import Line from '../../marketplace/empty/line'
|
||||
import { useInstalledPluginList, useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||
import { useInstalledPluginList } from '@/service/use-plugins'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config'
|
||||
|
||||
|
|
@ -29,14 +29,13 @@ const Empty = () => {
|
|||
}
|
||||
const filters = usePluginPageContext(v => v.filters)
|
||||
const { data: pluginList } = useInstalledPluginList()
|
||||
const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
|
||||
|
||||
const text = useMemo(() => {
|
||||
if (pluginList?.plugins.length === 0)
|
||||
return t('plugin.list.noInstalled')
|
||||
if (filters.categories.length > 0 || filters.tags.length > 0 || filters.searchQuery)
|
||||
return t('plugin.list.notFound')
|
||||
}, [pluginList, filters])
|
||||
}, [pluginList?.plugins.length, t, filters.categories.length, filters.tags.length, filters.searchQuery])
|
||||
|
||||
return (
|
||||
<div className='grow w-full relative z-0'>
|
||||
|
|
@ -100,7 +99,7 @@ const Empty = () => {
|
|||
</div>
|
||||
</div>
|
||||
{selectedAction === 'github' && <InstallFromGitHub
|
||||
onSuccess={() => { invalidateInstalledPluginList() }}
|
||||
onSuccess={() => { }}
|
||||
onClose={() => setSelectedAction(null)}
|
||||
/>}
|
||||
{selectedAction === 'local' && selectedFile
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import {
|
|||
PortalToFollowElemTrigger,
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
import { useSelector as useAppContextSelector } from '@/context/app-context'
|
||||
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { SUPPORT_INSTALL_LOCAL_FILE_EXTENSIONS } from '@/config'
|
||||
|
||||
|
|
@ -31,7 +30,6 @@ const InstallPluginDropdown = ({
|
|||
const [selectedAction, setSelectedAction] = useState<string | null>(null)
|
||||
const [selectedFile, setSelectedFile] = useState<File | null>(null)
|
||||
const { enable_marketplace } = useAppContextSelector(s => s.systemFeatures)
|
||||
const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
|
||||
|
||||
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = event.target.files?.[0]
|
||||
|
|
@ -120,7 +118,7 @@ const InstallPluginDropdown = ({
|
|||
</PortalToFollowElemContent>
|
||||
</div>
|
||||
{selectedAction === 'github' && <InstallFromGitHub
|
||||
onSuccess={() => { invalidateInstalledPluginList() }}
|
||||
onSuccess={() => { }}
|
||||
onClose={() => setSelectedAction(null)}
|
||||
/>}
|
||||
{selectedAction === 'local' && selectedFile
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import CardIcon from '@/app/components/plugins/card/base/card-icon'
|
|||
import cn from '@/utils/classnames'
|
||||
import { useGetLanguage } from '@/context/i18n'
|
||||
import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon'
|
||||
import DownloadingIcon from '@/app/components/header/plugins-nav/downloading-icon'
|
||||
|
||||
const PluginTasks = () => {
|
||||
const { t } = useTranslation()
|
||||
|
|
@ -87,12 +88,21 @@ const PluginTasks = () => {
|
|||
(isInstallingWithError || isFailed) && 'border-components-button-destructive-secondary-border-hover bg-state-destructive-hover hover:bg-state-destructive-hover-alt cursor-pointer',
|
||||
)}
|
||||
>
|
||||
<RiInstallLine
|
||||
className={cn(
|
||||
'w-4 h-4 text-components-button-secondary-text',
|
||||
(isInstallingWithError || isFailed) && 'text-components-button-destructive-secondary-text',
|
||||
)}
|
||||
/>
|
||||
{
|
||||
(isInstalling || isInstallingWithError) && (
|
||||
<DownloadingIcon />
|
||||
)
|
||||
}
|
||||
{
|
||||
!(isInstalling || isInstallingWithError) && (
|
||||
<RiInstallLine
|
||||
className={cn(
|
||||
'w-4 h-4 text-components-button-secondary-text',
|
||||
(isInstallingWithError || isFailed) && 'text-components-button-destructive-secondary-text',
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
<div className='absolute -right-1 -top-1'>
|
||||
{
|
||||
(isInstalling || isInstallingWithSuccess) && (
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ export type PluginDetail = {
|
|||
export type PluginInfoFromMarketPlace = {
|
||||
category: PluginType
|
||||
latest_package_identifier: string
|
||||
latest_version: string
|
||||
}
|
||||
|
||||
export type Plugin = {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import { useMarketplacePlugins } from '../../plugins/marketplace/hooks'
|
|||
|
||||
type AllToolsProps = {
|
||||
className?: string
|
||||
toolContentClassName?: string
|
||||
searchText: string
|
||||
tags: string[]
|
||||
buildInTools: ToolWithProvider[]
|
||||
|
|
@ -34,6 +35,7 @@ type AllToolsProps = {
|
|||
}
|
||||
const AllTools = ({
|
||||
className,
|
||||
toolContentClassName,
|
||||
searchText,
|
||||
tags = [],
|
||||
onSelect,
|
||||
|
|
@ -130,6 +132,7 @@ const AllTools = ({
|
|||
onScroll={(pluginRef.current as any)?.handleScroll}
|
||||
>
|
||||
<Tools
|
||||
className={toolContentClassName}
|
||||
showWorkflowEmpty={activeTab === ToolTypeEnum.Workflow}
|
||||
tools={tools}
|
||||
onSelect={onSelect}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { FC } from 'react'
|
||||
import { memo } from 'react'
|
||||
import { useStore } from '../store'
|
||||
import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools } from '@/service/use-tools'
|
||||
import type { BlockEnum } from '../types'
|
||||
import { useTabs } from './hooks'
|
||||
import type { ToolDefaultValue } from './types'
|
||||
|
|
@ -28,9 +28,9 @@ const Tabs: FC<TabsProps> = ({
|
|||
noBlocks,
|
||||
}) => {
|
||||
const tabs = useTabs()
|
||||
const buildInTools = useStore(s => s.buildInTools)
|
||||
const customTools = useStore(s => s.customTools)
|
||||
const workflowTools = useStore(s => s.workflowTools)
|
||||
const { data: buildInTools } = useAllBuiltInTools()
|
||||
const { data: customTools } = useAllCustomTools()
|
||||
const { data: workflowTools } = useAllWorkflowTools()
|
||||
|
||||
return (
|
||||
<div onClick={e => e.stopPropagation()}>
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ const ToolPicker: FC<Props> = ({
|
|||
</div>
|
||||
<AllTools
|
||||
className='mt-1'
|
||||
toolContentClassName='max-w-[360px]'
|
||||
tags={tags}
|
||||
searchText={searchText}
|
||||
onSelect={handleSelect}
|
||||
|
|
|
|||
|
|
@ -404,6 +404,7 @@ export const SUPPORT_OUTPUT_VARS_NODE = [
|
|||
BlockEnum.HttpRequest, BlockEnum.Tool, BlockEnum.VariableAssigner, BlockEnum.VariableAggregator, BlockEnum.QuestionClassifier,
|
||||
BlockEnum.ParameterExtractor, BlockEnum.Iteration,
|
||||
BlockEnum.DocExtractor, BlockEnum.ListFilter,
|
||||
BlockEnum.Agent,
|
||||
]
|
||||
|
||||
export const LLM_OUTPUT_STRUCT: Var[] = [
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { useStrategyInfo } from '../../agent/use-config'
|
|||
import { SwitchPluginVersion } from './switch-plugin-version'
|
||||
import PluginList from '@/app/components/workflow/block-selector/market-place-plugin/list'
|
||||
import { useMarketplacePlugins } from '@/app/components/plugins/marketplace/hooks'
|
||||
import { ToolTipContent } from '@/app/components/base/tooltip/content'
|
||||
|
||||
const NotFoundWarn = (props: {
|
||||
title: ReactNode,
|
||||
|
|
@ -178,7 +179,10 @@ export const AgentStrategySelector = memo((props: AgentStrategySelectorProps) =>
|
|||
}
|
||||
{showSwitchVersion && <SwitchPluginVersion
|
||||
uniqueIdentifier={'langgenius/openai:12'}
|
||||
tooltip={t('workflow.nodes.agent.switchToNewVersion')}
|
||||
tooltip={<ToolTipContent
|
||||
title={t('workflow.nodes.agent.unsupportedStrategy')}>
|
||||
{t('workflow.nodes.agent.strategyNotFoundDescAndSwitchVersion')}
|
||||
</ToolTipContent>}
|
||||
onChange={() => {
|
||||
// TODO: refresh all strategies
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -4,20 +4,22 @@ import Badge from '@/app/components/base/badge'
|
|||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import PluginVersionPicker from '@/app/components/plugins/update-plugin/plugin-version-picker'
|
||||
import { RiArrowLeftRightLine } from '@remixicon/react'
|
||||
import type { ReactNode } from 'react'
|
||||
import { type FC, useCallback, useState } from 'react'
|
||||
import cn from '@/utils/classnames'
|
||||
import UpdateFromMarketplace from '@/app/components/plugins/update-plugin/from-market-place'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { useCheckInstalled } from '@/service/use-plugins'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
export type SwitchPluginVersionProps = {
|
||||
uniqueIdentifier: string
|
||||
tooltip?: string
|
||||
tooltip?: ReactNode
|
||||
onChange?: (version: string) => void
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const SwitchPluginVersion: FC<SwitchPluginVersionProps> = (props) => {
|
||||
const { uniqueIdentifier, tooltip, onChange } = props
|
||||
const { uniqueIdentifier, tooltip, onChange, className } = props
|
||||
const [pluginId] = uniqueIdentifier.split(':')
|
||||
const [isShow, setIsShow] = useState(false)
|
||||
const [isShowUpdateModal, { setTrue: showUpdateModal, setFalse: hideUpdateModal }] = useBoolean(false)
|
||||
|
|
@ -33,8 +35,13 @@ export const SwitchPluginVersion: FC<SwitchPluginVersionProps> = (props) => {
|
|||
pluginDetails.refetch()
|
||||
onChange?.(targetVersion!)
|
||||
}, [hideUpdateModal, onChange, pluginDetails, targetVersion])
|
||||
|
||||
const targetUniqueIdentifier = (() => {
|
||||
if (!targetVersion || !pluginDetail) return uniqueIdentifier
|
||||
return uniqueIdentifier.replaceAll(pluginDetail.version, targetVersion)
|
||||
})()
|
||||
return <Tooltip popupContent={!isShow && !isShowUpdateModal && tooltip} triggerMethod='hover'>
|
||||
<div className='w-fit'>
|
||||
<div className={cn('w-fit', className)}>
|
||||
{isShowUpdateModal && pluginDetail && <UpdateFromMarketplace
|
||||
payload={{
|
||||
originalPackageInfo: {
|
||||
|
|
@ -42,7 +49,7 @@ export const SwitchPluginVersion: FC<SwitchPluginVersionProps> = (props) => {
|
|||
payload: pluginDetail.declaration,
|
||||
},
|
||||
targetPackageInfo: {
|
||||
id: uniqueIdentifier,
|
||||
id: targetUniqueIdentifier,
|
||||
version: targetVersion!,
|
||||
},
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -319,16 +319,13 @@ const formatItem = (
|
|||
case BlockEnum.Agent: {
|
||||
const payload = data as AgentNodeType
|
||||
const outputs: Var[] = []
|
||||
Object.keys(payload.output_schema.properties).forEach((outputKey) => {
|
||||
Object.keys(payload.output_schema?.properties || {}).forEach((outputKey) => {
|
||||
const output = payload.output_schema.properties[outputKey]
|
||||
outputs.push({
|
||||
variable: outputKey,
|
||||
type: output.type === 'array'
|
||||
? `Array[${output.items?.type.slice(0, 1).toLocaleUpperCase()}${output.items?.type.slice(1)}]` as VarType
|
||||
: `${output.type.slice(0, 1).toLocaleUpperCase()}${output.type.slice(1)}` as VarType,
|
||||
// TODO: is this required?
|
||||
// @ts-expect-error todo added
|
||||
description: output.description,
|
||||
})
|
||||
})
|
||||
res.vars = [
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => {
|
|||
return <ModelSelector
|
||||
key={model.param}
|
||||
modelList={modelList}
|
||||
triggerClassName='bg-workflow-block-parma-bg'
|
||||
triggerClassName='bg-workflow-block-parma-bg !h-6 !rounded-md'
|
||||
defaultModel={
|
||||
'provider' in model
|
||||
? {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ const Node: FC<NodeProps<LLMNodeType>> = ({
|
|||
<ModelSelector
|
||||
defaultModel={{ provider, model: modelId }}
|
||||
modelList={textGenerationModelList}
|
||||
triggerClassName='!h-6 !rounded-md'
|
||||
readonly
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ const Node: FC<NodeProps<ParameterExtractorNodeType>> = ({
|
|||
<ModelSelector
|
||||
defaultModel={{ provider, model: modelId }}
|
||||
modelList={textGenerationModelList}
|
||||
triggerClassName='!h-6 !rounded-md'
|
||||
readonly
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ const Node: FC<NodeProps<QuestionClassifierNodeType>> = (props) => {
|
|||
{hasSetModel && (
|
||||
<ModelSelector
|
||||
defaultModel={{ provider, model: modelId }}
|
||||
triggerClassName='!h-6 !rounded-md'
|
||||
modelList={textGenerationModelList}
|
||||
readonly
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -30,26 +30,26 @@ const AgentLogItem = ({
|
|||
<div className='border-[0.5px] border-components-panel-border rounded-[10px]'>
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center pl-1.5 pt-2 pr-3 pb-2',
|
||||
'flex items-center pl-1.5 pt-2 pr-3 pb-2 cursor-pointer',
|
||||
expanded && 'pb-1',
|
||||
)}
|
||||
onClick={() => setExpanded(!expanded)}
|
||||
>
|
||||
{
|
||||
expanded
|
||||
? <RiArrowRightSLine className='shrink-0 w-4 h-4 rotate-90' />
|
||||
: <RiArrowRightSLine className='shrink-0 w-4 h-4' />
|
||||
? <RiArrowRightSLine className='shrink-0 w-4 h-4 rotate-90 text-text-quaternary' />
|
||||
: <RiArrowRightSLine className='shrink-0 w-4 h-4 text-text-quaternary' />
|
||||
}
|
||||
<div className='shrink-0 mr-1.5 w-5 h-5'></div>
|
||||
<div className='grow system-sm-semibold-uppercase text-text-secondary truncate'>{label}</div>
|
||||
<div className='shrink-0 mr-2 system-xs-regular text-text-tertiary'>0.02s</div>
|
||||
{/* <div className='shrink-0 mr-2 system-xs-regular text-text-tertiary'>0.02s</div> */}
|
||||
<NodeStatusIcon status={status} />
|
||||
</div>
|
||||
{
|
||||
expanded && (
|
||||
<div className='p-1 pt-0'>
|
||||
{
|
||||
!!children.length && (
|
||||
!!children?.length && (
|
||||
<Button
|
||||
className='flex items-center justify-between mb-1 w-full'
|
||||
variant='tertiary'
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ const AgentLogNav = ({
|
|||
className='shrink-0 px-[5px]'
|
||||
size='small'
|
||||
variant='ghost-accent'
|
||||
onClick={() => onShowAgentOrToolLog()}
|
||||
onClick={() => {
|
||||
onShowAgentOrToolLog()
|
||||
}}
|
||||
>
|
||||
<RiArrowLeftLine className='mr-1 w-3.5 h-3.5' />
|
||||
Agent
|
||||
|
|
@ -31,7 +33,6 @@ const AgentLogNav = ({
|
|||
variant='ghost-accent'
|
||||
onClick={() => {}}
|
||||
>
|
||||
<RiArrowLeftLine className='mr-1 w-3.5 h-3.5' />
|
||||
Agent strategy
|
||||
</Button>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ const AgentLogTrigger = ({
|
|||
<div className='grow mx-0.5 px-1 system-xs-medium text-text-secondary'></div>
|
||||
<div
|
||||
className='shrink-0 flex items-center px-[1px] system-xs-regular-uppercase text-text-tertiary cursor-pointer'
|
||||
onClick={() => onShowAgentOrToolLog({ id: nodeInfo.id, children: agentLog || [] } as AgentLogItemWithChildren)}
|
||||
onClick={() => {
|
||||
onShowAgentOrToolLog({ id: nodeInfo.id, children: agentLog || [] } as AgentLogItemWithChildren)
|
||||
}}
|
||||
>
|
||||
Detail
|
||||
<RiArrowRightLine className='ml-0.5 w-3.5 h-3.5' />
|
||||
|
|
|
|||
|
|
@ -36,7 +36,10 @@ const SpecialResultPanel = ({
|
|||
handleShowAgentOrToolLog,
|
||||
}: SpecialResultPanelProps) => {
|
||||
return (
|
||||
<>
|
||||
<div onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
e.nativeEvent.stopImmediatePropagation()
|
||||
}}>
|
||||
{
|
||||
!!showRetryDetail && !!retryResultList?.length && setShowRetryDetailFalse && (
|
||||
<RetryResultPanel
|
||||
|
|
@ -63,7 +66,7 @@ const SpecialResultPanel = ({
|
|||
/>
|
||||
)
|
||||
}
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -166,7 +166,13 @@ const TracingPanel: FC<TracingPanelProps> = ({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className={cn(className || 'bg-components-panel-bg', 'py-2')}>
|
||||
<div
|
||||
className={cn(className || 'bg-components-panel-bg', 'py-2')}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
e.nativeEvent.stopImmediatePropagation()
|
||||
}}
|
||||
>
|
||||
{treeNodes.map(renderNode)}
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
'use client'
|
||||
|
||||
import { ToolTipContent } from '../components/base/tooltip/content'
|
||||
import { SwitchPluginVersion } from '../components/workflow/nodes/_base/components/switch-plugin-version'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
|
|
@ -8,7 +9,11 @@ export default function Page() {
|
|||
return <div className="p-20">
|
||||
<SwitchPluginVersion
|
||||
uniqueIdentifier={'langgenius/openai:12'}
|
||||
tooltip={t('workflow.nodes.agent.switchToNewVersion')}
|
||||
tooltip={<ToolTipContent
|
||||
title={t('workflow.nodes.agent.unsupportedStrategy')}
|
||||
>
|
||||
{t('workflow.nodes.agent.strategyNotFoundDescAndSwitchVersion')}
|
||||
</ToolTipContent>}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,17 @@ const translation = {
|
|||
all: 'All',
|
||||
models: 'Models',
|
||||
tools: 'Tools',
|
||||
agents: 'Agent Strategy',
|
||||
agents: 'Agent Strategies',
|
||||
extensions: 'Extensions',
|
||||
bundles: 'Bundles',
|
||||
},
|
||||
categorySingle: {
|
||||
model: 'Model',
|
||||
tool: 'Tool',
|
||||
agent: 'Agent Strategy',
|
||||
extension: 'Extension',
|
||||
bundle: 'Bundle',
|
||||
},
|
||||
search: 'Search',
|
||||
allCategories: 'All Categories',
|
||||
searchCategories: 'Search Categories',
|
||||
|
|
@ -77,6 +84,9 @@ const translation = {
|
|||
uninstalledTitle: 'Tool not installed',
|
||||
uninstalledContent: 'This plugin is installed from the local/GitHub repository. Please use after installation.',
|
||||
uninstalledLink: 'Manage in Plugins',
|
||||
unsupportedTitle: 'Unsupported Action',
|
||||
unsupportedContent: 'The installed plugin version does not provide this action.',
|
||||
unsupportedContent2: 'Click to switch version.',
|
||||
},
|
||||
configureApp: 'Configure App',
|
||||
configureModel: 'Configure model',
|
||||
|
|
|
|||
|
|
@ -722,6 +722,10 @@ const translation = {
|
|||
desc: 'This model is installed from Local or GitHub repository. Please use after installation.',
|
||||
manageInPlugins: 'Manage in Plugins',
|
||||
},
|
||||
modelNotSupport: {
|
||||
title: 'Unsupported Model',
|
||||
desc: 'The installed plugin version does not provide this model.',
|
||||
},
|
||||
configureModel: 'Configure Model',
|
||||
notAuthorized: 'Not Authorized',
|
||||
model: 'model',
|
||||
|
|
@ -755,7 +759,6 @@ const translation = {
|
|||
checkList: {
|
||||
strategyNotSelected: 'Strategy not selected',
|
||||
},
|
||||
switchToNewVersion: 'Switch to new version',
|
||||
},
|
||||
tracing: {
|
||||
stopBy: 'Stop by {{user}}',
|
||||
|
|
|
|||
|
|
@ -7,6 +7,13 @@ const translation = {
|
|||
extensions: '扩展',
|
||||
bundles: '插件集',
|
||||
},
|
||||
categorySingle: {
|
||||
model: '模型',
|
||||
tool: '工具',
|
||||
agent: 'Agent 策略',
|
||||
extension: '扩展',
|
||||
bundle: '插件集',
|
||||
},
|
||||
search: '搜索',
|
||||
allCategories: '所有类别',
|
||||
searchCategories: '搜索类别',
|
||||
|
|
@ -77,6 +84,9 @@ const translation = {
|
|||
uninstalledTitle: '工具未安装',
|
||||
uninstalledContent: '此插件安装自 本地 / GitHub 仓库,请安装后使用。',
|
||||
uninstalledLink: '在插件中管理',
|
||||
unsupportedTitle: '不支持的 Action',
|
||||
unsupportedContent: '已安装的插件版本不提供这个 action。',
|
||||
unsupportedContent2: '点击切换版本',
|
||||
},
|
||||
configureApp: '应用设置',
|
||||
configureModel: '模型设置',
|
||||
|
|
|
|||
|
|
@ -722,6 +722,10 @@ const translation = {
|
|||
desc: '此模型安装自本地或 GitHub 仓库。请安装后使用。',
|
||||
manageInPlugins: '在插件中管理',
|
||||
},
|
||||
modelNotSupport: {
|
||||
title: '不支持的模型',
|
||||
desc: '已安装的插件版本不提供此模型。',
|
||||
},
|
||||
model: '模型',
|
||||
toolbox: '工具箱',
|
||||
strategyNotSet: '代理策略未设置',
|
||||
|
|
@ -754,7 +758,6 @@ const translation = {
|
|||
checkList: {
|
||||
strategyNotSelected: '未选择策略',
|
||||
},
|
||||
switchToNewVersion: '切换到新版',
|
||||
},
|
||||
},
|
||||
tracing: {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export const useCheckInstalled = ({
|
|||
enabled: boolean
|
||||
}) => {
|
||||
return useQuery<{ plugins: PluginDetail[] }>({
|
||||
queryKey: [NAME_SPACE, 'checkInstalled'],
|
||||
queryKey: [NAME_SPACE, 'checkInstalled', pluginIds],
|
||||
queryFn: () => post<{ plugins: PluginDetail[] }>('/workspaces/current/plugin/list/installations/ids', {
|
||||
body: {
|
||||
plugin_ids: pluginIds,
|
||||
|
|
@ -82,8 +82,9 @@ export const useInstallPackageFromMarketPlace = (options?: MutateOptions<Install
|
|||
})
|
||||
}
|
||||
|
||||
export const useUpdatePackageFromMarketPlace = () => {
|
||||
export const useUpdatePackageFromMarketPlace = (options?: MutateOptions<InstallPackageResponse, Error, object>) => {
|
||||
return useMutation({
|
||||
...options,
|
||||
mutationFn: (body: object) => {
|
||||
return post<InstallPackageResponse>('/workspaces/current/plugin/upgrade/marketplace', {
|
||||
body,
|
||||
|
|
@ -364,7 +365,7 @@ export const usePluginTaskList = () => {
|
|||
queryKey: usePluginTaskListKey,
|
||||
queryFn: async () => {
|
||||
const currentData = await get<{ tasks: PluginTask[] }>('/workspaces/current/plugin/tasks?page=1&page_size=100')
|
||||
const taskDone = currentData.tasks.every(task => task.status === TaskStatus.success)
|
||||
const taskDone = currentData.tasks.every(task => task.status === TaskStatus.success || task.status === TaskStatus.failed)
|
||||
|
||||
if (taskDone)
|
||||
setEnabled(false)
|
||||
|
|
|
|||
Loading…
Reference in New Issue