Merge branch 'feat/plugins' into dev/plugin-deploy

This commit is contained in:
zxhlyh
2025-01-08 16:47:27 +08:00
30 changed files with 346 additions and 283 deletions

View File

@ -40,7 +40,7 @@ const ModelIcon: FC<ModelIconProps> = ({
return (
<div className={cn(
'flex items-center justify-center rounded-md border-[0.5px] border-components-panel-border-subtle bg-background-default-subtle',
'flex items-center justify-center rounded-md border-[0.5px] w-5 h-5 border-components-panel-border-subtle bg-background-default-subtle',
className,
)}>
<div className='flex w-5 h-5 items-center justify-center opacity-35'>

View File

@ -26,6 +26,7 @@ import cn from '@/utils/classnames'
import { useProviderContext } from '@/context/provider-context'
import { RiEqualizer2Line } from '@remixicon/react'
import { fetchPluginInfoFromMarketPlace } from '@/service/plugins'
import { fetchModelProviderModelList } from '@/service/common'
export type AgentModelTriggerProps = {
open?: boolean
@ -67,11 +68,22 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
const [pluginInfo, setPluginInfo] = useState<PluginInfoFromMarketPlace | null>(null)
const [isPluginChecked, setIsPluginChecked] = useState(false)
const [installed, setInstalled] = useState(false)
const [inModelList, setInModelList] = useState(false)
const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
const handleOpenModal = useModelModalHandler()
useEffect(() => {
(async () => {
if (providerName && !modelProvider) {
if (modelId && currentProvider) {
try {
const modelsData = await fetchModelProviderModelList(`/workspaces/current/model-providers/${currentProvider?.provider}/models`)
if (modelId && modelsData.data.find(item => item.model === modelId))
setInModelList(true)
}
catch (error) {
// pass
}
}
if (providerName) {
const parts = providerName.split('/')
const org = parts[0]
const name = parts[1]
@ -89,7 +101,7 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
setIsPluginChecked(true)
}
})()
}, [providerName, modelProvider])
}, [providerName, modelId, currentProvider])
if (modelId && !isPluginChecked)
return null
@ -121,6 +133,7 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
<StatusIndicators
needsConfiguration={needsConfiguration}
modelProvider={!!modelProvider}
inModelList={inModelList}
disabled={!!disabled}
pluginInfo={pluginInfo}
t={t}

View File

@ -1,46 +1,73 @@
import Tooltip from '@/app/components/base/tooltip'
import Link from 'next/link'
import { SwitchPluginVersion } from '@/app/components/workflow/nodes/_base/components/switch-plugin-version'
import { useInstalledPluginList } from '@/service/use-plugins'
import { RiErrorWarningFill } from '@remixicon/react'
type StatusIndicatorsProps = {
needsConfiguration: boolean
modelProvider: boolean
inModelList: boolean
disabled: boolean
pluginInfo: any
t: any
}
const StatusIndicators = ({ needsConfiguration, modelProvider, disabled, pluginInfo, t }: StatusIndicatorsProps) => {
const StatusIndicators = ({ needsConfiguration, modelProvider, inModelList, disabled, pluginInfo, t }: StatusIndicatorsProps) => {
const { data: pluginList } = useInstalledPluginList()
const renderTooltipContent = (title: string, description?: string, linkText?: string, linkHref?: string) => {
return (
<div className='flex w-[240px] max-w-[240px] gap-1 flex-col px-1 py-1.5' onClick={e => e.stopPropagation()}>
<div className='text-text-primary title-xs-semi-bold'>{title}</div>
{description && (
<div className='min-w-[200px] text-text-secondary body-xs-regular'>
{description}
</div>
)}
{linkText && linkHref && (
<div className='text-text-accent body-xs-regular cursor-pointer z-[100]'>
<Link
href={linkHref}
onClick={(e) => {
e.stopPropagation()
}}
>
{linkText}
</Link>
</div>
)}
</div>
)
}
// const installedPluginUniqueIdentifier = pluginList?.plugins.find(plugin => plugin.name === pluginInfo.name)?.plugin_unique_identifier
return (
<>
{/* plugin installed and model is in model list but disabled */}
{/* plugin installed from github/local and model is not in model list */}
{!needsConfiguration && modelProvider && disabled && (
<Tooltip
popupContent={t('workflow.nodes.agent.modelSelectorTooltips.deprecated')}
popupContent={inModelList ? t('workflow.nodes.agent.modelSelectorTooltips.deprecated')
: renderTooltipContent(
t('workflow.nodes.agent.modelNotSupport.title'),
!pluginInfo ? t('workflow.nodes.agent.modelNotSupport.desc') : t('workflow.nodes.agent.modelNotSupport.descForVersionSwitch'),
!pluginInfo ? t('workflow.nodes.agent.linkToPlugin') : '',
!pluginInfo ? '/plugins' : '',
)
}
asChild={false}
needsDelay={!inModelList}
>
<RiErrorWarningFill className='w-4 h-4 text-text-destructive' />
{!pluginInfo ? <RiErrorWarningFill className='w-4 h-4 text-text-destructive' /> : <SwitchPluginVersion uniqueIdentifier={pluginList?.plugins.find(plugin => plugin.name === pluginInfo.name)?.plugin_unique_identifier ?? ''} />}
</Tooltip>
)}
{!modelProvider && !pluginInfo && (
<Tooltip
popupContent={
<div className='flex w-[240px] max-w-[240px] gap-1 flex-col px-1 py-1.5'>
<div className='text-text-primary title-xs-semi-bold'>{t('workflow.nodes.agent.modelNotInMarketplace.title')}</div>
<div className='min-w-[200px] text-text-secondary body-xs-regular'>
{t('workflow.nodes.agent.modelNotInMarketplace.desc')}
</div>
<div className='text-text-accent body-xs-regular cursor-pointer z-[100]'>
<Link
href={'/plugins'}
onClick={(e) => {
e.stopPropagation()
}}
>
{t('workflow.nodes.agent.linkToPlugin')}
</Link>
</div>
</div>
}
popupContent={renderTooltipContent(
t('workflow.nodes.agent.modelNotInMarketplace.title'),
t('workflow.nodes.agent.modelNotInMarketplace.desc'),
t('workflow.nodes.agent.linkToPlugin'),
'/plugins',
)}
asChild={false}
needsDelay
>

View File

@ -22,11 +22,11 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
return (
<div
className={cn('group flex flex-grow items-center p-[3px] pl-1 h-6 gap-1 rounded-lg bg-components-input-bg-disabled cursor-pointer', className)}
className={cn('group flex flex-grow items-center p-[3px] pl-1 h-8 gap-1 rounded-lg bg-components-input-bg-disabled cursor-pointer', className)}
>
<div className='flex items-center py-[1px] gap-1 grow'>
<ModelIcon
className="m-0.5 w-4 h-4"
className="w-4 h-4"
provider={currentProvider}
modelName={modelName}
/>