feat: abort call on pipeline error and send rtf event

This commit is contained in:
Abhishek Kumar 2026-03-05 14:51:39 +05:30
parent 1614879ddd
commit dfb741e475
9 changed files with 86 additions and 10 deletions

View file

@ -20,6 +20,8 @@ interface RealtimeFeedbackEvent {
ttfb_seconds?: number;
processor?: string;
model?: string;
error?: string;
fatal?: boolean;
};
timestamp: string;
turn: number;
@ -74,13 +76,16 @@ function convertLogEventsToTranscriptEvents(events: RealtimeFeedbackEvent[]): Tr
case 'rtf-ttfb-metric':
type = 'ttfb-metric';
break;
case 'rtf-pipeline-error':
type = 'pipeline-error';
break;
default:
type = 'bot-text';
}
return {
type,
text: event.payload.text || event.payload.result || event.payload.function_name || event.payload.node_name || '',
text: event.payload.text || event.payload.error || event.payload.result || event.payload.function_name || event.payload.node_name || '',
final: event.payload.final,
timestamp: event.timestamp,
turn: event.turn,
@ -91,6 +96,7 @@ function convertLogEventsToTranscriptEvents(events: RealtimeFeedbackEvent[]): Tr
ttfbSeconds: event.payload.ttfb_seconds,
processor: event.payload.processor,
model: event.payload.model,
fatal: event.payload.fatal,
};
});
}
@ -111,6 +117,7 @@ function convertLiveMessagesToTranscriptEvents(messages: FeedbackMessage[]): Tra
ttfbSeconds: msg.ttfbSeconds,
processor: msg.processor,
model: msg.model,
fatal: msg.fatal,
}));
}

View file

@ -49,6 +49,7 @@ export const UnifiedTranscript = ({
status: msg.status,
nodeName: msg.nodeName,
ttfbSeconds: msg.ttfbSeconds,
fatal: msg.fatal,
}));
// Default empty state

View file

@ -1,17 +1,18 @@
'use client';
import { Brain, GitBranch, Wrench } from 'lucide-react';
import { AlertTriangle, Brain, GitBranch, Wrench } from 'lucide-react';
import { cn } from '@/lib/utils';
export interface TranscriptMessageData {
id: string;
type: 'user-transcription' | 'bot-text' | 'function-call' | 'node-transition' | 'ttfb-metric';
type: 'user-transcription' | 'bot-text' | 'function-call' | 'node-transition' | 'ttfb-metric' | 'pipeline-error';
text: string;
final?: boolean;
functionName?: string;
nodeName?: string;
ttfbSeconds?: number;
fatal?: boolean;
}
interface TranscriptMessageProps {
@ -36,6 +37,23 @@ export function TranscriptMessage({ message, nextMessage }: TranscriptMessagePro
);
}
// Pipeline error - show as a red alert
if (message.type === 'pipeline-error') {
return (
<div className="flex items-start gap-2 px-3 py-2 rounded-lg bg-red-500/10 border border-red-500/20">
<AlertTriangle className="h-4 w-4 text-red-500 mt-0.5 shrink-0" />
<div className="flex-1 min-w-0">
<div className="text-xs font-medium text-red-700 dark:text-red-400">
{message.fatal ? 'Fatal Pipeline Error' : 'Pipeline Error'}
</div>
<div className="text-sm text-red-600 dark:text-red-300 mt-0.5 break-words">
{message.text}
</div>
</div>
</div>
);
}
// TTFB metric - don't render standalone, it'll be shown with bot messages and function calls
if (message.type === 'ttfb-metric') {
return null;

View file

@ -18,7 +18,7 @@ interface UseWebSocketRTCProps {
export interface FeedbackMessage {
id: string;
type: 'user-transcription' | 'bot-text' | 'function-call' | 'node-transition' | 'ttfb-metric';
type: 'user-transcription' | 'bot-text' | 'function-call' | 'node-transition' | 'ttfb-metric' | 'pipeline-error';
text: string;
final?: boolean;
timestamp: string;
@ -31,6 +31,8 @@ export interface FeedbackMessage {
ttfbSeconds?: number;
processor?: string;
model?: string;
// Pipeline error fields
fatal?: boolean;
}
export const useWebSocketRTC = ({ workflowId, workflowRunId, accessToken, initialContextVariables }: UseWebSocketRTCProps) => {
@ -400,6 +402,19 @@ export const useWebSocketRTC = ({ workflowId, workflowRunId, accessToken, initia
break;
}
case 'rtf-pipeline-error': {
const { error, fatal, processor: errorProcessor } = message.payload;
setFeedbackMessages(prev => [...prev, {
id: `error-${Date.now()}`,
type: 'pipeline-error',
text: error,
fatal,
processor: errorProcessor,
timestamp: new Date().toISOString(),
}]);
break;
}
default:
logger.warn('Unknown message type:', message.type);
}

View file

@ -4,7 +4,7 @@
*/
export interface TranscriptEvent {
type: 'user-transcription' | 'bot-text' | 'function-call' | 'node-transition' | 'ttfb-metric';
type: 'user-transcription' | 'bot-text' | 'function-call' | 'node-transition' | 'ttfb-metric' | 'pipeline-error';
text: string;
final?: boolean;
timestamp: string;
@ -16,6 +16,7 @@ export interface TranscriptEvent {
ttfbSeconds?: number;
processor?: string;
model?: string;
fatal?: boolean;
}
export interface ProcessedMessage {
@ -28,6 +29,7 @@ export interface ProcessedMessage {
status?: 'running' | 'completed';
nodeName?: string;
ttfbSeconds?: number;
fatal?: boolean;
}
/**
@ -143,5 +145,6 @@ function convertToProcessedMessage(event: TranscriptEvent, overrideText?: string
status: event.status,
nodeName: event.nodeName,
ttfbSeconds: event.ttfbSeconds,
fatal: event.fatal,
};
}