add model install in model configuration for the agent node

pull/12372/head
Yi 1 year ago
parent afb3548e45
commit 9b6f580365

@ -3,7 +3,7 @@ import { RiInstallLine, RiLoader2Line } from '@remixicon/react'
type InstallButtonProps = { type InstallButtonProps = {
loading: boolean loading: boolean
onInstall: () => void onInstall: (e: React.MouseEvent) => void
t: any t: any
} }

@ -1,5 +1,5 @@
import type { FC } from 'react' import type { FC } from 'react'
import { useEffect, useState } from 'react' import { useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import type { import type {
CustomConfigurationModelFixedFields, CustomConfigurationModelFixedFields,
@ -9,6 +9,7 @@ import type {
import { import {
ConfigurationMethodEnum, ConfigurationMethodEnum,
CustomConfigurationStatusEnum, CustomConfigurationStatusEnum,
ModelTypeEnum,
} from '../declarations' } from '../declarations'
import { UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST } from '../provider-added-card' import { UPDATE_MODEL_PROVIDER_CUSTOM_MODEL_LIST } from '../provider-added-card'
import type { PluginInfoFromMarketPlace } from '@/app/components/plugins/types' import type { PluginInfoFromMarketPlace } from '@/app/components/plugins/types'
@ -54,13 +55,19 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
const updateModelProviders = useUpdateModelProviders() const updateModelProviders = useUpdateModelProviders()
const updateModelList = useUpdateModelList() const updateModelList = useUpdateModelList()
const { eventEmitter } = useEventEmitterContextContext() const { eventEmitter } = useEventEmitterContextContext()
const modelProvider = modelProviders.find(item => item.provider === providerName) const { modelProvider, needsConfiguration } = useMemo(() => {
const needsConfiguration = modelProvider?.custom_configuration.status === CustomConfigurationStatusEnum.noConfigure && !( const modelProvider = modelProviders.find(item => item.provider === providerName)
modelProvider.system_configuration.enabled === true const needsConfiguration = modelProvider?.custom_configuration.status === CustomConfigurationStatusEnum.noConfigure && !(
&& modelProvider.system_configuration.quota_configurations.find( modelProvider.system_configuration.enabled === true
item => item.quota_type === modelProvider.system_configuration.current_quota_type, && modelProvider.system_configuration.quota_configurations.find(
item => item.quota_type === modelProvider.system_configuration.current_quota_type,
)
) )
) return {
modelProvider,
needsConfiguration,
}
}, [modelProviders, providerName])
const [pluginInfo, setPluginInfo] = useState<PluginInfoFromMarketPlace | null>(null) const [pluginInfo, setPluginInfo] = useState<PluginInfoFromMarketPlace | null>(null)
const [isPluginChecked, setIsPluginChecked] = useState(false) const [isPluginChecked, setIsPluginChecked] = useState(false)
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
@ -124,6 +131,24 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
}) })
} }
const handleInstall = async (pluginInfo: PluginInfoFromMarketPlace) => {
setLoading(true)
try {
const { all_installed } = await installPackageFromMarketPlace(pluginInfo.latest_package_identifier)
if (all_installed) {
setInstalled(true)
updateModelProviders()
updateModelList(ModelTypeEnum.textGeneration)
}
}
catch (error) {
console.error('Installation failed:', error)
}
finally {
setLoading(false)
}
}
return ( return (
<div <div
className={cn( className={cn(
@ -158,15 +183,18 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
{!installed && !modelProvider && pluginInfo && ( {!installed && !modelProvider && pluginInfo && (
<InstallButton <InstallButton
loading={loading} loading={loading}
onInstall={async () => { onInstall={(e) => {
setLoading(true) e.stopPropagation()
const { all_installed } = await installPackageFromMarketPlace(pluginInfo.latest_package_identifier) handleInstall(pluginInfo)
if (all_installed)
setInstalled(true)
}} }}
t={t} t={t}
/> />
)} )}
{modelProvider && !disabled && (
<div className="flex pr-1 items-center">
<RiEqualizer2Line className="w-4 h-4 text-text-tertiary group-hover:text-text-secondary" />
</div>
)}
</> </>
) : ( ) : (
<> <>

@ -1,4 +1,5 @@
import Tooltip from '@/app/components/base/tooltip' import Tooltip from '@/app/components/base/tooltip'
import Link from 'next/link'
import { RiErrorWarningFill } from '@remixicon/react' import { RiErrorWarningFill } from '@remixicon/react'
type StatusIndicatorsProps = { type StatusIndicatorsProps = {
@ -28,7 +29,16 @@ const StatusIndicators = ({ needsConfiguration, modelProvider, disabled, pluginI
<div className='min-w-[200px] text-text-secondary body-xs-regular'> <div className='min-w-[200px] text-text-secondary body-xs-regular'>
{t('workflow.nodes.agent.modelNotInMarketplace.desc')} {t('workflow.nodes.agent.modelNotInMarketplace.desc')}
</div> </div>
<div className='text-text-accent body-xs-regular'>{t('workflow.nodes.agent.modelNotInMarketplace.manageInPlugins')}</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> </div>
} }
asChild={false} asChild={false}

@ -22,14 +22,14 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
return ( return (
<div <div
className={cn('group flex items-center px-2 h-8 rounded-lg bg-components-input-bg-disabled cursor-pointer', className)} className={cn('group flex items-center p-1 gap-0.5 rounded-lg bg-components-input-bg-disabled cursor-pointer', className)}
> >
<ModelIcon <ModelIcon
className='shrink-0 mr-1.5' className='shrink-0 mr-1.5'
provider={currentProvider} provider={currentProvider}
modelName={modelName} modelName={modelName}
/> />
<div className='mr-1 text-[13px] font-medium text-text-secondary truncate'> <div className='mr-1 system-sm-regular text-components-input-text-filled truncate'>
{modelName} {modelName}
</div> </div>
<div className='shrink-0 flex items-center justify-center w-4 h-4'> <div className='shrink-0 flex items-center justify-center w-4 h-4'>

@ -14,7 +14,7 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
return ( return (
<div <div
className={cn( className={cn(
'flex items-center px-2 h-8 rounded-lg bg-components-input-bg-normal hover:bg-components-input-bg-hover cursor-pointer', open && 'bg-components-input-bg-hover', 'flex items-center p-1 gap-0.5 rounded-lg bg-components-input-bg-normal hover:bg-components-input-bg-hover cursor-pointer', open && 'bg-components-input-bg-hover',
className, className,
)} )}
> >

@ -89,15 +89,15 @@ export const AgentStrategySelector = (props: AgentStrategySelectorProps) => {
const { t } = useTranslation() const { t } = useTranslation()
return <PortalToFollowElem open={open} onOpenChange={setOpen} placement='bottom'> return <PortalToFollowElem open={open} onOpenChange={setOpen} placement='bottom'>
<PortalToFollowElemTrigger className='w-full'> <PortalToFollowElemTrigger className='w-full'>
<div className='py-2 pl-3 pr-2 flex items-center rounded-lg bg-components-input-bg-normal w-full hover:bg-state-base-hover-alt select-none' onClick={() => setOpen(o => !o)}> <div className='p-1 gap-0.5 flex items-center rounded-lg bg-components-input-bg-normal w-full hover:bg-state-base-hover-alt select-none' onClick={() => setOpen(o => !o)}>
{/* eslint-disable-next-line @next/next/no-img-element */} {/* eslint-disable-next-line @next/next/no-img-element */}
{icon && <img {icon && <div className='flex items-center justify-center w-6 h-6'><img
src={icon} src={icon}
width={20} width={20}
height={20} height={20}
className='rounded-md border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge' className='rounded-md border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge'
alt='icon' alt='icon'
/>} /></div>}
<p <p
className={classNames(value ? 'text-components-input-text-filled' : 'text-components-input-text-placeholder', 'text-xs px-1')} className={classNames(value ? 'text-components-input-text-filled' : 'text-components-input-text-placeholder', 'text-xs px-1')}
> >

@ -716,7 +716,7 @@ const translation = {
}, },
modelNotInMarketplace: { modelNotInMarketplace: {
title: 'Model not installed', title: 'Model not installed',
desc: 'This model is not installed from the marketplace. Please go to Plugins to reinstall.', desc: 'This model is installed from Local or GitHub repository. Please use after installation.',
manageInPlugins: 'Manage in Plugins', manageInPlugins: 'Manage in Plugins',
}, },
configureModel: 'Configure Model', configureModel: 'Configure Model',

@ -716,7 +716,7 @@ const translation = {
}, },
modelNotInMarketplace: { modelNotInMarketplace: {
title: '模型未安装', title: '模型未安装',
desc: '此模型未从市场安装。请转到插件重新安装。', desc: '此模型安装自本地或 GitHub 仓库。请安装后使用。',
manageInPlugins: '在插件中管理', manageInPlugins: '在插件中管理',
}, },
model: '模型', model: '模型',

Loading…
Cancel
Save