{
options.map((option, index) => (
diff --git a/web/app/components/datasets/documents/index.tsx b/web/app/components/datasets/documents/index.tsx
index 854c984559..32980eea1e 100644
--- a/web/app/components/datasets/documents/index.tsx
+++ b/web/app/components/datasets/documents/index.tsx
@@ -264,8 +264,8 @@ const Documents: FC = ({ datasetId }) => {
target='_blank'
href={
locale === LanguagesSupported[1]
- ? 'https://docs.dify.ai/v/zh-hans/guides/knowledge-base/integrate-knowledge-within-application'
- : 'https://docs.dify.ai/guides/knowledge-base/integrate-knowledge-within-application'
+ ? 'https://docs.dify.ai/zh-hans/guides/knowledge-base/integrate-knowledge-within-application'
+ : 'https://docs.dify.ai/en/guides/knowledge-base/integrate-knowledge-within-application'
}
>
{t('datasetDocuments.list.learnMore')}
diff --git a/web/app/components/datasets/external-knowledge-base/create/InfoPanel.tsx b/web/app/components/datasets/external-knowledge-base/create/InfoPanel.tsx
index 33386940c4..5c3c1261b6 100644
--- a/web/app/components/datasets/external-knowledge-base/create/InfoPanel.tsx
+++ b/web/app/components/datasets/external-knowledge-base/create/InfoPanel.tsx
@@ -16,12 +16,12 @@ const InfoPanel = () => {
{t('dataset.connectDatasetIntro.content.front')}
-
+
{t('dataset.connectDatasetIntro.content.link')}
{t('dataset.connectDatasetIntro.content.end')}
-
+
{t('dataset.connectDatasetIntro.learnMore')}
diff --git a/web/app/components/datasets/external-knowledge-base/create/index.tsx b/web/app/components/datasets/external-knowledge-base/create/index.tsx
index 6cbfc05ca7..5fbddea06b 100644
--- a/web/app/components/datasets/external-knowledge-base/create/index.tsx
+++ b/web/app/components/datasets/external-knowledge-base/create/index.tsx
@@ -59,7 +59,7 @@ const ExternalKnowledgeBaseCreate: React.FC =
{t('dataset.connectHelper.helper1')}
{t('dataset.connectHelper.helper2')}
{t('dataset.connectHelper.helper3')}
-
+
{t('dataset.connectHelper.helper4')}
{t('dataset.connectHelper.helper5')}
diff --git a/web/app/components/develop/template/template_workflow.en.mdx b/web/app/components/develop/template/template_workflow.en.mdx
index 0f15c4406b..556b306a64 100644
--- a/web/app/components/develop/template/template_workflow.en.mdx
+++ b/web/app/components/develop/template/template_workflow.en.mdx
@@ -90,7 +90,7 @@ Workflow applications offers non-session support and is ideal for translation, a
Each streaming chunk starts with `data:`, separated by two newline characters `\n\n`, as shown below:
```streaming {{ title: 'Response' }}
- data: {"event": "message", "task_id": "900bbd43-dc0b-4383-a372-aa6e6c414227", "id": "663c5084-a254-4040-8ad3-51f2a3c1a77c", "answer": "Hi", "created_at": 1705398420}\n\n
+ data: {"event": "text_chunk", "workflow_run_id": "b85e5fc5-751b-454d-b14e-dc5f240b0a31", "task_id": "bd029338-b068-4d34-a331-fc85478922c2", "data": {"text": "\u4e3a\u4e86", "from_variable_selector": ["1745912968134", "text"]}}\n\n
```
The structure of the streaming chunks varies depending on the `event`:
@@ -116,6 +116,13 @@ Workflow applications offers non-session support and is ideal for translation, a
- `predecessor_node_id` (string) optional Prefix node ID, used for canvas display execution path
- `inputs` (object) Contents of all preceding node variables used in the node
- `created_at` (timestamp) timestamp of start, e.g., 1705395332
+ - `event: text_chunk` Text fragment
+ - `task_id` (string) Task ID, used for request tracking and the below Stop Generate API
+ - `workflow_run_id` (string) Unique ID of workflow execution
+ - `event` (string) fixed to `text_chunk`
+ - `data` (object) detail
+ - `text` (string) Text content
+ - `from_variable_selector` (array) Text source path, helping developers understand which node and variable generated the text
- `event: node_finished` node execution ends, success or failure in different states in the same event
- `task_id` (string) Task ID, used for request tracking and the below Stop Generate API
- `workflow_run_id` (string) Unique ID of workflow execution
diff --git a/web/app/components/develop/template/template_workflow.ja.mdx b/web/app/components/develop/template/template_workflow.ja.mdx
index 0239b40224..3f33be58b9 100644
--- a/web/app/components/develop/template/template_workflow.ja.mdx
+++ b/web/app/components/develop/template/template_workflow.ja.mdx
@@ -93,7 +93,7 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
各ストリーミングチャンクは`data:`で始まり、2つの改行文字`\n\n`で区切られます。以下のように表示されます:
```streaming {{ title: '応答' }}
- data: {"event": "message", "task_id": "900bbd43-dc0b-4383-a372-aa6e6c414227", "id": "663c5084-a254-4040-8ad3-51f2a3c1a77c", "answer": "Hi", "created_at": 1705398420}\n\n
+ data: {"event": "text_chunk", "workflow_run_id": "b85e5fc5-751b-454d-b14e-dc5f240b0a31", "task_id": "bd029338-b068-4d34-a331-fc85478922c2", "data": {"text": "\u4e3a\u4e86", "from_variable_selector": ["1745912968134", "text"]}}\n\n
```
ストリーミングチャンクの構造は`event`に応じて異なります:
@@ -119,6 +119,13 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
- `predecessor_node_id` (string) オプションのプレフィックスノードID、キャンバス表示実行パスに使用
- `inputs` (object) ノードで使用されるすべての前のノード変数の内容
- `created_at` (timestamp) 開始のタイムスタンプ、例:1705395332
+ - `event: text_chunk` テキストフラグメント
+ - `task_id` (string) タスクID、リクエスト追跡と以下のStop Generate APIに使用
+ - `workflow_run_id` (string) ワークフロー実行の一意のID
+ - `event` (string) `text_chunk`に固定
+ - `data` (object) 詳細
+ - `text` (string) テキスト内容
+ - `from_variable_selector` (array) テキスト生成元パス(開発者がどのノードのどの変数から生成されたかを理解するための情報)
- `event: node_finished` ノード実行終了、同じイベントで異なる状態で成功または失敗
- `task_id` (string) タスクID、リクエスト追跡と以下のStop Generate APIに使用
- `workflow_run_id` (string) ワークフロー実行の一意のID
diff --git a/web/app/components/develop/template/template_workflow.zh.mdx b/web/app/components/develop/template/template_workflow.zh.mdx
index 939df2703d..b032407ee9 100644
--- a/web/app/components/develop/template/template_workflow.zh.mdx
+++ b/web/app/components/develop/template/template_workflow.zh.mdx
@@ -87,7 +87,7 @@ Workflow 应用无会话支持,适合用于翻译/文章写作/总结 AI 等
每个流式块均为 data: 开头,块之间以 `\n\n` 即两个换行符分隔,如下所示:
```streaming {{ title: 'Response' }}
- data: {"event": "message", "task_id": "900bbd43-dc0b-4383-a372-aa6e6c414227", "id": "663c5084-a254-4040-8ad3-51f2a3c1a77c", "answer": "Hi", "created_at": 1705398420}\n\n
+ data: {"event": "text_chunk", "workflow_run_id": "b85e5fc5-751b-454d-b14e-dc5f240b0a31", "task_id": "bd029338-b068-4d34-a331-fc85478922c2", "data": {"text": "\u4e3a\u4e86", "from_variable_selector": ["1745912968134", "text"]}}\n\n
```
流式块中根据 `event` 不同,结构也不同,包含以下类型:
@@ -113,6 +113,13 @@ Workflow 应用无会话支持,适合用于翻译/文章写作/总结 AI 等
- `predecessor_node_id` (string) 前置节点 ID,用于画布展示执行路径
- `inputs` (object) 节点中所有使用到的前置节点变量内容
- `created_at` (timestamp) 开始时间
+ - `event: text_chunk` 文本片段
+ - `task_id` (string) 任务 ID,用于请求跟踪和下方的停止响应接口
+ - `workflow_run_id` (string) workflow 执行 ID
+ - `event` (string) 固定为 `text_chunk`
+ - `data` (object) 详细内容
+ - `text` (string) 文本内容
+ - `from_variable_selector` (array) 文本来源路径,帮助开发者了解文本是由哪个节点的哪个变量生成的
- `event: node_finished` node 执行结束,成功失败同一事件中不同状态
- `task_id` (string) 任务 ID,用于请求跟踪和下方的停止响应接口
- `workflow_run_id` (string) workflow 执行 ID
diff --git a/web/app/components/header/account-dropdown/workplace-selector/index.tsx b/web/app/components/header/account-dropdown/workplace-selector/index.tsx
index da3f8bae6d..98668c61d2 100644
--- a/web/app/components/header/account-dropdown/workplace-selector/index.tsx
+++ b/web/app/components/header/account-dropdown/workplace-selector/index.tsx
@@ -61,7 +61,8 @@ const WorkplaceSelector = () => {
diff --git a/web/app/components/share/text-generation/index.tsx b/web/app/components/share/text-generation/index.tsx
index 9dd86335b6..75a1937b7f 100644
--- a/web/app/components/share/text-generation/index.tsx
+++ b/web/app/components/share/text-generation/index.tsx
@@ -302,10 +302,17 @@ const TextGeneration: FC = ({
const varLen = promptConfig?.prompt_variables.length || 0
setIsCallBatchAPI(true)
const allTaskList: Task[] = payloadData.map((item, i) => {
- const inputs: Record = {}
+ const inputs: Record = {}
if (varLen > 0) {
item.slice(0, varLen).forEach((input, index) => {
- inputs[promptConfig?.prompt_variables[index].key as string] = input
+ const varSchema = promptConfig?.prompt_variables[index]
+ inputs[varSchema?.key as string] = input
+ if (!input) {
+ if (varSchema?.type === 'string' || varSchema?.type === 'paragraph')
+ inputs[varSchema?.key as string] = ''
+ else
+ inputs[varSchema?.key as string] = undefined
+ }
})
}
return {
diff --git a/web/app/components/share/text-generation/run-once/index.tsx b/web/app/components/share/text-generation/run-once/index.tsx
index 721dbb42c3..546b21d2b0 100644
--- a/web/app/components/share/text-generation/run-once/index.tsx
+++ b/web/app/components/share/text-generation/run-once/index.tsx
@@ -45,7 +45,7 @@ const RunOnce: FC = ({
const onClear = () => {
const newInputs: Record = {}
promptConfig.prompt_variables.forEach((item) => {
- if (item.type === 'text-input' || item.type === 'paragraph')
+ if (item.type === 'string' || item.type === 'paragraph')
newInputs[item.key] = ''
else
newInputs[item.key] = undefined
@@ -66,7 +66,7 @@ const RunOnce: FC = ({
useEffect(() => {
const newInputs: Record = {}
promptConfig.prompt_variables.forEach((item) => {
- if (item.type === 'text-input' || item.type === 'paragraph')
+ if (item.type === 'string' || item.type === 'paragraph')
newInputs[item.key] = ''
else
newInputs[item.key] = undefined
diff --git a/web/app/components/tools/provider/custom-create-card.tsx b/web/app/components/tools/provider/custom-create-card.tsx
index 87c30b9ddb..6dd268cb3a 100644
--- a/web/app/components/tools/provider/custom-create-card.tsx
+++ b/web/app/components/tools/provider/custom-create-card.tsx
@@ -28,7 +28,7 @@ const Contribute = ({ onRefreshData }: Props) => {
const linkUrl = useMemo(() => {
if (language.startsWith('zh_'))
return 'https://docs.dify.ai/zh-hans/guides/tools#ru-he-chuang-jian-zi-ding-yi-gong-ju'
- return 'https://docs.dify.ai/guides/tools#how-to-create-custom-tools'
+ return 'https://docs.dify.ai/en/guides/tools#how-to-create-custom-tools'
}, [language])
const [isShowEditCollectionToolModal, setIsShowEditCustomCollectionModal] = useState(false)
diff --git a/web/app/components/workflow-app/components/workflow-main.tsx b/web/app/components/workflow-app/components/workflow-main.tsx
index 4ff1f4c624..2f2295cb59 100644
--- a/web/app/components/workflow-app/components/workflow-main.tsx
+++ b/web/app/components/workflow-app/components/workflow-main.tsx
@@ -8,6 +8,7 @@ import type { WorkflowProps } from '@/app/components/workflow'
import WorkflowChildren from './workflow-children'
import {
useNodesSyncDraft,
+ useWorkflowRefreshDraft,
useWorkflowRun,
useWorkflowStartRun,
} from '../hooks'
@@ -32,6 +33,7 @@ const WorkflowMain = ({
doSyncWorkflowDraft,
syncWorkflowDraftWhenPageClose,
} = useNodesSyncDraft()
+ const { handleRefreshWorkflowDraft } = useWorkflowRefreshDraft()
const {
handleBackupDraft,
handleLoadBackupDraft,
@@ -49,6 +51,7 @@ const WorkflowMain = ({
return {
syncWorkflowDraftWhenPageClose,
doSyncWorkflowDraft,
+ handleRefreshWorkflowDraft,
handleBackupDraft,
handleLoadBackupDraft,
handleRestoreFromPublishedWorkflow,
@@ -61,6 +64,7 @@ const WorkflowMain = ({
}, [
syncWorkflowDraftWhenPageClose,
doSyncWorkflowDraft,
+ handleRefreshWorkflowDraft,
handleBackupDraft,
handleLoadBackupDraft,
handleRestoreFromPublishedWorkflow,
diff --git a/web/app/components/workflow-app/hooks/index.ts b/web/app/components/workflow-app/hooks/index.ts
index 1517eb9a16..6373a8591c 100644
--- a/web/app/components/workflow-app/hooks/index.ts
+++ b/web/app/components/workflow-app/hooks/index.ts
@@ -4,3 +4,4 @@ export * from './use-nodes-sync-draft'
export * from './use-workflow-run'
export * from './use-workflow-start-run'
export * from './use-is-chat-mode'
+export * from './use-workflow-refresh-draft'
diff --git a/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts b/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts
index 7c6eb6a5be..db21cfb05e 100644
--- a/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts
+++ b/web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts
@@ -6,20 +6,20 @@ import {
useWorkflowStore,
} from '@/app/components/workflow/store'
import { BlockEnum } from '@/app/components/workflow/types'
-import { useWorkflowUpdate } from '@/app/components/workflow/hooks'
import {
useNodesReadOnly,
} from '@/app/components/workflow/hooks/use-workflow'
import { syncWorkflowDraft } from '@/service/workflow'
import { useFeaturesStore } from '@/app/components/base/features/hooks'
import { API_PREFIX } from '@/config'
+import { useWorkflowRefreshDraft } from '.'
export const useNodesSyncDraft = () => {
const store = useStoreApi()
const workflowStore = useWorkflowStore()
const featuresStore = useFeaturesStore()
const { getNodesReadOnly } = useNodesReadOnly()
- const { handleRefreshWorkflowDraft } = useWorkflowUpdate()
+ const { handleRefreshWorkflowDraft } = useWorkflowRefreshDraft()
const params = useParams()
const getPostParams = useCallback(() => {
diff --git a/web/app/components/workflow-app/hooks/use-workflow-refresh-draft.ts b/web/app/components/workflow-app/hooks/use-workflow-refresh-draft.ts
new file mode 100644
index 0000000000..c944e10c4c
--- /dev/null
+++ b/web/app/components/workflow-app/hooks/use-workflow-refresh-draft.ts
@@ -0,0 +1,36 @@
+import { useCallback } from 'react'
+import { useWorkflowStore } from '@/app/components/workflow/store'
+import { fetchWorkflowDraft } from '@/service/workflow'
+import type { WorkflowDataUpdater } from '@/app/components/workflow/types'
+import { useWorkflowUpdate } from '@/app/components/workflow/hooks'
+
+export const useWorkflowRefreshDraft = () => {
+ const workflowStore = useWorkflowStore()
+ const { handleUpdateWorkflowCanvas } = useWorkflowUpdate()
+
+ const handleRefreshWorkflowDraft = useCallback(() => {
+ const {
+ appId,
+ setSyncWorkflowDraftHash,
+ setIsSyncingWorkflowDraft,
+ setEnvironmentVariables,
+ setEnvSecrets,
+ setConversationVariables,
+ } = workflowStore.getState()
+ setIsSyncingWorkflowDraft(true)
+ fetchWorkflowDraft(`/apps/${appId}/workflows/draft`).then((response) => {
+ handleUpdateWorkflowCanvas(response.graph as WorkflowDataUpdater)
+ 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))
+ setEnvironmentVariables(response.environment_variables?.map(env => env.value_type === 'secret' ? { ...env, value: '[__HIDDEN__]' } : env) || [])
+ setConversationVariables(response.conversation_variables || [])
+ }).finally(() => setIsSyncingWorkflowDraft(false))
+ }, [handleUpdateWorkflowCanvas, workflowStore])
+
+ return {
+ handleRefreshWorkflowDraft,
+ }
+}
diff --git a/web/app/components/workflow/hooks-store/store.ts b/web/app/components/workflow/hooks-store/store.ts
index 2e40cbfbc9..9f5e1a6650 100644
--- a/web/app/components/workflow/hooks-store/store.ts
+++ b/web/app/components/workflow/hooks-store/store.ts
@@ -18,6 +18,7 @@ type CommonHooksFnMap = {
}
) => Promise
syncWorkflowDraftWhenPageClose: () => void
+ handleRefreshWorkflowDraft: () => void
handleBackupDraft: () => void
handleLoadBackupDraft: () => void
handleRestoreFromPublishedWorkflow: (...args: any[]) => void
@@ -35,6 +36,7 @@ export type Shape = {
export const createHooksStore = ({
doSyncWorkflowDraft = async () => noop(),
syncWorkflowDraftWhenPageClose = noop,
+ handleRefreshWorkflowDraft = noop,
handleBackupDraft = noop,
handleLoadBackupDraft = noop,
handleRestoreFromPublishedWorkflow = noop,
@@ -48,6 +50,7 @@ export const createHooksStore = ({
refreshAll: props => set(state => ({ ...state, ...props })),
doSyncWorkflowDraft,
syncWorkflowDraftWhenPageClose,
+ handleRefreshWorkflowDraft,
handleBackupDraft,
handleLoadBackupDraft,
handleRestoreFromPublishedWorkflow,
diff --git a/web/app/components/workflow/hooks/index.ts b/web/app/components/workflow/hooks/index.ts
index 20a34c69e3..fda0f50aa6 100644
--- a/web/app/components/workflow/hooks/index.ts
+++ b/web/app/components/workflow/hooks/index.ts
@@ -16,3 +16,4 @@ export * from './use-shortcuts'
export * from './use-workflow-interactions'
export * from './use-workflow-mode'
export * from './use-format-time-from-now'
+export * from './use-workflow-refresh-draft'
diff --git a/web/app/components/workflow/hooks/use-workflow-interactions.ts b/web/app/components/workflow/hooks/use-workflow-interactions.ts
index 740868c594..636d3b94f9 100644
--- a/web/app/components/workflow/hooks/use-workflow-interactions.ts
+++ b/web/app/components/workflow/hooks/use-workflow-interactions.ts
@@ -313,7 +313,6 @@ export const useWorkflowZoom = () => {
export const useWorkflowUpdate = () => {
const reactflow = useReactFlow()
- const workflowStore = useWorkflowStore()
const { eventEmitter } = useEventEmitterContextContext()
const handleUpdateWorkflowCanvas = useCallback((payload: WorkflowDataUpdater) => {
@@ -333,32 +332,8 @@ export const useWorkflowUpdate = () => {
setViewport(viewport)
}, [eventEmitter, reactflow])
- const handleRefreshWorkflowDraft = useCallback(() => {
- const {
- appId,
- setSyncWorkflowDraftHash,
- setIsSyncingWorkflowDraft,
- setEnvironmentVariables,
- setEnvSecrets,
- setConversationVariables,
- } = workflowStore.getState()
- setIsSyncingWorkflowDraft(true)
- fetchWorkflowDraft(`/apps/${appId}/workflows/draft`).then((response) => {
- handleUpdateWorkflowCanvas(response.graph as WorkflowDataUpdater)
- 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))
- setEnvironmentVariables(response.environment_variables?.map(env => env.value_type === 'secret' ? { ...env, value: '[__HIDDEN__]' } : env) || [])
- // #TODO chatVar sync#
- setConversationVariables(response.conversation_variables || [])
- }).finally(() => setIsSyncingWorkflowDraft(false))
- }, [handleUpdateWorkflowCanvas, workflowStore])
-
return {
handleUpdateWorkflowCanvas,
- handleRefreshWorkflowDraft,
}
}
diff --git a/web/app/components/workflow/hooks/use-workflow-refresh-draft.ts b/web/app/components/workflow/hooks/use-workflow-refresh-draft.ts
new file mode 100644
index 0000000000..1948bd471d
--- /dev/null
+++ b/web/app/components/workflow/hooks/use-workflow-refresh-draft.ts
@@ -0,0 +1,9 @@
+import { useHooksStore } from '@/app/components/workflow/hooks-store'
+
+export const useWorkflowRefreshDraft = () => {
+ const handleRefreshWorkflowDraft = useHooksStore(s => s.handleRefreshWorkflowDraft)
+
+ return {
+ handleRefreshWorkflowDraft,
+ }
+}
diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx
index 3d7692ed7b..549117faf7 100644
--- a/web/app/components/workflow/index.tsx
+++ b/web/app/components/workflow/index.tsx
@@ -44,7 +44,7 @@ import {
useShortcuts,
useWorkflow,
useWorkflowReadOnly,
- useWorkflowUpdate,
+ useWorkflowRefreshDraft,
} from './hooks'
import CustomNode from './nodes'
import CustomNoteNode from './note-node'
@@ -160,7 +160,7 @@ export const Workflow: FC = memo(({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
- const { handleRefreshWorkflowDraft } = useWorkflowUpdate()
+ const { handleRefreshWorkflowDraft } = useWorkflowRefreshDraft()
const handleSyncWorkflowDraftWhenPageClose = useCallback(() => {
if (document.visibilityState === 'hidden')
syncWorkflowDraftWhenPageClose()
diff --git a/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx b/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx
index d67b7af1a4..1e9612b7c7 100644
--- a/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx
+++ b/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx
@@ -223,7 +223,7 @@ export const AgentStrategy = memo((props: AgentStrategyProps) => {
{t('workflow.nodes.agent.learnMore')}
diff --git a/web/app/components/workflow/nodes/_base/components/error-handle/default-value.tsx b/web/app/components/workflow/nodes/_base/components/error-handle/default-value.tsx
index fa2d50f2c2..51969f8510 100644
--- a/web/app/components/workflow/nodes/_base/components/error-handle/default-value.tsx
+++ b/web/app/components/workflow/nodes/_base/components/error-handle/default-value.tsx
@@ -34,7 +34,7 @@ const DefaultValue = ({
{t('workflow.nodes.common.errorHandle.defaultValue.desc')}
diff --git a/web/app/components/workflow/nodes/_base/components/variable/utils.ts b/web/app/components/workflow/nodes/_base/components/variable/utils.ts
index efbd663630..f804cf6902 100644
--- a/web/app/components/workflow/nodes/_base/components/variable/utils.ts
+++ b/web/app/components/workflow/nodes/_base/components/variable/utils.ts
@@ -134,18 +134,33 @@ const findExceptVarInObject = (obj: any, filterVar: (payload: Var, selector: Val
const { children } = obj
const isStructuredOutput = !!(children as StructuredOutput)?.schema?.properties
+ let childrenResult: Var[] | StructuredOutput | undefined
+
+ if (isStructuredOutput) {
+ childrenResult = findExceptVarInStructuredOutput(children, filterVar)
+ }
+ else if (Array.isArray(children)) {
+ childrenResult = children.filter((item: Var) => {
+ const { children: itemChildren } = item
+ const currSelector = [...value_selector, item.variable]
+
+ if (!itemChildren)
+ return filterVar(item, currSelector)
+
+ const filteredObj = findExceptVarInObject(item, filterVar, currSelector, false) // File doesn't contain file children
+ return filteredObj.children && (filteredObj.children as Var[])?.length > 0
+ })
+ }
+ else {
+ childrenResult = []
+ }
+
const res: Var = {
variable: obj.variable,
type: isFile ? VarType.file : VarType.object,
- children: isStructuredOutput ? findExceptVarInStructuredOutput(children, filterVar) : children.filter((item: Var) => {
- const { children } = item
- const currSelector = [...value_selector, item.variable]
- if (!children)
- return filterVar(item, currSelector)
- const obj = findExceptVarInObject(item, filterVar, currSelector, false) // File doesn't contains file children
- return obj.children && (obj.children as Var[])?.length > 0
- }),
+ children: childrenResult,
}
+
return res
}
@@ -562,8 +577,20 @@ export const toNodeOutputVars = (
chatVarList: conversationVariables,
},
}
+ // Sort nodes in reverse chronological order (most recent first)
+ const sortedNodes = [...nodes].sort((a, b) => {
+ if (a.data.type === BlockEnum.Start) return 1
+ if (b.data.type === BlockEnum.Start) return -1
+ if (a.data.type === 'env') return 1
+ if (b.data.type === 'env') return -1
+ if (a.data.type === 'conversation') return 1
+ if (b.data.type === 'conversation') return -1
+ // sort nodes by x position
+ return (b.position?.x || 0) - (a.position?.x || 0)
+ })
+
const res = [
- ...nodes.filter(node => SUPPORT_OUTPUT_VARS_NODE.includes(node?.data?.type)),
+ ...sortedNodes.filter(node => SUPPORT_OUTPUT_VARS_NODE.includes(node?.data?.type)),
...(environmentVariables.length > 0 ? [ENV_NODE] : []),
...((isChatMode && conversationVariables.length > 0) ? [CHAT_VAR_NODE] : []),
].map((node) => {
diff --git a/web/app/components/workflow/nodes/_base/hooks/use-node-help-link.ts b/web/app/components/workflow/nodes/_base/hooks/use-node-help-link.ts
index 3c68fbd1fd..daad6ffcc0 100644
--- a/web/app/components/workflow/nodes/_base/hooks/use-node-help-link.ts
+++ b/web/app/components/workflow/nodes/_base/hooks/use-node-help-link.ts
@@ -8,7 +8,7 @@ export const useNodeHelpLink = (nodeType: BlockEnum) => {
if (language === 'zh_Hans')
return 'https://docs.dify.ai/zh-hans/guides/workflow/node/'
- return 'https://docs.dify.ai/guides/workflow/node/'
+ return 'https://docs.dify.ai/en/guides/workflow/node/'
}, [language])
const linkMap = useMemo(() => {
if (language === 'zh_Hans') {
diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx
index d125e31dae..344d02c011 100644
--- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx
+++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-config.tsx
@@ -49,7 +49,7 @@ const DEFAULT_SCHEMA: SchemaRoot = {
const HELP_DOC_URL = {
zh_Hans: 'https://docs.dify.ai/zh-hans/guides/workflow/structured-outputs',
- en_US: 'https://docs.dify.ai/guides/workflow/structured-outputs',
+ en_US: 'https://docs.dify.ai/en/guides/workflow/structured-outputs',
ja_JP: 'https://docs.dify.ai/ja-jp/guides/workflow/structured-outputs',
}
diff --git a/web/app/signin/oneMoreStep.tsx b/web/app/signin/oneMoreStep.tsx
index a78a3ab3b1..7a326a13de 100644
--- a/web/app/signin/oneMoreStep.tsx
+++ b/web/app/signin/oneMoreStep.tsx
@@ -164,7 +164,7 @@ const OneMoreStep = () => {
{t('login.license.link')}