mirror of
https://github.com/langgenius/dify.git
synced 2026-03-29 01:49:57 +08:00
Made-with: Cursor # Conflicts: # api/controllers/console/app/workflow_draft_variable.py # api/core/agent/cot_agent_runner.py # api/core/agent/cot_chat_agent_runner.py # api/core/agent/cot_completion_agent_runner.py # api/core/agent/fc_agent_runner.py # api/core/app/apps/advanced_chat/app_generator.py # api/core/app/apps/advanced_chat/app_runner.py # api/core/app/apps/agent_chat/app_runner.py # api/core/app/apps/workflow/app_generator.py # api/core/app/apps/workflow/app_runner.py # api/core/app/entities/app_invoke_entities.py # api/core/app/entities/queue_entities.py # api/core/llm_generator/output_parser/structured_output.py # api/core/workflow/workflow_entry.py # api/dify_graph/context/__init__.py # api/dify_graph/entities/tool_entities.py # api/dify_graph/file/file_manager.py # api/dify_graph/graph_engine/response_coordinator/coordinator.py # api/dify_graph/graph_events/node.py # api/dify_graph/node_events/node.py # api/dify_graph/nodes/agent/agent_node.py # api/dify_graph/nodes/llm/entities.py # api/dify_graph/nodes/llm/llm_utils.py # api/dify_graph/nodes/llm/node.py # api/dify_graph/nodes/question_classifier/question_classifier_node.py # api/dify_graph/runtime/graph_runtime_state.py # api/dify_graph/variables/segments.py # api/factories/variable_factory.py # api/services/variable_truncator.py # api/tests/unit_tests/utils/structured_output_parser/test_structured_output_parser.py # api/uv.lock # web/app/components/app-sidebar/app-info.tsx # web/app/components/app-sidebar/app-sidebar-dropdown.tsx # web/app/components/app/create-app-modal/index.spec.tsx # web/app/components/apps/__tests__/list.spec.tsx # web/app/components/apps/app-card.tsx # web/app/components/apps/list.tsx # web/app/components/header/account-dropdown/compliance.tsx # web/app/components/header/account-dropdown/index.tsx # web/app/components/header/account-dropdown/support.tsx # web/app/components/workflow-app/components/workflow-onboarding-modal/index.tsx # web/app/components/workflow/panel/debug-and-preview/hooks.ts # web/contract/console/apps.ts # web/contract/router.ts # web/eslint-suppressions.json # web/next.config.ts # web/pnpm-lock.yaml
166 lines
6.0 KiB
TypeScript
166 lines
6.0 KiB
TypeScript
import type { Edge, Node } from '@/app/components/workflow/types'
|
|
import type { FileUploadConfigResponse } from '@/models/common'
|
|
import type { FetchWorkflowDraftResponse } from '@/types/workflow'
|
|
import {
|
|
useCallback,
|
|
useEffect,
|
|
useState,
|
|
} from 'react'
|
|
import { useStore as useAppStore } from '@/app/components/app/store'
|
|
import {
|
|
useStore,
|
|
useWorkflowStore,
|
|
} from '@/app/components/workflow/store'
|
|
import { BlockEnum } from '@/app/components/workflow/types'
|
|
import { STORAGE_KEYS } from '@/config/storage-keys'
|
|
import { useWorkflowConfig } from '@/service/use-workflow'
|
|
import {
|
|
fetchNodesDefaultConfigs,
|
|
fetchPublishedWorkflow,
|
|
fetchWorkflowDraft,
|
|
syncWorkflowDraft,
|
|
} from '@/service/workflow'
|
|
import { AppModeEnum } from '@/types/app'
|
|
import { storage } from '@/utils/storage'
|
|
import { useWorkflowTemplate } from './use-workflow-template'
|
|
|
|
const hasConnectedUserInput = (nodes: Node[] = [], edges: Edge[] = []): boolean => {
|
|
const startNodeIds = nodes
|
|
.filter(node => node?.data?.type === BlockEnum.Start)
|
|
.map(node => node.id)
|
|
|
|
if (!startNodeIds.length)
|
|
return false
|
|
|
|
return edges.some(edge => startNodeIds.includes(edge.source))
|
|
}
|
|
export const useWorkflowInit = () => {
|
|
const workflowStore = useWorkflowStore()
|
|
const {
|
|
nodes: nodesTemplate,
|
|
edges: edgesTemplate,
|
|
} = useWorkflowTemplate()
|
|
const appDetail = useAppStore(state => state.appDetail)!
|
|
const setSyncWorkflowDraftHash = useStore(s => s.setSyncWorkflowDraftHash)
|
|
const [data, setData] = useState<FetchWorkflowDraftResponse>()
|
|
const [isLoading, setIsLoading] = useState(true)
|
|
useEffect(() => {
|
|
workflowStore.setState({ appId: appDetail.id, appName: appDetail.name })
|
|
}, [appDetail.id, workflowStore])
|
|
|
|
const handleUpdateWorkflowFileUploadConfig = useCallback((config: FileUploadConfigResponse) => {
|
|
const { setFileUploadConfig } = workflowStore.getState()
|
|
setFileUploadConfig(config)
|
|
}, [workflowStore])
|
|
const {
|
|
data: fileUploadConfigResponse,
|
|
isLoading: isFileUploadConfigLoading,
|
|
} = useWorkflowConfig('/files/upload', handleUpdateWorkflowFileUploadConfig)
|
|
|
|
const handleGetInitialWorkflowData = useCallback(async () => {
|
|
try {
|
|
const res = await fetchWorkflowDraft(`/apps/${appDetail.id}/workflows/draft`)
|
|
setData(res)
|
|
workflowStore.setState({
|
|
envSecrets: (res.environment_variables || []).filter(env => env.value_type === 'secret').reduce((acc, env) => {
|
|
acc[env.id] = env.value
|
|
return acc
|
|
}, {} as Record<string, string>),
|
|
environmentVariables: res.environment_variables?.map(env => env.value_type === 'secret' ? { ...env, value: '[__HIDDEN__]' } : env) || [],
|
|
conversationVariables: res.conversation_variables || [],
|
|
isWorkflowDataLoaded: true,
|
|
})
|
|
setSyncWorkflowDraftHash(res.hash)
|
|
setIsLoading(false)
|
|
}
|
|
catch (error: any) {
|
|
if (error && error.json && !error.bodyUsed && appDetail) {
|
|
error.json().then((err: any) => {
|
|
if (err.code === 'draft_workflow_not_exist') {
|
|
const isAdvancedChat = appDetail.mode === AppModeEnum.ADVANCED_CHAT
|
|
workflowStore.setState({
|
|
notInitialWorkflow: true,
|
|
showOnboarding: !isAdvancedChat,
|
|
shouldAutoOpenStartNodeSelector: !isAdvancedChat,
|
|
hasShownOnboarding: false,
|
|
})
|
|
const nodesData = isAdvancedChat ? nodesTemplate : []
|
|
const edgesData = isAdvancedChat ? edgesTemplate : []
|
|
|
|
const runtimeStorageKey = `${STORAGE_KEYS.LOCAL.WORKFLOW.SANDBOX_RUNTIME_PREFIX}${appDetail.id}`
|
|
const enableSandboxRuntime = storage.getBoolean(runtimeStorageKey) === true
|
|
if (enableSandboxRuntime)
|
|
storage.remove(runtimeStorageKey)
|
|
|
|
syncWorkflowDraft({
|
|
url: `/apps/${appDetail.id}/workflows/draft`,
|
|
params: {
|
|
graph: {
|
|
nodes: nodesData,
|
|
edges: edgesData,
|
|
},
|
|
features: {
|
|
retriever_resource: { enabled: true },
|
|
sandbox: { enabled: enableSandboxRuntime },
|
|
},
|
|
environment_variables: [],
|
|
conversation_variables: [],
|
|
},
|
|
}).then((res) => {
|
|
workflowStore.getState().setDraftUpdatedAt(res.updated_at)
|
|
setSyncWorkflowDraftHash(res.hash)
|
|
handleGetInitialWorkflowData()
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}, [appDetail, nodesTemplate, edgesTemplate, workflowStore, setSyncWorkflowDraftHash])
|
|
|
|
useEffect(() => {
|
|
handleGetInitialWorkflowData()
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [])
|
|
|
|
const handleFetchPreloadData = useCallback(async () => {
|
|
try {
|
|
const nodesDefaultConfigsData = await fetchNodesDefaultConfigs(`/apps/${appDetail?.id}/workflows/default-workflow-block-configs`)
|
|
const publishedWorkflow = await fetchPublishedWorkflow(`/apps/${appDetail?.id}/workflows/publish`)
|
|
workflowStore.setState({
|
|
nodesDefaultConfigs: nodesDefaultConfigsData.reduce((acc, block) => {
|
|
if (!acc[block.type])
|
|
acc[block.type] = { ...block.config }
|
|
return acc
|
|
}, {} as Record<string, any>),
|
|
})
|
|
workflowStore.getState().setPublishedAt(publishedWorkflow?.created_at)
|
|
const graph = publishedWorkflow?.graph
|
|
workflowStore.getState().setLastPublishedHasUserInput(
|
|
hasConnectedUserInput(graph?.nodes, graph?.edges),
|
|
)
|
|
}
|
|
catch (e) {
|
|
console.error(e)
|
|
workflowStore.getState().setLastPublishedHasUserInput(false)
|
|
}
|
|
}, [workflowStore, appDetail])
|
|
|
|
useEffect(() => {
|
|
handleFetchPreloadData()
|
|
}, [handleFetchPreloadData])
|
|
|
|
useEffect(() => {
|
|
if (data) {
|
|
workflowStore.getState().setDraftUpdatedAt(data.updated_at)
|
|
workflowStore.getState().setToolPublished(data.tool_published)
|
|
}
|
|
}, [data, workflowStore])
|
|
|
|
return {
|
|
data,
|
|
isLoading: isLoading || isFileUploadConfigLoading,
|
|
fileUploadConfigResponse,
|
|
reload: handleGetInitialWorkflowData,
|
|
}
|
|
}
|