fix: clarify ai runtime errors
This commit is contained in:
@@ -21,6 +21,11 @@ function formatDuration(ms?: number) {
|
||||
if (ms < 1000) return `${ms}ms`;
|
||||
return `${(ms / 1000).toFixed(2)}s`;
|
||||
}
|
||||
|
||||
function getLogError(log: ExecutionLogEntry) {
|
||||
const item = log as any;
|
||||
return item.error || item.error_message || item.message || '';
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -52,10 +57,10 @@ function formatDuration(ms?: number) {
|
||||
{{ log.node_type }}
|
||||
</div>
|
||||
<div
|
||||
v-if="log.error"
|
||||
v-if="getLogError(log)"
|
||||
class="text-destructive mt-1 line-clamp-2 text-xs"
|
||||
>
|
||||
{{ log.error }}
|
||||
{{ getLogError(log) }}
|
||||
</div>
|
||||
</button>
|
||||
</ElTimelineItem>
|
||||
|
||||
@@ -178,7 +178,7 @@ const collaborationTimeline = computed(() => {
|
||||
subtitle: log.node_label || log.node_id,
|
||||
status: log.status,
|
||||
summary: summaryParts.join(' · '),
|
||||
message: communication.message || previewValue(log.error || log.output),
|
||||
message: communication.message || previewValue(getLogError(log) || log.output),
|
||||
elapsed: log.elapsed_time,
|
||||
timestamp,
|
||||
tokens: log.tokens_used || 0,
|
||||
@@ -233,7 +233,7 @@ const collaborationSupportSummary = computed(() => {
|
||||
log.node_type,
|
||||
log.branch_label,
|
||||
previewValue(log.output),
|
||||
previewValue(log.error),
|
||||
previewValue(getLogError(log)),
|
||||
].join(' '),
|
||||
)
|
||||
.join(' ')
|
||||
@@ -432,6 +432,21 @@ function getCollaboration(log: any) {
|
||||
return getLogMeta(log).collaboration || {};
|
||||
}
|
||||
|
||||
function getLogError(log: any) {
|
||||
const meta = getLogMeta(log);
|
||||
const communication = meta.communication || {};
|
||||
return (
|
||||
log?.error ||
|
||||
log?.error_message ||
|
||||
log?.message ||
|
||||
meta.error ||
|
||||
meta.error_message ||
|
||||
communication.error ||
|
||||
communication.message ||
|
||||
''
|
||||
);
|
||||
}
|
||||
|
||||
function getActorName(log: any) {
|
||||
const communication = getCommunication(log);
|
||||
const actor = communication.actor || {};
|
||||
@@ -747,8 +762,8 @@ defineExpose({ open });
|
||||
</template>
|
||||
|
||||
<div class="space-y-3 text-xs">
|
||||
<div v-if="log.error" class="text-destructive break-words">
|
||||
{{ log.error }}
|
||||
<div v-if="getLogError(log)" class="text-destructive break-words">
|
||||
{{ getLogError(log) }}
|
||||
</div>
|
||||
<div
|
||||
v-if="getCollaboration(log).agent_code || getCommunication(log).channel"
|
||||
|
||||
@@ -89,6 +89,15 @@ watch(
|
||||
const generateId = () =>
|
||||
`msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
||||
|
||||
const getStreamErrorMessage = (
|
||||
event: Error | Partial<WorkflowStreamEvent> | any,
|
||||
) =>
|
||||
event?.error_message ||
|
||||
event?.message ||
|
||||
event?.error ||
|
||||
event?.content ||
|
||||
$t('ai-platform.workflow.editor.chatPanel.execFailed');
|
||||
|
||||
// 发送消息
|
||||
const handleSend = (text: string) => {
|
||||
if (!text || running.value) return;
|
||||
@@ -222,17 +231,13 @@ const runWorkflow = (userMessage: string, inputs: Record<string, any>) => {
|
||||
},
|
||||
(error) => {
|
||||
console.error('Stream error:', error);
|
||||
const errorMessage = getStreamErrorMessage(error);
|
||||
updateAssistantMessage(assistantMsgId, {
|
||||
status: 'failed',
|
||||
error_message:
|
||||
error.message ||
|
||||
$t('ai-platform.workflow.editor.chatPanel.execFailed'),
|
||||
error_message: errorMessage,
|
||||
});
|
||||
running.value = false;
|
||||
ElMessage.error(
|
||||
error.message ||
|
||||
$t('ai-platform.workflow.editor.chatPanel.workflowExecFailed'),
|
||||
);
|
||||
ElMessage.error(errorMessage);
|
||||
},
|
||||
() => {
|
||||
cancelStream = null;
|
||||
@@ -355,11 +360,10 @@ const handleStreamEvent = (event: WorkflowStreamEvent, msgId: string) => {
|
||||
}
|
||||
|
||||
case 'error': {
|
||||
const errorMessage = getStreamErrorMessage(event);
|
||||
updateAssistantMessage(msgId, {
|
||||
status: 'failed',
|
||||
error_message:
|
||||
event.message ||
|
||||
$t('ai-platform.workflow.editor.chatPanel.execFailed'),
|
||||
error_message: errorMessage,
|
||||
});
|
||||
running.value = false;
|
||||
break;
|
||||
@@ -698,17 +702,13 @@ const resumeWorkflow = (userInput: any) => {
|
||||
},
|
||||
(error) => {
|
||||
console.error('Resume stream error:', error);
|
||||
const errorMessage = getStreamErrorMessage(error);
|
||||
updateAssistantMessage(assistantMsgId, {
|
||||
status: 'failed',
|
||||
error_message:
|
||||
error.message ||
|
||||
$t('ai-platform.workflow.editor.chatPanel.resumeFailed'),
|
||||
error_message: errorMessage,
|
||||
});
|
||||
running.value = false;
|
||||
ElMessage.error(
|
||||
error.message ||
|
||||
$t('ai-platform.workflow.editor.chatPanel.resumeWorkflowFailed'),
|
||||
);
|
||||
ElMessage.error(errorMessage);
|
||||
},
|
||||
() => {
|
||||
cancelStream = null;
|
||||
|
||||
@@ -152,6 +152,15 @@ const formatTime = (ms: number | undefined) => {
|
||||
return `${(ms / 1000).toFixed(1)}s`;
|
||||
};
|
||||
|
||||
const getStreamErrorMessage = (
|
||||
event: Error | Partial<WorkflowStreamEvent> | any,
|
||||
) =>
|
||||
event?.error_message ||
|
||||
event?.message ||
|
||||
event?.error ||
|
||||
event?.content ||
|
||||
$t('ai-platform.workflow.editor.runPanel.execFailed');
|
||||
|
||||
const handleRun = () => {
|
||||
if (!props.workflowId) return;
|
||||
running.value = true;
|
||||
@@ -185,15 +194,14 @@ const handleRun = () => {
|
||||
|
||||
case 'error': {
|
||||
stopTimer();
|
||||
const errorMessage = getStreamErrorMessage(event);
|
||||
// 将当前运行中的节点标记为失败(优先使用事件中的 node_id)
|
||||
const failedNodeId = event.node_id || currentNodeId.value;
|
||||
if (failedNodeId) {
|
||||
const state = nodeStates.value.get(failedNodeId);
|
||||
if (state && state.status === 'running') {
|
||||
state.status = 'failed';
|
||||
state.error_message =
|
||||
event.message ||
|
||||
$t('ai-platform.workflow.editor.runPanel.execFailed');
|
||||
state.error_message = errorMessage;
|
||||
state.elapsed_time = state.start_time
|
||||
? Date.now() - state.start_time
|
||||
: 0;
|
||||
@@ -201,16 +209,14 @@ const handleRun = () => {
|
||||
node_id: failedNodeId,
|
||||
node_type: state.node_type,
|
||||
status: 'failed',
|
||||
error_message:
|
||||
event.message ||
|
||||
$t('ai-platform.workflow.editor.runPanel.execFailed'),
|
||||
error_message: errorMessage,
|
||||
});
|
||||
}
|
||||
currentNodeId.value = '';
|
||||
}
|
||||
result.value = {
|
||||
status: 'failed',
|
||||
error_message: event.message,
|
||||
error_message: errorMessage,
|
||||
execution_log: nodeStateList.value,
|
||||
};
|
||||
running.value = false;
|
||||
@@ -400,32 +406,26 @@ const handleRun = () => {
|
||||
(error) => {
|
||||
console.error('Stream error:', error);
|
||||
stopTimer();
|
||||
const errorMessage = getStreamErrorMessage(error);
|
||||
// 将当前运行中的节点标记为失败
|
||||
if (currentNodeId.value) {
|
||||
const state = nodeStates.value.get(currentNodeId.value);
|
||||
if (state && state.status === 'running') {
|
||||
state.status = 'failed';
|
||||
state.error_message =
|
||||
error.message ||
|
||||
$t('ai-platform.workflow.editor.runPanel.execFailed');
|
||||
state.error_message = errorMessage;
|
||||
emit('node-complete', {
|
||||
node_id: currentNodeId.value,
|
||||
node_type: state.node_type,
|
||||
status: 'failed',
|
||||
error_message:
|
||||
error.message ||
|
||||
$t('ai-platform.workflow.editor.runPanel.execFailed'),
|
||||
error_message: errorMessage,
|
||||
});
|
||||
}
|
||||
currentNodeId.value = '';
|
||||
}
|
||||
ElMessage.error(
|
||||
error.message ||
|
||||
$t('ai-platform.workflow.editor.runPanel.workflowExecFailed'),
|
||||
);
|
||||
ElMessage.error(errorMessage);
|
||||
result.value = {
|
||||
status: 'failed',
|
||||
error_message: error.message,
|
||||
error_message: errorMessage,
|
||||
execution_log: nodeStateList.value,
|
||||
};
|
||||
running.value = false;
|
||||
|
||||
@@ -314,6 +314,18 @@ function getWorkflowFinalOutput(outputs?: Record<string, any>) {
|
||||
return previewRunValue(nodeValues.at(-1) || outputs, 800);
|
||||
}
|
||||
|
||||
function getWorkflowErrorMessage(
|
||||
event: Error | Partial<WorkflowStreamEvent> | any,
|
||||
) {
|
||||
return (
|
||||
event?.error_message ||
|
||||
event?.message ||
|
||||
event?.error ||
|
||||
event?.content ||
|
||||
'流程运行失败'
|
||||
);
|
||||
}
|
||||
|
||||
function pushRunEvent(
|
||||
title: string,
|
||||
status: 'failed' | 'info' | 'running' | 'success' | 'warning' = 'info',
|
||||
@@ -451,8 +463,7 @@ function handleWorkflowRunEvent(event: WorkflowStreamEvent) {
|
||||
}
|
||||
case 'error': {
|
||||
runStatus.value = 'failed';
|
||||
runError.value =
|
||||
event.message || event.error_message || event.error || '流程运行失败';
|
||||
runError.value = getWorkflowErrorMessage(event);
|
||||
pushRunEvent('流程运行失败', 'failed', runError.value);
|
||||
ElMessage.error(runError.value);
|
||||
cancelWorkflowRunStream = null;
|
||||
@@ -477,7 +488,7 @@ function handleRunWorkflow(inputs: Record<string, any>) {
|
||||
handleWorkflowRunEvent,
|
||||
(error) => {
|
||||
runStatus.value = 'failed';
|
||||
runError.value = error.message || '流程运行失败';
|
||||
runError.value = getWorkflowErrorMessage(error);
|
||||
pushRunEvent('流程运行失败', 'failed', runError.value);
|
||||
ElMessage.error(runError.value);
|
||||
cancelWorkflowRunStream = null;
|
||||
|
||||
@@ -50,6 +50,11 @@ function resolveNodeOutput(log: ExecutionLogEntry, run: WorkflowRun) {
|
||||
};
|
||||
}
|
||||
|
||||
function getLogError(log: ExecutionLogEntry) {
|
||||
const item = log as any;
|
||||
return item.error || item.error_message || item.message || '';
|
||||
}
|
||||
|
||||
function buildReplayInputs(
|
||||
logIndex: number,
|
||||
logs: ExecutionLogEntry[],
|
||||
@@ -122,13 +127,13 @@ export function applyRunReplay(
|
||||
status: isWaiting ? 'running' : isSuccess ? 'success' : 'failed',
|
||||
elapsed_time: log.elapsed_time,
|
||||
tokens_used: log.tokens_used,
|
||||
error: log.error,
|
||||
error: getLogError(log),
|
||||
},
|
||||
executionResult: {
|
||||
status: mapLogStatus(log.status || 'completed'),
|
||||
elapsed_time: log.elapsed_time,
|
||||
tokens_used: log.tokens_used,
|
||||
error_message: log.error,
|
||||
error_message: getLogError(log),
|
||||
output: nodeOutput,
|
||||
inputs: nodeInputs,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user