From 4f3872277cec828f219f75252a1764def6d8df6e Mon Sep 17 00:00:00 2001 From: StyleZhang Date: Fri, 22 Mar 2024 13:08:28 +0800 Subject: [PATCH] all tools --- .../workflow/block-selector/tools.tsx | 100 ++++++++++++++ .../workflow/block-selector/tools/index.tsx | 97 ------------- .../workflow/block-selector/tools/item.tsx | 129 ------------------ .../workflow/block-selector/types.ts | 13 -- .../components/workflow/hooks/use-workflow.ts | 61 +++++++-- .../_base/components/next-step/index.tsx | 13 +- .../_base/components/panel-operator/index.tsx | 51 ++----- .../components/workflow/nodes/_base/node.tsx | 14 +- .../components/workflow/nodes/_base/panel.tsx | 11 +- .../workflow/nodes/tool/use-config.ts | 56 ++------ web/app/components/workflow/store.ts | 22 ++- web/app/components/workflow/types.ts | 5 + web/context/i18n.ts | 13 +- web/service/tools.ts | 9 ++ 14 files changed, 217 insertions(+), 377 deletions(-) create mode 100644 web/app/components/workflow/block-selector/tools.tsx delete mode 100644 web/app/components/workflow/block-selector/tools/index.tsx delete mode 100644 web/app/components/workflow/block-selector/tools/item.tsx diff --git a/web/app/components/workflow/block-selector/tools.tsx b/web/app/components/workflow/block-selector/tools.tsx new file mode 100644 index 0000000000..720af28c05 --- /dev/null +++ b/web/app/components/workflow/block-selector/tools.tsx @@ -0,0 +1,100 @@ +import { + memo, + useCallback, + useMemo, +} from 'react' +import { useTranslation } from 'react-i18next' +import BlockIcon from '../block-icon' +import { BlockEnum } from '../types' +import type { ToolWithProvider } from '../types' +import { useStore } from '../store' +import type { ToolDefaultValue } from './types' +import Tooltip from '@/app/components/base/tooltip' +import { useGetLanguage } from '@/context/i18n' + +type ToolsProps = { + isCustom?: boolean + onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void + searchText: string +} +const Blocks = ({ + isCustom, + searchText, + onSelect, +}: ToolsProps) => { + const { t } = useTranslation() + const language = useGetLanguage() + const buildInTools = useStore(s => s.buildInTools) + const customTools = useStore(s => s.customTools) + + const tools = useMemo(() => { + const currentTools = isCustom ? customTools : buildInTools + + return currentTools.filter((toolWithProvider) => { + return toolWithProvider.tools.some((tool) => { + return tool.label[language].toLowerCase().includes(searchText.toLowerCase()) + }) + }) + }, [isCustom, customTools, buildInTools, searchText, language]) + + const renderGroup = useCallback((toolWithProvider: ToolWithProvider) => { + const list = toolWithProvider.tools + + return ( +
+
+ {toolWithProvider.label[language]} +
+ { + list.map(tool => ( + +
onSelect(BlockEnum.Tool, { + provider_id: toolWithProvider.id, + provider_type: toolWithProvider.type, + provider_name: toolWithProvider.name, + tool_name: tool.name, + tool_label: tool.label[language], + title: tool.label[language], + })} + > + +
{tool.label[language]}
+
+
+ )) + } +
+ ) + }, [onSelect, language]) + + return ( +
+ { + !tools.length && ( +
{t('workflow.tabs.noResult')}
+ ) + } + { + !!tools.length && tools.map(renderGroup) + } +
+ ) +} + +export default memo(Blocks) diff --git a/web/app/components/workflow/block-selector/tools/index.tsx b/web/app/components/workflow/block-selector/tools/index.tsx deleted file mode 100644 index 9dc3fcec0d..0000000000 --- a/web/app/components/workflow/block-selector/tools/index.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { - memo, - useCallback, - useMemo, -} from 'react' -import produce from 'immer' -import { useTranslation } from 'react-i18next' -import { useStore } from '../../store' -import type { BlockEnum } from '../../types' -import type { - ToolDefaultValue, - ToolInWorkflow, -} from '../types' -import Item from './item' - -type ToolsProps = { - isCustom?: boolean - onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void - searchText: string -} -const Tools = ({ - isCustom, - onSelect, - searchText, -}: ToolsProps) => { - const { t } = useTranslation() - const totalToolsets = useStore(state => state.toolsets) - const toolsets = useMemo(() => { - return totalToolsets.filter((toolset) => { - return toolset.type === (isCustom ? 'api' : 'builtin') && toolset.name.toLowerCase().includes(searchText.toLowerCase()) - }) - }, [totalToolsets, isCustom, searchText]) - const setToolsets = useStore(state => state.setToolsets) - const toolsMap = useStore(state => state.toolsMap) - const setToolsMap = useStore(state => state.setToolsMap) - - const handleExpand = useCallback((toolId: string) => { - const currentToolset = toolsets.find(toolset => toolset.id === toolId)! - - if (currentToolset.expanded) { - setToolsets(produce(toolsets, (draft) => { - const index = draft.findIndex(toolset => toolset.id === toolId) - draft[index].expanded = false - })) - return - } - - if (!currentToolset.expanded) { - setToolsets(produce(toolsets, (draft) => { - const index = draft.findIndex(toolset => toolset.id === toolId) - - if (!toolsMap[toolId]?.length && !currentToolset.fetching) - draft[index].fetching = true - - draft[index].expanded = true - })) - } - }, [setToolsets, toolsets, toolsMap]) - - const handleAddTools = useCallback((toolsetId: string, tools: ToolInWorkflow[]) => { - setToolsMap(produce(toolsMap, (draft) => { - draft[toolsetId] = tools - })) - }, [setToolsMap, toolsMap]) - - const handleFetched = useCallback((toolsetId: string) => { - setToolsets(produce(toolsets, (draft) => { - const index = draft.findIndex(toolset => toolset.id === toolsetId) - draft[index].fetching = false - })) - }, [setToolsets, toolsets]) - - return ( -
- { - !toolsets.length && ( -
{t('workflow.tabs.noResult')}
- ) - } - { - toolsets.map(toolset => ( - - )) - } -
- ) -} - -export default memo(Tools) diff --git a/web/app/components/workflow/block-selector/tools/item.tsx b/web/app/components/workflow/block-selector/tools/item.tsx deleted file mode 100644 index cbd12df62a..0000000000 --- a/web/app/components/workflow/block-selector/tools/item.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { - memo, - useCallback, - useEffect, - useMemo, -} from 'react' -import { useContext } from 'use-context-selector' -import { BlockEnum } from '../../types' -import type { - CollectionWithExpanded, - ToolDefaultValue, - ToolInWorkflow, -} from '../types' -import AppIcon from '@/app/components/base/app-icon' -import { ChevronDown } from '@/app/components/base/icons/src/vender/line/arrows' -import { - fetchBuiltInToolList, - fetchCustomToolList, -} from '@/service/tools' -import I18n from '@/context/i18n' -import { getLanguage } from '@/i18n/language' -import Loading from '@/app/components/base/loading' - -type ItemProps = { - data: CollectionWithExpanded - tools: ToolInWorkflow[] - onExpand: (toolsetId: string) => void - onAddTools: (toolsetId: string, tools: ToolInWorkflow[]) => void - onFetched: (toolsetId: string) => void - onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void -} -const Item = ({ - data, - tools, - onExpand, - onAddTools, - onFetched, - onSelect, -}: ItemProps) => { - const { locale } = useContext(I18n) - const language = getLanguage(locale) - - const fetchToolList = useMemo(() => { - return data.type === 'api' ? fetchCustomToolList : fetchBuiltInToolList - }, [data.type]) - - const handleFetchToolList = useCallback(() => { - fetchToolList(data.name).then((list) => { - onAddTools(data.id, list) - }).finally(() => { - onFetched(data.id) - }) - }, [data.id, data.name, fetchToolList, onAddTools, onFetched]) - - useEffect(() => { - if (data.fetching) - handleFetchToolList() - }, [data.fetching, handleFetchToolList]) - - return ( - <> -
onExpand(data.id)} - > - { - typeof data.icon === 'string' - ? ( -
- ) - : ( - - ) - } -
- {data.label[language]} -
- { - data.expanded - ? - : - } -
- { - data.expanded && !data.fetching && tools.map(tool => ( -
onSelect(BlockEnum.Tool, { - provider_id: data.id, - provider_type: data.type, - provider_name: data.name, - tool_name: tool.name, - tool_label: tool.label[language], - title: tool.label[language], - })} - > -
- {tool.label[language]} -
- )) - } - { - data.expanded && data.fetching && ( -
- -
- ) - } - - ) -} - -export default memo(Item) diff --git a/web/app/components/workflow/block-selector/types.ts b/web/app/components/workflow/block-selector/types.ts index 73cfaab4d8..9555cf164c 100644 --- a/web/app/components/workflow/block-selector/types.ts +++ b/web/app/components/workflow/block-selector/types.ts @@ -1,8 +1,3 @@ -import type { - Collection, - Tool, -} from '@/app/components/tools/types' - export enum TabsEnum { Blocks = 'blocks', BuiltInTool = 'built-in-tool', @@ -17,14 +12,6 @@ export enum BlockClassificationEnum { Utilities = 'utilities', } -export type CollectionWithExpanded = Collection & { - expanded?: boolean - fetching?: boolean -} - -export type ToolInWorkflow = Tool -export type ToolsMap = Record - export type ToolDefaultValue = { provider_id: string provider_type: string diff --git a/web/app/components/workflow/hooks/use-workflow.ts b/web/app/components/workflow/hooks/use-workflow.ts index aac4a303bc..fd4cfa4956 100644 --- a/web/app/components/workflow/hooks/use-workflow.ts +++ b/web/app/components/workflow/hooks/use-workflow.ts @@ -1,6 +1,7 @@ import { useCallback, useEffect, + useMemo, } from 'react' import dayjs from 'dayjs' import { uniqBy } from 'lodash-es' @@ -17,7 +18,6 @@ import type { Connection, Viewport, } from 'reactflow' -import type { ToolsMap } from '../block-selector/types' import { generateNewNode, getLayoutByDagre, @@ -55,7 +55,10 @@ import { fetchWorkflowDraft, syncWorkflowDraft, } from '@/service/workflow' -import { fetchCollectionList } from '@/service/tools' +import { + fetchAllBuiltInTools, + fetchAllCustomTools, +} from '@/service/tools' import I18n from '@/context/i18n' export const useIsChatMode = () => { const appDetail = useAppStore(s => s.appDetail) @@ -321,25 +324,42 @@ export const useWorkflow = () => { } } +export const useFetchToolsData = () => { + const workflowStore = useWorkflowStore() + + const handleFetchAllTools = useCallback(async (type: string) => { + if (type === 'builtin') { + const buildInTools = await fetchAllBuiltInTools() + + workflowStore.setState({ + buildInTools: buildInTools || [], + }) + } + if (type === 'custom') { + const customTools = await fetchAllCustomTools() + + workflowStore.setState({ + customTools: customTools || [], + }) + } + }, [workflowStore]) + + return { + handleFetchAllTools, + } +} + export const useWorkflowInit = () => { const workflowStore = useWorkflowStore() const nodesInitialData = useNodesInitialData() + const { handleFetchAllTools } = useFetchToolsData() const appDetail = useAppStore(state => state.appDetail)! const { data, error, mutate } = useSWR(`/apps/${appDetail.id}/workflows/draft`, fetchWorkflowDraft) const handleFetchPreloadData = useCallback(async () => { try { - const toolsets = await fetchCollectionList() const nodesDefaultConfigsData = await fetchNodesDefaultConfigs(`/apps/${appDetail?.id}/workflows/default-workflow-block-configs`) const publishedWorkflow = await fetchPublishedWorkflow(`/apps/${appDetail?.id}/workflows/publish`) - - workflowStore.setState({ - toolsets, - toolsMap: toolsets.reduce((acc, toolset) => { - acc[toolset.id] = [] - return acc - }, {} as ToolsMap), - }) workflowStore.setState({ nodesDefaultConfigs: nodesDefaultConfigsData.reduce((acc, block) => { if (!acc[block.type]) @@ -356,7 +376,9 @@ export const useWorkflowInit = () => { useEffect(() => { handleFetchPreloadData() - }, [handleFetchPreloadData]) + handleFetchAllTools('builtin') + handleFetchAllTools('custom') + }, [handleFetchPreloadData, handleFetchAllTools]) useEffect(() => { if (data) @@ -427,3 +449,18 @@ export const useNodesReadOnly = () => { getNodesReadOnly, } } + +export const useToolIcon = (data: Node['data']) => { + const buildInTools = useStore(s => s.buildInTools) + const customTools = useStore(s => s.customTools) + const toolIcon = useMemo(() => { + if (data.type === BlockEnum.Tool) { + if (data.provider_type === 'builtin') + return buildInTools.find(toolWithProvider => toolWithProvider.id === data.provider_id)?.icon + + return customTools.find(toolWithProvider => toolWithProvider.id === data.provider_id)?.icon + } + }, [data, buildInTools, customTools]) + + return toolIcon +} diff --git a/web/app/components/workflow/nodes/_base/components/next-step/index.tsx b/web/app/components/workflow/nodes/_base/components/next-step/index.tsx index d90269548f..73ceb50b52 100644 --- a/web/app/components/workflow/nodes/_base/components/next-step/index.tsx +++ b/web/app/components/workflow/nodes/_base/components/next-step/index.tsx @@ -1,15 +1,12 @@ -import { - memo, - useMemo, -} from 'react' +import { memo } from 'react' import { getConnectedEdges, getOutgoers, useEdges, useStoreApi, } from 'reactflow' +import { useToolIcon } from '../../../../hooks' import BlockIcon from '../../../../block-icon' -import { useStore } from '../../../../store' import type { Branch, Node, @@ -26,11 +23,7 @@ const NextStep = ({ selectedNode, }: NextStepProps) => { const data = selectedNode.data - const toolsets = useStore(s => s.toolsets) - const toolIcon = useMemo(() => { - if (data.type === BlockEnum.Tool) - return toolsets.find(toolset => toolset.id === data.provider_id)?.icon - }, [data, toolsets]) + const toolIcon = useToolIcon(data) const store = useStoreApi() const branches = data._targetBranches || [] const nodeWithBranches = data.type === BlockEnum.IfElse || data.type === BlockEnum.QuestionClassifier diff --git a/web/app/components/workflow/nodes/_base/components/panel-operator/index.tsx b/web/app/components/workflow/nodes/_base/components/panel-operator/index.tsx index 06df8e7ef9..68613dcb1a 100644 --- a/web/app/components/workflow/nodes/_base/components/panel-operator/index.tsx +++ b/web/app/components/workflow/nodes/_base/components/panel-operator/index.tsx @@ -1,12 +1,9 @@ import { memo, useCallback, - useEffect, useMemo, useState, } from 'react' -import produce from 'immer' -import { useContext } from 'use-context-selector' import { useTranslation } from 'react-i18next' import { useEdges } from 'reactflow' import type { OffsetOptions } from '@floating-ui/react' @@ -25,12 +22,7 @@ import { } from '@/app/components/base/portal-to-follow-elem' import type { Node } from '@/app/components/workflow/types' import { BlockEnum } from '@/app/components/workflow/types' -import I18n from '@/context/i18n' -import { getLanguage } from '@/i18n/language' -import { - fetchBuiltInToolList, - fetchCustomToolList, -} from '@/service/tools' +import { useGetLanguage } from '@/context/i18n' type PanelOperatorProps = { id: string @@ -52,53 +44,34 @@ const PanelOperator = ({ inNode, }: PanelOperatorProps) => { const { t } = useTranslation() - const { locale } = useContext(I18n) - const language = getLanguage(locale) + const language = useGetLanguage() const edges = useEdges() const { handleNodeDelete } = useNodesInteractions() const { nodesReadOnly } = useNodesReadOnly() const nodesExtraData = useNodesExtraData() - const toolsets = useStore(s => s.toolsets) - const toolsMap = useStore(s => s.toolsMap) - const setToolsMap = useStore(s => s.setToolsMap) + const buildInTools = useStore(s => s.buildInTools) + const customTools = useStore(s => s.customTools) const [open, setOpen] = useState(false) - const fetchToolList = useMemo(() => { - const toolset = toolsets.find(toolset => toolset.id === data.provider_id) - return toolset?.type === 'api' ? fetchCustomToolList : fetchBuiltInToolList - }, [toolsets, data.provider_id]) - - const handleGetAbout = useCallback(() => { - if (data.provider_id && !toolsMap[data.provider_id]?.length && open) { - fetchToolList(data.provider_id).then((list: any) => { - setToolsMap(produce(toolsMap, (draft) => { - draft[data.provider_id as string] = list - })) - }) - } - }, [data, toolsMap, fetchToolList, setToolsMap, open]) - useEffect(() => { - handleGetAbout() - }, [handleGetAbout]) - const edge = edges.find(edge => edge.target === id) - const author = useMemo(() => { if (data.type !== BlockEnum.Tool) return nodesExtraData[data.type].author - const toolset = toolsets.find(toolset => toolset.id === data.provider_id) + if (data.provider_type === 'builtin') + return buildInTools.find(toolWithProvider => toolWithProvider.id === data.provider_id)?.author - return toolset?.author - }, [data, nodesExtraData, toolsets]) + return customTools.find(toolWithProvider => toolWithProvider.id === data.provider_id)?.author + }, [data, nodesExtraData, buildInTools, customTools]) const about = useMemo(() => { if (data.type !== BlockEnum.Tool) return nodesExtraData[data.type].about - const tool = toolsMap[data.provider_id as string]?.find(tool => tool.name === data.tool_name) + if (data.provider_type === 'builtin') + return buildInTools.find(toolWithProvider => toolWithProvider.id === data.provider_id)?.description[language] - return tool?.description[language] || '' - }, [data, nodesExtraData, toolsMap, language]) + return customTools.find(toolWithProvider => toolWithProvider.id === data.provider_id)?.description[language] + }, [data, nodesExtraData, language, buildInTools, customTools]) const handleOpenChange = useCallback((newOpen: boolean) => { setOpen(newOpen) diff --git a/web/app/components/workflow/nodes/_base/node.tsx b/web/app/components/workflow/nodes/_base/node.tsx index ac38f79496..f60ef248d3 100644 --- a/web/app/components/workflow/nodes/_base/node.tsx +++ b/web/app/components/workflow/nodes/_base/node.tsx @@ -5,15 +5,16 @@ import type { import { cloneElement, memo, - useMemo, } from 'react' import type { NodeProps } from '../../types' import { BlockEnum, NodeRunningStatus, } from '../../types' -import { useStore } from '../../store' -import { useNodesReadOnly } from '../../hooks' +import { + useNodesReadOnly, + useToolIcon, +} from '../../hooks' import { NodeSourceHandle, NodeTargetHandle, @@ -36,12 +37,7 @@ const BaseNode: FC = ({ children, }) => { const { nodesReadOnly } = useNodesReadOnly() - const toolsets = useStore(s => s.toolsets) - const toolIcon = useMemo(() => { - if (data.type === BlockEnum.Tool) - return toolsets.find(toolset => toolset.id === data.provider_id)?.icon - }, [data, toolsets]) - + const toolIcon = useToolIcon(data) return (
= ({ const { nodesReadOnly } = useNodesReadOnly() const nodesExtraData = useNodesExtraData() const availableNextNodes = nodesExtraData[data.type].availableNextNodes - - const toolsets = useStore(s => s.toolsets) - const toolIcon = useMemo(() => { - if (data.type === BlockEnum.Tool) - return toolsets.find(toolset => toolset.id === data.provider_id)?.icon - }, [data, toolsets]) + const toolIcon = useToolIcon(data) const { handleNodeDataUpdate, diff --git a/web/app/components/workflow/nodes/tool/use-config.ts b/web/app/components/workflow/nodes/tool/use-config.ts index 0d874248b1..82d3396a9c 100644 --- a/web/app/components/workflow/nodes/tool/use-config.ts +++ b/web/app/components/workflow/nodes/tool/use-config.ts @@ -7,8 +7,7 @@ import { type ToolNodeType, type ToolVarInput, VarType } from './types' import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks' import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud' import { CollectionType } from '@/app/components/tools/types' -import type { Collection, Tool } from '@/app/components/tools/types' -import { fetchBuiltInToolList, fetchCollectionList, fetchCustomToolList, updateBuiltInToolCredential } from '@/service/tools' +import { updateBuiltInToolCredential } from '@/service/tools' import { addDefaultValue, toolParametersToFormSchemas } from '@/app/components/tools/utils/to-form-schema' import Toast from '@/app/components/base/toast' import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form' @@ -16,40 +15,27 @@ import { VarType as VarVarType } from '@/app/components/workflow/types' import type { InputVar, Var } from '@/app/components/workflow/types' import useOneStepRun from '@/app/components/workflow/nodes/_base/hooks/use-one-step-run' import { + useFetchToolsData, useNodesReadOnly, } from '@/app/components/workflow/hooks' const useConfig = (id: string, payload: ToolNodeType) => { const { nodesReadOnly: readOnly } = useNodesReadOnly() + const { handleFetchAllTools } = useFetchToolsData() const { t } = useTranslation() const language = useLanguage() - const toolsMap = useStore(s => s.toolsMap) - const setToolsMap = useStore(s => s.setToolsMap) - const { inputs, setInputs } = useNodeCrud(id, payload) /* * tool_configurations: tool setting, not dynamic setting * tool_parameters: tool dynamic setting(by user) */ - const { provider_id, provider_name, provider_type, tool_name, tool_configurations } = inputs + const { provider_id, provider_type, tool_name, tool_configurations } = inputs const isBuiltIn = provider_type === CollectionType.builtIn - const [currCollection, setCurrCollection] = useState(null) - const fetchCurrCollection = useCallback(async () => { - if (!provider_id) - return - const res = await fetchCollectionList() - const currCollection = res.find(item => item.id === provider_id) - setCurrCollection(currCollection) - }, [provider_id]) - - useEffect(() => { - if (!provider_id || !isBuiltIn) - return - - fetchCurrCollection() - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [provider_id]) + const buildInTools = useStore(s => s.buildInTools) + const customTools = useStore(s => s.customTools) + const currentTools = isBuiltIn ? buildInTools : customTools + const currCollection = currentTools.find(item => item.id === provider_id) // Auth const needAuth = !!currCollection?.allow_delete @@ -67,11 +53,11 @@ const useConfig = (id: string, payload: ToolNodeType) => { type: 'success', message: t('common.api.actionSuccess'), }) - await fetchCurrCollection() + handleFetchAllTools(provider_type) hideSetAuthModal() - }, [currCollection?.name, fetchCurrCollection, hideSetAuthModal, t]) + }, [currCollection?.name, hideSetAuthModal, t, handleFetchAllTools, provider_type]) - const [currTool, setCurrTool] = useState(null) + const currTool = currCollection?.tools.find(tool => tool.name === tool_name) const formSchemas = currTool ? toolParametersToFormSchemas(currTool.parameters) : [] const toolInputVarSchema = formSchemas.filter((item: any) => item.form === 'llm') // use setting @@ -122,26 +108,6 @@ const useConfig = (id: string, payload: ToolNodeType) => { const isLoading = currTool && (isBuiltIn ? !currCollection : false) - useEffect(() => { - (async () => { - let list: Tool[] = [] - if (toolsMap[provider_id]?.length) { - list = toolsMap[provider_id] - } - else { - list = isBuiltIn ? await fetchBuiltInToolList(provider_name || provider_id) : await fetchCustomToolList(provider_name) - - setToolsMap(produce(toolsMap, (draft) => { - draft[provider_id] = list - })) - } - const currTool = list.find(tool => tool.name === tool_name) - if (currTool) - setCurrTool(currTool) - })() - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [provider_name]) - // single run const [inputVarValues, doSetInputVarValues] = useState>({}) const setInputVarValues = (value: Record) => { diff --git a/web/app/components/workflow/store.ts b/web/app/components/workflow/store.ts index 9f82efd00e..03fa3ace44 100644 --- a/web/app/components/workflow/store.ts +++ b/web/app/components/workflow/store.ts @@ -9,16 +9,12 @@ import type { HelpLineHorizontalPosition, HelpLineVerticalPosition, } from './help-line/types' -import type { - CollectionWithExpanded, - ToolInWorkflow, - ToolsMap, -} from './block-selector/types' import type { Edge, HistoryWorkflowData, Node, RunFile, + ToolWithProvider, WorkflowRunningData, } from './types' import { WorkflowContext } from './context' @@ -36,10 +32,6 @@ type Shape = { setHelpLineHorizontal: (helpLineHorizontal?: HelpLineHorizontalPosition) => void helpLineVertical?: HelpLineVerticalPosition setHelpLineVertical: (helpLineVertical?: HelpLineVerticalPosition) => void - toolsets: CollectionWithExpanded[] - setToolsets: (toolsets: CollectionWithExpanded[]) => void - toolsMap: ToolsMap - setToolsMap: (toolsMap: Record) => void draftUpdatedAt: number setDraftUpdatedAt: (draftUpdatedAt: number) => void publishedAt: number @@ -65,6 +57,10 @@ type Shape = { isRestoring: boolean setIsRestoring: (isRestoring: boolean) => void debouncedSyncWorkflowDraft: (fn: () => void) => void + buildInTools: ToolWithProvider[] + setBuildInTools: (tools: ToolWithProvider[]) => void + customTools: ToolWithProvider[] + setCustomTools: (tools: ToolWithProvider[]) => void } export const createWorkflowStore = () => { @@ -81,10 +77,6 @@ export const createWorkflowStore = () => { setHelpLineHorizontal: helpLineHorizontal => set(() => ({ helpLineHorizontal })), helpLineVertical: undefined, setHelpLineVertical: helpLineVertical => set(() => ({ helpLineVertical })), - toolsets: [], - setToolsets: toolsets => set(() => ({ toolsets })), - toolsMap: {}, - setToolsMap: toolsMap => set(() => ({ toolsMap })), draftUpdatedAt: 0, setDraftUpdatedAt: draftUpdatedAt => set(() => ({ draftUpdatedAt: draftUpdatedAt ? draftUpdatedAt * 1000 : 0 })), publishedAt: 0, @@ -108,6 +100,10 @@ export const createWorkflowStore = () => { debouncedSyncWorkflowDraft: debounce((syncWorkflowDraft) => { syncWorkflowDraft() }, 5000), + buildInTools: [], + setBuildInTools: buildInTools => set(() => ({ buildInTools })), + customTools: [], + setCustomTools: customTools => set(() => ({ customTools })), })) } diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts index b5e2ba5531..d9d8e243aa 100644 --- a/web/app/components/workflow/types.ts +++ b/web/app/components/workflow/types.ts @@ -6,6 +6,7 @@ import type { TransferMethod } from '@/types/app' import type { ToolDefaultValue } from '@/app/components/workflow/block-selector/types' import type { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types' import type { NodeTracing } from '@/types/workflow' +import type { Collection, Tool } from '@/app/components/tools/types' export enum BlockEnum { Start = 'start', @@ -263,3 +264,7 @@ export type MoreInfo = { afterKey: string } } + +export type ToolWithProvider = Collection & { + tools: Tool[] +} diff --git a/web/context/i18n.ts b/web/context/i18n.ts index 985f716f80..5416ae7872 100644 --- a/web/context/i18n.ts +++ b/web/context/i18n.ts @@ -1,5 +1,9 @@ -import { createContext } from 'use-context-selector' +import { + createContext, + useContext, +} from 'use-context-selector' import type { Locale } from '@/i18n' +import { getLanguage } from '@/i18n/language' type II18NContext = { locale: Locale @@ -13,4 +17,11 @@ const I18NContext = createContext({ setLocaleOnClient: (lang: Locale, reloadPage?: boolean) => { }, }) +export const useI18N = () => useContext(I18NContext) +export const useGetLanguage = () => { + const { locale } = useI18N() + + return getLanguage(locale) +} + export default I18NContext diff --git a/web/service/tools.ts b/web/service/tools.ts index ac59e2e508..53430f89f5 100644 --- a/web/service/tools.ts +++ b/web/service/tools.ts @@ -1,5 +1,6 @@ import { get, post } from './base' import type { Collection, CustomCollectionBackend, CustomParamSchema, Tool, ToolCredential } from '@/app/components/tools/types' +import type { ToolWithProvider } from '@/app/components/workflow/types' export const fetchCollectionList = () => { return get('/workspaces/current/tool-providers') @@ -86,3 +87,11 @@ export const testAPIAvailable = (payload: any) => { }, }) } + +export const fetchAllBuiltInTools = () => { + return get('/workspaces/current/tools/builtin') +} + +export const fetchAllCustomTools = () => { + return get('/workspaces/current/tools/api') +}