@lastbrain/ai-ui-react 1.0.75 → 1.0.76

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.
Files changed (46) hide show
  1. package/dist/components/AiContextButton.d.ts +1 -1
  2. package/dist/components/AiContextButton.d.ts.map +1 -1
  3. package/dist/components/AiImageButton.js +2 -2
  4. package/dist/components/AiInput.d.ts +1 -1
  5. package/dist/components/AiInput.d.ts.map +1 -1
  6. package/dist/components/AiInput.js +4 -4
  7. package/dist/components/AiPromptPanel.js +30 -6
  8. package/dist/components/AiSelect.d.ts +1 -1
  9. package/dist/components/AiSelect.d.ts.map +1 -1
  10. package/dist/components/AiSelect.js +1 -1
  11. package/dist/components/AiStatusButton.d.ts.map +1 -1
  12. package/dist/components/AiStatusButton.js +2 -2
  13. package/dist/components/AiTextarea.d.ts +2 -1
  14. package/dist/components/AiTextarea.d.ts.map +1 -1
  15. package/dist/components/AiTextarea.js +16 -6
  16. package/dist/components/ErrorToast.js +3 -3
  17. package/dist/components/LBKeyPicker.js +9 -9
  18. package/dist/components/LBSigninModal.d.ts.map +1 -1
  19. package/dist/components/UsageToast.d.ts +3 -3
  20. package/dist/components/UsageToast.d.ts.map +1 -1
  21. package/dist/context/LBAuthProvider.d.ts.map +1 -1
  22. package/dist/context/LBAuthProvider.js +12 -5
  23. package/dist/examples/AiImageGenerator.js +1 -1
  24. package/dist/hooks/useAiStatus.d.ts.map +1 -1
  25. package/dist/hooks/useAiStatus.js +43 -5
  26. package/dist/styles.css +3 -3
  27. package/dist/utils/errorHandler.d.ts +2 -2
  28. package/dist/utils/errorHandler.d.ts.map +1 -1
  29. package/package.json +2 -2
  30. package/src/components/AiContextButton.tsx +1 -1
  31. package/src/components/AiImageButton.tsx +2 -2
  32. package/src/components/AiInput.tsx +9 -4
  33. package/src/components/AiPromptPanel.tsx +31 -6
  34. package/src/components/AiSelect.tsx +2 -2
  35. package/src/components/AiStatusButton.tsx +11 -8
  36. package/src/components/AiTextarea.tsx +25 -9
  37. package/src/components/ErrorToast.tsx +3 -3
  38. package/src/components/LBKeyPicker.tsx +10 -10
  39. package/src/components/LBSigninModal.tsx +2 -1
  40. package/src/components/UsageToast.tsx +4 -4
  41. package/src/context/LBAuthProvider.tsx +12 -5
  42. package/src/examples/AiImageGenerator.tsx +1 -1
  43. package/src/hooks/useAiStatus.ts +47 -5
  44. package/src/styles.css +3 -3
  45. package/src/utils/errorHandler.ts +3 -3
  46. package/src/utils/modelManagement.ts +3 -3
@@ -74,7 +74,7 @@ export function AiImageButton({
74
74
  requestId: string;
75
75
  tokens: number;
76
76
  } | null>(null);
77
- const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
77
+ const { showUsageToast } = useUsageToast();
78
78
  const { showErrorToast, errorData, errorKey, clearError } = useErrorToast();
79
79
 
80
80
  // Rendre l'authentification optionnelle
@@ -126,7 +126,7 @@ export function AiImageButton({
126
126
  type: "success",
127
127
  message: t("ai.image.savedSuccess", "Image saved"),
128
128
  });
129
- } catch (_error) {
129
+ } catch {
130
130
  onToast?.({
131
131
  type: "error",
132
132
  message: t("ai.image.saveError", "Error while saving"),
@@ -34,7 +34,7 @@ export function AiInput({
34
34
  context,
35
35
  model,
36
36
  prompt,
37
- editMode = false,
37
+ editMode: _editMode = false,
38
38
  enableModelManagement = true,
39
39
  storeOutputs,
40
40
  artifactTitle,
@@ -51,7 +51,12 @@ export function AiInput({
51
51
  inputProps.value?.toString() || inputProps.defaultValue?.toString() || ""
52
52
  );
53
53
  const inputRef = useRef<HTMLInputElement>(null);
54
- const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
54
+ const {
55
+ showUsageToast: _showUsageToast,
56
+ toastData,
57
+ toastKey,
58
+ clearToast,
59
+ } = useUsageToast();
55
60
 
56
61
  // Rendre l'authentification optionnelle
57
62
  let lbStatus: string | undefined;
@@ -77,7 +82,7 @@ export function AiInput({
77
82
  const baseUrl = propBaseUrl ?? ctxBaseUrl;
78
83
  const apiKeyId = propApiKeyId ?? ctxApiKeyId;
79
84
 
80
- const { models } = useAiModels({
85
+ const { models: _models } = useAiModels({
81
86
  baseUrl,
82
87
  apiKeyId,
83
88
  modelType: "text-or-language",
@@ -104,7 +109,7 @@ export function AiInput({
104
109
  const handleSubmit = async (
105
110
  selectedModel: string,
106
111
  selectedPrompt: string,
107
- promptId?: string
112
+ _promptId?: string
108
113
  ) => {
109
114
  try {
110
115
  const resolvedContext = inputValue || context || undefined;
@@ -102,7 +102,7 @@ function AiPromptPanelInternal({
102
102
  isOpen,
103
103
  onClose,
104
104
  onSubmit,
105
- uiMode: _uiMode = "modal",
105
+ uiMode = "modal",
106
106
  models = [],
107
107
  sourceText,
108
108
  children,
@@ -405,9 +405,29 @@ function AiPromptPanelInternal({
405
405
  return null;
406
406
  }
407
407
 
408
+ const isDrawer = uiMode === "drawer";
409
+ const panelContainerStyle = isDrawer
410
+ ? {
411
+ ...aiStyles.modal,
412
+ alignItems: "stretch",
413
+ justifyContent: "flex-end",
414
+ padding: "0",
415
+ }
416
+ : aiStyles.modal;
417
+ const panelContentStyle = isDrawer
418
+ ? {
419
+ ...aiStyles.modalContent,
420
+ width: "min(92vw, 640px)",
421
+ maxWidth: "640px",
422
+ maxHeight: "100vh",
423
+ height: "100vh",
424
+ borderRadius: "16px 0 0 16px",
425
+ }
426
+ : aiStyles.modalContent;
427
+
408
428
  if (children) {
409
429
  return createPortal(
410
- <div style={aiStyles.modal} onKeyDown={handleKeyDown}>
430
+ <div style={panelContainerStyle} onKeyDown={handleKeyDown}>
411
431
  {children(renderProps)}
412
432
  </div>,
413
433
  portalRoot
@@ -415,7 +435,7 @@ function AiPromptPanelInternal({
415
435
  }
416
436
 
417
437
  return createPortal(
418
- <div style={aiStyles.modal} onKeyDown={handleKeyDown}>
438
+ <div style={panelContainerStyle} onKeyDown={handleKeyDown}>
419
439
  <div
420
440
  style={{
421
441
  ...aiStyles.modalOverlay,
@@ -426,13 +446,18 @@ function AiPromptPanelInternal({
426
446
  />
427
447
  <div
428
448
  style={{
429
- ...aiStyles.modalContent,
449
+ ...panelContentStyle,
430
450
  opacity: isClosing ? 0 : 1,
431
- transform: isClosing ? "translateY(12px)" : "translateY(0)",
451
+ transform: isClosing
452
+ ? isDrawer
453
+ ? "translateX(16px)"
454
+ : "translateY(12px)"
455
+ : isDrawer
456
+ ? "translateX(0)"
457
+ : "translateY(0)",
432
458
  transition: "opacity 200ms ease, transform 200ms ease",
433
459
  display: "flex",
434
460
  flexDirection: "column",
435
- maxHeight: "85vh",
436
461
  overflow: "hidden",
437
462
  }}
438
463
  >
@@ -31,8 +31,8 @@ export function AiSelect({
31
31
  size = "md",
32
32
  radius = "full",
33
33
  context,
34
- model,
35
- prompt,
34
+ model: _model,
35
+ prompt: _prompt,
36
36
  storeOutputs,
37
37
  artifactTitle,
38
38
  onValue,
@@ -207,14 +207,17 @@ export function AiStatusButton({
207
207
 
208
208
  const canPortal = typeof document !== "undefined";
209
209
 
210
- const effectiveStatus =
211
- lbStatus === "ready"
212
- ? {
213
- ...(lbApiStatus || {}),
214
- ...(lbBasicStatus || {}),
215
- storage: lbStorageStatus?.storage || lbApiStatus?.storage,
216
- }
217
- : status || null;
210
+ const effectiveStatus = useMemo(
211
+ () =>
212
+ lbStatus === "ready"
213
+ ? {
214
+ ...(lbApiStatus || {}),
215
+ ...(lbBasicStatus || {}),
216
+ storage: lbStorageStatus?.storage || lbApiStatus?.storage,
217
+ }
218
+ : status || null,
219
+ [lbApiStatus, lbBasicStatus, lbStatus, lbStorageStatus, status]
220
+ );
218
221
 
219
222
  const hasApiKeySelected = Boolean(
220
223
  effectiveStatus?.apiKey?.id ||
@@ -27,6 +27,7 @@ export interface AiTextareaProps
27
27
  uiMode?: "modal" | "drawer";
28
28
  size?: AiSize;
29
29
  radius?: AiRadius;
30
+ onPanelOpenChange?: (isOpen: boolean) => void;
30
31
  }
31
32
 
32
33
  export function AiTextarea({
@@ -35,10 +36,11 @@ export function AiTextarea({
35
36
  uiMode = "modal",
36
37
  size = "md",
37
38
  radius = "lg",
39
+ onPanelOpenChange,
38
40
  context,
39
41
  model,
40
42
  prompt,
41
- editMode = false,
43
+ editMode: _editMode = false,
42
44
  enableModelManagement,
43
45
  storeOutputs,
44
46
  artifactTitle,
@@ -61,12 +63,15 @@ export function AiTextarea({
61
63
 
62
64
  // Rendre l'authentification optionnelle
63
65
  let lbStatus: string | undefined;
66
+ let hasLBProvider = false;
64
67
  try {
65
68
  const lbContext = useLB();
66
69
  lbStatus = lbContext.status;
70
+ hasLBProvider = true;
67
71
  } catch {
68
72
  // LBProvider n'est pas disponible, ignorer
69
73
  lbStatus = undefined;
74
+ hasLBProvider = false;
70
75
  }
71
76
 
72
77
  let ctxBaseUrl: string | undefined;
@@ -82,8 +87,11 @@ export function AiTextarea({
82
87
 
83
88
  const baseUrl = propBaseUrl ?? ctxBaseUrl;
84
89
  const apiKeyId = propApiKeyId ?? ctxApiKeyId;
90
+ const supportsSessionAuth =
91
+ typeof baseUrl === "string" &&
92
+ (baseUrl.includes("/api/ai") || baseUrl.includes("/api/lastbrain"));
85
93
 
86
- const { models } = useAiModels({
94
+ const { models: _models } = useAiModels({
87
95
  baseUrl,
88
96
  apiKeyId,
89
97
  modelType: "text-or-language",
@@ -92,7 +100,10 @@ export function AiTextarea({
92
100
  const { formatted: loadingElapsed } = useLoadingTimer(loading);
93
101
 
94
102
  const hasConfiguration = Boolean(model && prompt);
95
- const isAuthReady = lbStatus === "ready" || Boolean(process.env.LB_API_KEY);
103
+ const isAuthReady =
104
+ supportsSessionAuth ||
105
+ lbStatus === "ready" ||
106
+ Boolean(process.env.LB_API_KEY);
96
107
  const shouldShowSparkles = isAuthReady && !disabled;
97
108
 
98
109
  const handleOpenPanel = () => {
@@ -101,16 +112,18 @@ export function AiTextarea({
101
112
  return;
102
113
  }
103
114
  setIsOpen(true);
115
+ onPanelOpenChange?.(true);
104
116
  };
105
117
 
106
118
  const handleClosePanel = () => {
107
119
  setIsOpen(false);
120
+ onPanelOpenChange?.(false);
108
121
  };
109
122
 
110
123
  const handleSubmit = async (
111
124
  selectedModel: string,
112
125
  selectedPrompt: string,
113
- promptId?: string
126
+ _promptId?: string
114
127
  ) => {
115
128
  try {
116
129
  const resolvedContext = textareaValue || context || undefined;
@@ -141,13 +154,14 @@ export function AiTextarea({
141
154
  });
142
155
  showUsageToast(result);
143
156
  }
144
- } catch (error) {
157
+ } catch {
145
158
  onToast?.({
146
159
  type: "error",
147
160
  message: t("ai.generationError", "Failed to generate text"),
148
161
  });
149
162
  } finally {
150
163
  setIsOpen(false);
164
+ onPanelOpenChange?.(false);
151
165
  }
152
166
  };
153
167
 
@@ -280,10 +294,12 @@ export function AiTextarea({
280
294
  onComplete={clearToast}
281
295
  />
282
296
  )}
283
- <LBSigninModal
284
- isOpen={showAuthModal}
285
- onClose={() => setShowAuthModal(false)}
286
- />
297
+ {hasLBProvider ? (
298
+ <LBSigninModal
299
+ isOpen={showAuthModal}
300
+ onClose={() => setShowAuthModal(false)}
301
+ />
302
+ ) : null}
287
303
  </div>
288
304
  );
289
305
  }
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import "../styles/register";
4
- import { useEffect, useRef, useState } from "react";
4
+ import { useCallback, useEffect, useRef, useState } from "react";
5
5
  import { X, AlertCircle } from "lucide-react";
6
6
  import { useI18n } from "../context/I18nContext";
7
7
 
@@ -27,7 +27,7 @@ export function ErrorToast({
27
27
  const fadeTimeoutRef = useRef<number | null>(null);
28
28
  const autoCloseTimeoutRef = useRef<number | null>(null);
29
29
 
30
- const handleClose = () => {
30
+ const handleClose = useCallback(() => {
31
31
  if (isClosing) return;
32
32
 
33
33
  // Clear auto-close timeout if user closes manually
@@ -40,7 +40,7 @@ export function ErrorToast({
40
40
  setIsVisible(false);
41
41
  onComplete?.();
42
42
  }, 200);
43
- };
43
+ }, [isClosing, onComplete]);
44
44
 
45
45
  useEffect(() => {
46
46
  if (error) {
@@ -6,7 +6,7 @@ import "../styles/register";
6
6
  * Permet de changer de clé API sans se reconnecter
7
7
  */
8
8
 
9
- import { useEffect, useState } from "react";
9
+ import { useCallback, useEffect, useState } from "react";
10
10
  import { useLB } from "../hooks/useLB";
11
11
  import type { LBApiKey } from "@lastbrain/ai-ui-core";
12
12
  import { useI18n } from "../context/I18nContext";
@@ -30,25 +30,25 @@ export function LBKeyPicker({
30
30
  const [error, setError] = useState("");
31
31
  const [showDropdown, setShowDropdown] = useState(false);
32
32
 
33
- useEffect(() => {
34
- if (status === "ready" && accessToken) {
35
- loadKeys();
36
- }
37
- }, [status, accessToken]);
38
-
39
- const loadKeys = async () => {
33
+ const loadKeys = useCallback(async () => {
40
34
  if (!accessToken) return;
41
35
 
42
36
  try {
43
37
  setLoading(true);
44
38
  const keys = await fetchApiKeys(accessToken);
45
39
  setApiKeys(keys);
46
- } catch (err) {
40
+ } catch {
47
41
  setError(t("lb.keypicker.loadError", "Unable to load API keys"));
48
42
  } finally {
49
43
  setLoading(false);
50
44
  }
51
- };
45
+ }, [accessToken, fetchApiKeys, t]);
46
+
47
+ useEffect(() => {
48
+ if (status === "ready" && accessToken) {
49
+ loadKeys();
50
+ }
51
+ }, [accessToken, loadKeys, status]);
52
52
 
53
53
  const handleSelectKey = async (keyId: string) => {
54
54
  if (!accessToken) return;
@@ -7,6 +7,7 @@ import { AlertCircle, Loader2, Lock, Mail, Sparkles, X } from "lucide-react";
7
7
  import { useLB } from "../context/LBAuthProvider";
8
8
  import { LBApiKeySelector } from "./LBApiKeySelector";
9
9
  import { useI18n } from "../context/I18nContext";
10
+ import type { LBApiKey } from "@lastbrain/ai-ui-core";
10
11
 
11
12
  export interface LBSigninModalProps {
12
13
  isOpen: boolean;
@@ -23,7 +24,7 @@ export function LBSigninModal({ isOpen, onClose }: LBSigninModalProps) {
23
24
  const [loading, setLoading] = useState(false);
24
25
  const [error, setError] = useState("");
25
26
  const [showKeySelector, setShowKeySelector] = useState(false);
26
- const [currentApiKeys, setCurrentApiKeys] = useState<any[]>([]);
27
+ const [currentApiKeys, setCurrentApiKeys] = useState<LBApiKey[]>([]);
27
28
 
28
29
  const { login, selectApiKeyWithToken, fetchApiKeys } = lbContext || {};
29
30
 
@@ -6,7 +6,7 @@ import { X } from "lucide-react";
6
6
  import { useI18n } from "../context/I18nContext";
7
7
 
8
8
  interface UsageToastProps {
9
- result: unknown;
9
+ result: any;
10
10
  position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
11
11
  onComplete?: () => void;
12
12
  }
@@ -46,7 +46,7 @@ export function UsageToast({
46
46
  }, 200);
47
47
  };
48
48
 
49
- const extractUsageMessage = (data: unknown) => {
49
+ const extractUsageMessage = (data: any) => {
50
50
  const result = data as any;
51
51
 
52
52
  // Extract cost from various possible locations
@@ -165,10 +165,10 @@ export function UsageToast({
165
165
  }
166
166
 
167
167
  export function useUsageToast() {
168
- const [toastData, setToastData] = useState<unknown>(null);
168
+ const [toastData, setToastData] = useState<any>(null);
169
169
  const [toastKey, setToastKey] = useState(0);
170
170
 
171
- const showUsageToast = (result: unknown) => {
171
+ const showUsageToast = (result: any) => {
172
172
  // Replace any existing toast with new one
173
173
  setToastKey((prev) => prev + 1);
174
174
  setToastData(result);
@@ -416,7 +416,7 @@ export function LBProvider({
416
416
  try {
417
417
  let data: BasicStatus;
418
418
  try {
419
- data = await lbClient.getStatus();
419
+ data = (await lbClient.getStatus()) as BasicStatus;
420
420
  } catch {
421
421
  // Backward compatibility: older backends may not expose /auth/status
422
422
  const userData = await lbClient.getUser();
@@ -483,15 +483,17 @@ export function LBProvider({
483
483
 
484
484
  setIsLoadingStorage(true);
485
485
  try {
486
- const data = await lbClient.getStorageStatus();
487
- const storageData = data?.storage ? { storage: data.storage } : data;
486
+ const data = (await lbClient.getStorageStatus()) as StorageStatus;
487
+ const storageData: StorageStatus = data?.storage
488
+ ? { storage: data.storage }
489
+ : data;
488
490
  setStorageStatus(storageData);
489
491
  setStorageLastFetch(now);
490
492
 
491
493
  // Combiner avec le basic status
492
494
  const combinedStatus = {
493
495
  ...basicStatus,
494
- storage: storageData?.storage,
496
+ storage: storageData.storage,
495
497
  };
496
498
  setApiStatus(combinedStatus as AiStatus);
497
499
  } catch (error) {
@@ -624,7 +626,12 @@ export function LBProvider({
624
626
  setStorageStatus(null);
625
627
  setApiKeys([]);
626
628
  }
627
- }, [state.status]); // Supprimer les fonctions des dépendances pour éviter la boucle
629
+ }, [
630
+ fetchApiKeysWithSession,
631
+ refreshBasicStatus,
632
+ refreshStorageStatus,
633
+ state.status,
634
+ ]);
628
635
 
629
636
  const value: LBContextValue = {
630
637
  ...state,
@@ -125,7 +125,7 @@ export function ModelManagementList({
125
125
  }) {
126
126
  const {
127
127
  availableModels,
128
- userModels,
128
+ userModels: _userModels,
129
129
  loading,
130
130
  error,
131
131
  toggleModel,
@@ -1,8 +1,9 @@
1
1
  "use client";
2
2
 
3
- import { useState, useEffect, useCallback } from "react";
3
+ import { useState, useEffect, useCallback, useContext, useMemo } from "react";
4
4
  import type { AiStatus } from "@lastbrain/ai-ui-core";
5
5
  import { useAiClient } from "./useAiClient";
6
+ import { LBContext } from "../context/LBAuthProvider";
6
7
 
7
8
  export interface UseAiStatusOptions {
8
9
  baseUrl?: string;
@@ -18,11 +19,40 @@ export interface UseAiStatusResult {
18
19
 
19
20
  export function useAiStatus(options?: UseAiStatusOptions): UseAiStatusResult {
20
21
  const client = useAiClient(options);
22
+ const lbContext = useContext(LBContext);
21
23
  const [status, setStatus] = useState<AiStatus | null>(null);
22
24
  const [loading, setLoading] = useState(false);
23
25
  const [error, setError] = useState<Error | null>(null);
24
26
 
27
+ const statusFromLB = useMemo<AiStatus | null>(() => {
28
+ if (!lbContext || lbContext.status !== "ready") {
29
+ return null;
30
+ }
31
+ if (lbContext.apiStatus) {
32
+ return lbContext.apiStatus;
33
+ }
34
+ if (lbContext.basicStatus) {
35
+ return {
36
+ ...(lbContext.basicStatus as AiStatus),
37
+ storage:
38
+ lbContext.storageStatus?.storage ||
39
+ (lbContext.basicStatus as AiStatus)?.storage,
40
+ } as AiStatus;
41
+ }
42
+ return null;
43
+ }, [lbContext]);
44
+
25
45
  const fetchStatus = useCallback(async () => {
46
+ // If LBProvider is available, it already handles fast status + storage split.
47
+ if (lbContext && lbContext.status === "ready") {
48
+ try {
49
+ await lbContext.refreshBasicStatus();
50
+ } catch {
51
+ // Ignore: provider already tracks errors/status
52
+ }
53
+ return;
54
+ }
55
+
26
56
  console.log("[useAiStatus] Starting status fetch");
27
57
 
28
58
  setLoading(true);
@@ -39,15 +69,27 @@ export function useAiStatus(options?: UseAiStatusOptions): UseAiStatusResult {
39
69
  } finally {
40
70
  setLoading(false);
41
71
  }
42
- }, [client]);
72
+ }, [client, lbContext]);
43
73
 
44
74
  useEffect(() => {
75
+ if (statusFromLB) {
76
+ setStatus(statusFromLB);
77
+ setLoading(false);
78
+ setError(null);
79
+ return;
80
+ }
45
81
  fetchStatus();
46
- }, [fetchStatus]);
82
+ }, [fetchStatus, statusFromLB]);
83
+
84
+ const isLoadingFromLB =
85
+ !!lbContext &&
86
+ lbContext.status === "ready" &&
87
+ !statusFromLB &&
88
+ (lbContext.isLoadingStatus || lbContext.isLoadingStorage);
47
89
 
48
90
  return {
49
- status,
50
- loading,
91
+ status: statusFromLB || status,
92
+ loading: isLoadingFromLB || loading,
51
93
  error,
52
94
  refetch: fetchStatus,
53
95
  };
package/src/styles.css CHANGED
@@ -195,7 +195,7 @@
195
195
  align-items: center;
196
196
  gap: 10px;
197
197
  min-height: var(--ai-control-h, var(--ai-size-md-h));
198
- padding: 0 12px;
198
+ padding: 0 8px;
199
199
  border-radius: var(--ai-radius-current, var(--ai-radius-full));
200
200
  border: 1px solid var(--ai-border);
201
201
  background:
@@ -362,8 +362,8 @@
362
362
  .ai-shell--textarea .ai-control-action,
363
363
  .ai-shell--textarea .ai-spark {
364
364
  position: absolute;
365
- right: 12px;
366
- bottom: 12px;
365
+ right: 8px;
366
+ bottom: 8px;
367
367
  }
368
368
 
369
369
  /* Generic buttons */
@@ -13,7 +13,7 @@ type NormalizedErrorLike = {
13
13
  message: string;
14
14
  };
15
15
 
16
- function isNormalizedErrorLike(value: unknown): value is NormalizedErrorLike {
16
+ function isNormalizedErrorLike(value: any): value is NormalizedErrorLike {
17
17
  if (!value || typeof value !== "object") {
18
18
  return false;
19
19
  }
@@ -24,7 +24,7 @@ function isNormalizedErrorLike(value: unknown): value is NormalizedErrorLike {
24
24
  /**
25
25
  * Parse et uniformise la gestion des erreurs des composants AI
26
26
  */
27
- export function parseAIError(error: unknown): ParsedError {
27
+ export function parseAIError(error: any): ParsedError {
28
28
  // Si l'erreur est déjà un objet normalisé
29
29
  if (isNormalizedErrorLike(error)) {
30
30
  return {
@@ -173,7 +173,7 @@ export interface ErrorToastCallback {
173
173
  * @param showInternalToast Callback interne optionnelle pour afficher un toast dans le composant
174
174
  */
175
175
  export function handleAIError(
176
- error: unknown,
176
+ error: any,
177
177
  onToast?: ErrorToastCallback,
178
178
  showInternalToast?: (error: { message: string; code?: string }) => void
179
179
  ): void {
@@ -15,7 +15,7 @@ interface ProvidersResponse {
15
15
  providers?: Provider[];
16
16
  }
17
17
 
18
- interface ModelsResponse {
18
+ interface _ModelsResponse {
19
19
  models?: ModelInfo[];
20
20
  }
21
21
 
@@ -32,7 +32,7 @@ interface ModelInfo {
32
32
  costPer1M?: number;
33
33
  }
34
34
 
35
- function isModelCategory(value: unknown): value is ModelCategory {
35
+ function isModelCategory(value: any): value is ModelCategory {
36
36
  return (
37
37
  value === "text" ||
38
38
  value === "image" ||
@@ -41,7 +41,7 @@ function isModelCategory(value: unknown): value is ModelCategory {
41
41
  );
42
42
  }
43
43
 
44
- function isModelInfo(value: unknown): value is ModelInfo {
44
+ function isModelInfo(value: any): value is ModelInfo {
45
45
  if (!value || typeof value !== "object") return false;
46
46
  const v = value as Record<string, unknown>;
47
47
  return (