From 85edb8c73ef4b73d7b7e4222138fdbbdb1573630 Mon Sep 17 00:00:00 2001 From: JzoNg Date: Tue, 23 Jun 2026 11:24:45 +0800 Subject: [PATCH] feat(web): fix snippet input field vars --- .../use-nodes-available-var-list.spec.ts | 6 ++-- .../hooks/use-nodes-available-var-list.ts | 6 ++-- .../snippet-input-field-vars.spec.ts | 34 +++++++++++++++++++ .../__tests__/use-available-var-list.spec.ts | 4 +-- .../_base/hooks/snippet-input-field-vars.ts | 9 ++--- .../_base/hooks/use-available-var-list.ts | 4 +-- 6 files changed, 49 insertions(+), 14 deletions(-) create mode 100644 web/app/components/workflow/nodes/_base/hooks/__tests__/snippet-input-field-vars.spec.ts diff --git a/web/app/components/workflow/hooks/__tests__/use-nodes-available-var-list.spec.ts b/web/app/components/workflow/hooks/__tests__/use-nodes-available-var-list.spec.ts index 27edcbd1633..53c218d9b1e 100644 --- a/web/app/components/workflow/hooks/__tests__/use-nodes-available-var-list.spec.ts +++ b/web/app/components/workflow/hooks/__tests__/use-nodes-available-var-list.spec.ts @@ -1,6 +1,6 @@ import type { Node, NodeOutPutVar, Var } from '../../types' import { renderHook } from '@testing-library/react' -import { useSnippetDetailStore } from '@/app/components/snippets/store' +import { useSnippetDraftStore } from '@/app/components/snippets/draft-store' import { PipelineInputVarType } from '@/models/pipeline' import { FlowType } from '@/types/common' import { BlockEnum, VarType } from '../../types' @@ -83,7 +83,7 @@ describe('useNodesAvailableVarList', () => { vi.clearAllMocks() mockFlowType.value = undefined globalThis.history.pushState({}, '', '/') - useSnippetDetailStore.getState().reset() + useSnippetDraftStore.getState().reset() mockGetBeforeNodesInSameBranchIncludeParent.mockImplementation((nodeId: string) => [createNode({ id: `before-${nodeId}` })]) mockGetTreeLeafNodes.mockImplementation((nodeId: string) => [createNode({ id: `leaf-${nodeId}` })]) mockGetNodeAvailableVars.mockReturnValue(outputVars) @@ -130,7 +130,7 @@ describe('useNodesAvailableVarList', () => { it('adds snippet input fields as virtual start variables on snippet canvases', () => { globalThis.history.pushState({}, '', '/snippets/snippet-1/orchestrate') - useSnippetDetailStore.getState().setFields([{ + useSnippetDraftStore.getState().setInputFields([{ type: PipelineInputVarType.textInput, label: 'Topic', variable: 'topic', diff --git a/web/app/components/workflow/hooks/use-nodes-available-var-list.ts b/web/app/components/workflow/hooks/use-nodes-available-var-list.ts index 927096698d7..6b16c920bac 100644 --- a/web/app/components/workflow/hooks/use-nodes-available-var-list.ts +++ b/web/app/components/workflow/hooks/use-nodes-available-var-list.ts @@ -1,7 +1,7 @@ import type { Node, NodeOutPutVar, ValueSelector, Var } from '@/app/components/workflow/types' import { useCallback } from 'react' import { useTranslation } from 'react-i18next' -import { useSnippetDetailStore } from '@/app/components/snippets/store' +import { useSnippetDraftStore } from '@/app/components/snippets/draft-store' import { useIsChatMode, useWorkflow, @@ -51,7 +51,7 @@ const useNodesAvailableVarList = (nodes: Node[], { filterVar: () => true, }) => { const { t } = useTranslation() - const snippetInputFields = useSnippetDetailStore(s => s.fields) + const snippetInputFields = useSnippetDraftStore(s => s.inputFields) const { getTreeLeafNodes, getBeforeNodesInSameBranchIncludeParent } = useWorkflow() const { getNodeAvailableVars } = useWorkflowVariables() const isChatMode = useIsChatMode() @@ -97,7 +97,7 @@ const useNodesAvailableVarList = (nodes: Node[], { export const useGetNodesAvailableVarList = () => { const { t } = useTranslation() - const snippetInputFields = useSnippetDetailStore(s => s.fields) + const snippetInputFields = useSnippetDraftStore(s => s.inputFields) const { getTreeLeafNodes, getBeforeNodesInSameBranchIncludeParent } = useWorkflow() const { getNodeAvailableVars } = useWorkflowVariables() const isChatMode = useIsChatMode() diff --git a/web/app/components/workflow/nodes/_base/hooks/__tests__/snippet-input-field-vars.spec.ts b/web/app/components/workflow/nodes/_base/hooks/__tests__/snippet-input-field-vars.spec.ts new file mode 100644 index 00000000000..6ba689b1843 --- /dev/null +++ b/web/app/components/workflow/nodes/_base/hooks/__tests__/snippet-input-field-vars.spec.ts @@ -0,0 +1,34 @@ +import type { Node } from '@/app/components/workflow/types' +import { BlockEnum } from '@/app/components/workflow/types' +import { appendSnippetInputFieldVars } from '../snippet-input-field-vars' + +const createNode = (id = 'node-1'): Node => ({ + id, + type: 'custom', + position: { x: 0, y: 0 }, + data: { + type: BlockEnum.LLM, + title: 'Node', + desc: '', + }, +} as Node) + +describe('appendSnippetInputFieldVars', () => { + beforeEach(() => { + globalThis.history.pushState({}, '', '/') + }) + + it('should treat missing snippet input fields as empty on snippet canvases', () => { + globalThis.history.pushState({}, '', '/snippets/snippet-1/orchestrate') + const availableNodes = [createNode()] + + expect(appendSnippetInputFieldVars({ + availableNodes, + fields: undefined, + title: 'Snippet', + })).toEqual({ + availableNodes, + availableVars: [], + }) + }) +}) diff --git a/web/app/components/workflow/nodes/_base/hooks/__tests__/use-available-var-list.spec.ts b/web/app/components/workflow/nodes/_base/hooks/__tests__/use-available-var-list.spec.ts index cd88d29128b..58abbbcafe2 100644 --- a/web/app/components/workflow/nodes/_base/hooks/__tests__/use-available-var-list.spec.ts +++ b/web/app/components/workflow/nodes/_base/hooks/__tests__/use-available-var-list.spec.ts @@ -12,8 +12,8 @@ const mockFlowType = vi.hoisted(() => ({ value: undefined as FlowType | undefined, })) -vi.mock('@/app/components/snippets/store', () => ({ - useSnippetDetailStore: (selector: (state: { fields: unknown[] }) => unknown) => selector({ fields: [] }), +vi.mock('@/app/components/snippets/draft-store', () => ({ + useSnippetDraftStore: (selector: (state: { inputFields: unknown[] }) => unknown) => selector({ inputFields: [] }), })) vi.mock('@/app/components/workflow/hooks', () => ({ diff --git a/web/app/components/workflow/nodes/_base/hooks/snippet-input-field-vars.ts b/web/app/components/workflow/nodes/_base/hooks/snippet-input-field-vars.ts index de3f5d334b3..58b36e56db9 100644 --- a/web/app/components/workflow/nodes/_base/hooks/snippet-input-field-vars.ts +++ b/web/app/components/workflow/nodes/_base/hooks/snippet-input-field-vars.ts @@ -98,17 +98,18 @@ export const appendSnippetInputFieldVars = ({ title, }: { availableNodes: Node[] - fields: SnippetInputField[] + fields?: SnippetInputField[] title: string }) => { + const inputFields = fields ?? [] const shouldAppendSnippetInputFields = isSnippetCanvas() - && fields.length > 0 + && inputFields.length > 0 && !availableNodes.some(node => node.data.type === BlockEnum.Start) const snippetInputFieldNode = shouldAppendSnippetInputFields - ? buildSnippetInputFieldNode(fields, title) + ? buildSnippetInputFieldNode(inputFields, title) : undefined const snippetInputFieldVars = shouldAppendSnippetInputFields - ? buildSnippetInputFieldVars(fields, title) + ? buildSnippetInputFieldVars(inputFields, title) : undefined return { diff --git a/web/app/components/workflow/nodes/_base/hooks/use-available-var-list.ts b/web/app/components/workflow/nodes/_base/hooks/use-available-var-list.ts index 40b2b664ef8..02aaee0d6ae 100644 --- a/web/app/components/workflow/nodes/_base/hooks/use-available-var-list.ts +++ b/web/app/components/workflow/nodes/_base/hooks/use-available-var-list.ts @@ -1,6 +1,6 @@ import type { Node, NodeOutPutVar, ValueSelector, Var } from '@/app/components/workflow/types' import { useTranslation } from 'react-i18next' -import { useSnippetDetailStore } from '@/app/components/snippets/store' +import { useSnippetDraftStore } from '@/app/components/snippets/draft-store' import { useIsChatMode, useWorkflow, @@ -34,7 +34,7 @@ const useAvailableVarList = (nodeId: string, { filterVar: () => true, }) => { const { t } = useTranslation() - const snippetInputFields = useSnippetDetailStore(s => s.fields) + const snippetInputFields = useSnippetDraftStore(s => s.inputFields) const { getTreeLeafNodes, getNodeById, getBeforeNodesInSameBranchIncludeParent } = useWorkflow() const { getNodeAvailableVars } = useWorkflowVariables() const isChatMode = useIsChatMode()