Feat: Get the running log of each message through the trace interface #3221 (#8711)

### What problem does this PR solve?
Feat: Get the running log of each message through the trace interface
#3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-07-08 09:27:56 +08:00
committed by GitHub
parent 30065e2f43
commit 3e1e908422
7 changed files with 88 additions and 18 deletions

View File

@ -115,6 +115,7 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
setCurrentMessageId,
currentEventListWithoutMessage,
clearEventList,
currentMessageId,
} = useCacheChatLog();
const { showLogSheet, logSheetVisible, hideLogSheet } = useShowLogSheet({
@ -221,6 +222,7 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
<LogSheet
hideModal={hideLogSheet}
currentEventListWithoutMessage={currentEventListWithoutMessage}
currentMessageId={currentMessageId}
></LogSheet>
)}
</div>

View File

@ -57,5 +57,6 @@ export function useCacheChatLog() {
filterEventListByEventType,
filterEventListByMessageId,
setCurrentMessageId,
currentMessageId,
};
}

View File

@ -18,23 +18,24 @@ import {
SheetHeader,
SheetTitle,
} from '@/components/ui/sheet';
import {
ILogData,
ILogEvent,
MessageEventType,
} from '@/hooks/use-send-message';
import { useFetchMessageTrace } from '@/hooks/use-agent-request';
import { ILogEvent, MessageEventType } from '@/hooks/use-send-message';
import { IModalProps } from '@/interfaces/common';
import { ITraceData } from '@/interfaces/database/agent';
import { cn } from '@/lib/utils';
import { isEmpty } from 'lodash';
import { BellElectric, NotebookText } from 'lucide-react';
import { useCallback, useMemo } from 'react';
import { useCallback, useEffect, useMemo } from 'react';
import JsonView from 'react18-json-view';
import 'react18-json-view/src/style.css';
import { useCacheChatLog } from '../hooks/use-cache-chat-log';
import useGraphStore from '../store';
type LogSheetProps = IModalProps<any> &
Pick<ReturnType<typeof useCacheChatLog>, 'currentEventListWithoutMessage'>;
Pick<
ReturnType<typeof useCacheChatLog>,
'currentEventListWithoutMessage' | 'currentMessageId'
>;
function JsonViewer({
data,
@ -78,9 +79,16 @@ type EventWithIndex = { startNodeIdx: number } & ILogEvent;
export function LogSheet({
hideModal,
currentEventListWithoutMessage,
currentMessageId,
}: LogSheetProps) {
const getNode = useGraphStore((state) => state.getNode);
const { data: traceData, setMessageId } = useFetchMessageTrace();
useEffect(() => {
setMessageId(currentMessageId);
}, [currentMessageId, setMessageId]);
const getNodeName = useCallback(
(nodeId: string) => {
return getNode(nodeId)?.data.name;
@ -88,6 +96,28 @@ export function LogSheet({
[getNode],
);
const hasTrace = useCallback(
(componentId: string) => {
if (Array.isArray(traceData)) {
return traceData?.some((x) => x.component_id === componentId);
}
},
[traceData],
);
const filterTrace = useCallback(
(componentId: string) => {
return traceData
?.filter((x) => x.component_id === componentId)
.reduce<ITraceData['trace']>((pre, cur) => {
pre.push(...cur.trace);
return pre;
}, []);
},
[traceData],
);
// Look up to find the nearest start component id and concatenate the finish and log data into one
const finishedNodeList = useMemo(() => {
return currentEventListWithoutMessage.filter(
@ -109,19 +139,14 @@ export function LogSheet({
const item = pre.find((x) => x.startNodeIdx === startNodeIdx);
const { logs = {}, inputs = {}, outputs = {} } = cur.data;
const { inputs = {}, outputs = {} } = cur.data;
if (item) {
const {
inputs: inputList,
outputs: outputList,
logs: logList,
} = item.data;
const { inputs: inputList, outputs: outputList } = item.data;
item.data = {
...item.data,
inputs: concatData(inputList, inputs),
outputs: concatData(outputList, outputs),
logs: concatData(logList, logs),
};
} else {
pre.push({
@ -195,10 +220,10 @@ export function LogSheet({
title="Input"
></JsonViewer>
{isEmpty((x.data as ILogData)?.logs) || (
{hasTrace(x.data.component_id) && (
<JsonViewer
data={(x.data as ILogData)?.logs}
title={'Logs'}
data={filterTrace(x.data.component_id) ?? {}}
title={'Trace'}
></JsonViewer>
)}