| ... | @@ -123,7 +123,7 @@ import { | ... | @@ -123,7 +123,7 @@ import { |
| 123 | } from "../keybindings"; | 123 | } from "../keybindings"; |
| 124 | import ChatMarkdown from "./ChatMarkdown"; | 124 | import ChatMarkdown from "./ChatMarkdown"; |
| 125 | import ThreadTerminalDrawer from "./ThreadTerminalDrawer"; | 125 | import ThreadTerminalDrawer from "./ThreadTerminalDrawer"; |
| 126 | import { Alert, AlertDescription, AlertTitle } from "./ui/alert"; | 126 | import { Alert, AlertAction, AlertDescription, AlertTitle } from "./ui/alert"; |
| 127 | import { | 127 | import { |
| 128 | BotIcon, | 128 | BotIcon, |
| 129 | ChevronDownIcon, | 129 | ChevronDownIcon, |
| ... | @@ -3434,7 +3434,10 @@ export default function ChatView({ threadId }: ChatViewProps) { | ... | @@ -3434,7 +3434,10 @@ export default function ChatView({ threadId }: ChatViewProps) { |
| 3434 | | 3434 | |
| 3435 | {/* Error banner */} | 3435 | {/* Error banner */} |
| 3436 | <ProviderHealthBanner status={activeProviderStatus} /> | 3436 | <ProviderHealthBanner status={activeProviderStatus} /> |
| 3437 | <ThreadErrorBanner error={activeThread.error} /> | 3437 | <ThreadErrorBanner |
| | 3438 | error={activeThread.error} |
| | 3439 | onDismiss={() => setThreadError(activeThread.id, null)} |
| | 3440 | /> |
| 3438 | <PlanModePanel activePlan={activePlan} /> | 3441 | <PlanModePanel activePlan={activePlan} /> |
| 3439 | | 3442 | |
| 3440 | {/* Messages */} | 3443 | {/* Messages */} |
| ... | @@ -4095,7 +4098,13 @@ const ChatHeader = memo(function ChatHeader({ | ... | @@ -4095,7 +4098,13 @@ const ChatHeader = memo(function ChatHeader({ |
| 4095 | ); | 4098 | ); |
| 4096 | }); | 4099 | }); |
| 4097 | | 4100 | |
| 4098 | const ThreadErrorBanner = memo(function ThreadErrorBanner({ error }: { error: string | null }) { | 4101 | const ThreadErrorBanner = memo(function ThreadErrorBanner({ |
| | 4102 | error, |
| | 4103 | onDismiss, |
| | 4104 | }: { |
| | 4105 | error: string | null; |
| | 4106 | onDismiss?: () => void; |
| | 4107 | }) { |
| 4099 | if (!error) return null; | 4108 | if (!error) return null; |
| 4100 | return ( | 4109 | return ( |
| 4101 | <div className="pt-3 mx-auto max-w-3xl"> | 4110 | <div className="pt-3 mx-auto max-w-3xl"> |
| ... | @@ -4104,6 +4113,18 @@ const ThreadErrorBanner = memo(function ThreadErrorBanner({ error }: { error: st | ... | @@ -4104,6 +4113,18 @@ const ThreadErrorBanner = memo(function ThreadErrorBanner({ error }: { error: st |
| 4104 | <AlertDescription className="line-clamp-3" title={error}> | 4113 | <AlertDescription className="line-clamp-3" title={error}> |
| 4105 | {error} | 4114 | {error} |
| 4106 | </AlertDescription> | 4115 | </AlertDescription> |
| | 4116 | {onDismiss && ( |
| | 4117 | <AlertAction> |
| | 4118 | <button |
| | 4119 | type="button" |
| | 4120 | aria-label="Dismiss error" |
| | 4121 | className="inline-flex size-6 items-center justify-center rounded-md text-destructive/60 transition-colors hover:text-destructive" |
| | 4122 | onClick={onDismiss} |
| | 4123 | > |
| | 4124 | <XIcon className="size-3.5" /> |
| | 4125 | </button> |
| | 4126 | </AlertAction> |
| | 4127 | )} |
| 4107 | </Alert> | 4128 | </Alert> |
| 4108 | </div> | 4129 | </div> |
| 4109 | ); | 4130 | ); |