Feat/environment variables in workflow (#6515)

Co-authored-by: JzoNg <jzongcode@gmail.com>
This commit is contained in:
-LAN-
2024-07-22 15:29:39 +08:00
committed by GitHub
parent 87d583f454
commit 5e6fc58db3
146 changed files with 2486 additions and 746 deletions

View File

@@ -14,3 +14,4 @@ export * from './use-panel-interactions'
export * from './use-workflow-start-run'
export * from './use-nodes-layout'
export * from './use-workflow-history'
export * from './use-workflow-variables'

View File

@@ -31,6 +31,7 @@ export const useNodesSyncDraft = () => {
const [x, y, zoom] = transform
const {
appId,
environmentVariables,
syncWorkflowDraftHash,
} = workflowStore.getState()
@@ -80,6 +81,7 @@ export const useNodesSyncDraft = () => {
sensitive_word_avoidance: features.moderation,
file_upload: features.file,
},
environment_variables: environmentVariables,
hash: syncWorkflowDraftHash,
},
}

View File

@@ -5,7 +5,7 @@ import {
import { useTranslation } from 'react-i18next'
import { useReactFlow } from 'reactflow'
import { useWorkflowStore } from '../store'
import { WORKFLOW_DATA_UPDATE } from '../constants'
import { DSL_EXPORT_CHECK, WORKFLOW_DATA_UPDATE } from '../constants'
import type { WorkflowDataUpdator } from '../types'
import {
initialEdges,
@@ -66,11 +66,18 @@ export const useWorkflowUpdate = () => {
appId,
setSyncWorkflowDraftHash,
setIsSyncingWorkflowDraft,
setEnvironmentVariables,
setEnvSecrets,
} = workflowStore.getState()
setIsSyncingWorkflowDraft(true)
fetchWorkflowDraft(`/apps/${appId}/workflows/draft`).then((response) => {
handleUpdateWorkflowCanvas(response.graph as WorkflowDataUpdator)
setSyncWorkflowDraftHash(response.hash)
setEnvSecrets((response.environment_variables || []).filter(env => env.value_type === 'secret').reduce((acc, env) => {
acc[env.id] = env.value
return acc
}, {} as Record<string, string>))
setEnvironmentVariables(response.environment_variables?.map(env => env.value_type === 'secret' ? { ...env, value: '[__HIDDEN__]' } : env) || [])
}).finally(() => setIsSyncingWorkflowDraft(false))
}, [handleUpdateWorkflowCanvas, workflowStore])
@@ -83,12 +90,13 @@ export const useWorkflowUpdate = () => {
export const useDSL = () => {
const { t } = useTranslation()
const { notify } = useToastContext()
const { eventEmitter } = useEventEmitterContextContext()
const [exporting, setExporting] = useState(false)
const { doSyncWorkflowDraft } = useNodesSyncDraft()
const appDetail = useAppStore(s => s.appDetail)
const handleExportDSL = useCallback(async () => {
const handleExportDSL = useCallback(async (include = false) => {
if (!appDetail)
return
@@ -98,7 +106,10 @@ export const useDSL = () => {
try {
setExporting(true)
await doSyncWorkflowDraft()
const { data } = await exportAppConfig(appDetail.id)
const { data } = await exportAppConfig({
appID: appDetail.id,
include,
})
const a = document.createElement('a')
const file = new Blob([data], { type: 'application/yaml' })
a.href = URL.createObjectURL(file)
@@ -113,7 +124,30 @@ export const useDSL = () => {
}
}, [appDetail, notify, t, doSyncWorkflowDraft, exporting])
const exportCheck = useCallback(async () => {
if (!appDetail)
return
try {
const workflowDraft = await fetchWorkflowDraft(`/apps/${appDetail?.id}/workflows/draft`)
const list = (workflowDraft.environment_variables || []).filter(env => env.value_type === 'secret')
if (list.length === 0) {
handleExportDSL()
return
}
eventEmitter?.emit({
type: DSL_EXPORT_CHECK,
payload: {
data: list,
},
} as any)
}
catch (e) {
notify({ type: 'error', message: t('app.exportFailed') })
}
}, [appDetail, eventEmitter, handleExportDSL, notify, t])
return {
exportCheck,
handleExportDSL,
}
}

View File

@@ -41,6 +41,7 @@ export const useWorkflowRun = () => {
const {
backupDraft,
setBackupDraft,
environmentVariables,
} = workflowStore.getState()
const { features } = featuresStore!.getState()
@@ -50,6 +51,7 @@ export const useWorkflowRun = () => {
edges,
viewport: getViewport(),
features,
environmentVariables,
})
doSyncWorkflowDraft()
}
@@ -59,6 +61,7 @@ export const useWorkflowRun = () => {
const {
backupDraft,
setBackupDraft,
setEnvironmentVariables,
} = workflowStore.getState()
if (backupDraft) {
@@ -67,12 +70,14 @@ export const useWorkflowRun = () => {
edges,
viewport,
features,
environmentVariables,
} = backupDraft
handleUpdateWorkflowCanvas({
nodes,
edges,
viewport,
})
setEnvironmentVariables(environmentVariables)
featuresStore!.setState({ features })
setBackupDraft(undefined)
}
@@ -522,6 +527,7 @@ export const useWorkflowRun = () => {
})
featuresStore?.setState({ features: publishedWorkflow.features })
workflowStore.getState().setPublishedAt(publishedWorkflow.created_at)
workflowStore.getState().setEnvironmentVariables(publishedWorkflow.environment_variables || [])
}
}, [featuresStore, handleUpdateWorkflowCanvas, workflowStore])

View File

@@ -39,8 +39,11 @@ export const useWorkflowStartRun = () => {
showDebugAndPreviewPanel,
setShowDebugAndPreviewPanel,
setShowInputsPanel,
setShowEnvPanel,
} = workflowStore.getState()
setShowEnvPanel(false)
if (showDebugAndPreviewPanel) {
handleCancelDebugAndPreviewPanel()
return
@@ -63,8 +66,11 @@ export const useWorkflowStartRun = () => {
showDebugAndPreviewPanel,
setShowDebugAndPreviewPanel,
setHistoryWorkflowData,
setShowEnvPanel,
} = workflowStore.getState()
setShowEnvPanel(false)
if (showDebugAndPreviewPanel)
handleCancelDebugAndPreviewPanel()
else

View File

@@ -0,0 +1,69 @@
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useStore } from '../store'
import { getVarType, toNodeAvailableVars } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import type {
Node,
NodeOutPutVar,
ValueSelector,
Var,
} from '@/app/components/workflow/types'
export const useWorkflowVariables = () => {
const { t } = useTranslation()
const environmentVariables = useStore(s => s.environmentVariables)
const getNodeAvailableVars = useCallback(({
parentNode,
beforeNodes,
isChatMode,
filterVar,
hideEnv,
}: {
parentNode?: Node | null
beforeNodes: Node[]
isChatMode: boolean
filterVar: (payload: Var, selector: ValueSelector) => boolean
hideEnv?: boolean
}): NodeOutPutVar[] => {
return toNodeAvailableVars({
parentNode,
t,
beforeNodes,
isChatMode,
environmentVariables: hideEnv ? [] : environmentVariables,
filterVar,
})
}, [environmentVariables, t])
const getCurrentVariableType = useCallback(({
parentNode,
valueSelector,
isIterationItem,
availableNodes,
isChatMode,
isConstant,
}: {
valueSelector: ValueSelector
parentNode?: Node | null
isIterationItem?: boolean
availableNodes: any[]
isChatMode: boolean
isConstant?: boolean
}) => {
return getVarType({
parentNode,
valueSelector,
isIterationItem,
availableNodes,
isChatMode,
isConstant,
environmentVariables,
})
}, [environmentVariables])
return {
getNodeAvailableVars,
getCurrentVariableType,
}
}

View File

@@ -471,8 +471,14 @@ export const useWorkflowInit = () => {
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) || [],
})
setSyncWorkflowDraftHash(res.hash)
setIsLoading(false)
}
@@ -491,6 +497,7 @@ export const useWorkflowInit = () => {
features: {
retriever_resource: { enabled: true },
},
environment_variables: [],
},
}).then((res) => {
workflowStore.getState().setDraftUpdatedAt(res.updated_at)