diff --git a/web/app/components/base/prompt-editor/index.tsx b/web/app/components/base/prompt-editor/index.tsx index 6adcb3235c..1091c54792 100644 --- a/web/app/components/base/prompt-editor/index.tsx +++ b/web/app/components/base/prompt-editor/index.tsx @@ -20,6 +20,7 @@ import type { VariableBlockType, WorkflowVariableBlockType, } from './types' +import type { Node as WorkflowNode } from '@/app/components/workflow/types' import type { EventPayload } from '@/context/event-emitter' import { CodeNode } from '@lexical/code' import { LexicalComposer } from '@lexical/react/LexicalComposer' @@ -38,6 +39,8 @@ import { import * as React from 'react' import { useEffect, useState } from 'react' import { Trans } from 'react-i18next' +import { WorkflowContext } from '@/app/components/workflow/context' +import { HooksStoreContext } from '@/app/components/workflow/hooks-store/provider' import { FileReferenceNode } from '@/app/components/workflow/skill/editor/skill-editor/plugins/file-reference-block/node' import { FilePreviewContextProvider } from '@/app/components/workflow/skill/editor/skill-editor/plugins/file-reference-block/preview-context' import FileReferenceReplacementBlock from '@/app/components/workflow/skill/editor/skill-editor/plugins/file-reference-block/replacement-block' @@ -169,6 +172,30 @@ const EnterCommandPlugin: FC<{ onEnter?: (event: KeyboardEvent) => void }> = ({ return null } +type WorkflowAvailableNodesProps = { + nodeId?: string + isSupportSandbox?: boolean + children: (availableNodes: WorkflowNode[]) => React.ReactNode +} + +const WorkflowAvailableNodes: FC = ({ + nodeId, + isSupportSandbox, + children, +}) => { + const { getBeforeNodesInSameBranch } = useWorkflow() + const availableNodes = React.useMemo( + () => nodeId && isSupportSandbox ? getBeforeNodesInSameBranch(nodeId || '') : [], + [getBeforeNodesInSameBranch, isSupportSandbox, nodeId], + ) + + return ( + <> + {children(availableNodes)} + + ) +} + export type PromptEditorProps = { instanceId?: string nodeId?: string @@ -204,7 +231,11 @@ export type PromptEditorProps = { shortcutPopups?: Array<{ hotkey: Hotkey, Popup: React.ComponentType<{ onClose: () => void, onInsert: (command: LexicalCommand, params: unknown[]) => void }> }> } -const PromptEditor: FC = ({ +type PromptEditorContentProps = PromptEditorProps & { + availableNodes: WorkflowNode[] +} + +const PromptEditorContent: FC = ({ instanceId, nodeId, compact, @@ -237,6 +268,7 @@ const PromptEditor: FC = ({ disableToolBlocks, onEnter, shortcutPopups = [], + availableNodes, }) => { const { eventEmitter } = useEventEmitterContextContext() const initialConfig = { @@ -288,12 +320,6 @@ const PromptEditor: FC = ({ } as EventPayload) }, [eventEmitter, historyBlock?.history]) - const { getBeforeNodesInSameBranch } = useWorkflow() - const availableNodes = React.useMemo( - () => nodeId && isSupportSandbox ? getBeforeNodesInSameBranch(nodeId || '') : [], - [getBeforeNodesInSameBranch, isSupportSandbox, nodeId], - ) - const toolBlockContextValue = React.useMemo(() => { if (!onToolMetadataChange) return null @@ -549,4 +575,33 @@ const PromptEditor: FC = ({ ) } +const PromptEditor: FC = (props) => { + const workflowStore = React.useContext(WorkflowContext) + const hooksStore = React.useContext(HooksStoreContext) + const hasWorkflowContext = Boolean(workflowStore && hooksStore) + + if (!hasWorkflowContext) { + return ( + + ) + } + + return ( + + {availableNodes => ( + + )} + + ) +} + export default PromptEditor diff --git a/web/app/components/workflow-app/hooks/use-workflow-run.ts b/web/app/components/workflow-app/hooks/use-workflow-run.ts index 733a5c79ae..e07257da39 100644 --- a/web/app/components/workflow-app/hooks/use-workflow-run.ts +++ b/web/app/components/workflow-app/hooks/use-workflow-run.ts @@ -845,6 +845,7 @@ export const useWorkflowRun = () => { const handleStopRun = useCallback((taskId: string) => { const setStoppedState = () => { const { + workflowRunningData, setWorkflowRunningData, setIsListening, setShowVariableInspectPanel, @@ -852,16 +853,27 @@ export const useWorkflowRun = () => { setListeningTriggerNodeId, } = workflowStore.getState() - setWorkflowRunningData({ - result: { - status: WorkflowRunningStatus.Stopped, - inputs_truncated: false, - process_data_truncated: false, - outputs_truncated: false, - }, - tracing: [], - resultText: '', - }) + if (workflowRunningData) { + setWorkflowRunningData({ + ...workflowRunningData, + result: { + ...workflowRunningData.result, + status: WorkflowRunningStatus.Stopped, + }, + }) + } + else { + setWorkflowRunningData({ + result: { + status: WorkflowRunningStatus.Stopped, + inputs_truncated: false, + process_data_truncated: false, + outputs_truncated: false, + }, + tracing: [], + resultText: '', + }) + } setIsListening(false) setListeningTriggerType(null) setListeningTriggerNodeId(null) diff --git a/web/app/components/workflow/panel/workflow-preview.tsx b/web/app/components/workflow/panel/workflow-preview.tsx index 063e1813a7..beee21a96a 100644 --- a/web/app/components/workflow/panel/workflow-preview.tsx +++ b/web/app/components/workflow/panel/workflow-preview.tsx @@ -71,6 +71,10 @@ const WorkflowPreview = () => { return 'TRACING' })() + const shouldShowTracingLoading = effectiveTab === 'TRACING' + && !workflowRunningData?.tracing?.length + && (workflowRunningData?.result?.status === WorkflowRunningStatus.Running || !workflowRunningData?.result) + const handleTabChange = (tab: string) => { setUserSelectedTab(tab) } @@ -285,7 +289,7 @@ const WorkflowPreview = () => { /> ) : null} - {effectiveTab === 'TRACING' && !workflowRunningData?.tracing?.length + {shouldShowTracingLoading ? (