{JSON.stringify(error.data, null, 2)}
+ ) Data: (code: )"
+ const jsonRpcMatch = errorMessage.match(JSON_RPC_CODE_REGEX);
+ const dataMatch = errorMessage.match(JSON_RPC_DATA_REGEX);
+ const messageMatch = errorMessage.match(JSON_RPC_MESSAGE_REGEX);
+
+ // Extract just the core error message without wrapper text
+ let message = errorMessage;
+ if (messageMatch?.[1]) {
+ message = messageMatch[1].trim();
+ } else {
+ // Remove common prefixes
+ message = message
+ .replace(ERROR_PREFIX_STREAMING_REGEX, '')
+ .replace(ERROR_PREFIX_SSE_REGEX, '')
+ .replace(ERROR_SUFFIX_CODE_REGEX, '')
+ .trim();
+ }
+
+ const code = jsonRpcMatch?.[1] ? Number.parseInt(jsonRpcMatch[1], 10) : -1;
+
+ let data: Record | undefined;
+ if (dataMatch?.[1]) {
+ try {
+ data = JSON.parse(dataMatch[1]);
+ } catch {
+ // Invalid JSON in data field
+ }
+ }
+
+ return {
+ code,
+ message: message || 'Unknown error',
+ data,
+ };
+};
+
type StreamMessageParams = {
prompt: string;
agentId: string;
@@ -196,10 +260,38 @@ export const streamMessage = async ({
success: true,
};
} catch (error) {
- const connectError = ConnectError.from(error);
- toast.error(formatToastErrorMessageGRPC({ error: connectError, action: 'stream', entity: 'message' }));
+ // Parse JSON-RPC error details
+ const a2aError = parseA2AError(error);
+
+ // Create error content block
+ const errorBlock: ContentBlock = {
+ type: 'a2a-error',
+ error: a2aError,
+ timestamp: new Date(),
+ };
+
+ // Build message with error block
+ const errorMessage = buildMessageWithContentBlocks({
+ baseMessage: assistantMessage,
+ contentBlocks: [errorBlock],
+ taskId: undefined,
+ taskState: 'failed',
+ taskStartIndex: undefined,
+ });
+
+ // Update database with error
+ await updateMessage(assistantMessage.id, {
+ content: '',
+ isStreaming: false,
+ taskState: 'failed',
+ contentBlocks: [errorBlock],
+ });
+
+ // Notify caller about error message
+ onMessageUpdate(errorMessage);
+
return {
- assistantMessage,
+ assistantMessage: errorMessage,
success: false,
};
}
diff --git a/frontend/src/components/pages/agents/details/a2a/chat/types.ts b/frontend/src/components/pages/agents/details/a2a/chat/types.ts
index 637a5b9ff9..d8f410c405 100644
--- a/frontend/src/components/pages/agents/details/a2a/chat/types.ts
+++ b/frontend/src/components/pages/agents/details/a2a/chat/types.ts
@@ -9,7 +9,7 @@
* by the Apache License, Version 2.0
*/
-import type { TaskState } from '@a2a-js/sdk';
+import type { JSONRPCError, TaskState } from '@a2a-js/sdk';
import type { AIAgent } from 'protogen/redpanda/api/dataplane/v1alpha3/ai_agent_pb';
/**
@@ -55,6 +55,11 @@ export type ContentBlock =
final: boolean;
timestamp: Date;
usage?: MessageUsageMetadata;
+ }
+ | {
+ type: 'a2a-error';
+ error: JSONRPCError;
+ timestamp: Date;
};
// Message-level usage metadata (stored in database)