diff --git a/web/app/components/header/account-setting/model-provider-page/declarations.ts b/web/app/components/header/account-setting/model-provider-page/declarations.ts index 8f0adb1259..4500ebc1f7 100644 --- a/web/app/components/header/account-setting/model-provider-page/declarations.ts +++ b/web/app/components/header/account-setting/model-provider-page/declarations.ts @@ -17,6 +17,7 @@ export enum FormTypeEnum { file = 'file', modelSelector = 'model-selector', toolSelector = 'tool-selector', + multiToolSelector = 'array[tools]', appSelector = 'app-selector', } diff --git a/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx b/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx index b7a9a69870..b357c2cb49 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx @@ -19,6 +19,7 @@ import Tooltip from '@/app/components/base/tooltip' import Radio from '@/app/components/base/radio' import ModelParameterModal from '@/app/components/plugins/plugin-detail-panel/model-selector' import ToolSelector from '@/app/components/plugins/plugin-detail-panel/tool-selector' +import MultipleToolSelector from '@/app/components/plugins/plugin-detail-panel/multiple-tool-selector' import AppSelector from '@/app/components/plugins/plugin-detail-panel/app-selector' import RadioE from '@/app/components/base/radio/ui' @@ -328,7 +329,35 @@ function Form< scope={scope} disabled={readonly} value={value[variable]} - onSelect={item => handleFormChange(variable, item as any)} /> + onSelect={item => handleFormChange(variable, item as any)} + onDelete={() => handleFormChange(variable, null as any)} + /> + {fieldMoreInfo?.(formSchema)} + {validating && changeKey === variable && } + + ) + } + + if (formSchema.type === FormTypeEnum.multiToolSelector) { + const { + variable, + label, + tooltip, + required, + scope, + } = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput) + + return ( +
+ handleFormChange(variable, item as any)} + /> {fieldMoreInfo?.(formSchema)} {validating && changeKey === variable && }
diff --git a/web/app/components/plugins/plugin-detail-panel/index.tsx b/web/app/components/plugins/plugin-detail-panel/index.tsx index d14c0d96be..150158e42c 100644 --- a/web/app/components/plugins/plugin-detail-panel/index.tsx +++ b/web/app/components/plugins/plugin-detail-panel/index.tsx @@ -7,7 +7,6 @@ import ActionList from './action-list' import ModelList from './model-list' import AgentStrategyList from './agent-strategy-list' import Drawer from '@/app/components/base/drawer' -import ToolSelector from '@/app/components/plugins/plugin-detail-panel/tool-selector' import type { PluginDetail } from '@/app/components/plugins/types' import cn from '@/utils/classnames' @@ -33,9 +32,6 @@ const PluginDetailPanel: FC = ({ console.log('tool change', val) setValue(val) } - const testDelete = () => { - setValue(undefined) - } if (!detail) return null @@ -62,15 +58,13 @@ const PluginDetailPanel: FC = ({ {!!detail.declaration.agent_strategy && } {!!detail.declaration.endpoint && } {!!detail.declaration.model && } - {false && ( -
- testChange(item)} - onDelete={testDelete} - /> -
- )} + {/*
+ +
*/} )} diff --git a/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx b/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx index bbf5a8a1ef..47c6833369 100644 --- a/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx +++ b/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx @@ -1,12 +1,91 @@ import React from 'react' +import { useTranslation } from 'react-i18next' +import { + RiAddLine, + RiArrowDropDownLine, + RiQuestionLine, +} from '@remixicon/react' +import type { ToolValue } from '@/app/components/plugins/plugin-detail-panel/tool-selector' +import ActionButton from '@/app/components/base/action-button' +import Tooltip from '@/app/components/base/tooltip' +import Divider from '@/app/components/base/divider' +import cn from '@/utils/classnames' type Props = { - value: any[] + disabled?: boolean + value: ToolValue[] + label: string + required?: boolean + tooltip?: any + supportCollapse?: boolean + onChange: (value: ToolValue[]) => void + scope?: string } -const MultipleToolSelector = ({ value }: Props) => { +const MultipleToolSelector = ({ + value, + label, + required, + tooltip, + supportCollapse, +}: Props) => { + const { t } = useTranslation() + const [collapse, setCollapse] = React.useState(false) + + const handleCollapse = () => { + if (supportCollapse) + setCollapse(!collapse) + } + return ( -
+ <> +
+
+
{label}
+ {required &&
*
} + {tooltip && ( + +
+
+ )} + {supportCollapse && ( +
+ +
+ )} +
+ {value.length > 0 && ( + <> +
+ {`${value.length}/${value.length}`} + {t('appDebug.agent.tools.enabled')} +
+ + + )} + {}}> + + +
+ {!collapse && ( + <> + {value.length === 0 && ( +
{t('plugin.detailPanel.toolSelector.empty')}
+ )} + + )} + ) } diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/index.tsx b/web/app/components/plugins/plugin-detail-panel/tool-selector/index.tsx index 3e7993f761..7bf6165971 100644 --- a/web/app/components/plugins/plugin-detail-panel/tool-selector/index.tsx +++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/index.tsx @@ -40,13 +40,16 @@ import type { } from '@floating-ui/react' import cn from '@/utils/classnames' +export type ToolValue = { + provider_name: string + tool_name: string + parameters?: Record + enabled?: boolean + extra?: Record +} + type Props = { - value?: { - provider_name: string - tool_name: string - parameters?: Record - extra?: Record - } + value?: ToolValue disabled?: boolean placement?: Placement offset?: OffsetOptions diff --git a/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx b/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx index 3f0b05b8e6..c156aac671 100644 --- a/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx +++ b/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx @@ -10,6 +10,7 @@ import { Agent } from '@/app/components/base/icons/src/vender/workflow' import { InputNumber } from '@/app/components/base/input-number' import Slider from '@/app/components/base/slider' import ToolSelector from '@/app/components/plugins/plugin-detail-panel/tool-selector' +import MultipleToolSelector from '@/app/components/plugins/plugin-detail-panel/multiple-tool-selector' import Field from './field' import type { ComponentProps } from 'react' import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks' @@ -160,18 +161,31 @@ export const AgentStrategy = (props: AgentStrategyProps) => { props.onChange({ ...props.value, [schema.variable]: value }) } return ( - + onChange(item)} + onDelete={() => onChange(null)} /> ) } case 'array[tools]': { - return - multiple tool selector TODO - + const value = props.value[schema.variable] + const onChange = (value: any) => { + props.onChange({ ...props.value, [schema.variable]: value }) + } + return ( + + ) } } } diff --git a/web/i18n/en-US/plugin.ts b/web/i18n/en-US/plugin.ts index 38ec6d9be7..a706f8f042 100644 --- a/web/i18n/en-US/plugin.ts +++ b/web/i18n/en-US/plugin.ts @@ -73,6 +73,7 @@ const translation = { placeholder: 'Select a tool...', auth: 'AUTHORIZATION', settings: 'TOOL SETTINGS', + empty: 'Click the \'+\' button to add tools. You can add multiple tools.', }, configureApp: 'Configure App', configureModel: 'Configure model', diff --git a/web/i18n/zh-Hans/plugin.ts b/web/i18n/zh-Hans/plugin.ts index 8185f37b40..4b7c764d9f 100644 --- a/web/i18n/zh-Hans/plugin.ts +++ b/web/i18n/zh-Hans/plugin.ts @@ -73,6 +73,7 @@ const translation = { placeholder: '选择工具', auth: '授权', settings: '工具设置', + empty: '点击 "+" 按钮添加工具。您可以添加多个工具。', }, configureApp: '应用设置', configureModel: '模型设置',