feat: improve agent workflow observability

This commit is contained in:
2026-06-14 14:46:24 +08:00
parent c293cb5e3b
commit 3f75c966c2
7 changed files with 187 additions and 11 deletions
@@ -164,6 +164,12 @@ export function useEventHandler(config: EventHandlerConfig) {
return fallbackLabel || nodeType || '';
};
const getItemCount = (value: any): number => {
if (Array.isArray(value)) return value.length;
if (value && typeof value === 'object') return Object.keys(value).length;
return 0;
};
/** 处理流式事件 */
const handleStreamEvent = (event: StreamEvent, msgId: string) => {
switch (event.type) {
@@ -272,9 +278,18 @@ export function useEventHandler(config: EventHandlerConfig) {
}
case 'error': {
currentSteps.value.push({
type: 'error',
content: event.message || event.content || '执行失败',
node_id: event.node_id,
node_type: event.node_type,
status: 'completed',
timestamp: new Date().toISOString(),
});
updateAssistantMessage(msgId, {
status: 'failed',
error_message: event.message || event.content || '执行失败',
reasoning_steps: [...currentSteps.value],
});
running.value = false;
break;
@@ -322,6 +337,19 @@ export function useEventHandler(config: EventHandlerConfig) {
outputs[outputVar] = loopEvent.loop_results;
}
currentSteps.value.push({
type: 'loop_complete',
content: '循环执行完成',
node_id: loopEvent.node_id,
node_type: 'loop',
output: outputs,
status: 'completed',
timestamp: new Date().toISOString(),
});
updateAssistantMessage(msgId, {
reasoning_steps: [...currentSteps.value],
});
if (props.enableNodeEvents) {
emit('node-complete', {
node_id: loopEvent.node_id,
@@ -336,6 +364,19 @@ export function useEventHandler(config: EventHandlerConfig) {
}
case 'loop_iteration_complete': {
currentSteps.value.push({
type: 'loop_iteration_complete',
content: `循环第 ${event.iteration || '-'} 次完成`,
node_id: event.node_id,
node_type: 'loop',
output: event.output,
status: 'completed',
timestamp: new Date().toISOString(),
});
updateAssistantMessage(msgId, {
reasoning_steps: [...currentSteps.value],
});
if (props.enableNodeEvents) {
emit('loop-iteration', {
node_id: event.node_id,
@@ -349,6 +390,18 @@ export function useEventHandler(config: EventHandlerConfig) {
}
case 'loop_iteration_error': {
currentSteps.value.push({
type: 'loop_iteration_error',
content: `循环第 ${event.iteration || '-'} 次失败:${event.error || '执行失败'}`,
node_id: event.node_id,
node_type: 'loop',
status: 'completed',
timestamp: new Date().toISOString(),
});
updateAssistantMessage(msgId, {
reasoning_steps: [...currentSteps.value],
});
if (props.enableNodeEvents) {
emit('loop-iteration', {
node_id: event.node_id,
@@ -362,6 +415,19 @@ export function useEventHandler(config: EventHandlerConfig) {
}
case 'loop_iteration_start': {
currentSteps.value.push({
type: 'loop_iteration_start',
content: `循环第 ${event.iteration || '-'} 次开始`,
node_id: event.node_id,
node_type: 'loop',
params: { item: event.item, total: event.total },
status: 'running',
timestamp: new Date().toISOString(),
});
updateAssistantMessage(msgId, {
reasoning_steps: [...currentSteps.value],
});
if (props.enableNodeEvents) {
emit('loop-iteration', {
node_id: event.node_id,
@@ -423,6 +489,60 @@ export function useEventHandler(config: EventHandlerConfig) {
break;
}
case 'parallel_complete': {
const existingIndex = currentSteps.value.findIndex(
(s) => s.node_id === event.node_id && s.type === 'parallel_start',
);
const branchResults = event.branch_results || {};
const content = `并行分支完成:${getItemCount(branchResults)} 个分支`;
if (existingIndex === -1) {
currentSteps.value.push({
type: 'parallel_complete',
content,
node_id: event.node_id,
node_type: 'parallel',
output: {
branch_results: branchResults,
total_tokens: event.total_tokens,
},
status: 'completed',
timestamp: new Date().toISOString(),
});
} else {
currentSteps.value[existingIndex] = {
...currentSteps.value[existingIndex]!,
type: 'parallel_complete',
content,
output: {
branch_results: branchResults,
total_tokens: event.total_tokens,
},
status: 'completed',
};
}
updateAssistantMessage(msgId, {
reasoning_steps: [...currentSteps.value],
});
break;
}
case 'parallel_start': {
const branches = event.branches || [];
currentSteps.value.push({
type: 'parallel_start',
content: `并行分支开始:${getItemCount(branches)} 个分支`,
node_id: event.node_id,
node_type: 'parallel',
params: { branches },
status: 'running',
timestamp: new Date().toISOString(),
});
updateAssistantMessage(msgId, {
reasoning_steps: [...currentSteps.value],
});
break;
}
case 'node_event': {
const nodeEvent = event.event;
if (nodeEvent?.type === 'message') {
@@ -493,12 +613,28 @@ export function useEventHandler(config: EventHandlerConfig) {
waitingConfig.value = event.waiting_config || event.config;
const configData = event.waiting_config || (event as any).config;
currentSteps.value.push({
type: 'waiting_input',
content:
configData?.title ||
configData?.question ||
event.node_label ||
'等待用户输入',
node_id: event.node_id,
node_type: event.node_type,
params: configData,
status: 'running',
timestamp: new Date().toISOString(),
});
if (configData?.type === 'design_preview') {
handleDesignPreview(event, msgId, configData);
} else {
handleDialogFlowInteraction(msgId, configData);
}
updateAssistantMessage(msgId, {
reasoning_steps: [...currentSteps.value],
});
running.value = false;
break;