Merge remote-tracking branch 'origin/feat/support-agent-sandbox' into pre-align-hitl-frontend

# Conflicts:
#	web/app/components/base/prompt-editor/index.tsx
This commit is contained in:
yyh
2026-02-09 15:28:37 +08:00
3 changed files with 89 additions and 18 deletions

View File

@@ -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<WorkflowAvailableNodesProps> = ({
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<unknown>, params: unknown[]) => void }> }>
}
const PromptEditor: FC<PromptEditorProps> = ({
type PromptEditorContentProps = PromptEditorProps & {
availableNodes: WorkflowNode[]
}
const PromptEditorContent: FC<PromptEditorContentProps> = ({
instanceId,
nodeId,
compact,
@@ -237,6 +268,7 @@ const PromptEditor: FC<PromptEditorProps> = ({
disableToolBlocks,
onEnter,
shortcutPopups = [],
availableNodes,
}) => {
const { eventEmitter } = useEventEmitterContextContext()
const initialConfig = {
@@ -288,12 +320,6 @@ const PromptEditor: FC<PromptEditorProps> = ({
} 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<PromptEditorProps> = ({
)
}
const PromptEditor: FC<PromptEditorProps> = (props) => {
const workflowStore = React.useContext(WorkflowContext)
const hooksStore = React.useContext(HooksStoreContext)
const hasWorkflowContext = Boolean(workflowStore && hooksStore)
if (!hasWorkflowContext) {
return (
<PromptEditorContent
{...props}
availableNodes={[]}
/>
)
}
return (
<WorkflowAvailableNodes
nodeId={props.nodeId}
isSupportSandbox={props.isSupportSandbox}
>
{availableNodes => (
<PromptEditorContent
{...props}
availableNodes={availableNodes}
/>
)}
</WorkflowAvailableNodes>
)
}
export default PromptEditor

View File

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

View File

@@ -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
? (
<div className="flex h-full items-center justify-center !bg-background-section-burn">
<Loading />