All files / src/components/chat ErrorBlockTitle.tsx

94.11% Statements 48/51
80% Branches 12/15
100% Functions 1/1
94.11% Lines 48/51

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 751x 1x 1x                           1x 5x 5x 5x 5x 5x 5x 5x 5x       5x 5x 1x 1x       5x 1x 5x 1x   5x     5x 5x 5x 5x 5x 1x 1x 5x     4x 1x 1x 1x 4x 1x 1x 1x 1x 1x 3x 1x 1x 1x 1x   5x 5x   5x 5x  
import React from "react"
import { AiHydroError, AiHydroErrorType } from "../../../../src/services/error/AiHydroError"
import { ProgressIndicator } from "./ChatRow"
 
interface ErrorBlockTitleProps {
	cost?: number
	apiReqCancelReason?: string
	apiRequestFailedMessage?: string
	retryStatus?: {
		attempt: number
		maxAttempts: number
		delaySec?: number
		errorSnippet?: string
	}
}
 
export const ErrorBlockTitle = ({
	cost,
	apiReqCancelReason,
	apiRequestFailedMessage,
	retryStatus,
}: ErrorBlockTitleProps): [React.ReactElement, React.ReactElement] => {
	const getIconSpan = (iconName: string, colorClass: string) => (
		<div className="w-4 h-4 flex items-center justify-center">
			<span className={`codicon codicon-${iconName} text-base -mb-0.5 ${colorClass}`}></span>
		</div>
	)
 
	const icon =
		apiReqCancelReason != null ? (
			apiReqCancelReason === "user_cancelled" ? (
				getIconSpan("error", "text-[var(--vscode-descriptionForeground)]")
			) : (
				getIconSpan("error", "text-[var(--vscode-errorForeground)]")
			)
		) : cost != null ? (
			getIconSpan("check", "text-[var(--vscode-charts-green)]")
		) : apiRequestFailedMessage ? (
			getIconSpan("error", "text-[var(--vscode-errorForeground)]")
		) : (
			<ProgressIndicator />
		)
 
	const title = (() => {
		// Default loading state
		const details = { title: "API Request...", classNames: ["font-bold"] }
		// Handle cancellation states first
		if (apiReqCancelReason === "user_cancelled") {
			details.title = "API Request Cancelled"
			details.classNames.push("text-[var(--vscode-foreground)]")
		} else if (apiReqCancelReason != null) {
			details.title = "API Request Failed"
			details.classNames.push("text-[var(--vscode-errorForeground)]")
		} else if (cost != null) {
			// Handle completed request
			details.title = "API Request"
			details.classNames.push("text-[var(--vscode-foreground)]")
		} else if (apiRequestFailedMessage) {
			// Handle failed request
			const clineError = AiHydroError.parse(apiRequestFailedMessage)
			const titleText = clineError?.isErrorType(AiHydroErrorType.Balance) ? "Credit Limit Reached" : "API Request Failed"
			details.title = titleText
			details.classNames.push("font-bold text-[var(--vscode-errorForeground)]")
		} else if (retryStatus) {
			// Handle retry state
			details.title = "API Request"
			details.classNames.push("text-[var(--vscode-foreground)]")
		}
 
		return <span className={details.classNames.join(" ")}>{details.title}</span>
	})()
 
	return [icon, title]
}