feat: enhance error handling for LLM API calls
Add LLM error alert functionality to display specific error messages based on API responses. Introduce new LlmErrorAlertType interface for structured error alerts. Update chat components to manage and display LLM error alerts effectively, improving user feedback during error scenarios.
This commit is contained in:
109
app/components/chat/LLMApiAlert.tsx
Normal file
109
app/components/chat/LLMApiAlert.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import type { LlmErrorAlertType } from '~/types/actions';
|
||||
import { classNames } from '~/utils/classNames';
|
||||
|
||||
interface Props {
|
||||
alert: LlmErrorAlertType;
|
||||
clearAlert: () => void;
|
||||
}
|
||||
|
||||
export default function LlmErrorAlert({ alert, clearAlert }: Props) {
|
||||
const { title, description, provider, errorType } = alert;
|
||||
|
||||
const getErrorIcon = () => {
|
||||
switch (errorType) {
|
||||
case 'authentication':
|
||||
return 'i-ph:key-duotone';
|
||||
case 'rate_limit':
|
||||
return 'i-ph:clock-duotone';
|
||||
case 'quota':
|
||||
return 'i-ph:warning-circle-duotone';
|
||||
default:
|
||||
return 'i-ph:warning-duotone';
|
||||
}
|
||||
};
|
||||
|
||||
const getErrorMessage = () => {
|
||||
switch (errorType) {
|
||||
case 'authentication':
|
||||
return `Authentication failed with ${provider}. Please check your API key.`;
|
||||
case 'rate_limit':
|
||||
return `Rate limit exceeded for ${provider}. Please wait before retrying.`;
|
||||
case 'quota':
|
||||
return `Quota exceeded for ${provider}. Please check your account limits.`;
|
||||
default:
|
||||
return 'An error occurred while processing your request.';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: -20 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className="rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-background-depth-2 p-4 mb-2"
|
||||
>
|
||||
<div className="flex items-start">
|
||||
<motion.div
|
||||
className="flex-shrink-0"
|
||||
initial={{ scale: 0 }}
|
||||
animate={{ scale: 1 }}
|
||||
transition={{ delay: 0.2 }}
|
||||
>
|
||||
<div className={`${getErrorIcon()} text-xl text-bolt-elements-button-danger-text`}></div>
|
||||
</motion.div>
|
||||
|
||||
<div className="ml-3 flex-1">
|
||||
<motion.h3
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.1 }}
|
||||
className="text-sm font-medium text-bolt-elements-textPrimary"
|
||||
>
|
||||
{title}
|
||||
</motion.h3>
|
||||
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.2 }}
|
||||
className="mt-2 text-sm text-bolt-elements-textSecondary"
|
||||
>
|
||||
<p>{getErrorMessage()}</p>
|
||||
|
||||
{description && (
|
||||
<div className="text-xs text-bolt-elements-textSecondary p-2 bg-bolt-elements-background-depth-3 rounded mt-4 mb-4">
|
||||
Error Details: {description}
|
||||
</div>
|
||||
)}
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className="mt-4"
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.3 }}
|
||||
>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onClick={clearAlert}
|
||||
className={classNames(
|
||||
'px-2 py-1.5 rounded-md text-sm font-medium',
|
||||
'bg-bolt-elements-button-secondary-background',
|
||||
'hover:bg-bolt-elements-button-secondary-backgroundHover',
|
||||
'focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-bolt-elements-button-secondary-background',
|
||||
'text-bolt-elements-button-secondary-text',
|
||||
)}
|
||||
>
|
||||
Dismiss
|
||||
</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user