multiple tool selector
This commit is contained in:
parent
a863e9f674
commit
3c85363392
@ -7,6 +7,7 @@ import ActionList from './action-list'
|
||||
import ModelList from './model-list'
|
||||
import AgentStrategyList from './agent-strategy-list'
|
||||
import Drawer from '@/app/components/base/drawer'
|
||||
import MultipleToolSelector from '@/app/components/plugins/plugin-detail-panel/multiple-tool-selector'
|
||||
import type { PluginDetail } from '@/app/components/plugins/types'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
@ -58,13 +59,15 @@ const PluginDetailPanel: FC<Props> = ({
|
||||
{!!detail.declaration.agent_strategy && <AgentStrategyList detail={detail} />}
|
||||
{!!detail.declaration.endpoint && <EndpointList detail={detail} />}
|
||||
{!!detail.declaration.model && <ModelList detail={detail} />}
|
||||
{/* <div className='px-4 py-2'>
|
||||
<MultipleToolSelector
|
||||
value={value || []}
|
||||
label='TOOLS'
|
||||
onChange={testChange}
|
||||
/>
|
||||
</div> */}
|
||||
{false && (
|
||||
<div className='px-4 py-2'>
|
||||
<MultipleToolSelector
|
||||
value={value || []}
|
||||
label='TOOLS'
|
||||
onChange={testChange}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
@ -5,10 +5,11 @@ import {
|
||||
RiArrowDropDownLine,
|
||||
RiQuestionLine,
|
||||
} from '@remixicon/react'
|
||||
import type { ToolValue } from '@/app/components/plugins/plugin-detail-panel/tool-selector'
|
||||
import ToolSelector 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 type { ToolValue } from '@/app/components/plugins/plugin-detail-panel/tool-selector'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type Props = {
|
||||
@ -18,25 +19,57 @@ type Props = {
|
||||
required?: boolean
|
||||
tooltip?: any
|
||||
supportCollapse?: boolean
|
||||
onChange: (value: ToolValue[]) => void
|
||||
scope?: string
|
||||
onChange: (value: ToolValue[]) => void
|
||||
}
|
||||
|
||||
const MultipleToolSelector = ({
|
||||
disabled,
|
||||
value,
|
||||
label,
|
||||
required,
|
||||
tooltip,
|
||||
supportCollapse,
|
||||
scope,
|
||||
onChange,
|
||||
}: Props) => {
|
||||
const { t } = useTranslation()
|
||||
// collapse control
|
||||
const [collapse, setCollapse] = React.useState(false)
|
||||
|
||||
const handleCollapse = () => {
|
||||
if (supportCollapse)
|
||||
setCollapse(!collapse)
|
||||
}
|
||||
|
||||
// add tool
|
||||
const [open, setOpen] = React.useState(false)
|
||||
const handleAdd = (val: ToolValue) => {
|
||||
const newValue = [...value, val]
|
||||
// deduplication
|
||||
const deduplication = newValue.reduce((acc, cur) => {
|
||||
if (!acc.find(item => item.provider_name === cur.provider_name && item.tool_name === cur.tool_name))
|
||||
acc.push(cur)
|
||||
return acc
|
||||
}, [] as ToolValue[])
|
||||
// update value
|
||||
onChange(deduplication)
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
// delete tool
|
||||
const handleDelete = (index: number) => {
|
||||
const newValue = [...value]
|
||||
newValue.splice(index, 1)
|
||||
onChange(newValue)
|
||||
}
|
||||
|
||||
// configure tool
|
||||
const handleConfigure = (val: ToolValue, index: number) => {
|
||||
const newValue = [...value]
|
||||
newValue[index] = val
|
||||
onChange(newValue)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='flex items-center mb-1'>
|
||||
@ -74,15 +107,38 @@ const MultipleToolSelector = ({
|
||||
<Divider type='vertical' className='ml-3 mr-1 h-3' />
|
||||
</>
|
||||
)}
|
||||
<ActionButton className='mx-1' onClick={() => {}}>
|
||||
<RiAddLine className='w-4 h-4' />
|
||||
</ActionButton>
|
||||
{!disabled && (
|
||||
<ActionButton className='mx-1' onClick={() => setOpen(!open)}>
|
||||
<RiAddLine className='w-4 h-4' />
|
||||
</ActionButton>
|
||||
)}
|
||||
</div>
|
||||
{!collapse && (
|
||||
<>
|
||||
<ToolSelector
|
||||
scope={scope}
|
||||
value={undefined}
|
||||
onSelect={handleAdd}
|
||||
controlledState={open}
|
||||
onControlledStateChange={setOpen}
|
||||
trigger={
|
||||
<div className=''></div>
|
||||
}
|
||||
/>
|
||||
{value.length === 0 && (
|
||||
<div className='p-3 flex justify-center rounded-[10px] bg-background-section text-text-tertiary system-xs-regular'>{t('plugin.detailPanel.toolSelector.empty')}</div>
|
||||
)}
|
||||
{value.length > 0 && value.map((item, index) => (
|
||||
<div className='mb-1' key={index}>
|
||||
<ToolSelector
|
||||
scope={scope}
|
||||
value={item}
|
||||
onSelect={item => handleConfigure(item, index)}
|
||||
onDelete={() => handleDelete(index)}
|
||||
supportEnableSwitch
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
|
@ -49,10 +49,11 @@ export type ToolValue = {
|
||||
}
|
||||
|
||||
type Props = {
|
||||
value?: ToolValue
|
||||
disabled?: boolean
|
||||
placement?: Placement
|
||||
offset?: OffsetOptions
|
||||
scope?: string
|
||||
value?: ToolValue
|
||||
onSelect: (tool: {
|
||||
provider_name: string
|
||||
tool_name: string
|
||||
@ -60,8 +61,11 @@ type Props = {
|
||||
extra?: Record<string, any>
|
||||
}) => void
|
||||
onDelete?: () => void
|
||||
supportEnableSwitch?: boolean
|
||||
supportAddCustomTool?: boolean
|
||||
scope?: string
|
||||
trigger?: React.ReactNode
|
||||
controlledState?: boolean
|
||||
onControlledStateChange?: (state: boolean) => void
|
||||
}
|
||||
const ToolSelector: FC<Props> = ({
|
||||
value,
|
||||
@ -71,6 +75,10 @@ const ToolSelector: FC<Props> = ({
|
||||
onSelect,
|
||||
onDelete,
|
||||
scope,
|
||||
supportEnableSwitch,
|
||||
trigger,
|
||||
controlledState,
|
||||
onControlledStateChange,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const [isShow, onShowChange] = useState(false)
|
||||
@ -98,14 +106,13 @@ const ToolSelector: FC<Props> = ({
|
||||
provider_name: tool.provider_id,
|
||||
tool_name: tool.tool_name,
|
||||
parameters: paramValues,
|
||||
enabled: tool.is_team_authorization,
|
||||
extra: {
|
||||
description: '',
|
||||
},
|
||||
}
|
||||
onSelect(toolValue)
|
||||
setIsShowChooseTool(false)
|
||||
// if (tool.provider_type === CollectionType.builtIn && tool.is_team_authorization)
|
||||
// onShowChange(false)
|
||||
}
|
||||
|
||||
const handleDescriptionChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
@ -133,6 +140,13 @@ const ToolSelector: FC<Props> = ({
|
||||
onSelect(toolValue as any)
|
||||
}
|
||||
|
||||
const handleEnabledChange = (state: boolean) => {
|
||||
onSelect({
|
||||
...value,
|
||||
enabled: state,
|
||||
} as any)
|
||||
}
|
||||
|
||||
// authorization
|
||||
const { isCurrentWorkspaceManager } = useAppContext()
|
||||
const [isShowSettingAuth, setShowSettingAuth] = useState(false)
|
||||
@ -155,14 +169,15 @@ const ToolSelector: FC<Props> = ({
|
||||
<PortalToFollowElem
|
||||
placement={placement}
|
||||
offset={offset}
|
||||
open={isShow}
|
||||
onOpenChange={onShowChange}
|
||||
open={trigger ? controlledState : isShow}
|
||||
onOpenChange={trigger ? onControlledStateChange : onShowChange}
|
||||
>
|
||||
<PortalToFollowElemTrigger
|
||||
className='w-full'
|
||||
onClick={handleTriggerClick}
|
||||
>
|
||||
{!value?.provider_name && (
|
||||
{trigger}
|
||||
{!trigger && !value?.provider_name && (
|
||||
<ToolTrigger
|
||||
isConfigure
|
||||
open={isShow}
|
||||
@ -170,16 +185,20 @@ const ToolSelector: FC<Props> = ({
|
||||
provider={currentProvider}
|
||||
/>
|
||||
)}
|
||||
{value?.provider_name && (
|
||||
{!trigger && value?.provider_name && (
|
||||
<ToolItem
|
||||
open={isShow}
|
||||
icon={currentProvider?.icon}
|
||||
providerName={value.provider_name}
|
||||
toolName={value.tool_name}
|
||||
showSwitch={supportEnableSwitch}
|
||||
switchValue={value.enabled}
|
||||
onSwitchChange={handleEnabledChange}
|
||||
onDelete={onDelete}
|
||||
noAuth={currentProvider && !currentProvider.is_team_authorization}
|
||||
onAuth={() => setShowSettingAuth(true)}
|
||||
// uninstalled
|
||||
// uninstalled TODO
|
||||
// isError TODO
|
||||
errorTip={<div className='space-y-1 text-xs'>
|
||||
<h3 className='text-text-primary font-semibold'>{t('workflow.nodes.agent.pluginNotInstalled')}</h3>
|
||||
<p className='text-text-secondary tracking-tight'>{t('workflow.nodes.agent.pluginNotInstalledDesc')}</p>
|
||||
|
@ -77,7 +77,10 @@ const ToolItem = ({
|
||||
)}
|
||||
<div
|
||||
className='p-1 rounded-md text-text-tertiary cursor-pointer hover:text-text-destructive'
|
||||
onClick={onDelete}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onDelete?.()
|
||||
}}
|
||||
onMouseOver={() => setIsDeleting(true)}
|
||||
onMouseLeave={() => setIsDeleting(false)}
|
||||
>
|
||||
@ -85,11 +88,13 @@ const ToolItem = ({
|
||||
</div>
|
||||
</div>
|
||||
{!isError && !uninstalled && !noAuth && showSwitch && (
|
||||
<Switch
|
||||
className='mr-1'
|
||||
size='md'
|
||||
defaultValue={switchValue}
|
||||
onChange={onSwitchChange} />
|
||||
<div className='mr-1' onClick={e => e.stopPropagation()}>
|
||||
<Switch
|
||||
size='md'
|
||||
defaultValue={switchValue}
|
||||
onChange={onSwitchChange}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{!isError && !uninstalled && noAuth && (
|
||||
<Button variant='secondary' size='small' onClick={onAuth}>
|
||||
|
Loading…
Reference in New Issue
Block a user