mirror of
https://github.com/langgenius/dify.git
synced 2026-04-15 18:06:36 +08:00
fix workflow variable rename propagation
This commit is contained in:
parent
0d3ada2bc9
commit
a309d78f95
@ -0,0 +1,153 @@
|
|||||||
|
import type { Node, PromptItem } from '@/app/components/workflow/types'
|
||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
import { BlockEnum, EditionType, PromptRole } from '@/app/components/workflow/types'
|
||||||
|
import { AppModeEnum } from '@/types/app'
|
||||||
|
import { getNodeUsedVars, updateNodeVars } from '../utils'
|
||||||
|
|
||||||
|
const createNode = (data: Node['data']): Node => ({
|
||||||
|
id: 'node-1',
|
||||||
|
type: 'custom',
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
|
||||||
|
const createPromptItem = (overrides: Partial<PromptItem> = {}): PromptItem => ({
|
||||||
|
role: PromptRole.user,
|
||||||
|
text: '',
|
||||||
|
...overrides,
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('variable utils', () => {
|
||||||
|
describe('getNodeUsedVars', () => {
|
||||||
|
it('should read variables from llm jinja prompt text', () => {
|
||||||
|
const node = createNode({
|
||||||
|
type: BlockEnum.LLM,
|
||||||
|
title: 'LLM',
|
||||||
|
desc: '',
|
||||||
|
model: {
|
||||||
|
provider: 'provider',
|
||||||
|
name: 'model',
|
||||||
|
mode: AppModeEnum.CHAT,
|
||||||
|
completion_params: {},
|
||||||
|
},
|
||||||
|
prompt_template: [
|
||||||
|
createPromptItem({
|
||||||
|
edition_type: EditionType.jinja2,
|
||||||
|
jinja2_text: 'Hello {{#env.API_KEY#}}',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(getNodeUsedVars(node)).toContainEqual(['env', 'API_KEY'])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should read variables from human input email body', () => {
|
||||||
|
const node = createNode({
|
||||||
|
type: BlockEnum.HumanInput,
|
||||||
|
title: 'Human Input',
|
||||||
|
desc: '',
|
||||||
|
form_content: '',
|
||||||
|
inputs: [],
|
||||||
|
user_actions: [],
|
||||||
|
timeout: 1,
|
||||||
|
timeout_unit: 'day',
|
||||||
|
delivery_methods: [
|
||||||
|
{
|
||||||
|
id: 'email',
|
||||||
|
type: 'email',
|
||||||
|
enabled: true,
|
||||||
|
config: {
|
||||||
|
recipients: { whole_workspace: true, items: [] },
|
||||||
|
subject: 'Subject {{#conversation.memory#}}',
|
||||||
|
body: 'Body {{#env.API_KEY#}}',
|
||||||
|
debug_mode: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(getNodeUsedVars(node)).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
['env', 'API_KEY'],
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('updateNodeVars', () => {
|
||||||
|
it('should replace answer prompt references', () => {
|
||||||
|
const node = createNode({
|
||||||
|
type: BlockEnum.Answer,
|
||||||
|
title: 'Answer',
|
||||||
|
desc: '',
|
||||||
|
answer: 'Answer {{#env.API_KEY#}}',
|
||||||
|
variables: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
const updatedNode = updateNodeVars(node, ['env', 'API_KEY'], ['env', 'RENAMED_KEY'])
|
||||||
|
|
||||||
|
expect(updatedNode.data.answer).toBe('Answer {{#env.RENAMED_KEY#}}')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should replace llm jinja prompt references', () => {
|
||||||
|
const node = createNode({
|
||||||
|
type: BlockEnum.LLM,
|
||||||
|
title: 'LLM',
|
||||||
|
desc: '',
|
||||||
|
model: {
|
||||||
|
provider: 'provider',
|
||||||
|
name: 'model',
|
||||||
|
mode: AppModeEnum.CHAT,
|
||||||
|
completion_params: {},
|
||||||
|
},
|
||||||
|
prompt_template: [
|
||||||
|
createPromptItem({
|
||||||
|
text: '{{#env.API_KEY#}}',
|
||||||
|
edition_type: EditionType.jinja2,
|
||||||
|
jinja2_text: 'Hello {{#env.API_KEY#}}',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const updatedNode = updateNodeVars(node, ['env', 'API_KEY'], ['env', 'RENAMED_KEY'])
|
||||||
|
|
||||||
|
expect((updatedNode.data.prompt_template as PromptItem[])[0]).toMatchObject({
|
||||||
|
text: '{{#env.RENAMED_KEY#}}',
|
||||||
|
jinja2_text: 'Hello {{#env.RENAMED_KEY#}}',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should replace human input email template references', () => {
|
||||||
|
const node = createNode({
|
||||||
|
type: BlockEnum.HumanInput,
|
||||||
|
title: 'Human Input',
|
||||||
|
desc: '',
|
||||||
|
form_content: '',
|
||||||
|
inputs: [],
|
||||||
|
user_actions: [],
|
||||||
|
timeout: 1,
|
||||||
|
timeout_unit: 'day',
|
||||||
|
delivery_methods: [
|
||||||
|
{
|
||||||
|
id: 'email',
|
||||||
|
type: 'email',
|
||||||
|
enabled: true,
|
||||||
|
config: {
|
||||||
|
recipients: { whole_workspace: true, items: [] },
|
||||||
|
subject: 'Subject {{#conversation.memory#}}',
|
||||||
|
body: 'Body {{#env.API_KEY#}}',
|
||||||
|
debug_mode: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const updatedNode = updateNodeVars(node, ['env', 'API_KEY'], ['env', 'RENAMED_KEY'])
|
||||||
|
|
||||||
|
expect(updatedNode.data.delivery_methods[0]?.config).toMatchObject({
|
||||||
|
subject: 'Subject {{#conversation.memory#}}',
|
||||||
|
body: 'Body {{#env.RENAMED_KEY#}}',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -53,6 +53,7 @@ import {
|
|||||||
} from '@/app/components/workflow/constants'
|
} from '@/app/components/workflow/constants'
|
||||||
import DataSourceNodeDefault from '@/app/components/workflow/nodes/data-source/default'
|
import DataSourceNodeDefault from '@/app/components/workflow/nodes/data-source/default'
|
||||||
import HumanInputNodeDefault from '@/app/components/workflow/nodes/human-input/default'
|
import HumanInputNodeDefault from '@/app/components/workflow/nodes/human-input/default'
|
||||||
|
import { DeliveryMethodType } from '@/app/components/workflow/nodes/human-input/types'
|
||||||
import ToolNodeDefault from '@/app/components/workflow/nodes/tool/default'
|
import ToolNodeDefault from '@/app/components/workflow/nodes/tool/default'
|
||||||
import PluginTriggerNodeDefault from '@/app/components/workflow/nodes/trigger-plugin/default'
|
import PluginTriggerNodeDefault from '@/app/components/workflow/nodes/trigger-plugin/default'
|
||||||
import {
|
import {
|
||||||
@ -1310,6 +1311,25 @@ const replaceOldVarInText = (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getPromptItemTexts = (prompt: PromptItem): string[] => {
|
||||||
|
const texts = [prompt.text]
|
||||||
|
if (prompt.jinja2_text)
|
||||||
|
texts.push(prompt.jinja2_text)
|
||||||
|
return texts.filter((text): text is string => !!text)
|
||||||
|
}
|
||||||
|
|
||||||
|
const replaceOldVarInPromptItem = (
|
||||||
|
prompt: PromptItem,
|
||||||
|
oldVar: ValueSelector,
|
||||||
|
newVar: ValueSelector,
|
||||||
|
): PromptItem => ({
|
||||||
|
...prompt,
|
||||||
|
text: replaceOldVarInText(prompt.text, oldVar, newVar),
|
||||||
|
...(prompt.jinja2_text !== undefined
|
||||||
|
? { jinja2_text: replaceOldVarInText(prompt.jinja2_text, oldVar, newVar) }
|
||||||
|
: {}),
|
||||||
|
})
|
||||||
|
|
||||||
export const getNodeUsedVars = (node: Node): ValueSelector[] => {
|
export const getNodeUsedVars = (node: Node): ValueSelector[] => {
|
||||||
const { data } = node
|
const { data } = node
|
||||||
const { type } = data
|
const { type } = data
|
||||||
@ -1331,12 +1351,12 @@ export const getNodeUsedVars = (node: Node): ValueSelector[] => {
|
|||||||
let prompts: string[] = []
|
let prompts: string[] = []
|
||||||
if (isChatModel) {
|
if (isChatModel) {
|
||||||
prompts
|
prompts
|
||||||
= (payload.prompt_template as PromptItem[])?.map(p => p.text) || []
|
= (payload.prompt_template as PromptItem[])?.flatMap(getPromptItemTexts) || []
|
||||||
if (payload.memory?.query_prompt_template)
|
if (payload.memory?.query_prompt_template)
|
||||||
prompts.push(payload.memory.query_prompt_template)
|
prompts.push(payload.memory.query_prompt_template)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
prompts = [(payload.prompt_template as PromptItem).text]
|
prompts = getPromptItemTexts(payload.prompt_template as PromptItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputVars: ValueSelector[] = matchNotSystemVars(prompts)
|
const inputVars: ValueSelector[] = matchNotSystemVars(prompts)
|
||||||
@ -1505,7 +1525,12 @@ export const getNodeUsedVars = (node: Node): ValueSelector[] => {
|
|||||||
case BlockEnum.HumanInput: {
|
case BlockEnum.HumanInput: {
|
||||||
const payload = data as HumanInputNodeType
|
const payload = data as HumanInputNodeType
|
||||||
const formContent = payload.form_content
|
const formContent = payload.form_content
|
||||||
res = matchNotSystemVars([formContent])
|
const mailTemplates = payload.delivery_methods.flatMap((method) => {
|
||||||
|
if (method.type !== DeliveryMethodType.Email || !method.config)
|
||||||
|
return []
|
||||||
|
return [method.config.body]
|
||||||
|
})
|
||||||
|
res = matchNotSystemVars([formContent, ...mailTemplates])
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1651,6 +1676,11 @@ export const updateNodeVars = (
|
|||||||
}
|
}
|
||||||
case BlockEnum.Answer: {
|
case BlockEnum.Answer: {
|
||||||
const payload = data as AnswerNodeType
|
const payload = data as AnswerNodeType
|
||||||
|
payload.answer = replaceOldVarInText(
|
||||||
|
payload.answer,
|
||||||
|
oldVarSelector,
|
||||||
|
newVarSelector,
|
||||||
|
)
|
||||||
if (payload.variables) {
|
if (payload.variables) {
|
||||||
payload.variables = payload.variables.map((v) => {
|
payload.variables = payload.variables.map((v) => {
|
||||||
if (v.value_selector.join('.') === oldVarSelector.join('.'))
|
if (v.value_selector.join('.') === oldVarSelector.join('.'))
|
||||||
@ -1666,16 +1696,7 @@ export const updateNodeVars = (
|
|||||||
if (isChatModel) {
|
if (isChatModel) {
|
||||||
payload.prompt_template = (
|
payload.prompt_template = (
|
||||||
payload.prompt_template as PromptItem[]
|
payload.prompt_template as PromptItem[]
|
||||||
).map((prompt) => {
|
).map(prompt => replaceOldVarInPromptItem(prompt, oldVarSelector, newVarSelector))
|
||||||
return {
|
|
||||||
...prompt,
|
|
||||||
text: replaceOldVarInText(
|
|
||||||
prompt.text,
|
|
||||||
oldVarSelector,
|
|
||||||
newVarSelector,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (payload.memory?.query_prompt_template) {
|
if (payload.memory?.query_prompt_template) {
|
||||||
payload.memory.query_prompt_template = replaceOldVarInText(
|
payload.memory.query_prompt_template = replaceOldVarInText(
|
||||||
payload.memory.query_prompt_template,
|
payload.memory.query_prompt_template,
|
||||||
@ -1685,14 +1706,11 @@ export const updateNodeVars = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
payload.prompt_template = {
|
payload.prompt_template = replaceOldVarInPromptItem(
|
||||||
...payload.prompt_template,
|
payload.prompt_template as PromptItem,
|
||||||
text: replaceOldVarInText(
|
oldVarSelector,
|
||||||
(payload.prompt_template as PromptItem).text,
|
newVarSelector,
|
||||||
oldVarSelector,
|
)
|
||||||
newVarSelector,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
payload.context?.variable_selector?.join('.')
|
payload.context?.variable_selector?.join('.')
|
||||||
@ -1780,6 +1798,10 @@ export const updateNodeVars = (
|
|||||||
oldVarSelector,
|
oldVarSelector,
|
||||||
newVarSelector,
|
newVarSelector,
|
||||||
)
|
)
|
||||||
|
payload.classes = payload.classes.map(topic => ({
|
||||||
|
...topic,
|
||||||
|
name: replaceOldVarInText(topic.name, oldVarSelector, newVarSelector),
|
||||||
|
}))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case BlockEnum.HttpRequest: {
|
case BlockEnum.HttpRequest: {
|
||||||
@ -1889,6 +1911,46 @@ export const updateNodeVars = (
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case BlockEnum.Agent: {
|
||||||
|
const payload = data as AgentNodeType
|
||||||
|
if (payload.agent_parameters) {
|
||||||
|
Object.keys(payload.agent_parameters).forEach((key) => {
|
||||||
|
const value = payload.agent_parameters![key]
|
||||||
|
const { type } = value
|
||||||
|
|
||||||
|
if (
|
||||||
|
type === ToolVarType.variable
|
||||||
|
&& Array.isArray(value.value)
|
||||||
|
&& value.value.join('.') === oldVarSelector.join('.')
|
||||||
|
) {
|
||||||
|
payload.agent_parameters![key] = {
|
||||||
|
...value,
|
||||||
|
value: newVarSelector,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === ToolVarType.mixed && typeof value.value === 'string') {
|
||||||
|
payload.agent_parameters![key] = {
|
||||||
|
...value,
|
||||||
|
value: replaceOldVarInText(
|
||||||
|
value.value,
|
||||||
|
oldVarSelector,
|
||||||
|
newVarSelector,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload.memory?.query_prompt_template) {
|
||||||
|
payload.memory.query_prompt_template = replaceOldVarInText(
|
||||||
|
payload.memory.query_prompt_template,
|
||||||
|
oldVarSelector,
|
||||||
|
newVarSelector,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
case BlockEnum.VariableAssigner: {
|
case BlockEnum.VariableAssigner: {
|
||||||
const payload = data as VariableAssignerNodeType
|
const payload = data as VariableAssignerNodeType
|
||||||
if (payload.variables) {
|
if (payload.variables) {
|
||||||
@ -1954,6 +2016,22 @@ export const updateNodeVars = (
|
|||||||
oldVarSelector,
|
oldVarSelector,
|
||||||
newVarSelector,
|
newVarSelector,
|
||||||
)
|
)
|
||||||
|
payload.delivery_methods = payload.delivery_methods.map((method) => {
|
||||||
|
if (method.type !== DeliveryMethodType.Email || !method.config)
|
||||||
|
return method
|
||||||
|
|
||||||
|
return {
|
||||||
|
...method,
|
||||||
|
config: {
|
||||||
|
...method.config,
|
||||||
|
body: replaceOldVarInText(
|
||||||
|
method.config.body,
|
||||||
|
oldVarSelector,
|
||||||
|
newVarSelector,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ type MockWorkflowStoreState = {
|
|||||||
appId: string
|
appId: string
|
||||||
conversationVariables: ConversationVariable[]
|
conversationVariables: ConversationVariable[]
|
||||||
setConversationVariables: (value: ConversationVariable[]) => void
|
setConversationVariables: (value: ConversationVariable[]) => void
|
||||||
|
setControlPromptEditorRerenderKey: (value: number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
type MockFlowStore = {
|
type MockFlowStore = {
|
||||||
@ -18,6 +19,7 @@ type MockFlowStore = {
|
|||||||
|
|
||||||
const mockSetShowChatVariablePanel = vi.fn()
|
const mockSetShowChatVariablePanel = vi.fn()
|
||||||
const mockSetConversationVariables = vi.fn()
|
const mockSetConversationVariables = vi.fn()
|
||||||
|
const mockSetControlPromptEditorRerenderKey = vi.fn()
|
||||||
const mockInvalidateConversationVarValues = vi.fn()
|
const mockInvalidateConversationVarValues = vi.fn()
|
||||||
const mockUpdateConversationVariables = vi.fn().mockResolvedValue(undefined)
|
const mockUpdateConversationVariables = vi.fn().mockResolvedValue(undefined)
|
||||||
const mockFindUsedVarNodes = vi.fn<(selector: string[], nodes: Node[]) => Node[]>()
|
const mockFindUsedVarNodes = vi.fn<(selector: string[], nodes: Node[]) => Node[]>()
|
||||||
@ -64,6 +66,7 @@ vi.mock('@/app/components/workflow/store', () => ({
|
|||||||
appId: 'app-1',
|
appId: 'app-1',
|
||||||
conversationVariables: mockConversationVariables,
|
conversationVariables: mockConversationVariables,
|
||||||
setConversationVariables: mockSetConversationVariables,
|
setConversationVariables: mockSetConversationVariables,
|
||||||
|
setControlPromptEditorRerenderKey: mockSetControlPromptEditorRerenderKey,
|
||||||
}),
|
}),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@ -239,6 +242,7 @@ describe('ChatVariablePanel', () => {
|
|||||||
['conversation', 'conversation_var_next'],
|
['conversation', 'conversation_var_next'],
|
||||||
)
|
)
|
||||||
expect(mockSetNodes).toHaveBeenCalledWith([updatedNode, createNode('node-2')])
|
expect(mockSetNodes).toHaveBeenCalledWith([updatedNode, createNode('node-2')])
|
||||||
|
expect(mockSetControlPromptEditorRerenderKey).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should require confirmation before deleting variables referenced by workflow nodes', async () => {
|
it('should require confirmation before deleting variables referenced by workflow nodes', async () => {
|
||||||
|
|||||||
@ -29,6 +29,7 @@ const ChatVariablePanel = () => {
|
|||||||
const setShowChatVariablePanel = useStore(s => s.setShowChatVariablePanel)
|
const setShowChatVariablePanel = useStore(s => s.setShowChatVariablePanel)
|
||||||
const varList = useStore(s => s.conversationVariables) as ConversationVariable[]
|
const varList = useStore(s => s.conversationVariables) as ConversationVariable[]
|
||||||
const updateChatVarList = useStore(s => s.setConversationVariables)
|
const updateChatVarList = useStore(s => s.setConversationVariables)
|
||||||
|
const setControlPromptEditorRerenderKey = useStore(s => s.setControlPromptEditorRerenderKey)
|
||||||
const appId = useStore(s => s.appId) as string
|
const appId = useStore(s => s.appId) as string
|
||||||
const {
|
const {
|
||||||
invalidateConversationVarValues,
|
invalidateConversationVarValues,
|
||||||
@ -156,6 +157,7 @@ const ChatVariablePanel = () => {
|
|||||||
return node
|
return node
|
||||||
})
|
})
|
||||||
setNodes(newNodes)
|
setNodes(newNodes)
|
||||||
|
setControlPromptEditorRerenderKey(Date.now())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use new dedicated conversation variables API
|
// Use new dedicated conversation variables API
|
||||||
@ -179,7 +181,7 @@ const ChatVariablePanel = () => {
|
|||||||
// Revert local state on error
|
// Revert local state on error
|
||||||
updateChatVarList(varList)
|
updateChatVarList(varList)
|
||||||
}
|
}
|
||||||
}, [currentVar, getEffectedNodes, collaborativeWorkflow, updateChatVarList, varList, appId, invalidateConversationVarValues])
|
}, [currentVar, getEffectedNodes, collaborativeWorkflow, updateChatVarList, varList, appId, invalidateConversationVarValues, setControlPromptEditorRerenderKey])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -333,6 +333,7 @@ describe('EnvPanel container', () => {
|
|||||||
}),
|
}),
|
||||||
expect.objectContaining({ id: 'node-2' }),
|
expect.objectContaining({ id: 'node-2' }),
|
||||||
])
|
])
|
||||||
|
expect(store.getState().controlPromptEditorRerenderKey).toBeGreaterThan(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should convert edited plain variables into secrets and store the masked secret value', async () => {
|
it('should convert edited plain variables into secrets and store the masked secret value', async () => {
|
||||||
|
|||||||
@ -41,6 +41,7 @@ const useEnvPanelActions = ({
|
|||||||
envSecrets,
|
envSecrets,
|
||||||
updateEnvList,
|
updateEnvList,
|
||||||
setEnvSecrets,
|
setEnvSecrets,
|
||||||
|
setControlPromptEditorRerenderKey,
|
||||||
doSyncWorkflowDraft,
|
doSyncWorkflowDraft,
|
||||||
}: {
|
}: {
|
||||||
collaborativeWorkflow: ReturnType<typeof useCollaborativeWorkflow>
|
collaborativeWorkflow: ReturnType<typeof useCollaborativeWorkflow>
|
||||||
@ -48,6 +49,7 @@ const useEnvPanelActions = ({
|
|||||||
envSecrets: Record<string, string>
|
envSecrets: Record<string, string>
|
||||||
updateEnvList: (envList: EnvironmentVariable[]) => void
|
updateEnvList: (envList: EnvironmentVariable[]) => void
|
||||||
setEnvSecrets: (envSecrets: Record<string, string>) => void
|
setEnvSecrets: (envSecrets: Record<string, string>) => void
|
||||||
|
setControlPromptEditorRerenderKey: (controlPromptEditorRerenderKey: number) => void
|
||||||
doSyncWorkflowDraft: () => Promise<void>
|
doSyncWorkflowDraft: () => Promise<void>
|
||||||
}) => {
|
}) => {
|
||||||
const emitVarsAndFeaturesUpdate = useCallback(async () => {
|
const emitVarsAndFeaturesUpdate = useCallback(async () => {
|
||||||
@ -99,7 +101,8 @@ const useEnvPanelActions = ({
|
|||||||
return node
|
return node
|
||||||
})
|
})
|
||||||
setNodes(nextNodes)
|
setNodes(nextNodes)
|
||||||
}, [collaborativeWorkflow, getAffectedNodes])
|
setControlPromptEditorRerenderKey(Date.now())
|
||||||
|
}, [collaborativeWorkflow, getAffectedNodes, setControlPromptEditorRerenderKey])
|
||||||
|
|
||||||
const syncEnvList = useCallback(async (
|
const syncEnvList = useCallback(async (
|
||||||
nextEnvList: EnvironmentVariable[],
|
nextEnvList: EnvironmentVariable[],
|
||||||
@ -152,6 +155,7 @@ const EnvPanel = () => {
|
|||||||
const envSecrets = useStore(s => s.envSecrets)
|
const envSecrets = useStore(s => s.envSecrets)
|
||||||
const updateEnvList = useStore(s => s.setEnvironmentVariables)
|
const updateEnvList = useStore(s => s.setEnvironmentVariables)
|
||||||
const setEnvSecrets = useStore(s => s.setEnvSecrets)
|
const setEnvSecrets = useStore(s => s.setEnvSecrets)
|
||||||
|
const setControlPromptEditorRerenderKey = useStore(s => s.setControlPromptEditorRerenderKey)
|
||||||
const appId = useStore(s => s.appId) as string
|
const appId = useStore(s => s.appId) as string
|
||||||
const { doSyncWorkflowDraft } = useNodesSyncDraft()
|
const { doSyncWorkflowDraft } = useNodesSyncDraft()
|
||||||
const {
|
const {
|
||||||
@ -166,6 +170,7 @@ const EnvPanel = () => {
|
|||||||
envSecrets,
|
envSecrets,
|
||||||
updateEnvList,
|
updateEnvList,
|
||||||
setEnvSecrets,
|
setEnvSecrets,
|
||||||
|
setControlPromptEditorRerenderKey,
|
||||||
doSyncWorkflowDraft,
|
doSyncWorkflowDraft,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user