Remove payments components
[ProtonMail-WebClient.git] / packages / llm / lib / hooks / useAssistantErrors.ts
blob22d8af9019cddf6c714125ec11758f32cfd6f4fb
1 import { useState } from 'react';
3 import { c } from 'ttag';
5 import useAssistantTelemetry from '@proton/components/hooks/assistant/useAssistantTelemetry';
6 import { ASSISTANT_TYPE, ERROR_TYPE } from '@proton/shared/lib/assistant';
8 export enum AssistantErrorTypes {
9     globalError,
10     specificError,
13 interface AssistantGlobalError {
14     type: AssistantErrorTypes.globalError;
17 interface AssistantSpecificError {
18     type: AssistantErrorTypes.specificError;
19     assistantID: string;
22 export type AssistantError = (AssistantGlobalError | AssistantSpecificError) & {
23     error: string;
24     errorType?: ERROR_TYPE;
27 const getErrorMessage = (errorType: ERROR_TYPE, assistantType: ASSISTANT_TYPE) => {
28     if (errorType === ERROR_TYPE.GENERATION_HARMFUL) {
29         return c('Error').t`The writing assistant cannot proceed with your request. Please try a different prompt.`;
30     }
32     if (errorType === ERROR_TYPE.TOO_MANY_REQUESTS) {
33         return c('Error').t`The system is busy at the moment. Please try again in a few minutes.`;
34     }
36     if (errorType === ERROR_TYPE.GENERATION_FAIL && assistantType === ASSISTANT_TYPE.LOCAL) {
37         // There is a bug where the LLM will be unloaded from the GPU
38         // without notice. It hasn't been tracked down, in this scenario
39         // the user might want to refresh.
40         // The wording should be aligned with server mode when the issue is solved
41         return c('Error').t`Please try again or refresh the page.`;
42     }
44     if (errorType === ERROR_TYPE.GENERATION_FAIL) {
45         return c('Error').t`Please try generating the text again`;
46     }
48     if (errorType === ERROR_TYPE.GENERATION_CANCEL_FAIL) {
49         return c('Error').t`Due to an error, text generation couldn't be canceled`;
50     }
52     if (errorType === ERROR_TYPE.CACHING_FAILED) {
53         return c('Error')
54             .t`Problem downloading the writing assistant. If you're using private mode, try using normal browsing mode or run the writing assistant on servers.`;
55     }
57     if (errorType === ERROR_TYPE.DOWNLOAD_FAIL || errorType === ERROR_TYPE.DOWNLOAD_REQUEST_FAIL) {
58         return c('Error').t`Problem downloading the writing assistant. Please try again.`;
59     }
61     if (errorType === ERROR_TYPE.LOADGPU_FAIL) {
62         return c('Error').t`Problem loading the writing assistant to your device. Please try again.`;
63     }
65     if (errorType === ERROR_TYPE.UNLOAD_FAIL) {
66         return c('Error').t`Problem unloading data not needed when the writing assistant is inactive`;
67     }
69     if (errorType === ERROR_TYPE.GENERATION_TOO_LONG) {
70         return c('Error').t`Text is too long to refine`;
71     }
73     throw new Error('Unknown error type');
76 const useAssistantErrors = () => {
77     const [errors, setErrors] = useState<AssistantError[]>([]);
79     const { sendAssistantErrorReport } = useAssistantTelemetry();
81     const addSpecificError = ({
82         assistantID,
83         assistantType,
84         errorType,
85     }: {
86         assistantID: string;
87         assistantType: ASSISTANT_TYPE;
88         errorType: ERROR_TYPE;
89     }) => {
90         const newError: AssistantError = {
91             type: AssistantErrorTypes.specificError,
92             assistantID,
93             error: getErrorMessage(errorType, assistantType),
94             errorType,
95         };
97         sendAssistantErrorReport({
98             assistantType,
99             errorType,
100         });
102         setErrors((errors) => [...errors, newError]);
103     };
105     const addGlobalError = (assistantType: ASSISTANT_TYPE, errorType: ERROR_TYPE) => {
106         const errorMessage = getErrorMessage(errorType, assistantType);
107         const newError: AssistantError = {
108             type: AssistantErrorTypes.globalError,
109             error: getErrorMessage(errorType, assistantType),
110             errorType,
111         };
113         sendAssistantErrorReport({
114             assistantType,
115             errorType,
116         });
118         setErrors((errors) => [...errors, newError]);
120         return errorMessage;
121     };
123     const cleanSpecificErrors = (assistantID: string) => {
124         setErrors((errors) => {
125             return errors.filter((error) => {
126                 if (error.type === AssistantErrorTypes.specificError) {
127                     return error.assistantID !== assistantID;
128                 }
129                 return error;
130             });
131         });
132     };
134     const cleanGlobalErrors = () => {
135         setErrors((errors) => {
136             return errors.filter((error) => {
137                 return error.type !== AssistantErrorTypes.globalError;
138             });
139         });
140     };
142     return { errors, addSpecificError, cleanSpecificErrors, addGlobalError, cleanGlobalErrors };
145 export default useAssistantErrors;