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 {
13 interface AssistantGlobalError {
14 type: AssistantErrorTypes.globalError;
17 interface AssistantSpecificError {
18 type: AssistantErrorTypes.specificError;
22 export type AssistantError = (AssistantGlobalError | AssistantSpecificError) & {
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.`;
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.`;
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.`;
44 if (errorType === ERROR_TYPE.GENERATION_FAIL) {
45 return c('Error').t`Please try generating the text again`;
48 if (errorType === ERROR_TYPE.GENERATION_CANCEL_FAIL) {
49 return c('Error').t`Due to an error, text generation couldn't be canceled`;
52 if (errorType === ERROR_TYPE.CACHING_FAILED) {
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.`;
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.`;
61 if (errorType === ERROR_TYPE.LOADGPU_FAIL) {
62 return c('Error').t`Problem loading the writing assistant to your device. Please try again.`;
65 if (errorType === ERROR_TYPE.UNLOAD_FAIL) {
66 return c('Error').t`Problem unloading data not needed when the writing assistant is inactive`;
69 if (errorType === ERROR_TYPE.GENERATION_TOO_LONG) {
70 return c('Error').t`Text is too long to refine`;
73 throw new Error('Unknown error type');
76 const useAssistantErrors = () => {
77 const [errors, setErrors] = useState<AssistantError[]>([]);
79 const { sendAssistantErrorReport } = useAssistantTelemetry();
81 const addSpecificError = ({
87 assistantType: ASSISTANT_TYPE;
88 errorType: ERROR_TYPE;
90 const newError: AssistantError = {
91 type: AssistantErrorTypes.specificError,
93 error: getErrorMessage(errorType, assistantType),
97 sendAssistantErrorReport({
102 setErrors((errors) => [...errors, newError]);
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),
113 sendAssistantErrorReport({
118 setErrors((errors) => [...errors, newError]);
123 const cleanSpecificErrors = (assistantID: string) => {
124 setErrors((errors) => {
125 return errors.filter((error) => {
126 if (error.type === AssistantErrorTypes.specificError) {
127 return error.assistantID !== assistantID;
134 const cleanGlobalErrors = () => {
135 setErrors((errors) => {
136 return errors.filter((error) => {
137 return error.type !== AssistantErrorTypes.globalError;
142 return { errors, addSpecificError, cleanSpecificErrors, addGlobalError, cleanGlobalErrors };
145 export default useAssistantErrors;