Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
85ea1174
authored
Sep 04, 2025
by
Archer
Committed by
GitHub
Sep 04, 2025
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix workflow (#5592)
* fix: fileselector default * fix: workflow run process
parent
9be1e591
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
229 additions
and
191 deletions
+229
-191
document/content/docs/upgrading/4-12/4123.mdx
+2
-0
document/data/doc-last-modified.json
+1
-1
packages/global/core/app/constants.ts
+1
-1
packages/global/core/workflow/template/system/interactive/type.d.ts
+1
-0
packages/service/core/workflow/dispatch/index.ts
+116
-47
packages/service/core/workflow/dispatch/type.d.ts
+15
-5
projects/app/src/components/core/app/FileSelect.tsx
+1
-1
projects/app/src/global/core/workflow/api.d.ts
+3
-6
projects/app/src/pageComponents/app/detail/SimpleApp/EditForm.tsx
+1
-2
projects/app/src/pageComponents/app/detail/SimpleApp/index.tsx
+8
-1
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderDebug/NodeDebugResponse.tsx
+6
-8
projects/app/src/pageComponents/app/detail/WorkflowComponents/context/index.tsx
+45
-89
projects/app/src/pages/api/core/workflow/debug.ts
+29
-30
No files found.
document/content/docs/upgrading/4-12/4123.mdx
View file @
85ea1174
...
@@ -14,5 +14,7 @@ description: 'FastGPT V4.12.3 更新说明'
...
@@ -14,5 +14,7 @@ description: 'FastGPT V4.12.3 更新说明'
## 🐛 修复
## 🐛 修复
1. 单团队模式下,如果用户离开,则无法重新进入团队。
1. 单团队模式下,如果用户离开,则无法重新进入团队。
2. 工作流文件上传默认打开,但输入侧未添加文件输出。
3. 连续用户选择,分支无法正常运行。
## 🔨 工具更新
## 🔨 工具更新
document/data/doc-last-modified.json
View file @
85ea1174
...
@@ -105,7 +105,7 @@
...
@@ -105,7 +105,7 @@
"document/content/docs/upgrading/4-12/4120.mdx"
:
"2025-08-12T22:45:19+08:00"
,
"document/content/docs/upgrading/4-12/4120.mdx"
:
"2025-08-12T22:45:19+08:00"
,
"document/content/docs/upgrading/4-12/4121.mdx"
:
"2025-08-15T22:53:06+08:00"
,
"document/content/docs/upgrading/4-12/4121.mdx"
:
"2025-08-15T22:53:06+08:00"
,
"document/content/docs/upgrading/4-12/4122.mdx"
:
"2025-08-27T00:31:33+08:00"
,
"document/content/docs/upgrading/4-12/4122.mdx"
:
"2025-08-27T00:31:33+08:00"
,
"document/content/docs/upgrading/4-12/4123.mdx"
:
"2025-0
8-29T01:24:19
+08:00"
,
"document/content/docs/upgrading/4-12/4123.mdx"
:
"2025-0
9-04T13:48:03
+08:00"
,
"document/content/docs/upgrading/4-8/40.mdx"
:
"2025-08-02T19:38:37+08:00"
,
"document/content/docs/upgrading/4-8/40.mdx"
:
"2025-08-02T19:38:37+08:00"
,
"document/content/docs/upgrading/4-8/41.mdx"
:
"2025-08-02T19:38:37+08:00"
,
"document/content/docs/upgrading/4-8/41.mdx"
:
"2025-08-02T19:38:37+08:00"
,
"document/content/docs/upgrading/4-8/42.mdx"
:
"2025-08-02T19:38:37+08:00"
,
"document/content/docs/upgrading/4-8/42.mdx"
:
"2025-08-02T19:38:37+08:00"
,
...
...
packages/global/core/app/constants.ts
View file @
85ea1174
...
@@ -45,7 +45,7 @@ export const defaultChatInputGuideConfig = {
...
@@ -45,7 +45,7 @@ export const defaultChatInputGuideConfig = {
};
};
export
const
defaultAppSelectFileConfig
:
AppFileSelectConfigType
=
{
export
const
defaultAppSelectFileConfig
:
AppFileSelectConfigType
=
{
canSelectFile
:
tru
e
,
canSelectFile
:
fals
e
,
canSelectImg
:
false
,
canSelectImg
:
false
,
maxFiles
:
10
maxFiles
:
10
};
};
...
...
packages/global/core/workflow/template/system/interactive/type.d.ts
View file @
85ea1174
...
@@ -8,6 +8,7 @@ type InteractiveBasicType = {
...
@@ -8,6 +8,7 @@ type InteractiveBasicType = {
entryNodeIds
:
string
[];
entryNodeIds
:
string
[];
memoryEdges
:
RuntimeEdgeItemType
[];
memoryEdges
:
RuntimeEdgeItemType
[];
nodeOutputs
:
NodeOutputItemType
[];
nodeOutputs
:
NodeOutputItemType
[];
skipNodeQueue
?:
{
id
:
string
;
skippedNodeIdList
:
string
[]
}[];
// 需要记录目前在 queue 里的节点
toolParams
?:
{
toolParams
?:
{
entryNodeIds
:
string
[];
// 记录工具中,交互节点的 Id,而不是起始工作流的入口
entryNodeIds
:
string
[];
// 记录工具中,交互节点的 Id,而不是起始工作流的入口
memoryMessages
:
ChatCompletionMessageParam
[];
// 这轮工具中,产生的新的 messages
memoryMessages
:
ChatCompletionMessageParam
[];
// 这轮工具中,产生的新的 messages
...
...
packages/service/core/workflow/dispatch/index.ts
View file @
85ea1174
...
@@ -42,7 +42,7 @@ import type { RuntimeEdgeItemType } from '@fastgpt/global/core/workflow/type/edg
...
@@ -42,7 +42,7 @@ import type { RuntimeEdgeItemType } from '@fastgpt/global/core/workflow/type/edg
import
type
{
ChatNodeUsageType
}
from
'@fastgpt/global/support/wallet/bill/type'
;
import
type
{
ChatNodeUsageType
}
from
'@fastgpt/global/support/wallet/bill/type'
;
import
{
addLog
}
from
'../../../common/system/log'
;
import
{
addLog
}
from
'../../../common/system/log'
;
import
{
surrenderProcess
}
from
'../../../common/system/tools'
;
import
{
surrenderProcess
}
from
'../../../common/system/tools'
;
import
type
{
DispatchFlowResponse
}
from
'./type'
;
import
type
{
DispatchFlowResponse
,
WorkflowDebugResponse
}
from
'./type'
;
import
{
removeSystemVariable
,
rewriteRuntimeWorkFlow
}
from
'./utils'
;
import
{
removeSystemVariable
,
rewriteRuntimeWorkFlow
}
from
'./utils'
;
import
{
getHandleId
}
from
'@fastgpt/global/core/workflow/utils'
;
import
{
getHandleId
}
from
'@fastgpt/global/core/workflow/utils'
;
import
{
callbackMap
}
from
'./constants'
;
import
{
callbackMap
}
from
'./constants'
;
...
@@ -50,6 +50,7 @@ import { callbackMap } from './constants';
...
@@ -50,6 +50,7 @@ import { callbackMap } from './constants';
type
Props
=
Omit
<
ChatDispatchProps
,
'workflowDispatchDeep'
>
&
{
type
Props
=
Omit
<
ChatDispatchProps
,
'workflowDispatchDeep'
>
&
{
runtimeNodes
:
RuntimeNodeItemType
[];
runtimeNodes
:
RuntimeNodeItemType
[];
runtimeEdges
:
RuntimeEdgeItemType
[];
runtimeEdges
:
RuntimeEdgeItemType
[];
defaultSkipNodeQueue
?:
WorkflowDebugResponse
[
'skipNodeQueue'
];
};
};
type
NodeResponseType
=
DispatchNodeResultType
<
{
type
NodeResponseType
=
DispatchNodeResultType
<
{
[
key
:
string
]:
any
;
[
key
:
string
]:
any
;
...
@@ -100,6 +101,7 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
...
@@ -100,6 +101,7 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
// Init some props
// Init some props
return
runWorkflow
({
return
runWorkflow
({
...
data
,
...
data
,
defaultSkipNodeQueue
:
data
.
lastInteractive
?.
skipNodeQueue
||
data
.
defaultSkipNodeQueue
,
variables
:
defaultVariables
,
variables
:
defaultVariables
,
workflowDispatchDeep
:
0
workflowDispatchDeep
:
0
}).
finally
(()
=>
{
}).
finally
(()
=>
{
...
@@ -112,12 +114,14 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
...
@@ -112,12 +114,14 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
type
RunWorkflowProps
=
ChatDispatchProps
&
{
type
RunWorkflowProps
=
ChatDispatchProps
&
{
runtimeNodes
:
RuntimeNodeItemType
[];
runtimeNodes
:
RuntimeNodeItemType
[];
runtimeEdges
:
RuntimeEdgeItemType
[];
runtimeEdges
:
RuntimeEdgeItemType
[];
defaultSkipNodeQueue
?:
WorkflowDebugResponse
[
'skipNodeQueue'
];
};
};
export
const
runWorkflow
=
async
(
data
:
RunWorkflowProps
):
Promise
<
DispatchFlowResponse
>
=>
{
export
const
runWorkflow
=
async
(
data
:
RunWorkflowProps
):
Promise
<
DispatchFlowResponse
>
=>
{
let
{
let
{
res
,
res
,
runtimeNodes
=
[],
runtimeNodes
=
[],
runtimeEdges
=
[],
runtimeEdges
=
[],
defaultSkipNodeQueue
,
histories
=
[],
histories
=
[],
variables
=
{},
variables
=
{},
externalProvider
,
externalProvider
,
...
@@ -135,9 +139,10 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -135,9 +139,10 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
flowResponses
:
[],
flowResponses
:
[],
flowUsages
:
[],
flowUsages
:
[],
debugResponse
:
{
debugResponse
:
{
finishedNodes
:
[],
memoryEdges
:
[],
finishedEdges
:
[],
entryNodeIds
:
[],
nextStepRunNodes
:
[]
nodeResponses
:
{},
skipNodeQueue
:
[]
},
},
[
DispatchNodeResponseKeyEnum
.
runTimes
]:
1
,
[
DispatchNodeResponseKeyEnum
.
runTimes
]:
1
,
[
DispatchNodeResponseKeyEnum
.
assistantResponses
]:
[],
[
DispatchNodeResponseKeyEnum
.
assistantResponses
]:
[],
...
@@ -151,6 +156,8 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -151,6 +156,8 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
await
rewriteRuntimeWorkFlow
({
nodes
:
runtimeNodes
,
edges
:
runtimeEdges
,
lang
:
data
.
lang
});
await
rewriteRuntimeWorkFlow
({
nodes
:
runtimeNodes
,
edges
:
runtimeEdges
,
lang
:
data
.
lang
});
const
isDebugMode
=
data
.
mode
===
'debug'
;
/*
/*
工作流队列控制
工作流队列控制
特点:
特点:
...
@@ -176,7 +183,6 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -176,7 +183,6 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
chatAssistantResponse
:
AIChatItemValueItemType
[]
=
[];
// The value will be returned to the user
chatAssistantResponse
:
AIChatItemValueItemType
[]
=
[];
// The value will be returned to the user
chatNodeUsages
:
ChatNodeUsageType
[]
=
[];
chatNodeUsages
:
ChatNodeUsageType
[]
=
[];
toolRunResponse
:
ToolRunResponseItemType
;
// Run with tool mode. Result will response to tool node.
toolRunResponse
:
ToolRunResponseItemType
;
// Run with tool mode. Result will response to tool node.
debugNextStepRunNodes
:
RuntimeNodeItemType
[]
=
[];
// 记录 Debug 模式下,下一个阶段需要执行的节点。
// 记录交互节点,交互节点需要在工作流完全结束后再进行计算
// 记录交互节点,交互节点需要在工作流完全结束后再进行计算
nodeInteractiveResponse
:
nodeInteractiveResponse
:
|
{
|
{
...
@@ -186,22 +192,38 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -186,22 +192,38 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
|
undefined
;
|
undefined
;
system_memories
:
Record
<
string
,
any
>
=
{};
// Workflow node memories
system_memories
:
Record
<
string
,
any
>
=
{};
// Workflow node memories
// Debug
debugNextStepRunNodes
:
RuntimeNodeItemType
[]
=
[];
// 记录 Debug 模式下,下一个阶段需要执行的节点。
debugNodeResponses
:
WorkflowDebugResponse
[
'nodeResponses'
]
=
{};
// Queue variables
// Queue variables
private
activeRunQueue
=
new
Set
<
string
>
();
private
activeRunQueue
=
new
Set
<
string
>
();
private
skipNodeQueue
:
{
node
:
RuntimeNodeItemType
;
skippedNodeIdList
:
Set
<
string
>
}[]
=
[];
private
skipNodeQueue
=
new
Map
<
string
,
{
node
:
RuntimeNodeItemType
;
skippedNodeIdList
:
Set
<
string
>
}
>
();
private
runningNodeCount
=
0
;
private
runningNodeCount
=
0
;
private
maxConcurrency
:
number
;
private
maxConcurrency
:
number
;
private
resolve
:
(
e
:
WorkflowQueue
)
=>
void
;
private
resolve
:
(
e
:
WorkflowQueue
)
=>
void
;
constructor
({
constructor
({
maxConcurrency
=
10
,
maxConcurrency
=
10
,
defaultSkipNodeQueue
,
resolve
resolve
}:
{
}:
{
maxConcurrency
?:
number
;
maxConcurrency
?:
number
;
defaultSkipNodeQueue
?:
WorkflowDebugResponse
[
'skipNodeQueue'
];
resolve
:
(
e
:
WorkflowQueue
)
=>
void
;
resolve
:
(
e
:
WorkflowQueue
)
=>
void
;
})
{
})
{
this
.
maxConcurrency
=
maxConcurrency
;
this
.
maxConcurrency
=
maxConcurrency
;
this
.
resolve
=
resolve
;
this
.
resolve
=
resolve
;
// Init skip node queue
defaultSkipNodeQueue
?.
forEach
(({
id
,
skippedNodeIdList
})
=>
{
const
node
=
this
.
runtimeNodesMap
.
get
(
id
);
if
(
!
node
)
return
;
this
.
addSkipNode
(
node
,
new
Set
(
skippedNodeIdList
));
});
}
}
// Add active node to queue (if already in the queue, it will not be added again)
// Add active node to queue (if already in the queue, it will not be added again)
...
@@ -217,7 +239,18 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -217,7 +239,18 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
private
processActiveNode
()
{
private
processActiveNode
()
{
// Finish
// Finish
if
(
this
.
activeRunQueue
.
size
===
0
&&
this
.
runningNodeCount
===
0
)
{
if
(
this
.
activeRunQueue
.
size
===
0
&&
this
.
runningNodeCount
===
0
)
{
if
(
this
.
skipNodeQueue
.
length
>
0
&&
!
this
.
nodeInteractiveResponse
)
{
if
(
isDebugMode
)
{
// 没有下一个激活节点,说明debug 进入了一个“即将结束”状态。可以开始处理 skip 节点
if
(
this
.
debugNextStepRunNodes
.
length
===
0
&&
this
.
skipNodeQueue
.
size
>
0
)
{
this
.
processSkipNodes
();
}
else
{
this
.
resolve
(
this
);
}
return
;
}
// 如果没有交互响应,则开始处理 skip(交互响应的 skip 需要留给后续处理)
if
(
this
.
skipNodeQueue
.
size
>
0
&&
!
this
.
nodeInteractiveResponse
)
{
this
.
processSkipNodes
();
this
.
processSkipNodes
();
}
else
{
}
else
{
this
.
resolve
(
this
);
this
.
resolve
(
this
);
...
@@ -251,11 +284,19 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -251,11 +284,19 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
}
}
private
addSkipNode
(
node
:
RuntimeNodeItemType
,
skippedNodeIdList
:
Set
<
string
>
)
{
private
addSkipNode
(
node
:
RuntimeNodeItemType
,
skippedNodeIdList
:
Set
<
string
>
)
{
this
.
skipNodeQueue
.
push
({
node
,
skippedNodeIdList
});
// 保证一个node 只在queue里记录一次
const
skipNodeSkippedNodeIdList
=
this
.
skipNodeQueue
.
get
(
node
.
nodeId
)?.
skippedNodeIdList
||
new
Set
<
string
>
();
const
concatSkippedNodeIdList
=
new
Set
([...
skippedNodeIdList
,
...
skipNodeSkippedNodeIdList
]);
this
.
skipNodeQueue
.
set
(
node
.
nodeId
,
{
node
,
skippedNodeIdList
:
concatSkippedNodeIdList
});
}
}
private
processSkipNodes
()
{
private
processSkipNodes
()
{
const
skipItem
=
this
.
skipNodeQueue
.
shift
();
// 取一个 node,并且从队列里删除
const
skipItem
=
this
.
skipNodeQueue
.
values
().
next
().
value
;
if
(
skipItem
)
{
if
(
skipItem
)
{
this
.
skipNodeQueue
.
delete
(
skipItem
.
node
.
nodeId
);
this
.
checkNodeCanRun
(
skipItem
.
node
,
skipItem
.
skippedNodeIdList
).
finally
(()
=>
{
this
.
checkNodeCanRun
(
skipItem
.
node
,
skipItem
.
skippedNodeIdList
).
finally
(()
=>
{
this
.
processActiveNode
();
this
.
processActiveNode
();
});
});
...
@@ -351,7 +392,7 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -351,7 +392,7 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
runtimeNodes
,
runtimeNodes
,
runtimeEdges
,
runtimeEdges
,
params
,
params
,
mode
:
data
.
mode
===
'debug'
?
'test'
:
data
.
mode
mode
:
isDebugMode
?
'test'
:
data
.
mode
};
};
// run module
// run module
...
@@ -620,18 +661,6 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -620,18 +661,6 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
const
nextStepActiveNodes
=
Array
.
from
(
nextStepActiveNodesMap
.
values
());
const
nextStepActiveNodes
=
Array
.
from
(
nextStepActiveNodesMap
.
values
());
const
nextStepSkipNodes
=
Array
.
from
(
nextStepSkipNodesMap
.
values
());
const
nextStepSkipNodes
=
Array
.
from
(
nextStepSkipNodesMap
.
values
());
if
(
data
.
mode
===
'debug'
)
{
this
.
debugNextStepRunNodes
=
this
.
debugNextStepRunNodes
.
concat
(
data
.
lastInteractive
?
nextStepActiveNodes
:
[...
nextStepActiveNodes
,
...
nextStepSkipNodes
]
);
return
{
nextStepActiveNodes
:
[],
nextStepSkipNodes
:
[]
};
}
return
{
return
{
nextStepActiveNodes
,
nextStepActiveNodes
,
nextStepSkipNodes
nextStepSkipNodes
...
@@ -690,8 +719,31 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -690,8 +719,31 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
return
this
.
nodeRunWithSkip
(
node
);
return
this
.
nodeRunWithSkip
(
node
);
}
}
})();
})();
if
(
!
nodeRunResult
)
return
;
if
(
!
nodeRunResult
)
return
;
// Store debug data
if
(
isDebugMode
)
{
if
(
status
===
'run'
)
{
this
.
debugNodeResponses
[
node
.
nodeId
]
=
{
nodeId
:
node
.
nodeId
,
type
:
'run'
,
interactiveResponse
:
nodeRunResult
.
result
[
DispatchNodeResponseKeyEnum
.
interactive
],
response
:
nodeRunResult
.
result
[
DispatchNodeResponseKeyEnum
.
nodeResponse
]
};
}
else
if
(
status
===
'skip'
)
{
this
.
debugNodeResponses
[
node
.
nodeId
]
=
{
nodeId
:
node
.
nodeId
,
type
:
'skip'
,
response
:
nodeRunResult
.
result
[
DispatchNodeResponseKeyEnum
.
nodeResponse
]
};
}
}
// 如果一个节点 active 运行了,则需要把它从 skip queue 里删除
if
(
status
===
'run'
)
{
this
.
skipNodeQueue
.
delete
(
node
.
nodeId
);
}
/*
/*
特殊情况:
特殊情况:
通过 skipEdges 可以判断是运行了分支节点。
通过 skipEdges 可以判断是运行了分支节点。
...
@@ -704,12 +756,20 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -704,12 +756,20 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
skippedNodeIdList
.
add
(
node
.
nodeId
);
skippedNodeIdList
.
add
(
node
.
nodeId
);
}
}
// Update the node output at the end of the run and get the next nodes
const
{
nextStepActiveNodes
,
nextStepSkipNodes
}
=
nodeOutput
(
nodeRunResult
.
node
,
nodeRunResult
.
result
);
nextStepSkipNodes
.
forEach
((
node
)
=>
{
this
.
addSkipNode
(
node
,
skippedNodeIdList
);
});
// In the current version, only one interactive node is allowed at the same time
// In the current version, only one interactive node is allowed at the same time
const
interactiveResponse
=
nodeRunResult
.
result
?.
[
DispatchNodeResponseKeyEnum
.
interactive
];
const
interactiveResponse
=
nodeRunResult
.
result
[
DispatchNodeResponseKeyEnum
.
interactive
];
if
(
interactiveResponse
)
{
if
(
interactiveResponse
)
{
pushStore
(
nodeRunResult
.
result
);
if
(
isDebugMode
)
{
if
(
data
.
mode
===
'debug'
)
{
this
.
debugNextStepRunNodes
=
this
.
debugNextStepRunNodes
.
concat
([
nodeRunResult
.
node
]);
this
.
debugNextStepRunNodes
=
this
.
debugNextStepRunNodes
.
concat
([
nodeRunResult
.
node
]);
}
}
...
@@ -718,22 +778,14 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -718,22 +778,14 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
interactiveResponse
interactiveResponse
};
};
return
;
return
;
}
else
if
(
isDebugMode
)
{
// Debug 模式下一步时候,会自己增加 activeNode
this
.
debugNextStepRunNodes
=
this
.
debugNextStepRunNodes
.
concat
(
nextStepActiveNodes
);
}
else
{
nextStepActiveNodes
.
forEach
((
node
)
=>
{
this
.
addActiveNode
(
node
.
nodeId
);
});
}
}
// Update the node output at the end of the run and get the next nodes
const
{
nextStepActiveNodes
,
nextStepSkipNodes
}
=
nodeOutput
(
nodeRunResult
.
node
,
nodeRunResult
.
result
);
nextStepSkipNodes
.
forEach
((
node
)
=>
{
this
.
addSkipNode
(
node
,
skippedNodeIdList
);
});
// Run next nodes
nextStepActiveNodes
.
forEach
((
node
)
=>
{
this
.
addActiveNode
(
node
.
nodeId
);
});
}
}
/* Have interactive result, computed edges and node outputs */
/* Have interactive result, computed edges and node outputs */
...
@@ -760,6 +812,10 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -760,6 +812,10 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
const
interactiveResult
:
WorkflowInteractiveResponseType
=
{
const
interactiveResult
:
WorkflowInteractiveResponseType
=
{
...
interactiveResponse
,
...
interactiveResponse
,
skipNodeQueue
:
Array
.
from
(
this
.
skipNodeQueue
.
values
()).
map
((
item
)
=>
({
id
:
item
.
node
.
nodeId
,
skippedNodeIdList
:
Array
.
from
(
item
.
skippedNodeIdList
)
})),
entryNodeIds
,
entryNodeIds
,
memoryEdges
:
runtimeEdges
.
map
((
edge
)
=>
({
memoryEdges
:
runtimeEdges
.
map
((
edge
)
=>
({
...
edge
,
...
edge
,
...
@@ -781,6 +837,22 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -781,6 +837,22 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
interactive
:
interactiveResult
interactive
:
interactiveResult
};
};
}
}
getDebugResponse
():
WorkflowDebugResponse
{
const
entryNodeIds
=
this
.
debugNextStepRunNodes
.
map
((
item
)
=>
item
.
nodeId
);
return
{
memoryEdges
:
runtimeEdges
.
map
((
edge
)
=>
({
...
edge
,
status
:
entryNodeIds
.
includes
(
edge
.
target
)
?
'active'
:
edge
.
status
})),
entryNodeIds
,
nodeResponses
:
this
.
debugNodeResponses
,
skipNodeQueue
:
Array
.
from
(
this
.
skipNodeQueue
.
values
()).
map
((
item
)
=>
({
id
:
item
.
node
.
nodeId
,
skippedNodeIdList
:
Array
.
from
(
item
.
skippedNodeIdList
)
}))
};
}
}
}
// Start process width initInput
// Start process width initInput
...
@@ -799,7 +871,8 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -799,7 +871,8 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
const
workflowQueue
=
await
new
Promise
<
WorkflowQueue
>
((
resolve
)
=>
{
const
workflowQueue
=
await
new
Promise
<
WorkflowQueue
>
((
resolve
)
=>
{
const
workflowQueue
=
new
WorkflowQueue
({
const
workflowQueue
=
new
WorkflowQueue
({
resolve
resolve
,
defaultSkipNodeQueue
});
});
entryNodes
.
forEach
((
node
)
=>
{
entryNodes
.
forEach
((
node
)
=>
{
...
@@ -833,11 +906,7 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
...
@@ -833,11 +906,7 @@ export const runWorkflow = async (data: RunWorkflowProps): Promise<DispatchFlowR
return
{
return
{
flowResponses
:
workflowQueue
.
chatResponses
,
flowResponses
:
workflowQueue
.
chatResponses
,
flowUsages
:
workflowQueue
.
chatNodeUsages
,
flowUsages
:
workflowQueue
.
chatNodeUsages
,
debugResponse
:
{
debugResponse
:
workflowQueue
.
getDebugResponse
(),
finishedNodes
:
runtimeNodes
,
finishedEdges
:
runtimeEdges
,
nextStepRunNodes
:
workflowQueue
.
debugNextStepRunNodes
},
workflowInteractiveResponse
:
interactiveResult
,
workflowInteractiveResponse
:
interactiveResult
,
[
DispatchNodeResponseKeyEnum
.
runTimes
]:
workflowQueue
.
workflowRunTimes
,
[
DispatchNodeResponseKeyEnum
.
runTimes
]:
workflowQueue
.
workflowRunTimes
,
[
DispatchNodeResponseKeyEnum
.
assistantResponses
]:
mergeAssistantResponseAnswerText
(
[
DispatchNodeResponseKeyEnum
.
assistantResponses
]:
mergeAssistantResponseAnswerText
(
...
...
packages/service/core/workflow/dispatch/type.d.ts
View file @
85ea1174
...
@@ -13,14 +13,24 @@ import type { WorkflowInteractiveResponseType } from '@fastgpt/global/core/workf
...
@@ -13,14 +13,24 @@ import type { WorkflowInteractiveResponseType } from '@fastgpt/global/core/workf
import
type
{
RuntimeEdgeItemType
}
from
'@fastgpt/global/core/workflow/type/edge'
;
import
type
{
RuntimeEdgeItemType
}
from
'@fastgpt/global/core/workflow/type/edge'
;
import
type
{
ChatNodeUsageType
}
from
'@fastgpt/global/support/wallet/bill/type'
;
import
type
{
ChatNodeUsageType
}
from
'@fastgpt/global/support/wallet/bill/type'
;
export
type
WorkflowDebugResponse
=
{
memoryEdges
:
RuntimeEdgeItemType
[];
entryNodeIds
:
string
[];
// Next step entry nodes
nodeResponses
:
Record
<
string
,
{
nodeId
:
string
;
type
:
'skip'
|
'run'
;
response
?:
ChatHistoryItemResType
;
interactiveResponse
?:
InteractiveNodeResponseType
;
}
>
;
skipNodeQueue
?:
{
id
:
string
;
skippedNodeIdList
:
string
[]
}[];
// Cache
};
export
type
DispatchFlowResponse
=
{
export
type
DispatchFlowResponse
=
{
flowResponses
:
ChatHistoryItemResType
[];
flowResponses
:
ChatHistoryItemResType
[];
flowUsages
:
ChatNodeUsageType
[];
flowUsages
:
ChatNodeUsageType
[];
debugResponse
:
{
debugResponse
:
WorkflowDebugResponse
;
finishedNodes
:
RuntimeNodeItemType
[];
finishedEdges
:
RuntimeEdgeItemType
[];
nextStepRunNodes
:
RuntimeNodeItemType
[];
};
workflowInteractiveResponse
?:
WorkflowInteractiveResponseType
;
workflowInteractiveResponse
?:
WorkflowInteractiveResponseType
;
[
DispatchNodeResponseKeyEnum
.
toolResponses
]:
ToolRunResponseItemType
;
[
DispatchNodeResponseKeyEnum
.
toolResponses
]:
ToolRunResponseItemType
;
[
DispatchNodeResponseKeyEnum
.
assistantResponses
]:
AIChatItemValueItemType
[];
[
DispatchNodeResponseKeyEnum
.
assistantResponses
]:
AIChatItemValueItemType
[];
...
...
projects/app/src/components/core/app/FileSelect.tsx
View file @
85ea1174
...
@@ -17,7 +17,6 @@ import { useTranslation } from 'next-i18next';
...
@@ -17,7 +17,6 @@ import { useTranslation } from 'next-i18next';
import
type
{
AppFileSelectConfigType
}
from
'@fastgpt/global/core/app/type.d'
;
import
type
{
AppFileSelectConfigType
}
from
'@fastgpt/global/core/app/type.d'
;
import
MyModal
from
'@fastgpt/web/components/common/MyModal'
;
import
MyModal
from
'@fastgpt/web/components/common/MyModal'
;
import
MySlider
from
'@/components/Slider'
;
import
MySlider
from
'@/components/Slider'
;
import
{
defaultAppSelectFileConfig
}
from
'@fastgpt/global/core/app/constants'
;
import
ChatFunctionTip
from
'./Tip'
;
import
ChatFunctionTip
from
'./Tip'
;
import
FormLabel
from
'@fastgpt/web/components/common/MyBox/FormLabel'
;
import
FormLabel
from
'@fastgpt/web/components/common/MyBox/FormLabel'
;
import
{
useMount
}
from
'ahooks'
;
import
{
useMount
}
from
'ahooks'
;
...
@@ -25,6 +24,7 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
...
@@ -25,6 +24,7 @@ import { useSystemStore } from '@/web/common/system/useSystemStore';
import
QuestionTip
from
'@fastgpt/web/components/common/MyTooltip/QuestionTip'
;
import
QuestionTip
from
'@fastgpt/web/components/common/MyTooltip/QuestionTip'
;
import
MyTag
from
'@fastgpt/web/components/common/Tag/index'
;
import
MyTag
from
'@fastgpt/web/components/common/Tag/index'
;
import
MyDivider
from
'@fastgpt/web/components/common/MyDivider'
;
import
MyDivider
from
'@fastgpt/web/components/common/MyDivider'
;
import
{
defaultAppSelectFileConfig
}
from
'@fastgpt/global/core/app/constants'
;
const
FileSelect
=
({
const
FileSelect
=
({
forbidVision
=
false
,
forbidVision
=
false
,
...
...
projects/app/src/global/core/workflow/api.d.ts
View file @
85ea1174
...
@@ -5,21 +5,18 @@ import type { WorkflowInteractiveResponseType } from '@fastgpt/global/core/workf
...
@@ -5,21 +5,18 @@ import type { WorkflowInteractiveResponseType } from '@fastgpt/global/core/workf
import
{
StoreNodeItemType
}
from
'@fastgpt/global/core/workflow/type'
;
import
{
StoreNodeItemType
}
from
'@fastgpt/global/core/workflow/type'
;
import
type
{
RuntimeEdgeItemType
}
from
'@fastgpt/global/core/workflow/type/edge'
;
import
type
{
RuntimeEdgeItemType
}
from
'@fastgpt/global/core/workflow/type/edge'
;
import
{
StoreEdgeItemType
}
from
'@fastgpt/global/core/workflow/type/edge'
;
import
{
StoreEdgeItemType
}
from
'@fastgpt/global/core/workflow/type/edge'
;
import
type
{
WorkflowDebugResponse
}
from
'@fastgpt/service/core/workflow/dispatch/type'
;
export
type
PostWorkflowDebugProps
=
{
export
type
PostWorkflowDebugProps
=
{
nodes
:
RuntimeNodeItemType
[];
nodes
:
RuntimeNodeItemType
[];
edges
:
RuntimeEdgeItemType
[];
edges
:
RuntimeEdgeItemType
[];
skipNodeQueue
?:
WorkflowDebugResponse
[
'skipNodeQueue'
];
variables
:
Record
<
string
,
any
>
;
variables
:
Record
<
string
,
any
>
;
appId
:
string
;
appId
:
string
;
query
?:
UserChatItemValueItemType
[];
query
?:
UserChatItemValueItemType
[];
history
?:
ChatItemType
[];
history
?:
ChatItemType
[];
};
};
export
type
PostWorkflowDebugResponse
=
{
export
type
PostWorkflowDebugResponse
=
WorkflowDebugResponse
&
{
finishedNodes
:
RuntimeNodeItemType
[];
finishedEdges
:
RuntimeEdgeItemType
[];
nextStepRunNodes
:
RuntimeNodeItemType
[];
flowResponses
:
ChatHistoryItemResType
[];
workflowInteractiveResponse
?:
WorkflowInteractiveResponseType
;
newVariables
:
Record
<
string
,
any
>
;
newVariables
:
Record
<
string
,
any
>
;
};
};
projects/app/src/pageComponents/app/detail/SimpleApp/EditForm.tsx
View file @
85ea1174
...
@@ -31,7 +31,6 @@ import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
...
@@ -31,7 +31,6 @@ import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
import
VariableTip
from
'@/components/common/Textarea/MyTextarea/VariableTip'
;
import
VariableTip
from
'@/components/common/Textarea/MyTextarea/VariableTip'
;
import
{
getWebLLMModel
}
from
'@/web/common/system/utils'
;
import
{
getWebLLMModel
}
from
'@/web/common/system/utils'
;
import
ToolSelect
from
'./components/ToolSelect'
;
import
ToolSelect
from
'./components/ToolSelect'
;
import
{
useSystemStore
}
from
'@/web/common/system/useSystemStore'
;
import
OptimizerPopover
from
'@/components/common/PromptEditor/OptimizerPopover'
;
import
OptimizerPopover
from
'@/components/common/PromptEditor/OptimizerPopover'
;
const
DatasetSelectModal
=
dynamic
(()
=>
import
(
'@/components/core/app/DatasetSelectModal'
));
const
DatasetSelectModal
=
dynamic
(()
=>
import
(
'@/components/core/app/DatasetSelectModal'
));
...
@@ -148,7 +147,7 @@ const EditForm = ({
...
@@ -148,7 +147,7 @@ const EditForm = ({
},
},
[
appForm
.
aiSettings
.
systemPrompt
,
setAppForm
]
[
appForm
.
aiSettings
.
systemPrompt
,
setAppForm
]
);
);
console
.
log
(
appForm
.
chatConfig
.
fileSelectConfig
);
return
(
return
(
<>
<>
<
Box
>
<
Box
>
...
...
projects/app/src/pageComponents/app/detail/SimpleApp/index.tsx
View file @
85ea1174
...
@@ -11,6 +11,7 @@ import { type SimpleAppSnapshotType, useSimpleAppSnapshots } from './useSnapshot
...
@@ -11,6 +11,7 @@ import { type SimpleAppSnapshotType, useSimpleAppSnapshots } from './useSnapshot
import
{
useDebounceEffect
,
useMount
}
from
'ahooks'
;
import
{
useDebounceEffect
,
useMount
}
from
'ahooks'
;
import
{
v1Workflow2V2
}
from
'@/web/core/workflow/adapt'
;
import
{
v1Workflow2V2
}
from
'@/web/core/workflow/adapt'
;
import
{
getAppConfigByDiff
}
from
'@/web/core/app/diff'
;
import
{
getAppConfigByDiff
}
from
'@/web/core/app/diff'
;
import
{
defaultAppSelectFileConfig
}
from
'@fastgpt/global/core/app/constants'
;
const
Edit
=
dynamic
(()
=>
import
(
'./Edit'
));
const
Edit
=
dynamic
(()
=>
import
(
'./Edit'
));
const
Logs
=
dynamic
(()
=>
import
(
'../Logs/index'
));
const
Logs
=
dynamic
(()
=>
import
(
'../Logs/index'
));
...
@@ -79,7 +80,13 @@ const SimpleEdit = () => {
...
@@ -79,7 +80,13 @@ const SimpleEdit = () => {
if
(
past
.
length
===
0
)
{
if
(
past
.
length
===
0
)
{
const
appForm
=
appWorkflow2Form
({
const
appForm
=
appWorkflow2Form
({
nodes
:
appDetail
.
modules
,
nodes
:
appDetail
.
modules
,
chatConfig
:
appDetail
.
chatConfig
chatConfig
:
{
...
appDetail
.
chatConfig
,
fileSelectConfig
:
appDetail
.
chatConfig
.
fileSelectConfig
||
{
...
defaultAppSelectFileConfig
,
canSelectFile
:
true
}
}
});
});
saveSnapshot
({
saveSnapshot
({
appForm
,
appForm
,
...
...
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/RenderDebug/NodeDebugResponse.tsx
View file @
85ea1174
...
@@ -127,11 +127,9 @@ const NodeDebugResponse = ({ nodeId, debugResult }: NodeDebugResponseProps) => {
...
@@ -127,11 +127,9 @@ const NodeDebugResponse = ({ nodeId, debugResult }: NodeDebugResponseProps) => {
}
}
];
];
const
lastInteractive
=
getLastInteractiveValue
(
mockHistory
);
onNextNodeDebug
({
onNextNodeDebug
({
...
workflowDebugData
,
...
workflowDebugData
,
// Rewrite runtimeEdges
runtimeEdges
:
workflowDebugData
.
runtimeEdges
,
runtimeEdges
:
storeEdges2RuntimeEdges
(
workflowDebugData
.
runtimeEdges
,
lastInteractive
),
query
:
updatedQuery
,
query
:
updatedQuery
,
history
:
mockHistory
history
:
mockHistory
});
});
...
@@ -189,7 +187,7 @@ const NodeDebugResponse = ({ nodeId, debugResult }: NodeDebugResponseProps) => {
...
@@ -189,7 +187,7 @@ const NodeDebugResponse = ({ nodeId, debugResult }: NodeDebugResponseProps) => {
<
Box
fontWeight=
{
'bold'
}
flex=
{
'1'
}
>
<
Box
fontWeight=
{
'bold'
}
flex=
{
'1'
}
>
{
t
(
'common:core.workflow.debug.Run result'
)
}
{
t
(
'common:core.workflow.debug.Run result'
)
}
</
Box
>
</
Box
>
{
workflowDebugData
?.
nextRunNode
s
.
length
!==
0
&&
(
{
workflowDebugData
?.
entryNodeId
s
.
length
!==
0
&&
(
<
PopoverConfirm
<
PopoverConfirm
Trigger=
{
Trigger=
{
<
Button
<
Button
...
@@ -209,8 +207,8 @@ const NodeDebugResponse = ({ nodeId, debugResult }: NodeDebugResponseProps) => {
...
@@ -209,8 +207,8 @@ const NodeDebugResponse = ({ nodeId, debugResult }: NodeDebugResponseProps) => {
<>
<>
{
(
debugResult
.
status
===
'success'
||
debugResult
.
status
===
'skipped'
)
&&
{
(
debugResult
.
status
===
'success'
||
debugResult
.
status
===
'skipped'
)
&&
!
debugResult
.
isExpired
&&
!
debugResult
.
isExpired
&&
workflowDebugData
?.
nextRunNode
s
&&
workflowDebugData
?.
entryNodeId
s
&&
workflowDebugData
.
nextRunNode
s
.
length
>
0
&&
(
workflowDebugData
.
entryNodeId
s
.
length
>
0
&&
(
<
Button
<
Button
ml=
{
2
}
ml=
{
2
}
size=
{
'sm'
}
size=
{
'sm'
}
...
@@ -221,8 +219,8 @@ const NodeDebugResponse = ({ nodeId, debugResult }: NodeDebugResponseProps) => {
...
@@ -221,8 +219,8 @@ const NodeDebugResponse = ({ nodeId, debugResult }: NodeDebugResponseProps) => {
{
t
(
'common:next_step'
)
}
{
t
(
'common:next_step'
)
}
</
Button
>
</
Button
>
)
}
)
}
{
workflowDebugData
?.
nextRunNode
s
&&
{
workflowDebugData
?.
entryNodeId
s
&&
workflowDebugData
?.
nextRunNode
s
.
length
===
0
&&
(
workflowDebugData
?.
entryNodeId
s
.
length
===
0
&&
(
<
Button
ml=
{
2
}
size=
{
'sm'
}
variant=
{
'primary'
}
onClick=
{
onStopNodeDebug
}
>
<
Button
ml=
{
2
}
size=
{
'sm'
}
variant=
{
'primary'
}
onClick=
{
onStopNodeDebug
}
>
{
t
(
'common:core.workflow.debug.Done'
)
}
{
t
(
'common:core.workflow.debug.Done'
)
}
</
Button
>
</
Button
>
...
...
projects/app/src/pageComponents/app/detail/WorkflowComponents/context/index.tsx
View file @
85ea1174
...
@@ -54,12 +54,12 @@ import { cloneDeep } from 'lodash';
...
@@ -54,12 +54,12 @@ import { cloneDeep } from 'lodash';
import
{
type
AppVersionSchemaType
}
from
'@fastgpt/global/core/app/version'
;
import
{
type
AppVersionSchemaType
}
from
'@fastgpt/global/core/app/version'
;
import
WorkflowInitContextProvider
,
{
WorkflowNodeEdgeContext
}
from
'./workflowInitContext'
;
import
WorkflowInitContextProvider
,
{
WorkflowNodeEdgeContext
}
from
'./workflowInitContext'
;
import
WorkflowEventContextProvider
from
'./workflowEventContext'
;
import
WorkflowEventContextProvider
from
'./workflowEventContext'
;
import
{
getAppConfigByDiff
}
from
'@/web/core/app/diff'
;
import
WorkflowStatusContextProvider
from
'./workflowStatusContext'
;
import
WorkflowStatusContextProvider
from
'./workflowStatusContext'
;
import
{
type
ChatItemType
,
type
UserChatItemValueItemType
}
from
'@fastgpt/global/core/chat/type'
;
import
{
type
ChatItemType
,
type
UserChatItemValueItemType
}
from
'@fastgpt/global/core/chat/type'
;
import
{
type
WorkflowInteractiveResponseType
}
from
'@fastgpt/global/core/workflow/template/system/interactive/type'
;
import
{
type
WorkflowInteractiveResponseType
}
from
'@fastgpt/global/core/workflow/template/system/interactive/type'
;
import
{
FlowNodeOutputTypeEnum
}
from
'@fastgpt/global/core/workflow/node/constant'
;
import
{
FlowNodeOutputTypeEnum
}
from
'@fastgpt/global/core/workflow/node/constant'
;
import
{
useChatStore
}
from
'@/web/core/chat/context/useChatStore'
;
import
{
useChatStore
}
from
'@/web/core/chat/context/useChatStore'
;
import
type
{
WorkflowDebugResponse
}
from
'@fastgpt/service/core/workflow/dispatch/type'
;
/*
/*
Context
Context
...
@@ -266,7 +266,9 @@ type WorkflowContextType = {
...
@@ -266,7 +266,9 @@ type WorkflowContextType = {
export
type
DebugDataType
=
{
export
type
DebugDataType
=
{
runtimeNodes
:
RuntimeNodeItemType
[];
runtimeNodes
:
RuntimeNodeItemType
[];
runtimeEdges
:
RuntimeEdgeItemType
[];
runtimeEdges
:
RuntimeEdgeItemType
[];
nextRunNodes
:
RuntimeNodeItemType
[];
entryNodeIds
:
string
[];
skipNodeQueue
?:
WorkflowDebugResponse
[
'skipNodeQueue'
];
variables
:
Record
<
string
,
any
>
;
variables
:
Record
<
string
,
any
>
;
history
?:
ChatItemType
[];
history
?:
ChatItemType
[];
query
?:
UserChatItemValueItemType
[];
query
?:
UserChatItemValueItemType
[];
...
@@ -686,112 +688,67 @@ const WorkflowContextProvider = ({
...
@@ -686,112 +688,67 @@ const WorkflowContextProvider = ({
}))
}))
);
);
// 2. Set isEntry field and get entryNodes
// 2. Set isEntry field and get entryNodes
, and set running status
const
runtimeNodes
=
debugData
.
runtimeNodes
.
map
((
item
)
=>
({
const
runtimeNodes
=
debugData
.
runtimeNodes
.
map
((
item
)
=>
({
...
item
,
...
item
,
isEntry
:
debugData
.
nextRunNodes
.
some
((
node
)
=>
node
.
nodeI
d
===
item
.
nodeId
)
isEntry
:
debugData
.
entryNodeIds
.
some
((
id
)
=>
i
d
===
item
.
nodeId
)
}));
}));
const
entryNodes
=
runtimeNodes
.
filter
((
item
)
=>
item
.
isEntry
);
const
entryNodes
=
runtimeNodes
.
filter
((
item
)
=>
{
if
(
item
.
isEntry
)
{
const
runtimeNodeStatus
:
Record
<
string
,
string
>
=
entryNodes
.
map
((
node
)
=>
{
const
status
=
checkNodeRunStatus
({
node
,
nodesMap
:
new
Map
(
runtimeNodes
.
map
((
item
)
=>
[
item
.
nodeId
,
item
])),
runtimeEdges
:
debugData
?.
runtimeEdges
||
[]
});
return
{
nodeId
:
node
.
nodeId
,
status
};
})
.
reduce
(
(
acc
,
cur
)
=>
({
...
acc
,
[
cur
.
nodeId
]:
cur
.
status
}),
{}
);
// 3. Set entry node status to running
entryNodes
.
forEach
((
node
)
=>
{
if
(
runtimeNodeStatus
[
node
.
nodeId
]
!==
'wait'
)
{
onChangeNode
({
onChangeNode
({
nodeId
:
node
.
nodeId
,
nodeId
:
item
.
nodeId
,
type
:
'attr'
,
type
:
'attr'
,
key
:
'debugResult'
,
key
:
'debugResult'
,
value
:
defaultRunningStatus
value
:
defaultRunningStatus
});
});
return
true
;
}
}
});
});
try
{
try
{
// 4. Run one step
// 3. Run one step
const
{
const
{
memoryEdges
,
entryNodeIds
,
skipNodeQueue
,
nodeResponses
,
newVariables
}
=
finishedEdges
,
await
postWorkflowDebug
({
finishedNodes
,
nodes
:
runtimeNodes
,
nextStepRunNodes
,
edges
:
debugData
.
runtimeEdges
,
flowResponses
,
skipNodeQueue
:
debugData
.
skipNodeQueue
,
newVariables
,
variables
:
{
workflowInteractiveResponse
appId
,
}
=
await
postWorkflowDebug
({
cTime
:
formatTime2YMDHMW
(),
nodes
:
runtimeNodes
,
...
debugData
.
variables
edges
:
debugData
.
runtimeEdges
,
},
variables
:
{
query
:
debugData
.
query
,
// 添加 query 参数
appId
,
history
:
debugData
.
history
,
cTime
:
formatTime2YMDHMW
(),
appId
...
debugData
.
variables
});
},
query
:
debugData
.
query
,
// 添加 query 参数
history
:
debugData
.
history
,
appId
});
//
5
. Store debug result
//
4
. Store debug result
setWorkflowDebugData
({
setWorkflowDebugData
({
runtimeNodes
:
finishedNodes
,
runtimeNodes
:
debugData
.
runtimeNodes
,
// edges need to save status
runtimeEdges
:
memoryEdges
,
runtimeEdges
:
finishedEdges
,
entryNodeIds
,
nextRunNodes
:
nextStepRunNodes
,
skipNodeQueue
,
variables
:
newVariables
,
variables
:
newVariables
workflowInteractiveResponse
:
workflowInteractiveResponse
});
});
//
6
. selected entry node and Update entry node debug result
//
5
. selected entry node and Update entry node debug result
setNodes
((
state
)
=>
setNodes
((
state
)
=>
state
.
map
((
node
)
=>
{
state
.
map
((
node
)
=>
{
const
isEntryNode
=
entryNodes
.
some
((
item
)
=>
item
.
nodeId
===
node
.
data
.
nodeId
);
const
isEntryNode
=
entryNodes
.
some
((
item
)
=>
item
.
nodeId
===
node
.
data
.
nodeId
);
if
(
!
isEntryNode
||
runtimeNodeStatus
[
node
.
data
.
nodeId
]
===
'wait'
)
return
node
;
const
result
=
nodeResponses
[
node
.
data
.
nodeId
];
if
(
!
result
)
return
node
;
const
result
=
flowResponses
.
find
((
item
)
=>
item
.
nodeId
===
node
.
data
.
nodeId
);
if
(
runtimeNodeStatus
[
node
.
data
.
nodeId
]
===
'skip'
)
{
return
{
...
node
,
selected
:
isEntryNode
,
data
:
{
...
node
.
data
,
debugResult
:
{
status
:
'skipped'
,
showResult
:
true
,
isExpired
:
false
}
}
};
}
return
{
return
{
...
node
,
...
node
,
selected
:
isEntryNode
,
selected
:
result
.
type
===
'run'
&&
isEntryNode
,
data
:
{
data
:
{
...
node
.
data
,
...
node
.
data
,
debugResult
:
{
debugResult
:
{
status
:
'success
'
,
status
:
result
.
type
===
'run'
?
'success'
:
'skipped
'
,
response
:
result
,
response
:
result
.
response
,
showResult
:
true
,
showResult
:
true
,
isExpired
:
false
,
isExpired
:
false
,
workflowInteractiveResponse
:
workflowI
nteractiveResponse
workflowInteractiveResponse
:
result
.
i
nteractiveResponse
}
}
}
}
};
};
...
@@ -799,13 +756,9 @@ const WorkflowContextProvider = ({
...
@@ -799,13 +756,9 @@ const WorkflowContextProvider = ({
);
);
// Check for an empty response(Skip node)
// Check for an empty response(Skip node)
if
(
// if (!workflowInteractiveResponse && flowResponses.length === 0 && entryNodeIds.length > 0) {
!
workflowInteractiveResponse
&&
// onNextNodeDebug(debugData);
flowResponses
.
length
===
0
&&
// }
nextStepRunNodes
.
length
>
0
)
{
onNextNodeDebug
(
debugData
);
}
}
catch
(
error
)
{
}
catch
(
error
)
{
entryNodes
.
forEach
((
node
)
=>
{
entryNodes
.
forEach
((
node
)
=>
{
onChangeNode
({
onChangeNode
({
...
@@ -856,7 +809,10 @@ const WorkflowContextProvider = ({
...
@@ -856,7 +809,10 @@ const WorkflowContextProvider = ({
const
data
:
DebugDataType
=
{
const
data
:
DebugDataType
=
{
runtimeNodes
,
runtimeNodes
,
runtimeEdges
,
runtimeEdges
,
nextRunNodes
:
runtimeNodes
.
filter
((
node
)
=>
node
.
nodeId
===
entryNodeId
),
entryNodeIds
:
runtimeNodes
.
filter
((
node
)
=>
node
.
nodeId
===
entryNodeId
)
.
map
((
node
)
=>
node
.
nodeId
),
skipNodeQueue
:
[],
variables
,
variables
,
query
,
query
,
history
history
...
...
projects/app/src/pages/api/core/workflow/debug.ts
View file @
85ea1174
...
@@ -21,6 +21,7 @@ async function handler(
...
@@ -21,6 +21,7 @@ async function handler(
const
{
const
{
nodes
=
[],
nodes
=
[],
edges
=
[],
edges
=
[],
skipNodeQueue
,
variables
=
{},
variables
=
{},
appId
,
appId
,
query
=
[],
query
=
[],
...
@@ -47,34 +48,34 @@ async function handler(
...
@@ -47,34 +48,34 @@ async function handler(
// auth balance
// auth balance
const
{
timezone
,
externalProvider
}
=
await
getUserChatInfoAndAuthTeamPoints
(
tmbId
);
const
{
timezone
,
externalProvider
}
=
await
getUserChatInfoAndAuthTeamPoints
(
tmbId
);
const
lastI
nteractive
=
getLastInteractiveValue
(
history
);
const
i
nteractive
=
getLastInteractiveValue
(
history
);
/* start process */
/* start process */
const
{
flowUsages
,
flowResponses
,
debugResponse
,
newVariables
,
workflowInteractiveResponse
}
=
const
{
flowUsages
,
debugResponse
,
newVariables
}
=
await
dispatchWorkFlow
({
await
dispatchWorkFlow
({
res
,
res
,
lang
:
getLocale
(
req
)
,
lang
:
getLocale
(
req
)
,
requestOrigin
:
req
.
headers
.
origin
,
requestOrigin
:
req
.
headers
.
origin
,
mode
:
'debug'
,
mode
:
'debug'
,
timezone
,
timezone
,
externalProvider
,
externalProvider
,
uid
:
tmbId
,
uid
:
tmbId
,
runningAppInfo
:
{
runningAppInfo
:
{
id
:
app
.
_id
,
id
:
app
.
_i
d
,
teamId
:
app
.
teamI
d
,
teamId
:
app
.
teamId
,
tmbId
:
app
.
tmbId
tmbId
:
app
.
tmbId
},
}
,
runningUserInfo
:
await
getRunningUserInfoByTmbId
(
tmbId
)
,
runningUserInfo
:
await
getRunningUserInfoByTmbId
(
tmbId
)
,
runtimeNodes
:
nodes
,
runtimeNodes
:
nod
es
,
runtimeEdges
:
edg
es
,
runtimeEdges
:
edges
,
defaultSkipNodeQueue
:
skipNodeQueue
,
lastI
nteractive
,
lastInteractive
:
i
nteractive
,
variables
,
variables
,
query
:
query
,
query
:
query
,
chatConfig
:
defaultApp
.
chatConfig
,
chatConfig
:
defaultApp
.
chatConfig
,
histories
:
history
,
histories
:
history
,
stream
:
false
,
stream
:
false
,
maxRunTimes
:
WORKFLOW_MAX_RUN_TIMES
maxRunTimes
:
WORKFLOW_MAX_RUN_TIMES
});
});
createChatUsage
({
createChatUsage
({
appName
:
`
${
app
.
name
}
-Debug`
,
appName
:
`
${
app
.
name
}
-Debug`
,
...
@@ -86,10 +87,8 @@ async function handler(
...
@@ -86,10 +87,8 @@ async function handler(
});
});
return
{
return
{
...
debugResponse
,
...
debugResponse
!
,
newVariables
,
newVariables
flowResponses
,
workflowInteractiveResponse
};
};
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment