Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion web-ui/src/components/chat/ChatPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,14 @@
if (chatSessionId && chatSessionId !== sessionId) {
setSessionId(chatSessionId)
}
}, [chatSessionId])

Check warning on line 102 in web-ui/src/components/chat/ChatPanel.tsx

View workflow job for this annotation

GitHub Actions / web-ui

React Hook useEffect has a missing dependency: 'sessionId'. Either include it or remove the dependency array

const [configLoaded, setConfigLoaded] = useState(false)
const messagesEndRef = useRef<HTMLDivElement>(null)
const scrollContainerRef = useRef<HTMLDivElement>(null)
const shouldAutoScroll = useRef(true)
const textareaRef = useRef<HTMLTextAreaElement>(null)
const mentionPopupRef = useRef<{ _handleKeyDown?: (e: KeyboardEvent) => boolean } | null>(null)

Check warning on line 109 in web-ui/src/components/chat/ChatPanel.tsx

View workflow job for this annotation

GitHub Actions / web-ui

'mentionPopupRef' is assigned a value but never used
const abortControllerRef = useRef<AbortController | null>(null)
const reconnectingRef = useRef(false)
const messagesRef = useRef(messages)
Expand Down Expand Up @@ -300,7 +300,7 @@
}
}
if (auth.isAuthenticated) loadHistory()
}, [sessionId, auth.isAuthenticated])

Check warning on line 303 in web-ui/src/components/chat/ChatPanel.tsx

View workflow job for this annotation

GitHub Actions / web-ui

React Hook useEffect has missing dependencies: 'auth.user?.id_token' and 'deckId'. Either include them or remove the dependency array

// Reconnect to running background session (Local mode)
// Uses EventSource with Last-Event-ID for seamless SSE resume.
Expand Down Expand Up @@ -466,7 +466,7 @@
setAllDecks(data.decks)
}
if (auth.isAuthenticated) loadDecks()
}, [auth.isAuthenticated])

Check warning on line 469 in web-ui/src/components/chat/ChatPanel.tsx

View workflow job for this annotation

GitHub Actions / web-ui

React Hook useEffect has a missing dependency: 'auth.user?.id_token'. Either include it or remove the dependency array

useEffect(() => {
if (shouldAutoScroll.current) {
Expand Down Expand Up @@ -518,7 +518,7 @@
})

setMentionItems(items)
}, [slidePreviewUrls, allDecks, deckId])

Check warning on line 521 in web-ui/src/components/chat/ChatPanel.tsx

View workflow job for this annotation

GitHub Actions / web-ui

React Hook useEffect has a missing dependency: 'deckName'. Either include it or remove the dependency array

/**
* Handle file selection from + menu or drag-and-drop.
Expand Down Expand Up @@ -892,11 +892,21 @@
if (err instanceof DOMException && err.name === "AbortError") {
// Keep partial response as-is
} else {
const errorMessage = err instanceof Error ? err.message : String(err)
const isRetryable = errorMessage.includes("ThrottlingException") || errorMessage.includes("throttl")
|| errorMessage.includes("timed out") || errorMessage.includes("timeout")
|| errorMessage.includes("not ready") || errorMessage.includes("ServiceUnavailable")
const isConversationLimit = errorMessage.includes("Too much media") || errorMessage.includes("too long")
const displayMessage = isConversationLimit
? "This conversation is too long for the model to process. Please start a new chat to continue."
: isRetryable
? "The service is temporarily busy or timed out. Please wait a moment and try again."
: "Sorry, something went wrong. Please try again."
setMessages((prev) => {
const updated = [...prev]
updated[updated.length - 1] = {
...updated[updated.length - 1],
content: "Sorry, something went wrong. Please try again.",
content: displayMessage,
}
return updated
})
Expand Down
22 changes: 22 additions & 0 deletions web-ui/src/services/strandsParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,28 @@ export const parseStreamingChunk = (line, currentCompletion, updateCallback, too
// Keep-alive
if (json.keepalive) return currentCompletion;

// Agent-level error (e.g. Bedrock ValidationException, image/token limit exceeded)
if (json.status === 'error' && json.error) {
const msg = json.error;
let errorMessage;
if (msg.includes("Too much media") || msg.includes("too long")) {
errorMessage = "⚠️ This conversation is too long for the model to process. Please start a new chat to continue.";
} else if (msg.includes("ThrottlingException") || msg.includes("throttl")) {
errorMessage = "⚠️ The service is temporarily busy. Please wait a moment and try again.";
} else if (msg.includes("ModelTimeoutException") || msg.includes("timed out") || msg.includes("timeout")) {
errorMessage = "⚠️ The model took too long to respond. Please try again.";
} else if (msg.includes("ModelNotReadyException") || msg.includes("not ready")) {
errorMessage = "⚠️ The model is not ready yet. Please wait a moment and try again.";
} else if (msg.includes("ServiceUnavailable")) {
errorMessage = "⚠️ The service is temporarily unavailable. Please try again later.";
} else {
errorMessage = `⚠️ ${msg}`;
}
const newCompletion = currentCompletion + errorMessage;
updateCallback(newCompletion);
return newCompletion;
}

// MCP status event — pass to toolCallback with special type
if (json.mcp_status) {
if (toolCallback) toolCallback('__mcp_status__', { mcpStatus: json.mcp_status });
Expand Down
Loading