mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-04 13:30:41 +08:00
chore: change var inspect slice
This commit is contained in:
parent
1593ef0640
commit
8cd8da99d6
@ -2,11 +2,11 @@ import { useWorkflowStore } from '../store'
|
|||||||
const useCurrentVars = () => {
|
const useCurrentVars = () => {
|
||||||
const workflowStore = useWorkflowStore()
|
const workflowStore = useWorkflowStore()
|
||||||
const {
|
const {
|
||||||
currentNodes,
|
nodes: currentNodes,
|
||||||
getCurrentVar,
|
getInspectVar: getCurrentVar,
|
||||||
setCurrentVar,
|
setInspectVar: setCurrentVar,
|
||||||
clearCurrentVars,
|
clearInspectVars: clearCurrentVars,
|
||||||
clearCurrentNodeVars,
|
clearNodeInspectVars: clearCurrentNodeVars,
|
||||||
getLastRunVar,
|
getLastRunVar,
|
||||||
getLastRunInfos,
|
getLastRunInfos,
|
||||||
} = workflowStore.getState()
|
} = workflowStore.getState()
|
||||||
|
@ -5,13 +5,19 @@ import { NodeRunningStatus } from '@/app/components/workflow/types'
|
|||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import NoData from './no-data'
|
import NoData from './no-data'
|
||||||
|
import { useLastRun } from '@/service/use-workflow'
|
||||||
|
import Loading from '@/app/components/base/loading'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
isDataFromHistory: boolean
|
||||||
|
appId: string
|
||||||
nodeId: string
|
nodeId: string
|
||||||
runningStatus: NodeRunningStatus
|
runningStatus?: NodeRunningStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
const LastRun: FC<Props> = ({
|
const LastRun: FC<Props> = ({
|
||||||
|
isDataFromHistory,
|
||||||
|
appId,
|
||||||
nodeId,
|
nodeId,
|
||||||
runningStatus,
|
runningStatus,
|
||||||
}) => {
|
}) => {
|
||||||
@ -20,22 +26,31 @@ const LastRun: FC<Props> = ({
|
|||||||
const {
|
const {
|
||||||
getLastRunNodeInfo,
|
getLastRunNodeInfo,
|
||||||
} = workflowStore.getState()
|
} = workflowStore.getState()
|
||||||
const [runResult, setRunResult] = useState(getLastRunNodeInfo(nodeId))
|
const { data: runResultFromHistory, isFetching } = useLastRun(appId, nodeId, isDataFromHistory)
|
||||||
|
const [runResultFromSingleRun, setRunResult] = useState(isDataFromHistory ? getLastRunNodeInfo(nodeId) : null)
|
||||||
|
const runResult = isDataFromHistory ? runResultFromHistory : runResultFromSingleRun
|
||||||
const isRunning = runningStatus === NodeRunningStatus.Running
|
const isRunning = runningStatus === NodeRunningStatus.Running
|
||||||
|
|
||||||
|
// get data from current running result
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (isDataFromHistory)
|
||||||
|
return
|
||||||
|
|
||||||
setRunResult(getLastRunNodeInfo(nodeId))
|
setRunResult(getLastRunNodeInfo(nodeId))
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [runningStatus])
|
}, [runningStatus, isDataFromHistory])
|
||||||
|
|
||||||
const handleSingleRun = () => {
|
const handleSingleRun = () => {
|
||||||
console.log('run')
|
console.log('run')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isDataFromHistory && isFetching)
|
||||||
|
return <Loading />
|
||||||
|
|
||||||
if (isRunning)
|
if (isRunning)
|
||||||
return <ResultPanel status='running' showSteps={false} />
|
return <ResultPanel status='running' showSteps={false} />
|
||||||
|
|
||||||
if (!runResult) {
|
if (!runResultFromSingleRun) {
|
||||||
return (
|
return (
|
||||||
<NoData onSingleRun={handleSingleRun} />
|
<NoData onSingleRun={handleSingleRun} />
|
||||||
)
|
)
|
||||||
|
@ -156,7 +156,7 @@ const useOneStepRun = <T>({
|
|||||||
const workflowStore = useWorkflowStore()
|
const workflowStore = useWorkflowStore()
|
||||||
const {
|
const {
|
||||||
setLastRunNodeInfo,
|
setLastRunNodeInfo,
|
||||||
setCurrentNodeVars,
|
setNodeInspectVars: setCurrentNodeVars,
|
||||||
setShowSingleRunPanel,
|
setShowSingleRunPanel,
|
||||||
} = workflowStore.getState()
|
} = workflowStore.getState()
|
||||||
const [runResult, doSetRunResult] = useState<NodeRunResult | null>(null)
|
const [runResult, doSetRunResult] = useState<NodeRunResult | null>(null)
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
import type { StateCreator } from 'zustand'
|
|
||||||
import produce from 'immer'
|
|
||||||
import type { NodeTracing } from '@/types/workflow'
|
|
||||||
|
|
||||||
// TODO: Missing var type
|
|
||||||
type NodeVars = NodeTracing
|
|
||||||
|
|
||||||
type CurrentVarsState = {
|
|
||||||
currentNodes: NodeVars[]
|
|
||||||
}
|
|
||||||
|
|
||||||
type CurrentVarsActions = {
|
|
||||||
setCurrentVars: (vars: NodeVars[]) => void
|
|
||||||
getCurrentVars: () => NodeVars[]
|
|
||||||
clearCurrentVars: () => void
|
|
||||||
setCurrentNodeVars: (nodeId: string, payload: NodeVars) => void
|
|
||||||
clearCurrentNodeVars: (nodeId: string) => void
|
|
||||||
getCurrentNodeVars: (nodeId: string) => NodeVars | undefined
|
|
||||||
hasCurrentNodeVars: (nodeId: string) => boolean
|
|
||||||
setCurrentVar: (nodeId: string, key: string, value: any) => void
|
|
||||||
getCurrentVar: (nodeId: string, key: string) => any
|
|
||||||
}
|
|
||||||
|
|
||||||
export type CurrentVarsSliceShape = CurrentVarsState & CurrentVarsActions
|
|
||||||
|
|
||||||
export const createCurrentVarsSlice: StateCreator<CurrentVarsSliceShape> = (set, get) => {
|
|
||||||
return ({
|
|
||||||
currentNodes: [],
|
|
||||||
setCurrentVars: (vars) => {
|
|
||||||
set(() => ({
|
|
||||||
currentNodes: vars,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
getCurrentVars: () => {
|
|
||||||
return get().currentNodes
|
|
||||||
},
|
|
||||||
clearCurrentVars: () => {
|
|
||||||
set(() => ({
|
|
||||||
currentNodes: [],
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
setCurrentNodeVars: (nodeId, payload) => {
|
|
||||||
set((state) => {
|
|
||||||
const prevNodes = state.currentNodes
|
|
||||||
const nodes = produce(prevNodes, (draft) => {
|
|
||||||
const index = prevNodes.findIndex(node => node.id === nodeId)
|
|
||||||
if (index === -1)
|
|
||||||
draft.push(payload)
|
|
||||||
else
|
|
||||||
draft[index] = payload
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
currentNodes: nodes,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
clearCurrentNodeVars: (nodeId) => {
|
|
||||||
set(produce((state: CurrentVarsSliceShape) => {
|
|
||||||
const nodes = state.currentNodes.filter(node => node.node_id !== nodeId)
|
|
||||||
state.currentNodes = nodes
|
|
||||||
},
|
|
||||||
))
|
|
||||||
},
|
|
||||||
getCurrentNodeVars: (nodeId) => {
|
|
||||||
const nodes = get().currentNodes
|
|
||||||
return nodes.find(node => node.node_id === nodeId)
|
|
||||||
},
|
|
||||||
hasCurrentNodeVars: (nodeId) => {
|
|
||||||
return !!get().getCurrentNodeVars(nodeId)
|
|
||||||
},
|
|
||||||
setCurrentVar: (nodeId, key, value) => {
|
|
||||||
set(produce((state: CurrentVarsSliceShape) => {
|
|
||||||
const nodes = state.currentNodes.map((node) => {
|
|
||||||
if (node.id === nodeId) {
|
|
||||||
return produce(node, (draft) => {
|
|
||||||
if (!draft.outputs)
|
|
||||||
draft.outputs = {}
|
|
||||||
draft.outputs[key] = value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return node
|
|
||||||
})
|
|
||||||
state.currentNodes = nodes
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
getCurrentVar(nodeId, key) {
|
|
||||||
const node = get().getCurrentNodeVars(nodeId)
|
|
||||||
if (!node)
|
|
||||||
return undefined
|
|
||||||
|
|
||||||
const variable = node.outputs?.[key]
|
|
||||||
return variable
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
@ -30,8 +30,8 @@ import type { WorkflowSliceShape } from './workflow-slice'
|
|||||||
import { createWorkflowSlice } from './workflow-slice'
|
import { createWorkflowSlice } from './workflow-slice'
|
||||||
import type { LastRunSliceShape } from './last-run-slice'
|
import type { LastRunSliceShape } from './last-run-slice'
|
||||||
import { createLastRunSlice } from './last-run-slice'
|
import { createLastRunSlice } from './last-run-slice'
|
||||||
import type { CurrentVarsSliceShape } from './current-vars-slice'
|
import type { CurrentVarsSliceShape } from './var-inspect-slice'
|
||||||
import { createCurrentVarsSlice } from './current-vars-slice'
|
import { createInspectVarsSlice } from './var-inspect-slice'
|
||||||
|
|
||||||
import { WorkflowContext } from '@/app/components/workflow/context'
|
import { WorkflowContext } from '@/app/components/workflow/context'
|
||||||
import type { LayoutSliceShape } from './layout-slice'
|
import type { LayoutSliceShape } from './layout-slice'
|
||||||
@ -75,7 +75,7 @@ export const createWorkflowStore = (params: CreateWorkflowStoreParams) => {
|
|||||||
...createWorkflowDraftSlice(...args),
|
...createWorkflowDraftSlice(...args),
|
||||||
...createWorkflowSlice(...args),
|
...createWorkflowSlice(...args),
|
||||||
...createLastRunSlice(...args),
|
...createLastRunSlice(...args),
|
||||||
...createCurrentVarsSlice(...args),
|
...createInspectVarsSlice(...args),
|
||||||
...createLayoutSlice(...args),
|
...createLayoutSlice(...args),
|
||||||
...(injectWorkflowStoreSliceFn?.(...args) || {} as WorkflowAppSliceShape),
|
...(injectWorkflowStoreSliceFn?.(...args) || {} as WorkflowAppSliceShape),
|
||||||
}))
|
}))
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
import type { StateCreator } from 'zustand'
|
||||||
|
import produce from 'immer'
|
||||||
|
import type { NodeWithVar, VarInInspect } from '@/types/workflow'
|
||||||
|
import type { ValueSelector } from '../../types'
|
||||||
|
|
||||||
|
type InspectVarsState = {
|
||||||
|
currentFocusNodeId: string | null
|
||||||
|
nodes: NodeWithVar[] // the nodes have data
|
||||||
|
conversationVars: VarInInspect[]
|
||||||
|
}
|
||||||
|
|
||||||
|
type InspectVarsActions = {
|
||||||
|
getAllInspectVars: () => NodeWithVar[]
|
||||||
|
clearInspectVars: () => void
|
||||||
|
setNodeInspectVars: (nodeId: string, payload: NodeWithVar) => void
|
||||||
|
clearNodeInspectVars: (nodeId: string) => void
|
||||||
|
getNodeInspectVars: (nodeId: string) => NodeWithVar | undefined
|
||||||
|
hasNodeInspectVars: (nodeId: string) => boolean
|
||||||
|
setInspectVar: (nodeId: string, selector: ValueSelector, value: any) => void
|
||||||
|
getInspectVar: (nodeId: string, selector: ValueSelector) => any
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CurrentVarsSliceShape = InspectVarsState & InspectVarsActions
|
||||||
|
|
||||||
|
export const createInspectVarsSlice: StateCreator<CurrentVarsSliceShape> = (set, get) => {
|
||||||
|
return ({
|
||||||
|
currentFocusNodeId: null,
|
||||||
|
nodes: [],
|
||||||
|
conversationVars: [],
|
||||||
|
getAllInspectVars: () => {
|
||||||
|
return get().nodes
|
||||||
|
},
|
||||||
|
clearInspectVars: () => {
|
||||||
|
set(() => ({
|
||||||
|
nodes: [],
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
setNodeInspectVars: (nodeId, payload) => {
|
||||||
|
set((state) => {
|
||||||
|
const prevNodes = state.nodes
|
||||||
|
const nodes = produce(prevNodes, (draft) => {
|
||||||
|
const index = prevNodes.findIndex(node => node.nodeId === nodeId)
|
||||||
|
if (index === -1)
|
||||||
|
draft.push(payload)
|
||||||
|
else
|
||||||
|
draft[index] = payload
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
nodes,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
clearNodeInspectVars: (nodeId) => {
|
||||||
|
set(produce((state: CurrentVarsSliceShape) => {
|
||||||
|
const nodes = state.nodes.filter(node => node.nodeId !== nodeId)
|
||||||
|
state.nodes = nodes
|
||||||
|
},
|
||||||
|
))
|
||||||
|
},
|
||||||
|
getNodeInspectVars: (nodeId) => {
|
||||||
|
const nodes = get().nodes
|
||||||
|
return nodes.find(node => node.nodeId === nodeId)
|
||||||
|
},
|
||||||
|
hasNodeInspectVars: (nodeId) => {
|
||||||
|
return !!get().getNodeInspectVars(nodeId)
|
||||||
|
},
|
||||||
|
setInspectVar: (nodeId, selector, value) => {
|
||||||
|
set(produce((state: CurrentVarsSliceShape) => {
|
||||||
|
const nodes = state.nodes.map((node) => {
|
||||||
|
if (node.nodeId === nodeId) {
|
||||||
|
return produce(node, (draft) => {
|
||||||
|
const needChangeVarIndex = draft.vars.findIndex((varItem) => {
|
||||||
|
return varItem.selector.join('.') === selector.join('.')
|
||||||
|
})
|
||||||
|
if (needChangeVarIndex !== -1)
|
||||||
|
draft.vars[needChangeVarIndex].value = value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return node
|
||||||
|
})
|
||||||
|
state.nodes = nodes
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
getInspectVar(nodeId, key) {
|
||||||
|
const node = get().getNodeInspectVars(nodeId)
|
||||||
|
if (!node)
|
||||||
|
return undefined
|
||||||
|
|
||||||
|
const variable = node.vars.find((varItem) => {
|
||||||
|
return varItem.selector.join('.') === key.join('.')
|
||||||
|
})?.value
|
||||||
|
return variable
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
@ -4,12 +4,14 @@ import type {
|
|||||||
FetchWorkflowDraftPageParams,
|
FetchWorkflowDraftPageParams,
|
||||||
FetchWorkflowDraftPageResponse,
|
FetchWorkflowDraftPageResponse,
|
||||||
FetchWorkflowDraftResponse,
|
FetchWorkflowDraftResponse,
|
||||||
|
NodeTracing,
|
||||||
PublishWorkflowParams,
|
PublishWorkflowParams,
|
||||||
UpdateWorkflowParams,
|
UpdateWorkflowParams,
|
||||||
WorkflowConfigResponse,
|
WorkflowConfigResponse,
|
||||||
} from '@/types/workflow'
|
} from '@/types/workflow'
|
||||||
import type { CommonResponse } from '@/models/common'
|
import type { CommonResponse } from '@/models/common'
|
||||||
import { useReset } from './use-base'
|
import { useReset } from './use-base'
|
||||||
|
import { sleep } from '@/utils'
|
||||||
|
|
||||||
const NAME_SPACE = 'workflow'
|
const NAME_SPACE = 'workflow'
|
||||||
|
|
||||||
@ -85,3 +87,39 @@ export const usePublishWorkflow = (appId: string) => {
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useLastRun = (appID: string, nodeId: string, enabled: boolean) => {
|
||||||
|
return useQuery<NodeTracing>({
|
||||||
|
enabled,
|
||||||
|
queryKey: [NAME_SPACE, 'last-run', appID, nodeId],
|
||||||
|
queryFn: async () => {
|
||||||
|
// TODO: mock data
|
||||||
|
await sleep(1000)
|
||||||
|
return Promise.resolve({
|
||||||
|
node_id: nodeId,
|
||||||
|
status: 'success',
|
||||||
|
node_type: 'llm',
|
||||||
|
title: 'LLM',
|
||||||
|
inputs: null,
|
||||||
|
outputs: {
|
||||||
|
text: '"abc" is a simple sequence of three letters. Is there anything specific you\'d like to know about it, or are you just testing the system? \n\nLet me know if you have any other questions or tasks! 😊 \n',
|
||||||
|
usage: {
|
||||||
|
prompt_tokens: 3,
|
||||||
|
prompt_unit_price: '0',
|
||||||
|
prompt_price_unit: '0.000001',
|
||||||
|
prompt_price: '0',
|
||||||
|
completion_tokens: 48,
|
||||||
|
completion_unit_price: '0',
|
||||||
|
completion_price_unit: '0.000001',
|
||||||
|
completion_price: '0',
|
||||||
|
total_tokens: 51,
|
||||||
|
total_price: '0',
|
||||||
|
currency: 'USD',
|
||||||
|
latency: 0.7095853444188833,
|
||||||
|
},
|
||||||
|
finish_reason: '1',
|
||||||
|
},
|
||||||
|
} as any)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { Viewport } from 'reactflow'
|
import type { Viewport } from 'reactflow'
|
||||||
import type { BlockEnum, ConversationVariable, Edge, EnvironmentVariable, InputVar, Node, Variable } from '@/app/components/workflow/types'
|
import type { BlockEnum, ConversationVariable, Edge, EnvironmentVariable, InputVar, Node, ValueSelector, VarType, Variable } from '@/app/components/workflow/types'
|
||||||
import type { TransferMethod } from '@/types/app'
|
import type { TransferMethod } from '@/types/app'
|
||||||
import type { ErrorHandleTypeEnum } from '@/app/components/workflow/nodes/_base/components/error-handle/types'
|
import type { ErrorHandleTypeEnum } from '@/app/components/workflow/nodes/_base/components/error-handle/types'
|
||||||
import type { BeforeRunFormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form'
|
import type { BeforeRunFormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form'
|
||||||
@ -370,3 +370,28 @@ export type PanelProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type NodeRunResult = NodeTracing
|
export type NodeRunResult = NodeTracing
|
||||||
|
|
||||||
|
// Var Inspect
|
||||||
|
export enum VarInInspectType {
|
||||||
|
conversation = 'conversation',
|
||||||
|
environment = 'environment',
|
||||||
|
node = 'node',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type VarInInspect = {
|
||||||
|
id: string
|
||||||
|
type: VarInInspectType
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
selector: ValueSelector
|
||||||
|
value_type: VarType
|
||||||
|
value: any
|
||||||
|
edited: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type NodeWithVar = {
|
||||||
|
nodeId: string
|
||||||
|
nodeType: BlockEnum
|
||||||
|
title: string
|
||||||
|
vars: VarInInspect[]
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user