Feat: Combine the output logs of the same operator together #3221 (#8638)

### What problem does this PR solve?

Feat: Combine the output logs of the same operator together #3221

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
balibabu
2025-07-02 19:21:40 +08:00
committed by GitHub
parent 4243330d5c
commit 747da87a1e
2 changed files with 90 additions and 6 deletions

View File

@ -13,6 +13,7 @@ export enum MessageEventType {
MessageEnd = 'message_end',
WorkflowFinished = 'workflow_finished',
UserInputs = 'user_inputs',
NodeLogs = 'node_logs',
}
export interface IAnswerEvent<T> {
@ -42,12 +43,25 @@ export interface IMessageData {
content: string;
}
export interface ILogData extends INodeData {
logs: {
name: string;
result: string;
args: {
query: string;
topic: string;
};
};
}
export type INodeEvent = IAnswerEvent<INodeData>;
export type IMessageEvent = IAnswerEvent<IMessageData>;
export type IInputEvent = IAnswerEvent<IInputData>;
export type ILogEvent = IAnswerEvent<ILogData>;
export type IChatEvent = INodeEvent | IMessageEvent;
export type IEventList = Array<IChatEvent>;

View File

@ -18,9 +18,14 @@ import {
SheetHeader,
SheetTitle,
} from '@/components/ui/sheet';
import { INodeEvent, MessageEventType } from '@/hooks/use-send-message';
import {
ILogData,
ILogEvent,
MessageEventType,
} from '@/hooks/use-send-message';
import { IModalProps } from '@/interfaces/common';
import { cn } from '@/lib/utils';
import { isEmpty } from 'lodash';
import { BellElectric, NotebookText } from 'lucide-react';
import { useCallback, useMemo } from 'react';
import JsonView from 'react18-json-view';
@ -51,6 +56,25 @@ function JsonViewer({
);
}
function concatData(
firstRecord: Record<string, any> | Array<Record<string, any>>,
nextRecord: Record<string, any> | Array<Record<string, any>>,
) {
let result: Array<Record<string, any>> = [];
if (!isEmpty(firstRecord)) {
result = result.concat(firstRecord);
}
if (!isEmpty(nextRecord)) {
result = result.concat(nextRecord);
}
return isEmpty(result) ? {} : result;
}
type EventWithIndex = { startNodeIdx: number } & ILogEvent;
export function LogSheet({
hideModal,
currentEventListWithoutMessage,
@ -64,12 +88,51 @@ export function LogSheet({
[getNode],
);
// Look up to find the nearest start component id and concatenate the finish and log data into one
const finishedNodeList = useMemo(() => {
return currentEventListWithoutMessage.filter(
(x) => x.event === MessageEventType.NodeFinished,
) as INodeEvent[];
(x) =>
x.event === MessageEventType.NodeFinished ||
x.event === MessageEventType.NodeLogs,
) as ILogEvent[];
}, [currentEventListWithoutMessage]);
console.log('🚀 ~ finishedNodeList ~ finishedNodeList:', finishedNodeList);
const nextList = useMemo(() => {
return finishedNodeList.reduce<Array<EventWithIndex>>((pre, cur) => {
const startNodeIdx = (
currentEventListWithoutMessage as Array<ILogEvent>
).findLastIndex(
(x) =>
x.data.component_id === cur.data.component_id &&
x.event === MessageEventType.NodeStarted,
);
const item = pre.find((x) => x.startNodeIdx === startNodeIdx);
const { logs = {}, inputs = {}, outputs = {} } = cur.data;
if (item) {
const {
inputs: inputList,
outputs: outputList,
logs: logList,
} = item.data;
item.data = {
...item.data,
inputs: concatData(inputList, inputs),
outputs: concatData(outputList, outputs),
logs: concatData(logList, logs),
};
} else {
pre.push({
...cur,
startNodeIdx,
});
}
return pre;
}, []);
}, [currentEventListWithoutMessage, finishedNodeList]);
return (
<Sheet open onOpenChange={hideModal} modal={false}>
@ -82,7 +145,7 @@ export function LogSheet({
</SheetHeader>
<section className="max-h-[82vh] overflow-auto mt-6">
<Timeline>
{finishedNodeList.map((x, idx) => (
{nextList.map((x, idx) => (
<TimelineItem
key={idx}
step={idx}
@ -132,9 +195,16 @@ export function LogSheet({
title="Input"
></JsonViewer>
{isEmpty((x.data as ILogData)?.logs) || (
<JsonViewer
data={(x.data as ILogData)?.logs}
title={'Logs'}
></JsonViewer>
)}
<JsonViewer
data={x.data.outputs}
title="Output"
title={'Output'}
></JsonViewer>
</div>
</AccordionContent>