Merge branch 'feat/plugins' into dev/plugin-deploy
This commit is contained in:
commit
9ab39c3feb
@ -12,6 +12,7 @@ import {
|
|||||||
import type { PluginInfoFromMarketPlace } from '@/app/components/plugins/types'
|
import type { PluginInfoFromMarketPlace } from '@/app/components/plugins/types'
|
||||||
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
|
||||||
import ConfigurationButton from './configuration-button'
|
import ConfigurationButton from './configuration-button'
|
||||||
|
import Loading from '@/app/components/base/loading'
|
||||||
import { PluginType } from '@/app/components/plugins/types'
|
import { PluginType } from '@/app/components/plugins/types'
|
||||||
import {
|
import {
|
||||||
useModelModalHandler,
|
useModelModalHandler,
|
||||||
@ -104,7 +105,7 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
|
|||||||
}, [providerName, modelId, currentProvider])
|
}, [providerName, modelId, currentProvider])
|
||||||
|
|
||||||
if (modelId && !isPluginChecked)
|
if (modelId && !isPluginChecked)
|
||||||
return null
|
return <Loading />
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -45,20 +45,38 @@ const StatusIndicators = ({ needsConfiguration, modelProvider, inModelList, disa
|
|||||||
{/* plugin installed and model is in model list but disabled */}
|
{/* plugin installed and model is in model list but disabled */}
|
||||||
{/* plugin installed from github/local and model is not in model list */}
|
{/* plugin installed from github/local and model is not in model list */}
|
||||||
{!needsConfiguration && modelProvider && disabled && (
|
{!needsConfiguration && modelProvider && disabled && (
|
||||||
<Tooltip
|
<>
|
||||||
popupContent={inModelList ? t('workflow.nodes.agent.modelSelectorTooltips.deprecated')
|
{inModelList ? (
|
||||||
: renderTooltipContent(
|
<Tooltip
|
||||||
t('workflow.nodes.agent.modelNotSupport.title'),
|
popupContent={t('workflow.nodes.agent.modelSelectorTooltips.deprecated')}
|
||||||
!pluginInfo ? t('workflow.nodes.agent.modelNotSupport.desc') : t('workflow.nodes.agent.modelNotSupport.descForVersionSwitch'),
|
asChild={false}
|
||||||
!pluginInfo ? t('workflow.nodes.agent.linkToPlugin') : '',
|
needsDelay={false}
|
||||||
!pluginInfo ? '/plugins' : '',
|
>
|
||||||
)
|
<RiErrorWarningFill className='w-4 h-4 text-text-destructive' />
|
||||||
}
|
</Tooltip>
|
||||||
asChild={false}
|
) : !pluginInfo ? (
|
||||||
needsDelay={!inModelList}
|
<Tooltip
|
||||||
>
|
popupContent={renderTooltipContent(
|
||||||
{!pluginInfo ? <RiErrorWarningFill className='w-4 h-4 text-text-destructive' /> : <SwitchPluginVersion uniqueIdentifier={pluginList?.plugins.find(plugin => plugin.name === pluginInfo.name)?.plugin_unique_identifier ?? ''} />}
|
t('workflow.nodes.agent.modelNotSupport.title'),
|
||||||
</Tooltip>
|
t('workflow.nodes.agent.modelNotSupport.desc'),
|
||||||
|
t('workflow.nodes.agent.linkToPlugin'),
|
||||||
|
'/plugins',
|
||||||
|
)}
|
||||||
|
asChild={false}
|
||||||
|
needsDelay={true}
|
||||||
|
>
|
||||||
|
<RiErrorWarningFill className='w-4 h-4 text-text-destructive' />
|
||||||
|
</Tooltip>
|
||||||
|
) : (
|
||||||
|
<SwitchPluginVersion
|
||||||
|
tooltip={renderTooltipContent(
|
||||||
|
t('workflow.nodes.agent.modelNotSupport.title'),
|
||||||
|
t('workflow.nodes.agent.modelNotSupport.descForVersionSwitch'),
|
||||||
|
)}
|
||||||
|
uniqueIdentifier={pluginList?.plugins.find(plugin => plugin.name === pluginInfo.name)?.plugin_unique_identifier ?? ''}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
{!modelProvider && !pluginInfo && (
|
{!modelProvider && !pluginInfo && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
|
@ -21,7 +21,7 @@ export const tagKeys = [
|
|||||||
export const categoryKeys = [
|
export const categoryKeys = [
|
||||||
'model',
|
'model',
|
||||||
'tool',
|
'tool',
|
||||||
'agent',
|
'agent-strategy',
|
||||||
'extension',
|
'extension',
|
||||||
'bundle',
|
'bundle',
|
||||||
]
|
]
|
||||||
|
@ -42,10 +42,10 @@ export const useCategories = (translateFromOut?: TFunction) => {
|
|||||||
const t = translateFromOut || translation
|
const t = translateFromOut || translation
|
||||||
|
|
||||||
const categories = categoryKeys.map((category) => {
|
const categories = categoryKeys.map((category) => {
|
||||||
if (category === 'agent') {
|
if (category === 'agent-strategy') {
|
||||||
return {
|
return {
|
||||||
name: 'agent_strategy',
|
name: 'agent-strategy',
|
||||||
label: t(`plugin.category.${category}s`),
|
label: t('plugin.category.agents'),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@ -70,10 +70,10 @@ export const useSingleCategories = (translateFromOut?: TFunction) => {
|
|||||||
const t = translateFromOut || translation
|
const t = translateFromOut || translation
|
||||||
|
|
||||||
const categories = categoryKeys.map((category) => {
|
const categories = categoryKeys.map((category) => {
|
||||||
if (category === 'agent') {
|
if (category === 'agent-strategy') {
|
||||||
return {
|
return {
|
||||||
name: 'agent_strategy',
|
name: 'agent-strategy',
|
||||||
label: t(`plugin.categorySingle.${category}`),
|
label: t('plugin.categorySingle.agent'),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
import { sleep } from '@/utils'
|
||||||
|
|
||||||
|
// modalElem fold into plugin install task btn
|
||||||
|
const animTime = 2000
|
||||||
|
|
||||||
|
function getElemCenter(elem: HTMLElement) {
|
||||||
|
const rect = elem.getBoundingClientRect()
|
||||||
|
return {
|
||||||
|
x: rect.left + rect.width / 2 + window.scrollX,
|
||||||
|
y: rect.top + rect.height / 2 + window.scrollY,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const useFoldAnimInto = (onClose: () => void) => {
|
||||||
|
return async function foldIntoAnim(modalClassName: string) {
|
||||||
|
const modalElem = document.querySelector(`.${modalClassName}`) as HTMLElement
|
||||||
|
const pluginTaskTriggerElem = document.getElementById('plugin-task-trigger')
|
||||||
|
|
||||||
|
if (!modalElem || !pluginTaskTriggerElem) {
|
||||||
|
onClose()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const modelCenter = getElemCenter(modalElem)
|
||||||
|
const modalElemRect = modalElem.getBoundingClientRect()
|
||||||
|
const pluginTaskTriggerCenter = getElemCenter(pluginTaskTriggerElem)
|
||||||
|
const xDiff = pluginTaskTriggerCenter.x - modelCenter.x
|
||||||
|
const yDiff = pluginTaskTriggerCenter.y - modelCenter.y
|
||||||
|
const scale = 1 / Math.max(modalElemRect.width, modalElemRect.height)
|
||||||
|
modalElem.style.transition = `all cubic-bezier(0.4, 0, 0.2, 1) ${animTime}ms`
|
||||||
|
modalElem.style.transform = `translate(${xDiff}px, ${yDiff}px) scale(${scale})`
|
||||||
|
await sleep(animTime)
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useFoldAnimInto
|
@ -1,6 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import React, { useCallback, useState } from 'react'
|
import React, { useCallback, useRef, useState } from 'react'
|
||||||
import Modal from '@/app/components/base/modal'
|
import Modal from '@/app/components/base/modal'
|
||||||
import type { Dependency, Plugin, PluginManifestInMarket } from '../../types'
|
import type { Dependency, Plugin, PluginManifestInMarket } from '../../types'
|
||||||
import { InstallStep } from '../../types'
|
import { InstallStep } from '../../types'
|
||||||
@ -9,6 +9,8 @@ import Installed from '../base/installed'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import useRefreshPluginList from '../hooks/use-refresh-plugin-list'
|
import useRefreshPluginList from '../hooks/use-refresh-plugin-list'
|
||||||
import ReadyToInstallBundle from '../install-bundle/ready-to-install'
|
import ReadyToInstallBundle from '../install-bundle/ready-to-install'
|
||||||
|
import useFoldAnimInto from '../hooks/use-fold-anim-into'
|
||||||
|
import cn from '@/utils/classnames'
|
||||||
|
|
||||||
const i18nPrefix = 'plugin.installModal'
|
const i18nPrefix = 'plugin.installModal'
|
||||||
|
|
||||||
@ -35,6 +37,9 @@ const InstallFromMarketplace: React.FC<InstallFromMarketplaceProps> = ({
|
|||||||
const [errorMsg, setErrorMsg] = useState<string | null>(null)
|
const [errorMsg, setErrorMsg] = useState<string | null>(null)
|
||||||
const { refreshPluginList } = useRefreshPluginList()
|
const { refreshPluginList } = useRefreshPluginList()
|
||||||
|
|
||||||
|
const modalRef = useRef<HTMLElement>(null)
|
||||||
|
const foldAnimInto = useFoldAnimInto(onClose)
|
||||||
|
|
||||||
const getTitle = useCallback(() => {
|
const getTitle = useCallback(() => {
|
||||||
if (isBundle && step === InstallStep.installed)
|
if (isBundle && step === InstallStep.installed)
|
||||||
return t(`${i18nPrefix}.installComplete`)
|
return t(`${i18nPrefix}.installComplete`)
|
||||||
@ -56,12 +61,14 @@ const InstallFromMarketplace: React.FC<InstallFromMarketplaceProps> = ({
|
|||||||
setErrorMsg(errorMsg)
|
setErrorMsg(errorMsg)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const modalClassName = 'install-modal'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
isShow={true}
|
isShow={true}
|
||||||
onClose={onClose}
|
onClose={() => step === InstallStep.readyToInstall ? foldAnimInto(modalClassName) : onClose()}
|
||||||
wrapperClassName='z-[9999]'
|
wrapperClassName='z-[9999]'
|
||||||
className='flex min-w-[560px] p-0 flex-col items-start rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadows-shadow-xl'
|
className={cn(modalClassName, 'flex min-w-[560px] p-0 flex-col items-start rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadows-shadow-xl')}
|
||||||
closable
|
closable
|
||||||
>
|
>
|
||||||
<div className='flex pt-6 pl-6 pb-3 pr-14 items-start gap-2 self-stretch'>
|
<div className='flex pt-6 pl-6 pb-3 pr-14 items-start gap-2 self-stretch'>
|
||||||
|
@ -146,7 +146,7 @@ const PluginPage = ({
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'sticky top-0 flex min-h-[60px] px-12 pt-4 pb-2 items-center self-stretch gap-1 z-10', activeTab === 'discover' && 'bg-background-body',
|
'sticky top-0 flex min-h-[60px] px-12 pt-4 pb-2 items-center self-stretch gap-1 z-10 bg-components-panel-bg', activeTab === 'discover' && 'bg-background-body',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className='flex justify-between items-center w-full'>
|
<div className='flex justify-between items-center w-full'>
|
||||||
|
@ -87,6 +87,7 @@ const PluginTasks = () => {
|
|||||||
'relative flex items-center justify-center w-8 h-8 rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg shadow-xs hover:bg-components-button-secondary-bg-hover',
|
'relative flex items-center justify-center w-8 h-8 rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg shadow-xs hover:bg-components-button-secondary-bg-hover',
|
||||||
(isInstallingWithError || isFailed) && 'border-components-button-destructive-secondary-border-hover bg-state-destructive-hover hover:bg-state-destructive-hover-alt cursor-pointer',
|
(isInstallingWithError || isFailed) && 'border-components-button-destructive-secondary-border-hover bg-state-destructive-hover hover:bg-state-destructive-hover-alt cursor-pointer',
|
||||||
)}
|
)}
|
||||||
|
id="plugin-task-trigger"
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
(isInstalling || isInstallingWithError) && (
|
(isInstalling || isInstallingWithError) && (
|
||||||
|
@ -6,7 +6,7 @@ export enum PluginType {
|
|||||||
tool = 'tool',
|
tool = 'tool',
|
||||||
model = 'model',
|
model = 'model',
|
||||||
extension = 'extension',
|
extension = 'extension',
|
||||||
agent = 'agent_strategy',
|
agent = 'agent-strategy',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum PluginSource {
|
export enum PluginSource {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { ToolCredential, ToolParameter } from '../types'
|
import type { ToolCredential, ToolParameter } from '../types'
|
||||||
const toType = (type: string) => {
|
export const toType = (type: string) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'string':
|
case 'string':
|
||||||
return 'text-input'
|
return 'text-input'
|
||||||
|
@ -19,6 +19,7 @@ import { useWorkflowStore } from '../../../store'
|
|||||||
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
import { useRenderI18nObject } from '@/hooks/use-i18n'
|
||||||
import type { NodeOutPutVar } from '../../../types'
|
import type { NodeOutPutVar } from '../../../types'
|
||||||
import type { Node } from 'reactflow'
|
import type { Node } from 'reactflow'
|
||||||
|
import { toType } from '@/app/components/tools/utils/to-form-schema'
|
||||||
|
|
||||||
export type Strategy = {
|
export type Strategy = {
|
||||||
agent_strategy_provider_name: string
|
agent_strategy_provider_name: string
|
||||||
@ -150,7 +151,7 @@ export const AgentStrategy = memo((props: AgentStrategyProps) => {
|
|||||||
onGenerated={handleGenerated}
|
onGenerated={handleGenerated}
|
||||||
title={renderI18nObject(schema.label)}
|
title={renderI18nObject(schema.label)}
|
||||||
headerClassName='bg-transparent px-0 text-text-secondary system-sm-semibold-uppercase'
|
headerClassName='bg-transparent px-0 text-text-secondary system-sm-semibold-uppercase'
|
||||||
containerClassName='bg-transparent'
|
containerBackgroundClassName='bg-transparent'
|
||||||
gradientBorder={false}
|
gradientBorder={false}
|
||||||
isSupportPromptGenerator={!!schema.auto_generate?.type}
|
isSupportPromptGenerator={!!schema.auto_generate?.type}
|
||||||
titleTooltip={schema.tooltip && renderI18nObject(schema.tooltip)}
|
titleTooltip={schema.tooltip && renderI18nObject(schema.tooltip)}
|
||||||
@ -181,7 +182,18 @@ export const AgentStrategy = memo((props: AgentStrategyProps) => {
|
|||||||
strategy
|
strategy
|
||||||
? <div>
|
? <div>
|
||||||
<Form<CustomField>
|
<Form<CustomField>
|
||||||
formSchemas={formSchema}
|
formSchemas={[...formSchema, {
|
||||||
|
name: 'max_iteration',
|
||||||
|
type: toType('number'),
|
||||||
|
required: true,
|
||||||
|
label: {
|
||||||
|
en_US: 'Max Iteration',
|
||||||
|
zh_Hans: '最大迭代次数',
|
||||||
|
pt_BR: 'Max Iteration',
|
||||||
|
},
|
||||||
|
show_on: [],
|
||||||
|
variable: 'max-ite',
|
||||||
|
}]}
|
||||||
value={formValue}
|
value={formValue}
|
||||||
onChange={onFormValueChange}
|
onChange={onFormValueChange}
|
||||||
validating={false}
|
validating={false}
|
||||||
|
@ -68,7 +68,7 @@ type Props = {
|
|||||||
onEditionTypeChange?: (editionType: EditionType) => void
|
onEditionTypeChange?: (editionType: EditionType) => void
|
||||||
varList?: Variable[]
|
varList?: Variable[]
|
||||||
handleAddVariable?: (payload: any) => void
|
handleAddVariable?: (payload: any) => void
|
||||||
containerClassName?: string
|
containerBackgroundClassName?: string
|
||||||
gradientBorder?: boolean
|
gradientBorder?: boolean
|
||||||
titleTooltip?: ReactNode
|
titleTooltip?: ReactNode
|
||||||
inputClassName?: string
|
inputClassName?: string
|
||||||
@ -103,7 +103,7 @@ const Editor: FC<Props> = ({
|
|||||||
handleAddVariable,
|
handleAddVariable,
|
||||||
onGenerated,
|
onGenerated,
|
||||||
modelConfig,
|
modelConfig,
|
||||||
containerClassName,
|
containerBackgroundClassName: containerClassName,
|
||||||
gradientBorder = true,
|
gradientBorder = true,
|
||||||
titleTooltip,
|
titleTooltip,
|
||||||
inputClassName,
|
inputClassName,
|
||||||
|
@ -61,7 +61,7 @@ export const SwitchPluginVersion: FC<SwitchPluginVersionProps> = (props) => {
|
|||||||
}
|
}
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
return <Tooltip popupContent={!isShow && !isShowUpdateModal && tooltip} triggerMethod='hover'>
|
return <Tooltip popupContent={!isShow && !isShowUpdateModal && tooltip} triggerMethod='hover'>
|
||||||
<div className={cn('w-fit flex items-center justify-center', className)}>
|
<div className={cn('w-fit flex items-center justify-center', className)} onClick={e => e.stopPropagation()}>
|
||||||
{isShowUpdateModal && pluginDetail && <PluginMutationModel
|
{isShowUpdateModal && pluginDetail && <PluginMutationModel
|
||||||
onCancel={hideUpdateModal}
|
onCancel={hideUpdateModal}
|
||||||
plugin={pluginManifestToCardPluginProps({
|
plugin={pluginManifestToCardPluginProps({
|
||||||
|
@ -807,10 +807,17 @@ export const getNodeUsedVars = (node: Node): ValueSelector[] => {
|
|||||||
|
|
||||||
case BlockEnum.Agent: {
|
case BlockEnum.Agent: {
|
||||||
const payload = data as AgentNodeType
|
const payload = data as AgentNodeType
|
||||||
const params = payload.agent_parameters || {}
|
const valueSelectors: ValueSelector[] = []
|
||||||
const mixVars = matchNotSystemVars(Object.keys(params)?.filter(key => params[key].type === ToolVarType.mixed).map(key => params[key].value) as string[])
|
if (!payload.agent_parameters)
|
||||||
const vars = Object.keys(params).filter(key => params[key].type === ToolVarType.variable).map(key => params[key].value as string) || []
|
break
|
||||||
res = [...(mixVars as ValueSelector[]), ...(vars as any)]
|
|
||||||
|
Object.keys(payload.agent_parameters || {}).forEach((key) => {
|
||||||
|
const { value } = payload.agent_parameters![key]
|
||||||
|
if (typeof value === 'string')
|
||||||
|
valueSelectors.push(...matchNotSystemVars([value]))
|
||||||
|
})
|
||||||
|
res = valueSelectors
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res || []
|
return res || []
|
||||||
|
@ -14,6 +14,7 @@ import ResultPanel from '@/app/components/workflow/run/result-panel'
|
|||||||
import formatTracing from '@/app/components/workflow/run/utils/format-log'
|
import formatTracing from '@/app/components/workflow/run/utils/format-log'
|
||||||
import { useLogs } from '@/app/components/workflow/run/hooks'
|
import { useLogs } from '@/app/components/workflow/run/hooks'
|
||||||
import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form'
|
import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form'
|
||||||
|
import { toType } from '@/app/components/tools/utils/to-form-schema'
|
||||||
|
|
||||||
const i18nPrefix = 'workflow.nodes.agent'
|
const i18nPrefix = 'workflow.nodes.agent'
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ export function strategyParamToCredientialForm(param: StrategyParamItem): Creden
|
|||||||
...param as any,
|
...param as any,
|
||||||
variable: param.name,
|
variable: param.name,
|
||||||
show_on: [],
|
show_on: [],
|
||||||
|
type: toType(param.type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user