mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-05 16:10:43 +00:00
fix: sre-agent error propogation (#10383)
### **PR Type**
Bug fix
___
### **Description**
- Display streamed `error` events in chat
- Finalize active tool calls on errors
- Persist error messages to history
- Stop further stream processing on error
___
### Diagram Walkthrough
```mermaid
flowchart LR
stream["Streamed event payloads"]
toolcall["Active tool call state"]
chat["Assistant chat message"]
history["Saved chat history"]
stream -- "type=error" --> toolcall
toolcall -- "finalize tool_call block" --> chat
stream -- "format error + suggestion" --> chat
chat -- "saveToHistory()" --> history
```
<details> <summary><h3> File Walkthrough</h3></summary>
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Bug
fix</strong></td><td><table>
<tr>
<td>
<details>
<summary><strong>O2AIChat.vue</strong><dd><code>Handle streamed errors
and finalize tool calls</code>
</dd></summary>
<hr>
web/src/components/O2AIChat.vue
<ul><li>Add <code>data.type === 'error'</code> handling in stream
loops<br> <li> Convert any <code>activeToolCall</code> into a completed
<code>tool_call</code> block<br> <li> Append/create assistant message
with formatted error and optional <br>suggestion<br> <li> Save error to
history, scroll, then return</ul>
</details>
</td>
<td><a
href="https://github.com/openobserve/openobserve/pull/10383/files#diff-a6a125719a7b32b31b53fcfe05c12081d82c139a401699affdda0db8e73887e3">+112/-0</a>
</td>
</tr>
</table></td></tr></tr></tbody></table>
</details>
___
This commit is contained in:
@@ -816,6 +816,71 @@ export default defineComponent({
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle error events - display error message to user
|
||||
if (data && data.type === 'error') {
|
||||
// Complete any active tool call first
|
||||
let lastMessage = chatMessages.value[chatMessages.value.length - 1];
|
||||
if (activeToolCall.value) {
|
||||
const completedToolBlock: ContentBlock = {
|
||||
type: 'tool_call',
|
||||
tool: activeToolCall.value.tool,
|
||||
message: activeToolCall.value.message,
|
||||
context: activeToolCall.value.context
|
||||
};
|
||||
if (lastMessage && lastMessage.role === 'assistant') {
|
||||
if (!lastMessage.contentBlocks) lastMessage.contentBlocks = [];
|
||||
lastMessage.contentBlocks.push(completedToolBlock);
|
||||
} else {
|
||||
pendingToolCalls.value.push(completedToolBlock);
|
||||
}
|
||||
activeToolCall.value = null;
|
||||
}
|
||||
|
||||
// Format error message with suggestion if available
|
||||
// Handle case where error/message might be an object instead of string
|
||||
const rawError = data.error ?? data.message ?? 'An unexpected error occurred';
|
||||
const errorText = typeof rawError === 'string' ? rawError : JSON.stringify(rawError, null, 2);
|
||||
|
||||
let errorMessage = `Error: ${errorText}`;
|
||||
if (data.suggestion) {
|
||||
errorMessage += `\n\n${data.suggestion}`;
|
||||
}
|
||||
|
||||
// Get or create assistant message for error (reuse lastMessage)
|
||||
lastMessage = chatMessages.value[chatMessages.value.length - 1];
|
||||
if (!lastMessage || lastMessage.role !== 'assistant') {
|
||||
chatMessages.value.push({
|
||||
role: 'assistant',
|
||||
content: errorMessage,
|
||||
contentBlocks: [...pendingToolCalls.value, { type: 'text', text: errorMessage }]
|
||||
});
|
||||
pendingToolCalls.value = [];
|
||||
} else {
|
||||
// Append error to existing message
|
||||
if (lastMessage.content) {
|
||||
lastMessage.content += '\n\n' + errorMessage;
|
||||
} else {
|
||||
lastMessage.content = errorMessage;
|
||||
}
|
||||
if (!lastMessage.contentBlocks) {
|
||||
lastMessage.contentBlocks = [];
|
||||
}
|
||||
lastMessage.contentBlocks.push({ type: 'text', text: errorMessage });
|
||||
// Clear pending tool calls to avoid leaking into later messages
|
||||
pendingToolCalls.value = [];
|
||||
}
|
||||
|
||||
// Reset streaming state
|
||||
currentTextSegment.value = '';
|
||||
|
||||
// Save error message to history
|
||||
await saveToHistory();
|
||||
await scrollToBottom();
|
||||
|
||||
// Stop processing further as error occurred
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle complete events - complete any active tool call
|
||||
if (data && data.type === 'complete') {
|
||||
if (activeToolCall.value) {
|
||||
@@ -969,6 +1034,71 @@ export default defineComponent({
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle error events - display error message to user
|
||||
if (data && data.type === 'error') {
|
||||
// Complete any active tool call first
|
||||
let lastMessage = chatMessages.value[chatMessages.value.length - 1];
|
||||
if (activeToolCall.value) {
|
||||
const completedToolBlock: ContentBlock = {
|
||||
type: 'tool_call',
|
||||
tool: activeToolCall.value.tool,
|
||||
message: activeToolCall.value.message,
|
||||
context: activeToolCall.value.context
|
||||
};
|
||||
if (lastMessage && lastMessage.role === 'assistant') {
|
||||
if (!lastMessage.contentBlocks) lastMessage.contentBlocks = [];
|
||||
lastMessage.contentBlocks.push(completedToolBlock);
|
||||
} else {
|
||||
pendingToolCalls.value.push(completedToolBlock);
|
||||
}
|
||||
activeToolCall.value = null;
|
||||
}
|
||||
|
||||
// Format error message with suggestion if available
|
||||
// Handle case where error/message might be an object instead of string
|
||||
const rawError = data.error ?? data.message ?? 'An unexpected error occurred';
|
||||
const errorText = typeof rawError === 'string' ? rawError : JSON.stringify(rawError, null, 2);
|
||||
|
||||
let errorMessage = `Error: ${errorText}`;
|
||||
if (data.suggestion) {
|
||||
errorMessage += `\n\n${data.suggestion}`;
|
||||
}
|
||||
|
||||
// Get or create assistant message for error (reuse lastMessage)
|
||||
lastMessage = chatMessages.value[chatMessages.value.length - 1];
|
||||
if (!lastMessage || lastMessage.role !== 'assistant') {
|
||||
chatMessages.value.push({
|
||||
role: 'assistant',
|
||||
content: errorMessage,
|
||||
contentBlocks: [...pendingToolCalls.value, { type: 'text', text: errorMessage }]
|
||||
});
|
||||
pendingToolCalls.value = [];
|
||||
} else {
|
||||
// Append error to existing message
|
||||
if (lastMessage.content) {
|
||||
lastMessage.content += '\n\n' + errorMessage;
|
||||
} else {
|
||||
lastMessage.content = errorMessage;
|
||||
}
|
||||
if (!lastMessage.contentBlocks) {
|
||||
lastMessage.contentBlocks = [];
|
||||
}
|
||||
lastMessage.contentBlocks.push({ type: 'text', text: errorMessage });
|
||||
// Clear pending tool calls to avoid leaking into later messages
|
||||
pendingToolCalls.value = [];
|
||||
}
|
||||
|
||||
// Reset streaming state
|
||||
currentTextSegment.value = '';
|
||||
|
||||
// Save error message to history
|
||||
await saveToHistory();
|
||||
await scrollToBottom();
|
||||
|
||||
// Stop processing further as error occurred
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle complete events - complete any active tool call
|
||||
if (data && data.type === 'complete') {
|
||||
if (activeToolCall.value) {
|
||||
|
||||
Reference in New Issue
Block a user