Repository navigation
Fix/mcp error handling - #128
Conversation
Integrate Centralized LLM Error Handling and Offline Preact Dashboard UIOverviewThis update introduces centralized LLM error categorization, standardized UI fallback error templates, and ActionCard support across agent integrations. Additionally, it ships a complete offline Preact and HTM frontend dashboard export with static JSON data shims. Technical Highlights
Impact
|
b1536ea to
6bc80af
Compare
Implement Centralized LLM Error Categorization and Action Card UIOverviewThis change introduces a centralized LLM error categorization system and maps error templates to UI action cards. It standardizes error handling across backend agent loops and improves frontend chat rendering with graceful failure messages. Technical Highlights
Impact
|
Centralize LLM Error Handling and Structured Action CardsOverviewThis update centralizes LLM error categorization in backend connectors to map raw SDK failures into standard UI states. It introduces structured action cards and collapsible debug logs across chat handlers and frontend components. Technical Highlights
Impact
|
Implement Structured AI Error Handling and Action CardsOverviewThis change introduces a standardized system for categorizing AI model errors and presenting user-friendly feedback. It integrates structured action cards into chat responses. This provides clear, actionable error messages and interactive elements for users. Technical Highlights
Impact
|
Implement Centralized LLM Error Handling and Action CardsOverviewThis update centralizes LLM error categorization, introduces structured action cards, and updates UI components to render rich error feedback. Backend modules now map provider errors into standardized templates, while frontend chat views safely display raw debug data and interactive UI actions. Technical Highlights
Impact
|
| const url = msg.actionCard?.action_url; | ||
| if (url === ACTION_RETRY) { | ||
| // Find the most recent user message before this error | ||
| let prevUserMsg = undefined; |
There was a problem hiding this comment.
Severity: info
Consider iterating backwards through the messages to find the most recent user message.
| } | ||
| } | ||
|
|
||
| if (prevUserMsg?.text) { |
There was a problem hiding this comment.
Severity: warning
Please check if prevUserMsg?.text is defined before calling the handleSend function.
Suggestions:
- Add null check for
prevUserMsg?.textbefore callinghandleSendto prevent potential errors.
| {msg.actionCard.button_text} | ||
| </button> | ||
| </div> | ||
| {msg.debugArtifacts?.raw_llm_error && ( |
There was a problem hiding this comment.
Severity: info
Display the raw LLM error in the debug logs.
| import { isDailyTrendChart, buildTrendSpec, formatAxisDate, Granularity } from './rebucketChart'; | ||
| import { buildJsonExport, downloadJsonExport } from './jsonExport'; | ||
| import ProductionUrlWarning from '../../components/ProductionUrlWarning'; | ||
| import { ChatActionCard } from './ChatActionCard'; |
There was a problem hiding this comment.
Severity: info
Import the ChatActionCard component.
| import { buildJsonExport, downloadJsonExport } from './jsonExport'; | ||
| import ProductionUrlWarning from '../../components/ProductionUrlWarning'; | ||
| import { ChatActionCard } from './ChatActionCard'; | ||
| import { ChatErrorBlockquote } from './ChatErrorHandling'; |
There was a problem hiding this comment.
Severity: info
Import the ChatErrorBlockquote component.
| const LiviLogo: React.FC<{ className?: string }> = ({ className = '' }) => ( | ||
| <div className={`w-12 flex-shrink-0 flex justify-center ${className}`}> | ||
| <img src="/assets/lrbot/lrbot.png" alt="Bot" width={32} height={32} decoding="async" className="w-8 h-8 rounded-full" /> | ||
| </div> |
There was a problem hiding this comment.
Severity: info
Refactor the LiviLogo component to directly return the img element.
| repaired_sql?: string; | ||
| }>; | ||
| }>; | ||
| raw_llm_error?: string; |
There was a problem hiding this comment.
Severity: info
Add a raw_llm_error field to the DebugArtifacts interface.
| } | ||
|
|
||
| interface ChatEntry { | ||
| export interface ChatEntry { |
There was a problem hiding this comment.
Severity: info
Export the ChatEntry interface to allow for external use.
| files?: ChatFile[]; | ||
| suggestedQuestions?: SuggestedQuestionCategory[]; | ||
| debugArtifacts?: DebugArtifacts | null; | ||
| isError?: boolean; |
There was a problem hiding this comment.
Severity: info
Add an isError field to the ChatEntry interface.
| suggestedQuestions?: SuggestedQuestionCategory[]; | ||
| debugArtifacts?: DebugArtifacts | null; | ||
| isError?: boolean; | ||
| actionCard?: { |
There was a problem hiding this comment.
Severity: info
Add an actionCard field to the ChatEntry interface.
| } | ||
|
|
||
| function formatText(rawText: string): React.ReactNode[] { | ||
| function formatText(rawText: string, isErrorMsg: boolean = false): React.ReactNode[] { |
There was a problem hiding this comment.
Severity: info
Add an isErrorMsg parameter to the formatText function.
| const isError = blockquoteLines.length > 0 && blockquoteLines[0].includes('Action Required:'); | ||
|
|
||
| if (isError) { | ||
| if (isErrorMsg) { |
There was a problem hiding this comment.
Severity: info
Conditionally render the ChatErrorBlockquote component when the message is an error.
| files: m.files && m.files.length > 0 ? m.files : undefined, | ||
| suggestedQuestions: m.suggested_questions, | ||
| debugArtifacts: m.debug_artifacts as DebugArtifacts | undefined, | ||
| isError: m.is_error, |
There was a problem hiding this comment.
Severity: info
Map the is_error field from the API response to the ChatEntry.
Summary
This PR adds error handling for LLM Provider connections. It improves the frontend parsing logic and the backend parsing logic for chat payloads. These changes remove extra work and extra memory allocations.
Backend Changes:
internal/aiconnectors/errors.goto interceptlangchaingonormalizations. It detects network timeouts. It combines the HTTP status code interfaces (StatusCodeandHTTPStatusCode). This removes duplicate code branches.internal/api/chat_conversations_handler.goandwebchat_handler.go. I replaced the full JSON marshal loop with direct map access and interface type assertions. It falls back to marshaling only when necessary. I restored the error logging for this fallback.internal/mcpagent/agent.go. This fixes static analysis warnings about potential map accesses or nil pointer accesses. I do this when I append Action Cards and debug artifacts to the history.Frontend Changes:
ChatActionCard.tsxwith a backwardsforloop. The loop uses no extra memory allocations.React.SyntheticEventtype union fromhandleSendinChatConversation.tsx. I added missing boundary checks for array accesses inChatErrorHandling.tsx. These checks prevent crashes on empty error states.extractPlainTextinslideshowParser.jsto useDOMParser. This completely strips HTML tags and decodes HTML entities (like&).Validation
I checked all MCP cases and verified that everything works.
Checklist
SECURITY.mdand updated related documentation if needed.