@lastbrain/ai-ui-react 1.0.27 → 1.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"AiImageButton.d.ts","sourceRoot":"","sources":["../../src/components/AiImageButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAS5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQ5C,MAAM,WAAW,kBACf,SACE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC,EACrC,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACvE,OAAO,CAAC,EAAE,CACR,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAC7C,IAAI,CAAC;IACV,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,EACtB,MAAgB,EAChB,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,aAAoB,EACpB,WAAW,EACX,YAAY,EACZ,aAAa,EACb,GAAG,WAAW,EACf,EAAE,kBAAkB,2CAuYpB"}
1
+ {"version":3,"file":"AiImageButton.d.ts","sourceRoot":"","sources":["../../src/components/AiImageButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAS5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQ5C,MAAM,WAAW,kBACf,SACE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC,EACrC,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACvE,OAAO,CAAC,EAAE,CACR,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAC7C,IAAI,CAAC;IACV,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,EACtB,MAAgB,EAChB,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,aAAoB,EACpB,WAAW,EACX,YAAY,EACZ,aAAa,EACb,GAAG,WAAW,EACf,EAAE,kBAAkB,2CA2ZpB"}
@@ -132,10 +132,29 @@ export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, ui
132
132
  }
133
133
  }
134
134
  catch (error) {
135
+ let errorMessage = "Erreur lors de la génération de l'image";
136
+ let errorCode;
137
+ // Parse JSON error response for INSUFFICIENT_TOKENS
138
+ if (error instanceof Error) {
139
+ try {
140
+ const errorData = JSON.parse(error.message);
141
+ if (errorData.error?.code === "INSUFFICIENT_TOKENS") {
142
+ errorMessage = `Solde insuffisant. ${errorData.error.message || "Veuillez recharger votre compte."}`;
143
+ errorCode = "INSUFFICIENT_TOKENS";
144
+ }
145
+ }
146
+ catch {
147
+ // If parsing fails, check if error message contains the code
148
+ if (error.message.includes("INSUFFICIENT_TOKENS")) {
149
+ errorMessage = "Solde insuffisant. Veuillez recharger votre compte pour continuer.";
150
+ errorCode = "INSUFFICIENT_TOKENS";
151
+ }
152
+ }
153
+ }
135
154
  onToast?.({
136
155
  type: "error",
137
- message: "Erreur lors de la génération de l'image",
138
- code: error instanceof Error ? error.message : undefined,
156
+ message: errorMessage,
157
+ code: errorCode || (error instanceof Error ? error.message : undefined),
139
158
  });
140
159
  }
141
160
  finally {
@@ -41,9 +41,7 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode: _uiMode = "m
41
41
  apiKey,
42
42
  baseUrl,
43
43
  category: "text", // Par défaut pour AiPromptPanel
44
- autoFetch: enableModelManagement &&
45
- availableModels.length === 0 &&
46
- (!!apiKey || !!baseUrl),
44
+ autoFetch: enableModelManagement && availableModels.length === 0,
47
45
  });
48
46
  // Utiliser soit les props externes soit la gestion automatique
49
47
  const effectiveAvailableModels = availableModels.length > 0
@@ -1 +1 @@
1
- {"version":3,"file":"useModelManagement.d.ts","sourceRoot":"","sources":["../../src/hooks/useModelManagement.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAQlC,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,yBAA0B,SAAQ,kBAAkB;IACnE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;CACjD;AAED,MAAM,WAAW,wBAAwB;IAEvC,eAAe,EAAE,OAAO,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAGrB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAGvC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,eAAe,EAAE,MAAM,OAAO,EAAE,CAAC;IACjC,iBAAiB,EAAE,MAAM,OAAO,EAAE,CAAC;CACpC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,yBAA8B,GACtC,wBAAwB,CA6M1B"}
1
+ {"version":3,"file":"useModelManagement.d.ts","sourceRoot":"","sources":["../../src/hooks/useModelManagement.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAQlC,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,yBAA0B,SAAQ,kBAAkB;IACnE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;CACjD;AAED,MAAM,WAAW,wBAAwB;IAEvC,eAAe,EAAE,OAAO,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAGrB,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAGvC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,eAAe,EAAE,MAAM,OAAO,EAAE,CAAC;IACjC,iBAAiB,EAAE,MAAM,OAAO,EAAE,CAAC;CACpC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,yBAA8B,GACtC,wBAAwB,CAyN1B"}
@@ -1,4 +1,4 @@
1
- import { useState, useCallback, useEffect } from "react";
1
+ import { useState, useCallback, useEffect, useMemo } from "react";
2
2
  import { useAiContext } from "../context/AiProvider";
3
3
  import { toggleUserModel, getAvailableModels, getUserModels, } from "../utils/modelManagement";
4
4
  import { getCached, setCache, isRateLimited, getRateLimitResetTime, } from "../utils/cache";
@@ -12,12 +12,12 @@ export function useModelManagement(options = {}) {
12
12
  const [userModels, setUserModels] = useState([]);
13
13
  const [loading, setLoading] = useState(false);
14
14
  const [error, setError] = useState(null);
15
- // Utiliser baseUrl et apiKey du contexte
16
- const effectiveOptions = {
17
- ...apiOptions,
18
- baseUrl: apiOptions.baseUrl || baseUrl,
19
- apiKey: apiOptions.apiKey || apiKeyId,
20
- };
15
+ const [apiUnavailable, setApiUnavailable] = useState(false);
16
+ // Utiliser baseUrl et apiKey du contexte avec memoization
17
+ const effectiveOptions = useMemo(() => ({
18
+ baseUrl: options.baseUrl || baseUrl,
19
+ apiKey: options.apiKey || apiKeyId,
20
+ }), [options.baseUrl, options.apiKey, baseUrl, apiKeyId]);
21
21
  const refreshModels = useCallback(async () => {
22
22
  try {
23
23
  setLoading(true);
@@ -67,6 +67,11 @@ export function useModelManagement(options = {}) {
67
67
  }
68
68
  }, [category, effectiveOptions]);
69
69
  const refreshUserModels = useCallback(async () => {
70
+ // Si l'API est marquée comme indisponible, ne pas faire l'appel
71
+ if (apiUnavailable) {
72
+ console.log("[useModelManagement] Skipping user models fetch - API marked as unavailable");
73
+ return;
74
+ }
70
75
  try {
71
76
  setLoading(true);
72
77
  setError(null);
@@ -84,15 +89,17 @@ export function useModelManagement(options = {}) {
84
89
  const errorMessage = err instanceof Error ? err.message : "Erreur inconnue";
85
90
  console.error("[useModelManagement] Error fetching user models:", errorMessage);
86
91
  setError(errorMessage);
87
- // En cas d'erreur 404 (API non disponible), utiliser un array vide
92
+ // En cas d'erreur 404 (API non disponible), utiliser un array vide et ne pas retry
88
93
  if (errorMessage.includes("404") || errorMessage.includes("Not Found")) {
89
94
  setUserModels([]);
95
+ setApiUnavailable(true);
96
+ console.warn("[useModelManagement] User models API not available (404), disabling further requests");
90
97
  }
91
98
  }
92
99
  finally {
93
100
  setLoading(false);
94
101
  }
95
- }, [effectiveOptions]);
102
+ }, [effectiveOptions, apiUnavailable]);
96
103
  const toggleModel = useCallback(async (modelId, isActive) => {
97
104
  const currentlyActive = userModels.includes(modelId);
98
105
  const targetState = isActive !== undefined ? isActive : !currentlyActive;
@@ -129,7 +136,7 @@ export function useModelManagement(options = {}) {
129
136
  const getInactiveModels = useCallback(() => {
130
137
  return availableModels.filter((model) => !userModels.includes(model.id));
131
138
  }, [availableModels, userModels]);
132
- // Auto-fetch au mount - si autoFetch ET (apiKey OU baseUrl avec proxy externe)
139
+ // Auto-fetch au mount - si autoFetch ET (apiKey OU baseUrl avec proxy externe) ET API disponible
133
140
  useEffect(() => {
134
141
  const isExternalProxy = effectiveOptions.baseUrl &&
135
142
  effectiveOptions.baseUrl.includes("/api/lastbrain");
@@ -138,25 +145,30 @@ export function useModelManagement(options = {}) {
138
145
  hasApiKey: !!effectiveOptions.apiKey,
139
146
  hasBaseUrl: !!effectiveOptions.baseUrl,
140
147
  isExternalProxy,
148
+ apiUnavailable,
141
149
  apiKeyPreview: effectiveOptions.apiKey
142
150
  ? effectiveOptions.apiKey.substring(0, 10) + "..."
143
151
  : "none",
144
152
  baseUrl: effectiveOptions.baseUrl || "none",
145
153
  });
146
- // Auto-fetch si autoFetch est activé ET qu'on a soit une apiKey soit un proxy externe
147
- if (autoFetch && (effectiveOptions.apiKey || isExternalProxy)) {
154
+ // Auto-fetch si autoFetch est activé ET qu'on a soit une apiKey soit un proxy externe ET API disponible
155
+ if (autoFetch && !apiUnavailable && (effectiveOptions.apiKey || isExternalProxy)) {
148
156
  console.log("[useModelManagement] Starting auto-fetch...");
149
157
  Promise.all([refreshModels(), refreshUserModels()]);
150
158
  }
151
159
  else if (autoFetch && !effectiveOptions.apiKey && !isExternalProxy) {
152
160
  console.warn("[useModelManagement] autoFetch is enabled but no apiKey or baseUrl provided. Skipping automatic fetch.");
153
161
  }
162
+ else if (autoFetch && apiUnavailable) {
163
+ console.log("[useModelManagement] autoFetch skipped - API marked as unavailable");
164
+ }
154
165
  }, [
155
166
  autoFetch,
156
167
  refreshModels,
157
168
  refreshUserModels,
158
169
  effectiveOptions.apiKey,
159
170
  effectiveOptions.baseUrl,
171
+ apiUnavailable,
160
172
  ]);
161
173
  return {
162
174
  availableModels,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lastbrain/ai-ui-react",
3
- "version": "1.0.27",
3
+ "version": "1.0.28",
4
4
  "description": "Headless React components for LastBrain AI UI Kit",
5
5
  "private": false,
6
6
  "type": "module",
@@ -193,10 +193,30 @@ export function AiImageButton({
193
193
  });
194
194
  }
195
195
  } catch (error) {
196
+ let errorMessage = "Erreur lors de la génération de l'image";
197
+ let errorCode: string | undefined;
198
+
199
+ // Parse JSON error response for INSUFFICIENT_TOKENS
200
+ if (error instanceof Error) {
201
+ try {
202
+ const errorData = JSON.parse(error.message);
203
+ if (errorData.error?.code === "INSUFFICIENT_TOKENS") {
204
+ errorMessage = `Solde insuffisant. ${errorData.error.message || "Veuillez recharger votre compte."}`;
205
+ errorCode = "INSUFFICIENT_TOKENS";
206
+ }
207
+ } catch {
208
+ // If parsing fails, check if error message contains the code
209
+ if (error.message.includes("INSUFFICIENT_TOKENS")) {
210
+ errorMessage = "Solde insuffisant. Veuillez recharger votre compte pour continuer.";
211
+ errorCode = "INSUFFICIENT_TOKENS";
212
+ }
213
+ }
214
+ }
215
+
196
216
  onToast?.({
197
217
  type: "error",
198
- message: "Erreur lors de la génération de l'image",
199
- code: error instanceof Error ? error.message : undefined,
218
+ message: errorMessage,
219
+ code: errorCode || (error instanceof Error ? error.message : undefined),
200
220
  });
201
221
  } finally {
202
222
  setIsOpen(false);
@@ -118,10 +118,7 @@ function AiPromptPanelInternal({
118
118
  apiKey,
119
119
  baseUrl,
120
120
  category: "text", // Par défaut pour AiPromptPanel
121
- autoFetch:
122
- enableModelManagement &&
123
- availableModels.length === 0 &&
124
- (!!apiKey || !!baseUrl),
121
+ autoFetch: enableModelManagement && availableModels.length === 0,
125
122
  });
126
123
 
127
124
  // Utiliser soit les props externes soit la gestion automatique
@@ -1,4 +1,4 @@
1
- import { useState, useCallback, useEffect } from "react";
1
+ import { useState, useCallback, useEffect, useMemo } from "react";
2
2
  import { useAiContext } from "../context/AiProvider";
3
3
  import {
4
4
  toggleUserModel,
@@ -60,13 +60,13 @@ export function useModelManagement(
60
60
  const [userModels, setUserModels] = useState<string[]>([]);
61
61
  const [loading, setLoading] = useState(false);
62
62
  const [error, setError] = useState<string | null>(null);
63
+ const [apiUnavailable, setApiUnavailable] = useState(false);
63
64
 
64
- // Utiliser baseUrl et apiKey du contexte
65
- const effectiveOptions = {
66
- ...apiOptions,
67
- baseUrl: apiOptions.baseUrl || baseUrl,
68
- apiKey: apiOptions.apiKey || apiKeyId,
69
- };
65
+ // Utiliser baseUrl et apiKey du contexte avec memoization
66
+ const effectiveOptions = useMemo(() => ({
67
+ baseUrl: options.baseUrl || baseUrl,
68
+ apiKey: options.apiKey || apiKeyId,
69
+ }), [options.baseUrl, options.apiKey, baseUrl, apiKeyId]);
70
70
 
71
71
  const refreshModels = useCallback(async () => {
72
72
  try {
@@ -134,6 +134,12 @@ export function useModelManagement(
134
134
  }, [category, effectiveOptions]);
135
135
 
136
136
  const refreshUserModels = useCallback(async () => {
137
+ // Si l'API est marquée comme indisponible, ne pas faire l'appel
138
+ if (apiUnavailable) {
139
+ console.log("[useModelManagement] Skipping user models fetch - API marked as unavailable");
140
+ return;
141
+ }
142
+
137
143
  try {
138
144
  setLoading(true);
139
145
  setError(null);
@@ -156,14 +162,16 @@ export function useModelManagement(
156
162
  errorMessage
157
163
  );
158
164
  setError(errorMessage);
159
- // En cas d'erreur 404 (API non disponible), utiliser un array vide
165
+ // En cas d'erreur 404 (API non disponible), utiliser un array vide et ne pas retry
160
166
  if (errorMessage.includes("404") || errorMessage.includes("Not Found")) {
161
167
  setUserModels([]);
168
+ setApiUnavailable(true);
169
+ console.warn("[useModelManagement] User models API not available (404), disabling further requests");
162
170
  }
163
171
  } finally {
164
172
  setLoading(false);
165
173
  }
166
- }, [effectiveOptions]);
174
+ }, [effectiveOptions, apiUnavailable]);
167
175
 
168
176
  const toggleModel = useCallback(
169
177
  async (modelId: string, isActive?: boolean) => {
@@ -211,7 +219,7 @@ export function useModelManagement(
211
219
  return availableModels.filter((model) => !userModels.includes(model.id));
212
220
  }, [availableModels, userModels]);
213
221
 
214
- // Auto-fetch au mount - si autoFetch ET (apiKey OU baseUrl avec proxy externe)
222
+ // Auto-fetch au mount - si autoFetch ET (apiKey OU baseUrl avec proxy externe) ET API disponible
215
223
  useEffect(() => {
216
224
  const isExternalProxy =
217
225
  effectiveOptions.baseUrl &&
@@ -222,20 +230,23 @@ export function useModelManagement(
222
230
  hasApiKey: !!effectiveOptions.apiKey,
223
231
  hasBaseUrl: !!effectiveOptions.baseUrl,
224
232
  isExternalProxy,
233
+ apiUnavailable,
225
234
  apiKeyPreview: effectiveOptions.apiKey
226
235
  ? effectiveOptions.apiKey.substring(0, 10) + "..."
227
236
  : "none",
228
237
  baseUrl: effectiveOptions.baseUrl || "none",
229
238
  });
230
239
 
231
- // Auto-fetch si autoFetch est activé ET qu'on a soit une apiKey soit un proxy externe
232
- if (autoFetch && (effectiveOptions.apiKey || isExternalProxy)) {
240
+ // Auto-fetch si autoFetch est activé ET qu'on a soit une apiKey soit un proxy externe ET API disponible
241
+ if (autoFetch && !apiUnavailable && (effectiveOptions.apiKey || isExternalProxy)) {
233
242
  console.log("[useModelManagement] Starting auto-fetch...");
234
243
  Promise.all([refreshModels(), refreshUserModels()]);
235
244
  } else if (autoFetch && !effectiveOptions.apiKey && !isExternalProxy) {
236
245
  console.warn(
237
246
  "[useModelManagement] autoFetch is enabled but no apiKey or baseUrl provided. Skipping automatic fetch."
238
247
  );
248
+ } else if (autoFetch && apiUnavailable) {
249
+ console.log("[useModelManagement] autoFetch skipped - API marked as unavailable");
239
250
  }
240
251
  }, [
241
252
  autoFetch,
@@ -243,6 +254,7 @@ export function useModelManagement(
243
254
  refreshUserModels,
244
255
  effectiveOptions.apiKey,
245
256
  effectiveOptions.baseUrl,
257
+ apiUnavailable,
246
258
  ]);
247
259
 
248
260
  return {