feat: workflow new nodes (#4683)
Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: Patryk Garstecki <patryk20120@yahoo.pl> Co-authored-by: Sebastian.W <thiner@gmail.com> Co-authored-by: 呆萌闷油瓶 <253605712@qq.com> Co-authored-by: takatost <takatost@users.noreply.github.com> Co-authored-by: rechardwang <wh_goodjob@163.com> Co-authored-by: Nite Knite <nkCoding@gmail.com> Co-authored-by: Chenhe Gu <guchenhe@gmail.com> Co-authored-by: Joshua <138381132+joshua20231026@users.noreply.github.com> Co-authored-by: Weaxs <459312872@qq.com> Co-authored-by: Ikko Eltociear Ashimine <eltociear@gmail.com> Co-authored-by: leejoo0 <81673835+leejoo0@users.noreply.github.com> Co-authored-by: JzoNg <jzongcode@gmail.com> Co-authored-by: sino <sino2322@gmail.com> Co-authored-by: Vikey Chen <vikeytk@gmail.com> Co-authored-by: wanghl <Wang-HL@users.noreply.github.com> Co-authored-by: Haolin Wang-汪皓临 <haolin.wang@atlaslovestravel.com> Co-authored-by: Zixuan Cheng <61724187+Theysua@users.noreply.github.com> Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> Co-authored-by: Bowen Liang <bowenliang@apache.org> Co-authored-by: Bowen Liang <liangbowen@gf.com.cn> Co-authored-by: fanghongtai <42790567+fanghongtai@users.noreply.github.com> Co-authored-by: wxfanghongtai <wxfanghongtai@gf.com.cn> Co-authored-by: Matri <qjp@bithuman.io> Co-authored-by: Benjamin <benjaminx@gmail.com>
This commit is contained in:
@@ -23,6 +23,8 @@ import { PlayCircle } from '@/app/components/base/icons/src/vender/line/mediaAnd
|
||||
import { CodeBrowser } from '@/app/components/base/icons/src/vender/line/development'
|
||||
import { LeftIndent02 } from '@/app/components/base/icons/src/vender/line/editor'
|
||||
import { FileText } from '@/app/components/base/icons/src/vender/line/files'
|
||||
import WorkflowToolConfigureButton from '@/app/components/tools/workflow-tool/configure-button'
|
||||
import type { InputVar } from '@/app/components/workflow/types'
|
||||
|
||||
export type AppPublisherProps = {
|
||||
disabled?: boolean
|
||||
@@ -37,6 +39,9 @@ export type AppPublisherProps = {
|
||||
onRestore?: () => Promise<any> | any
|
||||
onToggle?: (state: boolean) => void
|
||||
crossAxisOffset?: number
|
||||
toolPublished?: boolean
|
||||
inputs?: InputVar[]
|
||||
onRefreshData?: () => void
|
||||
}
|
||||
|
||||
const AppPublisher = ({
|
||||
@@ -50,6 +55,9 @@ const AppPublisher = ({
|
||||
onRestore,
|
||||
onToggle,
|
||||
crossAxisOffset = 0,
|
||||
toolPublished,
|
||||
inputs,
|
||||
onRefreshData,
|
||||
}: AppPublisherProps) => {
|
||||
const { t } = useTranslation()
|
||||
const [published, setPublished] = useState(false)
|
||||
@@ -122,7 +130,7 @@ const AppPublisher = ({
|
||||
</Button>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className='z-[11]'>
|
||||
<div className='w-[320px] bg-white rounded-2xl border-[0.5px] border-gray-200 shadow-xl'>
|
||||
<div className='w-[336px] bg-white rounded-2xl border-[0.5px] border-gray-200 shadow-xl'>
|
||||
<div className='p-4 pt-3'>
|
||||
<div className='flex items-center h-6 text-xs font-medium text-gray-500 uppercase'>
|
||||
{publishedAt ? t('workflow.common.latestPublished') : t('workflow.common.currentDraftUnpublished')}
|
||||
@@ -202,6 +210,23 @@ const AppPublisher = ({
|
||||
</SuggestedAction>
|
||||
)}
|
||||
<SuggestedAction disabled={!publishedAt} link='./develop' icon={<FileText className='w-4 h-4' />}>{t('workflow.common.accessAPIReference')}</SuggestedAction>
|
||||
{appDetail?.mode === 'workflow' && (
|
||||
<WorkflowToolConfigureButton
|
||||
disabled={!publishedAt}
|
||||
published={!!toolPublished}
|
||||
detailNeedUpdate={!!toolPublished && published}
|
||||
workflowAppId={appDetail?.id}
|
||||
icon={{
|
||||
content: appDetail?.icon,
|
||||
background: appDetail?.icon_background,
|
||||
}}
|
||||
name={appDetail?.name}
|
||||
description={appDetail?.description}
|
||||
inputs={inputs}
|
||||
handlePublish={handlePublish}
|
||||
onRefreshData={onRefreshData}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</PortalToFollowElemContent>
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import produce from 'immer'
|
||||
import Tools from '@/app/components/tools'
|
||||
import { LOC } from '@/app/components/tools/types'
|
||||
import Drawer from '@/app/components/base/drawer-plus'
|
||||
import ConfigContext from '@/context/debug-configuration'
|
||||
import type { ModelConfig } from '@/models/debug'
|
||||
import I18n from '@/context/i18n'
|
||||
|
||||
type Props = {
|
||||
show: boolean
|
||||
onHide: () => void
|
||||
selectedProviderId?: string
|
||||
}
|
||||
|
||||
const ChooseTool: FC<Props> = ({
|
||||
show,
|
||||
onHide,
|
||||
selectedProviderId,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { locale } = useContext(I18n)
|
||||
const {
|
||||
modelConfig,
|
||||
setModelConfig,
|
||||
} = useContext(ConfigContext)
|
||||
if (!show)
|
||||
return null
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
isShow
|
||||
onHide={onHide}
|
||||
title={t('tools.addTool') as string}
|
||||
panelClassName='mt-2 !w-[760px]'
|
||||
maxWidthClassName='!max-w-[760px]'
|
||||
height='calc(100vh - 16px)'
|
||||
contentClassName='!bg-gray-100'
|
||||
headerClassName='!border-b-black/5'
|
||||
body={
|
||||
<Tools
|
||||
loc={LOC.app}
|
||||
selectedProviderId={selectedProviderId}
|
||||
onAddTool={(collection, tool) => {
|
||||
const parameters: Record<string, string> = {}
|
||||
if (tool.parameters) {
|
||||
tool.parameters.forEach((item) => {
|
||||
parameters[item.name] = ''
|
||||
})
|
||||
}
|
||||
|
||||
const nexModelConfig = produce(modelConfig, (draft: ModelConfig) => {
|
||||
draft.agentConfig.tools.push({
|
||||
provider_id: collection.id || collection.name,
|
||||
provider_type: collection.type,
|
||||
provider_name: collection.name,
|
||||
tool_name: tool.name,
|
||||
tool_label: tool.label[locale] || tool.label[locale.replaceAll('-', '_')],
|
||||
tool_parameters: parameters,
|
||||
enabled: true,
|
||||
})
|
||||
})
|
||||
setModelConfig(nexModelConfig)
|
||||
}}
|
||||
addedTools={(modelConfig?.agentConfig?.tools as any) || []}
|
||||
/>
|
||||
}
|
||||
isShowMask={true}
|
||||
clickOutsideNotOpen={false}
|
||||
/>
|
||||
)
|
||||
}
|
||||
export default React.memo(ChooseTool)
|
||||
@@ -6,7 +6,6 @@ import cn from 'classnames'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import produce from 'immer'
|
||||
import { useFormattingChangedDispatcher } from '../../../debug/hooks'
|
||||
import ChooseTool from './choose-tool'
|
||||
import SettingBuiltInTool from './setting-built-in-tool'
|
||||
import Panel from '@/app/components/app/configuration/base/feature-panel'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
@@ -22,6 +21,7 @@ import { MAX_TOOLS_NUM } from '@/config'
|
||||
import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
|
||||
import TooltipPlus from '@/app/components/base/tooltip-plus'
|
||||
import { DefaultToolIcon } from '@/app/components/base/icons/src/public/other'
|
||||
import AddToolModal from '@/app/components/tools/add-tool-modal'
|
||||
|
||||
type AgentToolWithMoreInfo = AgentTool & { icon: any; collection?: Collection } | null
|
||||
const AgentTools: FC = () => {
|
||||
@@ -31,7 +31,6 @@ const AgentTools: FC = () => {
|
||||
const formattingChangedDispatcher = useFormattingChangedDispatcher()
|
||||
|
||||
const [currentTool, setCurrentTool] = useState<AgentToolWithMoreInfo>(null)
|
||||
const [selectedProviderId, setSelectedProviderId] = useState<string | undefined>(undefined)
|
||||
const [isShowSettingTool, setIsShowSettingTool] = useState(false)
|
||||
const tools = (modelConfig?.agentConfig?.tools as AgentTool[] || []).map((item) => {
|
||||
const collection = collectionList.find(collection => collection.id === item.provider_id && collection.type === item.provider_type)
|
||||
@@ -78,10 +77,7 @@ const AgentTools: FC = () => {
|
||||
{tools.length < MAX_TOOLS_NUM && (
|
||||
<>
|
||||
<div className='ml-3 mr-1 h-3.5 w-px bg-gray-200'></div>
|
||||
<OperationBtn type="add" onClick={() => {
|
||||
setSelectedProviderId(undefined)
|
||||
setIsShowChooseTool(true)
|
||||
}} />
|
||||
<OperationBtn type="add" onClick={() => setIsShowChooseTool(true)} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
@@ -116,10 +112,14 @@ const AgentTools: FC = () => {
|
||||
/>
|
||||
))}
|
||||
<div
|
||||
title={item.tool_name}
|
||||
className={cn((item.isDeleted || item.notAuthor) ? 'line-through opacity-50' : '', 'grow w-0 ml-2 leading-[18px] text-[13px] font-medium text-gray-800 truncate')}
|
||||
>
|
||||
{item.tool_label || item.tool_name}
|
||||
<span className='text-gray-800 pr-2'>{item.provider_type === CollectionType.builtIn ? item.provider_name : item.tool_label}</span>
|
||||
<TooltipPlus
|
||||
popupContent={t('tools.toolNameUsageTip')}
|
||||
>
|
||||
<span className='text-gray-500'>{item.tool_name}</span>
|
||||
</TooltipPlus>
|
||||
</div>
|
||||
</div>
|
||||
<div className='shrink-0 ml-1 flex items-center'>
|
||||
@@ -130,10 +130,8 @@ const AgentTools: FC = () => {
|
||||
popupContent={t(`tools.${item.isDeleted ? 'toolRemoved' : 'notAuthorized'}`)}
|
||||
>
|
||||
<div className='mr-1 p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => {
|
||||
if (item.notAuthor) {
|
||||
setSelectedProviderId(item.provider_id)
|
||||
if (item.notAuthor)
|
||||
setIsShowChooseTool(true)
|
||||
}
|
||||
}}>
|
||||
<AlertTriangle className='w-4 h-4 text-[#F79009]' />
|
||||
</div>
|
||||
@@ -153,7 +151,6 @@ const AgentTools: FC = () => {
|
||||
)
|
||||
: (
|
||||
<div className='hidden group-hover:flex items-center'>
|
||||
{/* {item.provider_type === CollectionType.builtIn && ( */}
|
||||
<TooltipPlus
|
||||
popupContent={t('tools.setBuiltInTools.infoAndSetting')}
|
||||
>
|
||||
@@ -164,7 +161,6 @@ const AgentTools: FC = () => {
|
||||
<InfoCircle className='w-4 h-4 text-gray-500' />
|
||||
</div>
|
||||
</TooltipPlus>
|
||||
{/* )} */}
|
||||
|
||||
<div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => {
|
||||
const newModelConfig = produce(modelConfig, (draft) => {
|
||||
@@ -197,11 +193,7 @@ const AgentTools: FC = () => {
|
||||
</div >
|
||||
</Panel >
|
||||
{isShowChooseTool && (
|
||||
<ChooseTool
|
||||
show
|
||||
onHide={() => setIsShowChooseTool(false)}
|
||||
selectedProviderId={selectedProviderId}
|
||||
/>
|
||||
<AddToolModal onHide={() => setIsShowChooseTool(false)} />
|
||||
)}
|
||||
{
|
||||
isShowSettingTool && (
|
||||
|
||||
@@ -8,7 +8,8 @@ import Drawer from '@/app/components/base/drawer-plus'
|
||||
import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form'
|
||||
import { addDefaultValue, toolParametersToFormSchemas } from '@/app/components/tools/utils/to-form-schema'
|
||||
import type { Collection, Tool } from '@/app/components/tools/types'
|
||||
import { fetchBuiltInToolList, fetchCustomToolList, fetchModelToolList } from '@/service/tools'
|
||||
import { CollectionType } from '@/app/components/tools/types'
|
||||
import { fetchBuiltInToolList, fetchCustomToolList, fetchModelToolList, fetchWorkflowToolList } from '@/service/tools'
|
||||
import I18n from '@/context/i18n'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
@@ -64,6 +65,8 @@ const SettingBuiltInTool: FC<Props> = ({
|
||||
resolve(await fetchModelToolList(collection.name))
|
||||
else if (isBuiltIn)
|
||||
resolve(await fetchBuiltInToolList(collection.name))
|
||||
else if (collection.type === CollectionType.workflow)
|
||||
resolve(await fetchWorkflowToolList(collection.id))
|
||||
else
|
||||
resolve(await fetchCustomToolList(collection.name))
|
||||
}())
|
||||
@@ -78,7 +81,7 @@ const SettingBuiltInTool: FC<Props> = ({
|
||||
catch (e) { }
|
||||
setIsLoading(false)
|
||||
})()
|
||||
}, [collection?.name])
|
||||
}, [collection?.name, collection?.id, collection?.type])
|
||||
|
||||
useEffect(() => {
|
||||
setCurrType((!readonly && hasSetting) ? 'setting' : 'info')
|
||||
@@ -150,7 +153,7 @@ const SettingBuiltInTool: FC<Props> = ({
|
||||
onHide={onHide}
|
||||
title={(
|
||||
<div className='flex'>
|
||||
{collection.icon === 'string'
|
||||
{typeof collection.icon === 'string'
|
||||
? (
|
||||
<div
|
||||
className='w-6 h-6 bg-cover bg-center rounded-md'
|
||||
@@ -189,8 +192,8 @@ const SettingBuiltInTool: FC<Props> = ({
|
||||
</>)}
|
||||
</div>
|
||||
)}
|
||||
panelClassName='mt-[65px] !w-[480px]'
|
||||
maxWidthClassName='!max-w-[480px]'
|
||||
panelClassName='mt-[65px] !w-[405px]'
|
||||
maxWidthClassName='!max-w-[405px]'
|
||||
height='calc(100vh - 65px)'
|
||||
headerClassName='!border-b-black/5'
|
||||
body={
|
||||
@@ -212,7 +215,7 @@ const SettingBuiltInTool: FC<Props> = ({
|
||||
</div>)}
|
||||
</div>
|
||||
}
|
||||
isShowMask={true}
|
||||
isShowMask={false}
|
||||
clickOutsideNotOpen={false}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -164,7 +164,7 @@ function DetailPanel<T extends ChatConversationFullDetailResponse | CompletionCo
|
||||
const { userProfile: { timezone } } = useAppContext()
|
||||
const { formatTime } = useTimestamp()
|
||||
const { onClose, appDetail } = useContext(DrawerContext)
|
||||
const { currentLogItem, setCurrentLogItem, showPromptLogModal, setShowPromptLogModal, showAgentLogModal, setShowAgentLogModal, showMessageLogModal, setShowMessageLogModal } = useAppStore(useShallow(state => ({
|
||||
const { currentLogItem, setCurrentLogItem, showPromptLogModal, setShowPromptLogModal, showAgentLogModal, setShowAgentLogModal, showMessageLogModal, setShowMessageLogModal, currentLogModalActiveTab } = useAppStore(useShallow(state => ({
|
||||
currentLogItem: state.currentLogItem,
|
||||
setCurrentLogItem: state.setCurrentLogItem,
|
||||
showPromptLogModal: state.showPromptLogModal,
|
||||
@@ -173,6 +173,7 @@ function DetailPanel<T extends ChatConversationFullDetailResponse | CompletionCo
|
||||
setShowAgentLogModal: state.setShowAgentLogModal,
|
||||
showMessageLogModal: state.showMessageLogModal,
|
||||
setShowMessageLogModal: state.setShowMessageLogModal,
|
||||
currentLogModalActiveTab: state.currentLogModalActiveTab,
|
||||
})))
|
||||
const { t } = useTranslation()
|
||||
const [items, setItems] = React.useState<IChatItem[]>([])
|
||||
@@ -444,6 +445,7 @@ function DetailPanel<T extends ChatConversationFullDetailResponse | CompletionCo
|
||||
setCurrentLogItem()
|
||||
setShowMessageLogModal(false)
|
||||
}}
|
||||
defaultTab={currentLogModalActiveTab}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,7 @@ type State = {
|
||||
appDetail?: App
|
||||
appSidebarExpand: string
|
||||
currentLogItem?: IChatItem
|
||||
currentLogModalActiveTab: string
|
||||
showPromptLogModal: boolean
|
||||
showAgentLogModal: boolean
|
||||
showMessageLogModal: boolean
|
||||
@@ -15,6 +16,7 @@ type Action = {
|
||||
setAppDetail: (appDetail?: App) => void
|
||||
setAppSiderbarExpand: (state: string) => void
|
||||
setCurrentLogItem: (item?: IChatItem) => void
|
||||
setCurrentLogModalActiveTab: (tab: string) => void
|
||||
setShowPromptLogModal: (showPromptLogModal: boolean) => void
|
||||
setShowAgentLogModal: (showAgentLogModal: boolean) => void
|
||||
setShowMessageLogModal: (showMessageLogModal: boolean) => void
|
||||
@@ -26,11 +28,23 @@ export const useStore = create<State & Action>(set => ({
|
||||
appSidebarExpand: '',
|
||||
setAppSiderbarExpand: appSidebarExpand => set(() => ({ appSidebarExpand })),
|
||||
currentLogItem: undefined,
|
||||
currentLogModalActiveTab: 'DETAIL',
|
||||
setCurrentLogItem: currentLogItem => set(() => ({ currentLogItem })),
|
||||
setCurrentLogModalActiveTab: currentLogModalActiveTab => set(() => ({ currentLogModalActiveTab })),
|
||||
showPromptLogModal: false,
|
||||
setShowPromptLogModal: showPromptLogModal => set(() => ({ showPromptLogModal })),
|
||||
showAgentLogModal: false,
|
||||
setShowAgentLogModal: showAgentLogModal => set(() => ({ showAgentLogModal })),
|
||||
showMessageLogModal: false,
|
||||
setShowMessageLogModal: showMessageLogModal => set(() => ({ showMessageLogModal })),
|
||||
setShowMessageLogModal: showMessageLogModal => set(() => {
|
||||
if (showMessageLogModal) {
|
||||
return { showMessageLogModal }
|
||||
}
|
||||
else {
|
||||
return {
|
||||
showMessageLogModal,
|
||||
currentLogModalActiveTab: 'DETAIL',
|
||||
}
|
||||
}
|
||||
}),
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user