feat: add history parameter to PostWorkflowDebugProps and update related components
This commit is contained in:
@@ -16,9 +16,15 @@ import {
|
||||
} from '@fastgpt/global/core/workflow/template/system/interactive/type';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context';
|
||||
import { ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants';
|
||||
import { UserChatItemValueItemType } from '@fastgpt/global/core/chat/type';
|
||||
import { ChatItemValueTypeEnum, ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
|
||||
import {
|
||||
AIChatItemValueItemType,
|
||||
ChatItemType,
|
||||
UserChatItemValueItemType
|
||||
} from '@fastgpt/global/core/chat/type';
|
||||
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({
|
||||
interactive,
|
||||
@@ -29,42 +35,78 @@ export const RenderUserSelectInteractive = React.memo(function RenderInteractive
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [selectedValue, setSelectedValue] = useState<string | undefined>(undefined);
|
||||
const { onChangeNode, onNextNodeDebug, workflowDebugData, setWorkflowDebugData } =
|
||||
useContextSelector(WorkflowContext, (v) => ({
|
||||
// 在两个组件中更新上下文选择器,添加 onStartNodeDebug
|
||||
const { onChangeNode, onStartNodeDebug, workflowDebugData } = useContextSelector(
|
||||
WorkflowContext,
|
||||
(v) => ({
|
||||
onChangeNode: v.onChangeNode,
|
||||
onNextNodeDebug: v.onNextNodeDebug,
|
||||
workflowDebugData: v.workflowDebugData,
|
||||
setWorkflowDebugData: v.setWorkflowDebugData
|
||||
onStartNodeDebug: v.onStartNodeDebug,
|
||||
// onNextNodeDebug: v.onNextNodeDebug, // 不再使用
|
||||
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(
|
||||
(value: string) => {
|
||||
if (!nodeId || !workflowDebugData) return;
|
||||
|
||||
// 保存选中的值到本地状态
|
||||
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(() => {
|
||||
if (!nodeId || !workflowDebugData) return;
|
||||
|
||||
@@ -76,10 +118,67 @@ export const RenderUserSelectInteractive = React.memo(function RenderInteractive
|
||||
value: true
|
||||
});
|
||||
|
||||
// 然后调用onNextNodeDebug函数
|
||||
onNextNodeDebug();
|
||||
}, [nodeId, workflowDebugData, onNextNodeDebug, onChangeNode]);
|
||||
// 更新此节点的值(将用户选择保存到节点)
|
||||
if (selectedValue) {
|
||||
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 (
|
||||
<Box px={4} py={3}>
|
||||
{interactive?.params?.description && (
|
||||
@@ -155,7 +254,6 @@ export const RenderUserSelectInteractive = React.memo(function RenderInteractive
|
||||
</Box>
|
||||
);
|
||||
});
|
||||
|
||||
export const RenderUserFormInteractive = React.memo(function RenderFormInput({
|
||||
interactive,
|
||||
nodeId
|
||||
@@ -164,61 +262,167 @@ export const RenderUserFormInteractive = React.memo(function RenderFormInput({
|
||||
nodeId?: string;
|
||||
}) {
|
||||
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 { onChangeNode, onNextNodeDebug, workflowDebugData, setWorkflowDebugData } =
|
||||
useContextSelector(WorkflowContext, (v) => ({
|
||||
// 在两个组件中更新上下文选择器,添加 onStartNodeDebug
|
||||
const { onChangeNode, onStartNodeDebug, workflowDebugData } = useContextSelector(
|
||||
WorkflowContext,
|
||||
(v) => ({
|
||||
onChangeNode: v.onChangeNode,
|
||||
onNextNodeDebug: v.onNextNodeDebug,
|
||||
workflowDebugData: v.workflowDebugData,
|
||||
setWorkflowDebugData: v.setWorkflowDebugData
|
||||
onStartNodeDebug: v.onStartNodeDebug,
|
||||
workflowDebugData: v.workflowDebugData
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* 创建交互数据结构
|
||||
* @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(
|
||||
(data: any) => {
|
||||
if (!nodeId || !workflowDebugData) return;
|
||||
|
||||
// 标记表单已提交
|
||||
setIsSubmitted(true);
|
||||
|
||||
const jsonData = JSON.stringify(data);
|
||||
// 直接调用 handleStartDebug,合并提交和下一步操作
|
||||
const formData = getValues();
|
||||
|
||||
onChangeNode({
|
||||
nodeId,
|
||||
type: 'attr',
|
||||
key: 'isEntry',
|
||||
value: true
|
||||
});
|
||||
|
||||
// 更新查询以包含用户的表单数据
|
||||
const updatedQuery: UserChatItemValueItemType[] = [
|
||||
...(workflowDebugData.query || []),
|
||||
{
|
||||
type: ChatItemValueTypeEnum.text,
|
||||
text: {
|
||||
content: jsonData
|
||||
content: JSON.stringify(formData)
|
||||
}
|
||||
} as UserChatItemValueItemType
|
||||
];
|
||||
|
||||
// 更新工作流调试数据
|
||||
setWorkflowDebugData({
|
||||
...workflowDebugData,
|
||||
query: updatedQuery
|
||||
const updatedInteractive = {
|
||||
...interactive,
|
||||
params: {
|
||||
...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(() => {
|
||||
if (interactive.type === 'userInput') {
|
||||
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}>
|
||||
{!isSubmitted && !interactive.params.submitted && (
|
||||
<Button
|
||||
type="submit"
|
||||
colorScheme="blue"
|
||||
size="md"
|
||||
height="44px"
|
||||
px={8}
|
||||
fontWeight="medium"
|
||||
borderRadius="md"
|
||||
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>
|
||||
)}
|
||||
<Button
|
||||
type="submit"
|
||||
size="sm"
|
||||
leftIcon={<MyIcon name={'core/workflow/debugNext'} w={'16px'} />}
|
||||
colorScheme="blue"
|
||||
variant="solid"
|
||||
>
|
||||
{t('common:Submit')}
|
||||
</Button>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Box>
|
||||
|
||||
@@ -10,6 +10,7 @@ export type PostWorkflowDebugProps = {
|
||||
variables: Record<string, any>;
|
||||
appId: string;
|
||||
query?: UserChatItemValueItemType[];
|
||||
history?: ChatItemType[];
|
||||
};
|
||||
|
||||
export type PostWorkflowDebugResponse = {
|
||||
|
||||
@@ -830,6 +830,7 @@ const NodeDebugResponse = React.memo(function NodeDebugResponse({
|
||||
</Button>
|
||||
)}
|
||||
{(debugResult.status === 'success' || debugResult.status === 'skipped') &&
|
||||
!firstInteractive &&
|
||||
!debugResult.isExpired &&
|
||||
workflowDebugData?.nextRunNodes &&
|
||||
workflowDebugData.nextRunNodes.length > 0 && (
|
||||
|
||||
@@ -36,7 +36,6 @@ import WorkflowEventContextProvider from './workflowEventContext';
|
||||
import { getAppConfigByDiff } from '@/web/core/app/diff';
|
||||
import WorkflowStatusContextProvider from './workflowStatusContext';
|
||||
import { ChatItemType, UserChatItemValueItemType } from '@fastgpt/global/core/chat/type';
|
||||
import { ChatRoleEnum, ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants';
|
||||
|
||||
/*
|
||||
Context
|
||||
@@ -163,35 +162,35 @@ type WorkflowContextType = {
|
||||
runtimeNodes: RuntimeNodeItemType[];
|
||||
runtimeEdges: RuntimeEdgeItemType[];
|
||||
nextRunNodes: RuntimeNodeItemType[];
|
||||
query?: UserChatItemValueItemType[];
|
||||
variables: Record<string, any>;
|
||||
query?: UserChatItemValueItemType[];
|
||||
history?: ChatItemType[];
|
||||
}
|
||||
| undefined;
|
||||
setWorkflowDebugData: React.Dispatch<
|
||||
React.SetStateAction<
|
||||
| {
|
||||
runtimeNodes: RuntimeNodeItemType[];
|
||||
runtimeEdges: RuntimeEdgeItemType[];
|
||||
nextRunNodes: RuntimeNodeItemType[];
|
||||
query?: UserChatItemValueItemType[];
|
||||
variables: Record<string, any>;
|
||||
}
|
||||
| undefined
|
||||
>
|
||||
>;
|
||||
onNextNodeDebug: () => Promise<void>;
|
||||
onNextNodeDebug: (
|
||||
history?: ChatItemType[],
|
||||
query?: UserChatItemValueItemType[],
|
||||
debugData?: {
|
||||
runtimeNodes: RuntimeNodeItemType[];
|
||||
runtimeEdges: RuntimeEdgeItemType[];
|
||||
nextRunNodes: RuntimeNodeItemType[];
|
||||
variables: Record<string, any>;
|
||||
}
|
||||
) => Promise<void>;
|
||||
onStartNodeDebug: ({
|
||||
entryNodeId,
|
||||
runtimeNodes,
|
||||
runtimeEdges,
|
||||
variables,
|
||||
query,
|
||||
variables
|
||||
history
|
||||
}: {
|
||||
entryNodeId: string;
|
||||
runtimeNodes: RuntimeNodeItemType[];
|
||||
runtimeEdges: RuntimeEdgeItemType[];
|
||||
query?: UserChatItemValueItemType[];
|
||||
variables: Record<string, any>;
|
||||
query?: UserChatItemValueItemType[];
|
||||
history?: ChatItemType[];
|
||||
}) => Promise<void>;
|
||||
onStopNodeDebug: () => void;
|
||||
|
||||
@@ -212,7 +211,6 @@ type DebugDataType = {
|
||||
runtimeEdges: RuntimeEdgeItemType[];
|
||||
nextRunNodes: RuntimeNodeItemType[];
|
||||
variables: Record<string, any>;
|
||||
query?: UserChatItemValueItemType[];
|
||||
};
|
||||
|
||||
export const WorkflowContext = createContext<WorkflowContextType>({
|
||||
@@ -255,31 +253,25 @@ export const WorkflowContext = createContext<WorkflowContextType>({
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
workflowDebugData: undefined,
|
||||
setWorkflowDebugData: function (
|
||||
value: React.SetStateAction<
|
||||
| {
|
||||
runtimeNodes: RuntimeNodeItemType[];
|
||||
runtimeEdges: RuntimeEdgeItemType[];
|
||||
nextRunNodes: RuntimeNodeItemType[];
|
||||
query?: UserChatItemValueItemType[];
|
||||
variables: Record<string, any>;
|
||||
}
|
||||
| undefined
|
||||
>
|
||||
): void {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
onNextNodeDebug: function (): Promise<void> {
|
||||
onNextNodeDebug: function (
|
||||
history?: ChatItemType[],
|
||||
query?: UserChatItemValueItemType[],
|
||||
debugData?: any
|
||||
): Promise<void> {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
onStartNodeDebug: function ({
|
||||
entryNodeId,
|
||||
runtimeNodes,
|
||||
runtimeEdges
|
||||
runtimeEdges,
|
||||
query,
|
||||
history
|
||||
}: {
|
||||
entryNodeId: string;
|
||||
runtimeNodes: RuntimeNodeItemType[];
|
||||
runtimeEdges: RuntimeEdgeItemType[];
|
||||
query?: UserChatItemValueItemType[];
|
||||
history?: ChatItemType[];
|
||||
}): Promise<void> {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
@@ -582,39 +574,13 @@ const WorkflowContextProvider = ({
|
||||
});
|
||||
|
||||
/* debug */
|
||||
const [workflowDebugData, setWorkflowDebugData] = useState<
|
||||
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 [workflowDebugData, setWorkflowDebugData] = useState<DebugDataType>();
|
||||
const onNextNodeDebug = useCallback(
|
||||
async (debugData = workflowDebugData) => {
|
||||
async (
|
||||
history?: ChatItemType[],
|
||||
query?: UserChatItemValueItemType[],
|
||||
debugData = workflowDebugData
|
||||
) => {
|
||||
if (!debugData) return;
|
||||
// 1. Cancel node selected status and debugResult.showStatus
|
||||
setNodes((state) =>
|
||||
@@ -674,7 +640,7 @@ const WorkflowContextProvider = ({
|
||||
});
|
||||
|
||||
try {
|
||||
// 4. Run one step - 添加历史记录和查询到请求中
|
||||
// 4. Run one step
|
||||
const { finishedEdges, finishedNodes, nextStepRunNodes, flowResponses, newVariables } =
|
||||
await postWorkflowDebug({
|
||||
nodes: runtimeNodes,
|
||||
@@ -684,7 +650,8 @@ const WorkflowContextProvider = ({
|
||||
cTime: formatTime2YMDHMW(),
|
||||
...debugData.variables
|
||||
},
|
||||
query: debugData.query || [],
|
||||
query, // 添加 query 参数
|
||||
history,
|
||||
appId
|
||||
});
|
||||
// 5. Store debug result
|
||||
@@ -694,7 +661,8 @@ const WorkflowContextProvider = ({
|
||||
runtimeEdges: finishedEdges,
|
||||
nextRunNodes: nextStepRunNodes,
|
||||
variables: newVariables,
|
||||
query: debugData.query // 保留查询
|
||||
query,
|
||||
history
|
||||
};
|
||||
setWorkflowDebugData(newStoreDebugData);
|
||||
|
||||
@@ -739,7 +707,7 @@ const WorkflowContextProvider = ({
|
||||
|
||||
// Check for an empty response
|
||||
if (flowResponses.length === 0 && nextStepRunNodes.length > 0) {
|
||||
onNextNodeDebug(newStoreDebugData);
|
||||
onNextNodeDebug(history, query, newStoreDebugData);
|
||||
}
|
||||
} catch (error) {
|
||||
entryNodes.forEach((node) => {
|
||||
@@ -777,25 +745,29 @@ const WorkflowContextProvider = ({
|
||||
entryNodeId,
|
||||
runtimeNodes,
|
||||
runtimeEdges,
|
||||
variables
|
||||
variables,
|
||||
query,
|
||||
history
|
||||
}: {
|
||||
entryNodeId: string;
|
||||
runtimeNodes: RuntimeNodeItemType[];
|
||||
runtimeEdges: RuntimeEdgeItemType[];
|
||||
variables: Record<string, any>;
|
||||
query?: UserChatItemValueItemType[];
|
||||
history?: ChatItemType[];
|
||||
}) => {
|
||||
const debugHistoryData = prepareDebugData(entryNodeId, runtimeNodes);
|
||||
const data = {
|
||||
runtimeNodes,
|
||||
runtimeEdges,
|
||||
nextRunNodes: runtimeNodes.filter((node) => node.nodeId === entryNodeId),
|
||||
query: debugHistoryData?.query || [],
|
||||
variables
|
||||
variables,
|
||||
query,
|
||||
history
|
||||
};
|
||||
onStopNodeDebug();
|
||||
setWorkflowDebugData(data);
|
||||
|
||||
onNextNodeDebug(data);
|
||||
onNextNodeDebug(history, query, data);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1059,7 +1031,6 @@ const WorkflowContextProvider = ({
|
||||
flowData2StoreData,
|
||||
|
||||
// debug
|
||||
setWorkflowDebugData,
|
||||
workflowDebugData,
|
||||
onNextNodeDebug,
|
||||
onStartNodeDebug,
|
||||
|
||||
@@ -10,9 +10,7 @@ import { NextAPI } from '@/service/middleware/entry';
|
||||
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { defaultApp } from '@/web/core/app/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 { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
|
||||
async function handler(
|
||||
req: NextApiRequest,
|
||||
@@ -24,10 +22,10 @@ async function handler(
|
||||
variables = {},
|
||||
appId,
|
||||
query: requestQuery,
|
||||
histories: requestHistories
|
||||
history: requestHistories
|
||||
} = req.body as PostWorkflowDebugProps & {
|
||||
query?: UserChatItemValueItemType[];
|
||||
histories?: ChatItemType[];
|
||||
history?: ChatItemType[];
|
||||
};
|
||||
|
||||
if (!nodes) {
|
||||
@@ -39,26 +37,16 @@ async function handler(
|
||||
if (!Array.isArray(edges)) {
|
||||
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 || [
|
||||
{
|
||||
type: ChatItemValueTypeEnum.text,
|
||||
text: {
|
||||
content: '{"未知":"未知","数字":2}'
|
||||
}
|
||||
}
|
||||
];
|
||||
const isEntryNodeInteractive =
|
||||
entryNode.flowNodeType === 'formInput' || entryNode.flowNodeType === 'userSelect';
|
||||
|
||||
const query: UserChatItemValueItemType[] =
|
||||
requestQuery ||
|
||||
[
|
||||
// {
|
||||
// type: ChatItemValueTypeEnum.text,
|
||||
// text: {
|
||||
// content: 'Cancel'
|
||||
// }
|
||||
// }
|
||||
];
|
||||
const histories: ChatItemType[] = isEntryNodeInteractive ? requestHistories || [] : [];
|
||||
const query: UserChatItemValueItemType[] = requestQuery || [];
|
||||
|
||||
/* user auth */
|
||||
const [{ teamId, tmbId }, { app }] = await Promise.all([
|
||||
@@ -96,7 +84,7 @@ async function handler(
|
||||
variables,
|
||||
query: query,
|
||||
chatConfig: defaultApp.chatConfig,
|
||||
histories: [],
|
||||
histories: histories,
|
||||
stream: false,
|
||||
maxRunTimes: WORKFLOW_MAX_RUN_TIMES
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user