feat: add history parameter to PostWorkflowDebugProps and update related components

This commit is contained in:
sd0ric4
2025-03-26 15:53:08 +08:00
parent 5ec7bbf3d3
commit 51fa72717e
7 changed files with 337 additions and 192 deletions

View File

@@ -65,6 +65,7 @@ export type ModuleDispatchProps<T> = ChatDispatchProps & {
runtimeNodes: RuntimeNodeItemType[]; runtimeNodes: RuntimeNodeItemType[];
runtimeEdges: RuntimeEdgeItemType[]; runtimeEdges: RuntimeEdgeItemType[];
params: T; params: T;
realmode: 'chat' | 'debug' | 'test';
}; };
export type SystemVariablesType = { export type SystemVariablesType = {

View File

@@ -581,7 +581,8 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
runtimeNodes, runtimeNodes,
runtimeEdges, runtimeEdges,
params, params,
mode: props.mode === 'debug' ? 'test' : props.mode mode: props.mode === 'debug' ? 'test' : props.mode,
realmode: props.mode
}; };
// run module // run module

View File

@@ -16,9 +16,15 @@ import {
} from '@fastgpt/global/core/workflow/template/system/interactive/type'; } from '@fastgpt/global/core/workflow/template/system/interactive/type';
import { useContextSelector } from 'use-context-selector'; import { useContextSelector } from 'use-context-selector';
import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context'; import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context';
import { ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants'; import { ChatItemValueTypeEnum, ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
import { UserChatItemValueItemType } from '@fastgpt/global/core/chat/type'; import {
AIChatItemValueItemType,
ChatItemType,
UserChatItemValueItemType
} from '@fastgpt/global/core/chat/type';
import MyIcon from '@fastgpt/web/components/common/Icon'; import MyIcon from '@fastgpt/web/components/common/Icon';
import { StoreEdgeItemType, RuntimeEdgeItemType } from '@fastgpt/global/core/workflow/type/edge';
import { initWorkflowEdgeStatus } from '@fastgpt/global/core/workflow/runtime/utils';
export const RenderUserSelectInteractive = React.memo(function RenderInteractive({ export const RenderUserSelectInteractive = React.memo(function RenderInteractive({
interactive, interactive,
@@ -29,42 +35,78 @@ export const RenderUserSelectInteractive = React.memo(function RenderInteractive
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const [selectedValue, setSelectedValue] = useState<string | undefined>(undefined); const [selectedValue, setSelectedValue] = useState<string | undefined>(undefined);
const { onChangeNode, onNextNodeDebug, workflowDebugData, setWorkflowDebugData } = // 在两个组件中更新上下文选择器,添加 onStartNodeDebug
useContextSelector(WorkflowContext, (v) => ({ const { onChangeNode, onStartNodeDebug, workflowDebugData } = useContextSelector(
WorkflowContext,
(v) => ({
onChangeNode: v.onChangeNode, onChangeNode: v.onChangeNode,
onNextNodeDebug: v.onNextNodeDebug, onStartNodeDebug: v.onStartNodeDebug,
workflowDebugData: v.workflowDebugData, // onNextNodeDebug: v.onNextNodeDebug, // 不再使用
setWorkflowDebugData: v.setWorkflowDebugData workflowDebugData: v.workflowDebugData
})
);
/**
* 创建交互数据结构
* @param nodeId 交互节点ID
* @param interactive 交互组件数据
* @param edges 当前的边数组
* @returns 交互数据结构
*/
const createInteractiveData = (
nodeId: string,
interactive: UserSelectInteractive | UserInputInteractive,
edges: StoreEdgeItemType[]
) => {
// 创建 memoryEdges - 指向交互节点的边设为 active
const memoryEdges: RuntimeEdgeItemType[] = edges.map((edge) => ({
...edge,
status: edge.target === nodeId ? ('active' as const) : ('waiting' as const)
})); }));
return {
...interactive,
entryNodeIds: [nodeId],
memoryEdges,
nodeOutputs: [] // 如果有需要可以填充节点输出数据
};
};
/**
* 创建模拟的历史记录
* @param nodeId 交互节点ID
* @param interactive 交互组件数据
* @param edges 当前的边数组
* @returns 模拟的历史记录
*/
const createMockHistory = (
nodeId: string,
interactive: UserSelectInteractive | UserInputInteractive,
edges: StoreEdgeItemType[]
): ChatItemType[] => {
const interactiveData = createInteractiveData(nodeId, interactive, edges);
return [
{
obj: ChatRoleEnum.AI,
value: [
{
type: ChatItemValueTypeEnum.interactive,
interactive: interactiveData
}
]
}
];
};
const handleSelect = useCallback( const handleSelect = useCallback(
(value: string) => { (value: string) => {
if (!nodeId || !workflowDebugData) return; if (!nodeId || !workflowDebugData) return;
// 保存选中的值到本地状态 // 保存选中的值到本地状态
setSelectedValue(value); setSelectedValue(value);
// 更新查询以包含用户的选择
const updatedQuery: UserChatItemValueItemType[] = [
...(workflowDebugData.query || []),
{
type: ChatItemValueTypeEnum.text,
text: {
content: value
}
} as UserChatItemValueItemType
];
// 更新工作流调试数据
setWorkflowDebugData({
...workflowDebugData,
query: updatedQuery
});
}, },
[nodeId, onChangeNode, workflowDebugData, setWorkflowDebugData] [nodeId, workflowDebugData]
); );
// 处理下一步调试的逻辑
const handleStartDebug = useCallback(() => { const handleStartDebug = useCallback(() => {
if (!nodeId || !workflowDebugData) return; if (!nodeId || !workflowDebugData) return;
@@ -76,10 +118,67 @@ export const RenderUserSelectInteractive = React.memo(function RenderInteractive
value: true value: true
}); });
// 然后调用onNextNodeDebug函数 // 更新此节点的值(将用户选择保存到节点)
onNextNodeDebug(); if (selectedValue) {
}, [nodeId, workflowDebugData, onNextNodeDebug, onChangeNode]); onChangeNode({
nodeId,
type: 'attr',
key: 'userSelectedVal',
value: selectedValue
});
}
// 创建包含用户选择的查询数据
const updatedQuery: UserChatItemValueItemType[] = [
...(workflowDebugData.query || []),
{
type: ChatItemValueTypeEnum.text,
text: {
content: selectedValue || ''
}
} as UserChatItemValueItemType
];
// 创建模拟的历史记录
const mockHistory = createMockHistory(nodeId, interactive, workflowDebugData.runtimeEdges);
// 使用模拟的历史记录初始化边状态
const updatedRuntimeEdges = initWorkflowEdgeStatus(workflowDebugData.runtimeEdges, mockHistory);
// 更新 runtimeNodes 以反映用户的选择
const updatedRuntimeNodes = workflowDebugData.runtimeNodes.map((node) => {
if (node.nodeId === nodeId) {
// 找到我们需要的输入字段并更新它
return {
...node,
inputs: node.inputs.map((input) => {
// 根据您的实际字段结构,这里可能需要调整
if (input.key === 'userSelect' || input.key === 'selectedOption') {
return {
...input,
value: selectedValue
};
}
return input;
}),
// 添加或更新任何需要的节点属性
userSelectedVal: selectedValue
};
}
return node;
});
// 更新 runtimeEdges 状态
// 使用 onStartNodeDebug 替代 onNextNodeDebug带上更新后的 nodes 和 edges
onStartNodeDebug({
entryNodeId: nodeId,
runtimeNodes: updatedRuntimeNodes,
runtimeEdges: updatedRuntimeEdges,
variables: workflowDebugData.variables,
query: updatedQuery,
history: mockHistory
});
}, [nodeId, workflowDebugData, onStartNodeDebug, onChangeNode, selectedValue, interactive]);
return ( return (
<Box px={4} py={3}> <Box px={4} py={3}>
{interactive?.params?.description && ( {interactive?.params?.description && (
@@ -155,7 +254,6 @@ export const RenderUserSelectInteractive = React.memo(function RenderInteractive
</Box> </Box>
); );
}); });
export const RenderUserFormInteractive = React.memo(function RenderFormInput({ export const RenderUserFormInteractive = React.memo(function RenderFormInput({
interactive, interactive,
nodeId nodeId
@@ -164,61 +262,167 @@ export const RenderUserFormInteractive = React.memo(function RenderFormInput({
nodeId?: string; nodeId?: string;
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { register, setValue, handleSubmit: handleSubmitChat, control, reset } = useForm(); const {
register,
setValue,
handleSubmit: handleSubmitChat,
control,
reset,
getValues
} = useForm();
const [isSubmitted, setIsSubmitted] = useState(false); const [isSubmitted, setIsSubmitted] = useState(false);
const { onChangeNode, onNextNodeDebug, workflowDebugData, setWorkflowDebugData } = // 在两个组件中更新上下文选择器,添加 onStartNodeDebug
useContextSelector(WorkflowContext, (v) => ({ const { onChangeNode, onStartNodeDebug, workflowDebugData } = useContextSelector(
WorkflowContext,
(v) => ({
onChangeNode: v.onChangeNode, onChangeNode: v.onChangeNode,
onNextNodeDebug: v.onNextNodeDebug, onStartNodeDebug: v.onStartNodeDebug,
workflowDebugData: v.workflowDebugData, workflowDebugData: v.workflowDebugData
setWorkflowDebugData: v.setWorkflowDebugData })
);
/**
* 创建交互数据结构
* @param nodeId 交互节点ID
* @param interactive 交互组件数据
* @param edges 当前的边数组
* @returns 交互数据结构
*/
const createInteractiveData = (
nodeId: string,
interactive: UserInputInteractive,
edges: StoreEdgeItemType[]
) => {
// 创建 memoryEdges - 指向交互节点的边设为 active
const memoryEdges: RuntimeEdgeItemType[] = edges.map((edge) => ({
...edge,
status: edge.target === nodeId ? ('active' as const) : ('waiting' as const)
})); }));
return {
...interactive,
entryNodeIds: [nodeId],
memoryEdges,
nodeOutputs: [] // 如果有需要可以填充节点输出数据
};
};
/**
* 创建模拟的历史记录
* @param nodeId 交互节点ID
* @param interactive 交互组件数据
* @param edges 当前的边数组
* @returns 模拟的历史记录
*/
const createMockHistory = (
nodeId: string,
interactive: UserInputInteractive,
edges: StoreEdgeItemType[]
): ChatItemType[] => {
// 创建一个新的 interactive 对象,确保 submitted 为 false
const adjustedInteractive = {
...interactive,
params: {
...interactive.params,
submitted: false // 关键修改点:确保 submitted 为 false
}
};
const interactiveData = createInteractiveData(nodeId, adjustedInteractive, edges);
return [
{
obj: ChatRoleEnum.AI,
value: [
{
type: ChatItemValueTypeEnum.interactive,
interactive: interactiveData
}
]
}
];
};
const onSubmit = useCallback( const onSubmit = useCallback(
(data: any) => { (data: any) => {
if (!nodeId || !workflowDebugData) return; if (!nodeId || !workflowDebugData) return;
// 标记表单已提交
setIsSubmitted(true); setIsSubmitted(true);
const jsonData = JSON.stringify(data); // 直接调用 handleStartDebug合并提交和下一步操作
const formData = getValues();
onChangeNode({
nodeId,
type: 'attr',
key: 'isEntry',
value: true
});
// 更新查询以包含用户的表单数据
const updatedQuery: UserChatItemValueItemType[] = [ const updatedQuery: UserChatItemValueItemType[] = [
...(workflowDebugData.query || []), ...(workflowDebugData.query || []),
{ {
type: ChatItemValueTypeEnum.text, type: ChatItemValueTypeEnum.text,
text: { text: {
content: jsonData content: JSON.stringify(formData)
} }
} as UserChatItemValueItemType } as UserChatItemValueItemType
]; ];
// 更新工作流调试数据 const updatedInteractive = {
setWorkflowDebugData({ ...interactive,
...workflowDebugData, params: {
query: updatedQuery ...interactive.params,
submitted: true
}
};
const mockHistory = createMockHistory(
nodeId,
updatedInteractive,
workflowDebugData.runtimeEdges
);
const updatedRuntimeEdges = initWorkflowEdgeStatus(
workflowDebugData.runtimeEdges,
mockHistory
);
const updatedRuntimeNodes = workflowDebugData.runtimeNodes.map((node) => {
if (node.nodeId === nodeId) {
return {
...node,
inputs: node.inputs.map((input) => {
const formField = interactive.params.inputForm?.find(
(field) => field.label === input.key || field.key === input.key
);
if (formField) {
return {
...input,
value: formData[formField.label]
};
}
return input;
}),
formSubmitted: true
};
}
return node;
});
onStartNodeDebug({
entryNodeId: nodeId,
runtimeNodes: updatedRuntimeNodes,
runtimeEdges: updatedRuntimeEdges,
variables: workflowDebugData.variables,
query: updatedQuery,
history: mockHistory
}); });
}, },
[nodeId, onChangeNode, workflowDebugData, setWorkflowDebugData] [nodeId, workflowDebugData, onStartNodeDebug, onChangeNode, getValues, interactive]
); );
// 处理下一步调试的逻辑
const handleStartDebug = useCallback(() => {
if (!nodeId || !workflowDebugData) return;
// 先将当前节点设置为入口节点
onChangeNode({
nodeId,
type: 'attr',
key: 'isEntry',
value: true
});
// 然后调用onNextNodeDebug函数
onNextNodeDebug();
}, [nodeId, workflowDebugData, onNextNodeDebug, onChangeNode]);
useEffect(() => { useEffect(() => {
if (interactive.type === 'userInput') { if (interactive.type === 'userInput') {
const defaultValues = interactive.params.inputForm?.reduce( const defaultValues = interactive.params.inputForm?.reduce(
@@ -375,37 +579,15 @@ export const RenderUserFormInteractive = React.memo(function RenderFormInput({
))} ))}
<Flex w={'full'} justifyContent={'flex-end'} mt={3} gap={2}> <Flex w={'full'} justifyContent={'flex-end'} mt={3} gap={2}>
{!isSubmitted && !interactive.params.submitted && ( <Button
<Button type="submit"
type="submit" size="sm"
colorScheme="blue" leftIcon={<MyIcon name={'core/workflow/debugNext'} w={'16px'} />}
size="md" colorScheme="blue"
height="44px" variant="solid"
px={8} >
fontWeight="medium" {t('common:Submit')}
borderRadius="md" </Button>
boxShadow="sm"
_hover={{ transform: 'translateY(-1px)', boxShadow: 'md' }}
_active={{ transform: 'translateY(0)' }}
transition="all 0.2s"
>
{t('common:Submit')}
</Button>
)}
{/* 提交完成后显示下一步按钮 */}
{(isSubmitted || interactive.params.submitted) && (
<Button
size="md"
height="44px"
leftIcon={<MyIcon name={'core/workflow/debugNext'} w={'16px'} />}
colorScheme="blue"
variant="solid"
onClick={handleStartDebug}
>
{t('common:common.Next Step')}
</Button>
)}
</Flex> </Flex>
</Flex> </Flex>
</Box> </Box>

View File

@@ -10,6 +10,7 @@ export type PostWorkflowDebugProps = {
variables: Record<string, any>; variables: Record<string, any>;
appId: string; appId: string;
query?: UserChatItemValueItemType[]; query?: UserChatItemValueItemType[];
history?: ChatItemType[];
}; };
export type PostWorkflowDebugResponse = { export type PostWorkflowDebugResponse = {

View File

@@ -830,6 +830,7 @@ const NodeDebugResponse = React.memo(function NodeDebugResponse({
</Button> </Button>
)} )}
{(debugResult.status === 'success' || debugResult.status === 'skipped') && {(debugResult.status === 'success' || debugResult.status === 'skipped') &&
!firstInteractive &&
!debugResult.isExpired && !debugResult.isExpired &&
workflowDebugData?.nextRunNodes && workflowDebugData?.nextRunNodes &&
workflowDebugData.nextRunNodes.length > 0 && ( workflowDebugData.nextRunNodes.length > 0 && (

View File

@@ -36,7 +36,6 @@ import WorkflowEventContextProvider from './workflowEventContext';
import { getAppConfigByDiff } from '@/web/core/app/diff'; import { getAppConfigByDiff } from '@/web/core/app/diff';
import WorkflowStatusContextProvider from './workflowStatusContext'; import WorkflowStatusContextProvider from './workflowStatusContext';
import { ChatItemType, UserChatItemValueItemType } from '@fastgpt/global/core/chat/type'; import { ChatItemType, UserChatItemValueItemType } from '@fastgpt/global/core/chat/type';
import { ChatRoleEnum, ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants';
/* /*
Context Context
@@ -163,35 +162,35 @@ type WorkflowContextType = {
runtimeNodes: RuntimeNodeItemType[]; runtimeNodes: RuntimeNodeItemType[];
runtimeEdges: RuntimeEdgeItemType[]; runtimeEdges: RuntimeEdgeItemType[];
nextRunNodes: RuntimeNodeItemType[]; nextRunNodes: RuntimeNodeItemType[];
query?: UserChatItemValueItemType[];
variables: Record<string, any>; variables: Record<string, any>;
query?: UserChatItemValueItemType[];
history?: ChatItemType[];
} }
| undefined; | undefined;
setWorkflowDebugData: React.Dispatch< onNextNodeDebug: (
React.SetStateAction< history?: ChatItemType[],
| { query?: UserChatItemValueItemType[],
runtimeNodes: RuntimeNodeItemType[]; debugData?: {
runtimeEdges: RuntimeEdgeItemType[]; runtimeNodes: RuntimeNodeItemType[];
nextRunNodes: RuntimeNodeItemType[]; runtimeEdges: RuntimeEdgeItemType[];
query?: UserChatItemValueItemType[]; nextRunNodes: RuntimeNodeItemType[];
variables: Record<string, any>; variables: Record<string, any>;
} }
| undefined ) => Promise<void>;
>
>;
onNextNodeDebug: () => Promise<void>;
onStartNodeDebug: ({ onStartNodeDebug: ({
entryNodeId, entryNodeId,
runtimeNodes, runtimeNodes,
runtimeEdges, runtimeEdges,
variables,
query, query,
variables history
}: { }: {
entryNodeId: string; entryNodeId: string;
runtimeNodes: RuntimeNodeItemType[]; runtimeNodes: RuntimeNodeItemType[];
runtimeEdges: RuntimeEdgeItemType[]; runtimeEdges: RuntimeEdgeItemType[];
query?: UserChatItemValueItemType[];
variables: Record<string, any>; variables: Record<string, any>;
query?: UserChatItemValueItemType[];
history?: ChatItemType[];
}) => Promise<void>; }) => Promise<void>;
onStopNodeDebug: () => void; onStopNodeDebug: () => void;
@@ -212,7 +211,6 @@ type DebugDataType = {
runtimeEdges: RuntimeEdgeItemType[]; runtimeEdges: RuntimeEdgeItemType[];
nextRunNodes: RuntimeNodeItemType[]; nextRunNodes: RuntimeNodeItemType[];
variables: Record<string, any>; variables: Record<string, any>;
query?: UserChatItemValueItemType[];
}; };
export const WorkflowContext = createContext<WorkflowContextType>({ export const WorkflowContext = createContext<WorkflowContextType>({
@@ -255,31 +253,25 @@ export const WorkflowContext = createContext<WorkflowContextType>({
throw new Error('Function not implemented.'); throw new Error('Function not implemented.');
}, },
workflowDebugData: undefined, workflowDebugData: undefined,
setWorkflowDebugData: function ( onNextNodeDebug: function (
value: React.SetStateAction< history?: ChatItemType[],
| { query?: UserChatItemValueItemType[],
runtimeNodes: RuntimeNodeItemType[]; debugData?: any
runtimeEdges: RuntimeEdgeItemType[]; ): Promise<void> {
nextRunNodes: RuntimeNodeItemType[];
query?: UserChatItemValueItemType[];
variables: Record<string, any>;
}
| undefined
>
): void {
throw new Error('Function not implemented.');
},
onNextNodeDebug: function (): Promise<void> {
throw new Error('Function not implemented.'); throw new Error('Function not implemented.');
}, },
onStartNodeDebug: function ({ onStartNodeDebug: function ({
entryNodeId, entryNodeId,
runtimeNodes, runtimeNodes,
runtimeEdges runtimeEdges,
query,
history
}: { }: {
entryNodeId: string; entryNodeId: string;
runtimeNodes: RuntimeNodeItemType[]; runtimeNodes: RuntimeNodeItemType[];
runtimeEdges: RuntimeEdgeItemType[]; runtimeEdges: RuntimeEdgeItemType[];
query?: UserChatItemValueItemType[];
history?: ChatItemType[];
}): Promise<void> { }): Promise<void> {
throw new Error('Function not implemented.'); throw new Error('Function not implemented.');
}, },
@@ -582,39 +574,13 @@ const WorkflowContextProvider = ({
}); });
/* debug */ /* debug */
const [workflowDebugData, setWorkflowDebugData] = useState< const [workflowDebugData, setWorkflowDebugData] = useState<DebugDataType>();
DebugDataType & {
query?: UserChatItemValueItemType[];
}
>();
// 添加这个函数用于捕获入口节点的输入值
const captureEntryInputValues = (entryNodeId: string, nodes: RuntimeNodeItemType[]) => {
const entryNode = nodes.find((node) => node.nodeId === entryNodeId);
if (!entryNode || !entryNode.inputs) return null;
// 提取用户输入值
const userInput = entryNode.inputs.find((input) => input.key === 'userChatInput')?.value || '';
return userInput;
};
// 添加函数用于准备调试数据
const prepareDebugData = (entryNodeId: string, nodes: RuntimeNodeItemType[]) => {
const userInput = captureEntryInputValues(entryNodeId, nodes);
if (!userInput) return null;
// 构建查询项
const queryItem: UserChatItemValueItemType = {
type: ChatItemValueTypeEnum.text,
text: {
content: userInput
}
};
return {
query: [queryItem]
};
};
const onNextNodeDebug = useCallback( const onNextNodeDebug = useCallback(
async (debugData = workflowDebugData) => { async (
history?: ChatItemType[],
query?: UserChatItemValueItemType[],
debugData = workflowDebugData
) => {
if (!debugData) return; if (!debugData) return;
// 1. Cancel node selected status and debugResult.showStatus // 1. Cancel node selected status and debugResult.showStatus
setNodes((state) => setNodes((state) =>
@@ -674,7 +640,7 @@ const WorkflowContextProvider = ({
}); });
try { try {
// 4. Run one step - 添加历史记录和查询到请求中 // 4. Run one step
const { finishedEdges, finishedNodes, nextStepRunNodes, flowResponses, newVariables } = const { finishedEdges, finishedNodes, nextStepRunNodes, flowResponses, newVariables } =
await postWorkflowDebug({ await postWorkflowDebug({
nodes: runtimeNodes, nodes: runtimeNodes,
@@ -684,7 +650,8 @@ const WorkflowContextProvider = ({
cTime: formatTime2YMDHMW(), cTime: formatTime2YMDHMW(),
...debugData.variables ...debugData.variables
}, },
query: debugData.query || [], query, // 添加 query 参数
history,
appId appId
}); });
// 5. Store debug result // 5. Store debug result
@@ -694,7 +661,8 @@ const WorkflowContextProvider = ({
runtimeEdges: finishedEdges, runtimeEdges: finishedEdges,
nextRunNodes: nextStepRunNodes, nextRunNodes: nextStepRunNodes,
variables: newVariables, variables: newVariables,
query: debugData.query // 保留查询 query,
history
}; };
setWorkflowDebugData(newStoreDebugData); setWorkflowDebugData(newStoreDebugData);
@@ -739,7 +707,7 @@ const WorkflowContextProvider = ({
// Check for an empty response // Check for an empty response
if (flowResponses.length === 0 && nextStepRunNodes.length > 0) { if (flowResponses.length === 0 && nextStepRunNodes.length > 0) {
onNextNodeDebug(newStoreDebugData); onNextNodeDebug(history, query, newStoreDebugData);
} }
} catch (error) { } catch (error) {
entryNodes.forEach((node) => { entryNodes.forEach((node) => {
@@ -777,25 +745,29 @@ const WorkflowContextProvider = ({
entryNodeId, entryNodeId,
runtimeNodes, runtimeNodes,
runtimeEdges, runtimeEdges,
variables variables,
query,
history
}: { }: {
entryNodeId: string; entryNodeId: string;
runtimeNodes: RuntimeNodeItemType[]; runtimeNodes: RuntimeNodeItemType[];
runtimeEdges: RuntimeEdgeItemType[]; runtimeEdges: RuntimeEdgeItemType[];
variables: Record<string, any>; variables: Record<string, any>;
query?: UserChatItemValueItemType[];
history?: ChatItemType[];
}) => { }) => {
const debugHistoryData = prepareDebugData(entryNodeId, runtimeNodes);
const data = { const data = {
runtimeNodes, runtimeNodes,
runtimeEdges, runtimeEdges,
nextRunNodes: runtimeNodes.filter((node) => node.nodeId === entryNodeId), nextRunNodes: runtimeNodes.filter((node) => node.nodeId === entryNodeId),
query: debugHistoryData?.query || [], variables,
variables query,
history
}; };
onStopNodeDebug(); onStopNodeDebug();
setWorkflowDebugData(data); setWorkflowDebugData(data);
onNextNodeDebug(data); onNextNodeDebug(history, query, data);
} }
); );
@@ -1059,7 +1031,6 @@ const WorkflowContextProvider = ({
flowData2StoreData, flowData2StoreData,
// debug // debug
setWorkflowDebugData,
workflowDebugData, workflowDebugData,
onNextNodeDebug, onNextNodeDebug,
onStartNodeDebug, onStartNodeDebug,

View File

@@ -10,9 +10,7 @@ import { NextAPI } from '@/service/middleware/entry';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { defaultApp } from '@/web/core/app/constants'; import { defaultApp } from '@/web/core/app/constants';
import { WORKFLOW_MAX_RUN_TIMES } from '@fastgpt/service/core/workflow/constants'; import { WORKFLOW_MAX_RUN_TIMES } from '@fastgpt/service/core/workflow/constants';
import { ChatItemValueTypeEnum, ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
import { ChatItemType, UserChatItemValueItemType } from '@fastgpt/global/core/chat/type'; import { ChatItemType, UserChatItemValueItemType } from '@fastgpt/global/core/chat/type';
import { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
async function handler( async function handler(
req: NextApiRequest, req: NextApiRequest,
@@ -24,10 +22,10 @@ async function handler(
variables = {}, variables = {},
appId, appId,
query: requestQuery, query: requestQuery,
histories: requestHistories history: requestHistories
} = req.body as PostWorkflowDebugProps & { } = req.body as PostWorkflowDebugProps & {
query?: UserChatItemValueItemType[]; query?: UserChatItemValueItemType[];
histories?: ChatItemType[]; history?: ChatItemType[];
}; };
if (!nodes) { if (!nodes) {
@@ -39,26 +37,16 @@ async function handler(
if (!Array.isArray(edges)) { if (!Array.isArray(edges)) {
throw new Error('Edges is not array'); throw new Error('Edges is not array');
} }
const entryNode = nodes.find((node) => node.isEntry === true);
if (!entryNode) {
throw new Error('No entry node found');
}
const query_form_input: UserChatItemValueItemType[] = requestQuery || [ const isEntryNodeInteractive =
{ entryNode.flowNodeType === 'formInput' || entryNode.flowNodeType === 'userSelect';
type: ChatItemValueTypeEnum.text,
text: {
content: '{"未知":"未知","数字":2}'
}
}
];
const query: UserChatItemValueItemType[] = const histories: ChatItemType[] = isEntryNodeInteractive ? requestHistories || [] : [];
requestQuery || const query: UserChatItemValueItemType[] = requestQuery || [];
[
// {
// type: ChatItemValueTypeEnum.text,
// text: {
// content: 'Cancel'
// }
// }
];
/* user auth */ /* user auth */
const [{ teamId, tmbId }, { app }] = await Promise.all([ const [{ teamId, tmbId }, { app }] = await Promise.all([
@@ -96,7 +84,7 @@ async function handler(
variables, variables,
query: query, query: query,
chatConfig: defaultApp.chatConfig, chatConfig: defaultApp.chatConfig,
histories: [], histories: histories,
stream: false, stream: false,
maxRunTimes: WORKFLOW_MAX_RUN_TIMES maxRunTimes: WORKFLOW_MAX_RUN_TIMES
}); });