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:
zxhlyh
2024-05-27 21:57:08 +08:00
committed by GitHub
parent 444fdb79dc
commit 45deaee762
210 changed files with 9951 additions and 2223 deletions

View File

@@ -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>

View File

@@ -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)

View File

@@ -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 && (

View File

@@ -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}
/>
)

View File

@@ -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>

View File

@@ -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',
}
}
}),
}))