From 5e4d2f9501bfb604cf763a6e9f78c76e2c3eea9b Mon Sep 17 00:00:00 2001 From: AkaraChen Date: Wed, 8 Jan 2025 14:55:55 +0800 Subject: [PATCH 1/5] Revert "chore: remove switch version component in strategy select" This reverts commit f63cc9e0691ce2f7eca2a15f6b96b469aeddd148. --- .../components/agent-strategy-selector.tsx | 23 +++++++++++++++---- web/i18n/en-US/workflow.ts | 1 + web/i18n/zh-Hans/workflow.ts | 1 + 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx b/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx index 076d171108..db684ea2df 100644 --- a/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx +++ b/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx @@ -17,8 +17,10 @@ import type { ToolWithProvider } from '../../../types' import { CollectionType } from '@/app/components/tools/types' import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon' import { useStrategyInfo } from '../../agent/use-config' +import { SwitchPluginVersion } from './switch-plugin-version' import PluginList from '@/app/components/workflow/block-selector/market-place-plugin/list' import { useMarketplacePlugins } from '@/app/components/plugins/marketplace/hooks' +import { ToolTipContent } from '@/app/components/base/tooltip/content' const NotFoundWarn = (props: { title: ReactNode, @@ -102,14 +104,15 @@ export const AgentStrategySelector = memo((props: AgentStrategySelectorProps) => value?.agent_strategy_name, ) - // plugin not found and is not found in marketplace - const showPluginNotInstalledWarn = !strategyStatus?.isExistInPlugin && strategyStatus?.plugin?.source === 'external' + const showPluginNotInstalledWarn = strategyStatus?.plugin?.source === 'external' && !strategyStatus.plugin.installed - // strategy not found - const showUnsupportedStrategy = !strategyStatus?.isExistInPlugin + const showUnsupportedStrategy = strategyStatus?.plugin.source === 'external' + && !strategyStatus?.isExistInPlugin + + const showSwitchVersion = !strategyStatus?.isExistInPlugin + && strategyStatus?.plugin.source === 'marketplace' && strategyStatus.plugin.installed - // plugin not found and is founded in marketplace const showInstallButton = !strategyStatus?.isExistInPlugin && strategyStatus?.plugin.source === 'marketplace' && !strategyStatus.plugin.installed @@ -174,6 +177,16 @@ export const AgentStrategySelector = memo((props: AgentStrategySelectorProps) => /> : } + {showSwitchVersion && + {t('workflow.nodes.agent.strategyNotFoundDescAndSwitchVersion')} + } + onChange={() => { + // TODO: refresh all strategies + }} + />} } diff --git a/web/i18n/en-US/workflow.ts b/web/i18n/en-US/workflow.ts index b494a48e5b..279654a857 100644 --- a/web/i18n/en-US/workflow.ts +++ b/web/i18n/en-US/workflow.ts @@ -740,6 +740,7 @@ const translation = { unsupportedStrategy: 'Unsupported strategy', pluginNotFoundDesc: 'This plugin is installed from GitHub. Please go to Plugins to reinstall', strategyNotFoundDesc: 'The installed plugin version does not provide this strategy.', + strategyNotFoundDescAndSwitchVersion: 'The installed plugin version does not provide this strategy. Click to switch version.', modelSelectorTooltips: { deprecated: 'This model is deprecated', }, diff --git a/web/i18n/zh-Hans/workflow.ts b/web/i18n/zh-Hans/workflow.ts index ded2a712a7..80c53702ab 100644 --- a/web/i18n/zh-Hans/workflow.ts +++ b/web/i18n/zh-Hans/workflow.ts @@ -740,6 +740,7 @@ const translation = { unsupportedStrategy: '不支持的策略', strategyNotFoundDesc: '安装的插件版本不提供此策略。', pluginNotFoundDesc: '此插件安装自 GitHub。请转到插件重新安装。', + strategyNotFoundDescAndSwitchVersion: '安装的插件版本不提供此策略。点击切换版本。', modelSelectorTooltips: { deprecated: '此模型已弃用', }, From fa83f2e2faeecf7112acc2652bbf8c2eb9feda6b Mon Sep 17 00:00:00 2001 From: AkaraChen Date: Wed, 8 Jan 2025 15:13:19 +0800 Subject: [PATCH 2/5] fix: switch version plugin --- .../components/switch-plugin-version.tsx | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/web/app/components/workflow/nodes/_base/components/switch-plugin-version.tsx b/web/app/components/workflow/nodes/_base/components/switch-plugin-version.tsx index 8f6f751bc3..fc517ccf1d 100644 --- a/web/app/components/workflow/nodes/_base/components/switch-plugin-version.tsx +++ b/web/app/components/workflow/nodes/_base/components/switch-plugin-version.tsx @@ -23,7 +23,10 @@ export const SwitchPluginVersion: FC = (props) => { const [pluginId] = uniqueIdentifier.split(':') const [isShow, setIsShow] = useState(false) const [isShowUpdateModal, { setTrue: showUpdateModal, setFalse: hideUpdateModal }] = useBoolean(false) - const [targetVersion, setTargetVersion] = useState() + const [target, setTarget] = useState<{ + version: string, + pluginUniqueIden: string; + }>() const pluginDetails = useCheckInstalled({ pluginIds: [pluginId], enabled: true, @@ -33,13 +36,8 @@ export const SwitchPluginVersion: FC = (props) => { const handleUpdatedFromMarketplace = useCallback(() => { hideUpdateModal() pluginDetails.refetch() - onChange?.(targetVersion!) - }, [hideUpdateModal, onChange, pluginDetails, targetVersion]) - - const targetUniqueIdentifier = (() => { - if (!targetVersion || !pluginDetail) return uniqueIdentifier - return uniqueIdentifier.replaceAll(pluginDetail.version, targetVersion) - })() + onChange?.(target!.version) + }, [hideUpdateModal, onChange, pluginDetails, target]) return
{isShowUpdateModal && pluginDetail && = (props) => { payload: pluginDetail.declaration, }, targetPackageInfo: { - id: targetUniqueIdentifier, - version: targetVersion!, + id: target!.pluginUniqueIden, + version: target!.version, }, }} onCancel={hideUpdateModal} @@ -62,7 +60,10 @@ export const SwitchPluginVersion: FC = (props) => { pluginID={pluginId} currentVersion={pluginDetail.version} onSelect={(state) => { - setTargetVersion(state.version) + setTarget({ + pluginUniqueIden: state.unique_identifier, + version: state.version, + }) showUpdateModal() }} trigger={ From 5481b42257fe1db738d0bd7e46bb6050928c9aa1 Mon Sep 17 00:00:00 2001 From: JzoNg Date: Wed, 8 Jan 2025 15:28:29 +0800 Subject: [PATCH 3/5] dark mode for tracing dropdown --- .../overview/tracing/config-button.tsx | 10 ++- .../[appId]/overview/tracing/panel.tsx | 87 +++++++++++-------- .../overview/tracing/toggle-fold-btn.tsx | 45 ---------- web/context/app-context.tsx | 2 +- 4 files changed, 59 insertions(+), 85 deletions(-) delete mode 100644 web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/toggle-fold-btn.tsx diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx index 977e3f057c..39fc81a274 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx @@ -1,12 +1,14 @@ 'use client' import type { FC } from 'react' import React, { useCallback, useEffect, useRef, useState } from 'react' +import { + RiEqualizer2Line, +} from '@remixicon/react' import { useTranslation } from 'react-i18next' import type { PopupProps } from './config-popup' import ConfigPopup from './config-popup' import cn from '@/utils/classnames' import Button from '@/app/components/base/button' -import { Settings04 } from '@/app/components/base/icons/src/vender/line/general' import { PortalToFollowElem, PortalToFollowElemContent, @@ -52,15 +54,15 @@ const ConfigBtn: FC = ({ const triggerContent = hasConfigured ? ( -
- +
+
) : ( ) diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx index bc724c1449..790705e9fb 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx @@ -1,6 +1,10 @@ 'use client' import type { FC } from 'react' import React, { useCallback, useEffect, useState } from 'react' +import { + RiArrowDownDoubleLine, + RiEqualizer2Line, +} from '@remixicon/react' import { useTranslation } from 'react-i18next' import { usePathname } from 'next/navigation' import { useBoolean } from 'ahooks' @@ -8,7 +12,6 @@ import type { LangFuseConfig, LangSmithConfig } from './type' import { TracingProvider } from './type' import TracingIcon from './tracing-icon' import ConfigButton from './config-button' -import cn from '@/utils/classnames' import { LangfuseIcon, LangsmithIcon } from '@/app/components/base/icons/src/public/tracing' import Indicator from '@/app/components/header/indicator' import { fetchTracingConfig as doFetchTracingConfig, fetchTracingStatus, updateTracingStatus } from '@/service/apps' @@ -16,6 +19,8 @@ import type { TracingStatus } from '@/models/app' import Toast from '@/app/components/base/toast' import { useAppContext } from '@/context/app-context' import Loading from '@/app/components/base/loading' +import Divider from '@/app/components/base/divider' +import cn from '@/utils/classnames' const I18N_PREFIX = 'app.tracing' @@ -27,7 +32,7 @@ const Title = ({ const { t } = useTranslation() return ( -
+
{t('common.appMenus.overview')}
) @@ -135,43 +140,55 @@ const Panel: FC = () => { return (
- <div className='flex items-center p-2 rounded-xl border-[0.5px] border-gray-200 shadow-xs cursor-pointer hover:bg-gray-100' onClick={showPopup}> - {!inUseTracingProvider - ? <> - <TracingIcon size='md' className='mr-2' /> - <div className='leading-5 text-sm font-semibold text-gray-700'>{t(`${I18N_PREFIX}.title`)}</div> - </> - : <InUseProviderIcon className='ml-1 h-4' />} - - {hasConfiguredTracing && ( - <div className='ml-4 mr-1 flex items-center'> - <Indicator color={enabled ? 'green' : 'gray'} /> - <div className='ml-1.5 text-xs font-semibold text-gray-500 uppercase'> - {t(`${I18N_PREFIX}.${enabled ? 'enabled' : 'disabled'}`)} + <div + className={cn( + 'flex items-center p-2 rounded-xl bg-background-default-dodge border-t border-l-[0.5px] border-effects-highlight shadow-xs cursor-pointer hover:bg-background-default-lighter hover:border-effects-highlight-lightmode-off', + controlShowPopup && 'bg-background-default-lighter border-effects-highlight-lightmode-off', + )} + onClick={showPopup} + > + {!inUseTracingProvider && ( + <> + <TracingIcon size='md' /> + <div className='mx-2 system-sm-semibold text-text-secondary'>{t(`${I18N_PREFIX}.title`)}</div> + <div className='p-1 rounded-md'> + <RiEqualizer2Line className='w-4 h-4 text-text-tertiary' /> </div> - </div> + <Divider type='vertical' className='h-3.5' /> + <div className='p-1 rounded-md'> + <RiArrowDownDoubleLine className='w-4 h-4 text-text-tertiary' /> + </div> + </> )} - {hasConfiguredTracing && ( - <div className='ml-2 w-px h-3.5 bg-gray-200'></div> + <> + <div className='ml-4 mr-1 flex items-center'> + <Indicator color={enabled ? 'green' : 'gray'} /> + <div className='ml-1.5 system-xs-semibold-uppercase text-text-tertiary'> + {t(`${I18N_PREFIX}.${enabled ? 'enabled' : 'disabled'}`)} + </div> + </div> + <InUseProviderIcon className='ml-1 h-4' /> + <Divider type='vertical' className='h-3.5' /> + <div className='flex items-center' onClick={e => e.stopPropagation()}> + <ConfigButton + appId={appId} + readOnly={readOnly} + hasConfigured + className='ml-2' + enabled={enabled} + onStatusChange={handleTracingEnabledChange} + chosenProvider={inUseTracingProvider} + onChooseProvider={handleChooseProvider} + langSmithConfig={langSmithConfig} + langFuseConfig={langFuseConfig} + onConfigUpdated={handleTracingConfigUpdated} + onConfigRemoved={handleTracingConfigRemoved} + controlShowPopup={controlShowPopup} + /> + </div> + </> )} - <div className='flex items-center' onClick={e => e.stopPropagation()}> - <ConfigButton - appId={appId} - readOnly={readOnly} - hasConfigured - className='ml-2' - enabled={enabled} - onStatusChange={handleTracingEnabledChange} - chosenProvider={inUseTracingProvider} - onChooseProvider={handleChooseProvider} - langSmithConfig={langSmithConfig} - langFuseConfig={langFuseConfig} - onConfigUpdated={handleTracingConfigUpdated} - onConfigRemoved={handleTracingConfigRemoved} - controlShowPopup={controlShowPopup} - /> - </div> </div> </div> ) diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/toggle-fold-btn.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/toggle-fold-btn.tsx deleted file mode 100644 index 934eb681b9..0000000000 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/toggle-fold-btn.tsx +++ /dev/null @@ -1,45 +0,0 @@ -'use client' -import { ChevronDoubleDownIcon } from '@heroicons/react/20/solid' -import type { FC } from 'react' -import { useTranslation } from 'react-i18next' -import React, { useCallback } from 'react' -import Tooltip from '@/app/components/base/tooltip' - -const I18N_PREFIX = 'app.tracing' - -type Props = { - isFold: boolean - onFoldChange: (isFold: boolean) => void -} - -const ToggleFoldBtn: FC<Props> = ({ - isFold, - onFoldChange, -}) => { - const { t } = useTranslation() - - const handleFoldChange = useCallback((e: React.MouseEvent<HTMLDivElement>) => { - e.stopPropagation() - onFoldChange(!isFold) - }, [isFold, onFoldChange]) - return ( - // text-[0px] to hide spacing between tooltip elements - <div className='shrink-0 cursor-pointer text-[0px]' onClick={handleFoldChange}> - <Tooltip - popupContent={t(`${I18N_PREFIX}.${isFold ? 'expand' : 'collapse'}`)} - > - {isFold && ( - <div className='p-1 rounded-md text-gray-500 hover:text-gray-800 hover:bg-black/5'> - <ChevronDoubleDownIcon className='w-4 h-4' /> - </div> - )} - {!isFold && ( - <div className='p-2 rounded-lg text-gray-500 border-[0.5px] border-gray-200 hover:text-gray-800 hover:bg-black/5'> - <ChevronDoubleDownIcon className='w-4 h-4 transform rotate-180' /> - </div> - )} - </Tooltip> - </div> - ) -} -export default React.memo(ToggleFoldBtn) diff --git a/web/context/app-context.tsx b/web/context/app-context.tsx index 7addfb83d4..25a313a76b 100644 --- a/web/context/app-context.tsx +++ b/web/context/app-context.tsx @@ -127,7 +127,7 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) => setCurrentWorkspace(currentWorkspaceResponse) }, [currentWorkspaceResponse]) - const [theme, setTheme] = useState<Theme>(Theme.light) + const [theme, setTheme] = useState<Theme>(Theme.dark) const handleSetTheme = useCallback((theme: Theme) => { setTheme(theme) globalThis.document.documentElement.setAttribute('data-theme', theme) From 05d273d643244d7853d87c5c8bbfd8ee00bbdf51 Mon Sep 17 00:00:00 2001 From: JzoNg <jzongcode@gmail.com> Date: Wed, 8 Jan 2025 15:40:13 +0800 Subject: [PATCH 4/5] fix tracing dropdown --- .../overview/tracing/config-button.tsx | 26 +++---------------- .../[appId]/overview/tracing/panel.tsx | 18 ++++++++++--- web/context/app-context.tsx | 2 +- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx index 39fc81a274..ca6fa3a904 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-button.tsx @@ -4,19 +4,15 @@ import React, { useCallback, useEffect, useRef, useState } from 'react' import { RiEqualizer2Line, } from '@remixicon/react' -import { useTranslation } from 'react-i18next' import type { PopupProps } from './config-popup' import ConfigPopup from './config-popup' import cn from '@/utils/classnames' -import Button from '@/app/components/base/button' import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger, } from '@/app/components/base/portal-to-follow-elem' -const I18N_PREFIX = 'app.tracing' - type Props = { readOnly: boolean className?: string @@ -30,7 +26,6 @@ const ConfigBtn: FC<Props> = ({ controlShowPopup, ...popupProps }) => { - const { t } = useTranslation() const [open, doSetOpen] = useState(false) const openRef = useRef(open) const setOpen = useCallback((v: boolean) => { @@ -52,21 +47,6 @@ const ConfigBtn: FC<Props> = ({ if (popupProps.readOnly && !hasConfigured) return null - const triggerContent = hasConfigured - ? ( - <div className={cn(className, 'p-1 rounded-md')}> - <RiEqualizer2Line className='w-4 h-4 text-text-tertiary' /> - </div> - ) - : ( - <Button variant='primary' - className={cn(className, '!h-8 !px-3 select-none')} - > - <RiEqualizer2Line className='mr-1 w-4 h-4' /> - <span className='text-[13px]'>{t(`${I18N_PREFIX}.config`)}</span> - </Button> - ) - return ( <PortalToFollowElem open={open} @@ -74,11 +54,13 @@ const ConfigBtn: FC<Props> = ({ placement='bottom-end' offset={{ mainAxis: 12, - crossAxis: hasConfigured ? 8 : 0, + crossAxis: hasConfigured ? 8 : 49, }} > <PortalToFollowElemTrigger onClick={handleTrigger}> - {triggerContent} + <div className={cn(className, 'p-1 rounded-md')}> + <RiEqualizer2Line className='w-4 h-4 text-text-tertiary' /> + </div> </PortalToFollowElemTrigger> <PortalToFollowElemContent className='z-[11]'> <ConfigPopup {...popupProps} /> diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx index 790705e9fb..06621a2ae4 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/panel.tsx @@ -3,7 +3,6 @@ import type { FC } from 'react' import React, { useCallback, useEffect, useState } from 'react' import { RiArrowDownDoubleLine, - RiEqualizer2Line, } from '@remixicon/react' import { useTranslation } from 'react-i18next' import { usePathname } from 'next/navigation' @@ -151,8 +150,21 @@ const Panel: FC = () => { <> <TracingIcon size='md' /> <div className='mx-2 system-sm-semibold text-text-secondary'>{t(`${I18N_PREFIX}.title`)}</div> - <div className='p-1 rounded-md'> - <RiEqualizer2Line className='w-4 h-4 text-text-tertiary' /> + <div className='flex items-center' onClick={e => e.stopPropagation()}> + <ConfigButton + appId={appId} + readOnly={readOnly} + hasConfigured={false} + enabled={enabled} + onStatusChange={handleTracingEnabledChange} + chosenProvider={inUseTracingProvider} + onChooseProvider={handleChooseProvider} + langSmithConfig={langSmithConfig} + langFuseConfig={langFuseConfig} + onConfigUpdated={handleTracingConfigUpdated} + onConfigRemoved={handleTracingConfigRemoved} + controlShowPopup={controlShowPopup} + /> </div> <Divider type='vertical' className='h-3.5' /> <div className='p-1 rounded-md'> diff --git a/web/context/app-context.tsx b/web/context/app-context.tsx index 25a313a76b..7addfb83d4 100644 --- a/web/context/app-context.tsx +++ b/web/context/app-context.tsx @@ -127,7 +127,7 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) => setCurrentWorkspace(currentWorkspaceResponse) }, [currentWorkspaceResponse]) - const [theme, setTheme] = useState<Theme>(Theme.dark) + const [theme, setTheme] = useState<Theme>(Theme.light) const handleSetTheme = useCallback((theme: Theme) => { setTheme(theme) globalThis.document.documentElement.setAttribute('data-theme', theme) From 4b01ef2b48ece91a5fe144c43eef50a94876a998 Mon Sep 17 00:00:00 2001 From: zxhlyh <jasonapring2015@outlook.com> Date: Wed, 8 Jan 2025 15:41:59 +0800 Subject: [PATCH 5/5] fix: chat log --- .../chat/chat/answer/workflow-process.tsx | 23 +---- .../steps/install.tsx | 5 ++ .../panel/debug-and-preview/chat-wrapper.tsx | 2 +- .../workflow/panel/debug-and-preview/hooks.ts | 88 +++++++------------ .../panel/debug-and-preview/index.tsx | 2 +- .../workflow/panel/workflow-preview.tsx | 3 +- web/app/components/workflow/run/index.tsx | 3 +- .../components/workflow/run/tracing-panel.tsx | 5 +- web/types/workflow.ts | 1 + 9 files changed, 46 insertions(+), 86 deletions(-) diff --git a/web/app/components/base/chat/chat/answer/workflow-process.tsx b/web/app/components/base/chat/chat/answer/workflow-process.tsx index 47ad5291db..c7e17d10d3 100644 --- a/web/app/components/base/chat/chat/answer/workflow-process.tsx +++ b/web/app/components/base/chat/chat/answer/workflow-process.tsx @@ -1,5 +1,4 @@ import { - useCallback, useEffect, useMemo, useState, @@ -15,9 +14,8 @@ import TracingPanel from '@/app/components/workflow/run/tracing-panel' import cn from '@/utils/classnames' import { CheckCircle } from '@/app/components/base/icons/src/vender/solid/general' import { WorkflowRunningStatus } from '@/app/components/workflow/types' -import { useStore as useAppStore } from '@/app/components/app/store' -interface WorkflowProcessProps { +type WorkflowProcessProps = { data: WorkflowProcess item?: ChatItem expand?: boolean @@ -26,7 +24,6 @@ interface WorkflowProcessProps { } const WorkflowProcessItem = ({ data, - item, expand = false, hideInfo = false, hideProcessDetail = false, @@ -54,22 +51,6 @@ const WorkflowProcessItem = ({ setCollapse(!expand) }, [expand]) - const setCurrentLogItem = useAppStore(s => s.setCurrentLogItem) - const setShowMessageLogModal = useAppStore(s => s.setShowMessageLogModal) - const setCurrentLogModalActiveTab = useAppStore(s => s.setCurrentLogModalActiveTab) - - const showIterationDetail = useCallback(() => { - setCurrentLogItem(item) - setCurrentLogModalActiveTab('TRACING') - setShowMessageLogModal(true) - }, [item, setCurrentLogItem, setCurrentLogModalActiveTab, setShowMessageLogModal]) - - const showRetryDetail = useCallback(() => { - setCurrentLogItem(item) - setCurrentLogModalActiveTab('TRACING') - setShowMessageLogModal(true) - }, [item, setCurrentLogItem, setCurrentLogModalActiveTab, setShowMessageLogModal]) - return ( <div className={cn( @@ -110,8 +91,6 @@ const WorkflowProcessItem = ({ { <TracingPanel list={data.tracing} - onShowIterationDetail={showIterationDetail} - onShowRetryDetail={showRetryDetail} hideNodeInfo={hideInfo} hideNodeProcessDetail={hideProcessDetail} /> diff --git a/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx b/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx index a3bb50076b..01c4d44bad 100644 --- a/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx +++ b/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx @@ -12,6 +12,7 @@ import { useInstallPackageFromMarketPlace, useUpdatePackageFromMarketPlace } fro import checkTaskStatus from '../../base/check-task-status' import useCheckInstalled from '@/app/components/plugins/install-plugin/hooks/use-check-installed' import Version from '../../base/version' +import { usePluginTaskList } from '@/service/use-plugins' const i18nPrefix = 'plugin.installModal' @@ -50,6 +51,7 @@ const Installed: FC<Props> = ({ check, stop, } = checkTaskStatus() + const { handleRefetch } = usePluginTaskList() useEffect(() => { if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier) @@ -93,6 +95,9 @@ const Installed: FC<Props> = ({ onInstalled() return } + + handleRefetch() + const { status, error } = await check({ taskId, pluginUniqueIdentifier: uniqueIdentifier, diff --git a/web/app/components/workflow/panel/debug-and-preview/chat-wrapper.tsx b/web/app/components/workflow/panel/debug-and-preview/chat-wrapper.tsx index eb0ca15ee0..42c30df7cf 100644 --- a/web/app/components/workflow/panel/debug-and-preview/chat-wrapper.tsx +++ b/web/app/components/workflow/panel/debug-and-preview/chat-wrapper.tsx @@ -28,7 +28,7 @@ import { import { useStore as useAppStore } from '@/app/components/app/store' import { getLastAnswer } from '@/app/components/base/chat/utils' -interface ChatWrapperProps { +type ChatWrapperProps = { showConversationVariableModal: boolean onConversationModalHide: () => void showInputsFieldsPanel: boolean diff --git a/web/app/components/workflow/panel/debug-and-preview/hooks.ts b/web/app/components/workflow/panel/debug-and-preview/hooks.ts index 9dca8c0502..d91cf1082d 100644 --- a/web/app/components/workflow/panel/debug-and-preview/hooks.ts +++ b/web/app/components/workflow/panel/debug-and-preview/hooks.ts @@ -27,10 +27,9 @@ import { getProcessedFilesFromResponse, } from '@/app/components/base/file-uploader/utils' import type { FileEntity } from '@/app/components/base/file-uploader/types' -import type { NodeTracing } from '@/types/workflow' type GetAbortController = (abortController: AbortController) => void -interface SendCallback { +type SendCallback = { onGetSuggestedQuestions?: (responseItemId: string, getAbortController: GetAbortController) => Promise<any> } export const useChat = ( @@ -276,6 +275,7 @@ export const useChat = ( ) setSuggestQuestions(data) } + // eslint-disable-next-line unused-imports/no-unused-vars catch (error) { setSuggestQuestions([]) } @@ -331,8 +331,7 @@ export const useChat = ( responseItem.workflowProcess!.tracing!.push({ ...data, status: NodeRunningStatus.Running, - details: [], - } as any) + }) handleUpdateChatList(produce(chatListRef.current, (draft) => { const currentIndex = draft.findIndex(item => item.id === responseItem.id) draft[currentIndex] = { @@ -341,30 +340,21 @@ export const useChat = ( } })) }, - onIterationNext: ({ data }) => { - const tracing = responseItem.workflowProcess!.tracing! - const iterations = tracing.find(item => item.node_id === data.node_id - && (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id))! - iterations.details!.push([]) - - handleUpdateChatList(produce(chatListRef.current, (draft) => { - const currentIndex = draft.length - 1 - draft[currentIndex] = responseItem - })) - }, onIterationFinish: ({ data }) => { - const tracing = responseItem.workflowProcess!.tracing! - const iterationsIndex = tracing.findIndex(item => item.node_id === data.node_id - && (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id))! - tracing[iterationsIndex] = { - ...tracing[iterationsIndex], - ...data, - status: NodeRunningStatus.Succeeded, - } as any - handleUpdateChatList(produce(chatListRef.current, (draft) => { - const currentIndex = draft.length - 1 - draft[currentIndex] = responseItem - })) + const currentTracingIndex = responseItem.workflowProcess!.tracing!.findIndex(item => item.id === data.id) + if (currentTracingIndex > -1) { + responseItem.workflowProcess!.tracing[currentTracingIndex] = { + ...responseItem.workflowProcess!.tracing[currentTracingIndex], + ...data, + } + handleUpdateChatList(produce(chatListRef.current, (draft) => { + const currentIndex = draft.findIndex(item => item.id === responseItem.id) + draft[currentIndex] = { + ...draft[currentIndex], + ...responseItem, + } + })) + } }, onNodeStarted: ({ data }) => { if (data.iteration_id) @@ -386,16 +376,7 @@ export const useChat = ( if (data.iteration_id) return - const currentIndex = responseItem.workflowProcess!.tracing!.findIndex((item) => { - if (!item.execution_metadata?.parallel_id) - return item.node_id === data.node_id - return item.node_id === data.node_id && (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id) - }) - if (responseItem.workflowProcess!.tracing[currentIndex].retryDetail) - responseItem.workflowProcess!.tracing[currentIndex].retryDetail?.push(data as NodeTracing) - else - responseItem.workflowProcess!.tracing[currentIndex].retryDetail = [data as NodeTracing] - + responseItem.workflowProcess!.tracing!.push(data) handleUpdateChatList(produce(chatListRef.current, (draft) => { const currentIndex = draft.findIndex(item => item.id === responseItem.id) draft[currentIndex] = { @@ -408,27 +389,20 @@ export const useChat = ( if (data.iteration_id) return - const currentIndex = responseItem.workflowProcess!.tracing!.findIndex((item) => { - if (!item.execution_metadata?.parallel_id) - return item.node_id === data.node_id - return item.node_id === data.node_id && (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id || item.parallel_id === data.execution_metadata?.parallel_id) - }) - responseItem.workflowProcess!.tracing[currentIndex] = { - ...(responseItem.workflowProcess!.tracing[currentIndex]?.extras - ? { extras: responseItem.workflowProcess!.tracing[currentIndex].extras } - : {}), - ...(responseItem.workflowProcess!.tracing[currentIndex]?.retryDetail - ? { retryDetail: responseItem.workflowProcess!.tracing[currentIndex].retryDetail } - : {}), - ...data, - } as any - handleUpdateChatList(produce(chatListRef.current, (draft) => { - const currentIndex = draft.findIndex(item => item.id === responseItem.id) - draft[currentIndex] = { - ...draft[currentIndex], - ...responseItem, + const currentTracingIndex = responseItem.workflowProcess!.tracing!.findIndex(item => item.id === data.id) + if (currentTracingIndex > -1) { + responseItem.workflowProcess!.tracing[currentTracingIndex] = { + ...responseItem.workflowProcess!.tracing[currentTracingIndex], + ...data, } - })) + handleUpdateChatList(produce(chatListRef.current, (draft) => { + const currentIndex = draft.findIndex(item => item.id === responseItem.id) + draft[currentIndex] = { + ...draft[currentIndex], + ...responseItem, + } + })) + } }, }, ) diff --git a/web/app/components/workflow/panel/debug-and-preview/index.tsx b/web/app/components/workflow/panel/debug-and-preview/index.tsx index 1e74a5c27d..d4a3f24d4a 100644 --- a/web/app/components/workflow/panel/debug-and-preview/index.tsx +++ b/web/app/components/workflow/panel/debug-and-preview/index.tsx @@ -22,7 +22,7 @@ import Tooltip from '@/app/components/base/tooltip' import ActionButton, { ActionButtonState } from '@/app/components/base/action-button' import { useStore } from '@/app/components/workflow/store' -export interface ChatWrapperRefType { +export type ChatWrapperRefType = { handleRestart: () => void } const DebugAndPreview = () => { diff --git a/web/app/components/workflow/panel/workflow-preview.tsx b/web/app/components/workflow/panel/workflow-preview.tsx index aa64229e30..b4e4d4c5d1 100644 --- a/web/app/components/workflow/panel/workflow-preview.tsx +++ b/web/app/components/workflow/panel/workflow-preview.tsx @@ -24,7 +24,6 @@ import Toast from '../../base/toast' import InputsPanel from './inputs-panel' import cn from '@/utils/classnames' import Loading from '@/app/components/base/loading' -import formatNodeList from '@/app/components/workflow/run/utils/format-log' const WorkflowPreview = () => { const { t } = useTranslation() @@ -161,7 +160,7 @@ const WorkflowPreview = () => { {currentTab === 'TRACING' && ( <TracingPanel className='bg-background-section-burn' - list={formatNodeList(workflowRunningData?.tracing || [], t)} + list={workflowRunningData?.tracing || []} /> )} {currentTab === 'TRACING' && !workflowRunningData?.tracing?.length && ( diff --git a/web/app/components/workflow/run/index.tsx b/web/app/components/workflow/run/index.tsx index c1249f7224..eaa88d2df8 100644 --- a/web/app/components/workflow/run/index.tsx +++ b/web/app/components/workflow/run/index.tsx @@ -13,7 +13,6 @@ import { fetchRunDetail, fetchTracingList } from '@/service/log' import type { NodeTracing } from '@/types/workflow' import type { WorkflowRunDetailResponse } from '@/models/log' import { useStore as useAppStore } from '@/app/components/app/store' -import formatNodeList from './utils/format-log' export type RunProps = { hideResult?: boolean activeTab?: 'RESULT' | 'DETAIL' | 'TRACING' @@ -61,7 +60,7 @@ const RunPanel: FC<RunProps> = ({ hideResult, activeTab = 'RESULT', runID, getRe const { data: nodeList } = await fetchTracingList({ url: `/apps/${appID}/workflow-runs/${runID}/node-executions`, }) - setList(formatNodeList(nodeList, t)) + setList(nodeList) } catch (err) { notify({ diff --git a/web/app/components/workflow/run/tracing-panel.tsx b/web/app/components/workflow/run/tracing-panel.tsx index 758e9cfcf8..7739c8f836 100644 --- a/web/app/components/workflow/run/tracing-panel.tsx +++ b/web/app/components/workflow/run/tracing-panel.tsx @@ -11,10 +11,12 @@ import { RiArrowDownSLine, RiMenu4Line, } from '@remixicon/react' +import { useTranslation } from 'react-i18next' import { useLogs } from './hooks' import NodePanel from './node' import SpecialResultPanel from './special-result-panel' import type { NodeTracing } from '@/types/workflow' +import formatNodeList from '@/app/components/workflow/run/utils/format-log' type TracingPanelProps = { list: NodeTracing[] @@ -29,7 +31,8 @@ const TracingPanel: FC<TracingPanelProps> = ({ hideNodeInfo = false, hideNodeProcessDetail = false, }) => { - const treeNodes = list + const { t } = useTranslation() + const treeNodes = formatNodeList(list, t) const [collapsedNodes, setCollapsedNodes] = useState<Set<string>>(new Set()) const [hoveredParallel, setHoveredParallel] = useState<string | null>(null) diff --git a/web/types/workflow.ts b/web/types/workflow.ts index 9287cba471..b152c3615b 100644 --- a/web/types/workflow.ts +++ b/web/types/workflow.ts @@ -23,6 +23,7 @@ export type NodeTracing = { index: number predecessor_node_id: string node_id: string + iteration_id?: string node_type: BlockEnum title: string inputs: any