@lastbrain/ai-ui-react 1.0.34 → 1.0.36
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.
- package/dist/components/AiChipLabel.d.ts.map +1 -1
- package/dist/components/AiChipLabel.js +5 -1
- package/dist/components/AiContextButton.d.ts.map +1 -1
- package/dist/components/AiContextButton.js +1 -0
- package/dist/components/AiImageButton.d.ts.map +1 -1
- package/dist/components/AiImageButton.js +15 -2
- package/dist/components/AiInput.d.ts.map +1 -1
- package/dist/components/AiInput.js +5 -1
- package/dist/components/AiPromptPanel.d.ts +1 -1
- package/dist/components/AiPromptPanel.d.ts.map +1 -1
- package/dist/components/AiPromptPanel.js +9 -5
- package/dist/components/AiSelect.d.ts.map +1 -1
- package/dist/components/AiSelect.js +5 -1
- package/dist/components/AiTextarea.d.ts.map +1 -1
- package/dist/components/AiTextarea.js +5 -1
- package/dist/context/AiProvider.d.ts +28 -0
- package/dist/context/AiProvider.d.ts.map +1 -1
- package/dist/context/AiProvider.js +159 -1
- package/dist/hooks/useAiModels.d.ts +6 -1
- package/dist/hooks/useAiModels.d.ts.map +1 -1
- package/dist/hooks/useAiModels.js +71 -24
- package/dist/hooks/useModelManagement.d.ts +2 -10
- package/dist/hooks/useModelManagement.d.ts.map +1 -1
- package/dist/hooks/useModelManagement.js +42 -150
- package/dist/utils/modelManagement.d.ts.map +1 -1
- package/dist/utils/modelManagement.js +7 -3
- package/package.json +2 -2
- package/src/components/AiChipLabel.tsx +5 -1
- package/src/components/AiContextButton.tsx +1 -0
- package/src/components/AiImageButton.tsx +16 -2
- package/src/components/AiInput.tsx +5 -1
- package/src/components/AiPromptPanel.tsx +24 -1
- package/src/components/AiSelect.tsx +5 -1
- package/src/components/AiTextarea.tsx +5 -1
- package/src/context/AiProvider.tsx +223 -1
- package/src/hooks/useAiModels.ts +96 -27
- package/src/hooks/useModelManagement.ts +52 -203
- package/src/utils/modelManagement.ts +7 -3
package/src/hooks/useAiModels.ts
CHANGED
|
@@ -1,50 +1,119 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useMemo, useCallback } from "react";
|
|
4
4
|
import type { ModelRef } from "@lastbrain/ai-ui-core";
|
|
5
|
-
import {
|
|
5
|
+
import { useAiContext } from "../context/AiProvider";
|
|
6
6
|
|
|
7
7
|
export interface UseAiModelsOptions {
|
|
8
8
|
baseUrl?: string;
|
|
9
9
|
apiKeyId?: string;
|
|
10
|
+
modelType?: "text" | "language" | "image" | "embed" | "text-or-language"; // Filtrer par type
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export interface UseAiModelsResult {
|
|
13
|
-
models: ModelRef[]
|
|
14
|
+
models: ModelRef[];
|
|
14
15
|
loading: boolean;
|
|
15
16
|
error: Error | null;
|
|
16
17
|
refetch: () => void;
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Hook pour récupérer les modèles disponibles
|
|
22
|
+
* Utilise les données du contexte pour éviter les appels API multiples
|
|
23
|
+
*/
|
|
19
24
|
export function useAiModels(options?: UseAiModelsOptions): UseAiModelsResult {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
const context = useAiContext();
|
|
26
|
+
|
|
27
|
+
// Si les options ne correspondent pas au contexte, on peut faire un appel direct
|
|
28
|
+
// Mais dans la plupart des cas, on utilise le contexte
|
|
29
|
+
const useContextData =
|
|
30
|
+
(!options?.baseUrl || options.baseUrl === context.baseUrl) &&
|
|
31
|
+
(!options?.apiKeyId || options.apiKeyId === context.apiKeyId);
|
|
32
|
+
|
|
33
|
+
// Filtrer les modèles selon le type demandé
|
|
34
|
+
const filteredModels = useMemo(() => {
|
|
35
|
+
console.log("[useAiModels] Filtering models:", {
|
|
36
|
+
useContextData,
|
|
37
|
+
allModelsLength: context.allModels.length,
|
|
38
|
+
modelType: options?.modelType,
|
|
39
|
+
loading: context.loadingProviders,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (!useContextData) {
|
|
43
|
+
console.log("[useAiModels] Not using context data");
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Pendant le chargement, retourner un tableau vide
|
|
48
|
+
if (context.loadingProviders) {
|
|
49
|
+
console.log("[useAiModels] Still loading...");
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Si pas de modèles après le chargement
|
|
54
|
+
if (!context.allModels.length) {
|
|
55
|
+
console.log("[useAiModels] No models in context");
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!options?.modelType) {
|
|
60
|
+
console.log(
|
|
61
|
+
"[useAiModels] Returning all models:",
|
|
62
|
+
context.allModels.length
|
|
63
|
+
);
|
|
64
|
+
return context.allModels;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Cas spécial: text ou language
|
|
68
|
+
if (options.modelType === "text-or-language") {
|
|
69
|
+
const textModels = context.getTextModels();
|
|
70
|
+
console.log("[useAiModels] Returning text models:", textModels.length);
|
|
71
|
+
return textModels;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Cas spécial: image
|
|
75
|
+
if (options.modelType === "image") {
|
|
76
|
+
const imageModels = context.getImageModels();
|
|
77
|
+
console.log(
|
|
78
|
+
"[useAiModels] Returning image models:",
|
|
79
|
+
imageModels.length,
|
|
80
|
+
imageModels
|
|
34
81
|
);
|
|
35
|
-
|
|
36
|
-
|
|
82
|
+
return imageModels;
|
|
83
|
+
}
|
|
84
|
+
const filtered = context.getModelsByType(options.modelType);
|
|
85
|
+
console.log(
|
|
86
|
+
`[useAiModels] Returning ${options.modelType} models:`,
|
|
87
|
+
filtered.length
|
|
88
|
+
);
|
|
89
|
+
return filtered;
|
|
90
|
+
return filtered;
|
|
91
|
+
}, [useContextData, context, options?.modelType]);
|
|
92
|
+
|
|
93
|
+
const refetch = useCallback(() => {
|
|
94
|
+
if (useContextData) {
|
|
95
|
+
context.refetchProviders();
|
|
37
96
|
}
|
|
38
|
-
}, [
|
|
97
|
+
}, [useContextData, context]);
|
|
39
98
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
99
|
+
if (useContextData) {
|
|
100
|
+
return {
|
|
101
|
+
models: filteredModels,
|
|
102
|
+
loading: context.loadingProviders,
|
|
103
|
+
error: null,
|
|
104
|
+
refetch,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
43
107
|
|
|
108
|
+
// Fallback: si les options ne correspondent pas, retourner des valeurs vides
|
|
109
|
+
// (cas rare, la plupart du temps on utilise le contexte)
|
|
110
|
+
console.log("[useAiModels] Using fallback (no context match)");
|
|
44
111
|
return {
|
|
45
|
-
models,
|
|
46
|
-
loading,
|
|
47
|
-
error
|
|
48
|
-
|
|
112
|
+
models: [],
|
|
113
|
+
loading: false,
|
|
114
|
+
error: new Error(
|
|
115
|
+
"useAiModels called with different baseUrl/apiKeyId than context"
|
|
116
|
+
),
|
|
117
|
+
refetch: () => {},
|
|
49
118
|
};
|
|
50
119
|
}
|
|
@@ -1,28 +1,9 @@
|
|
|
1
|
-
import { useState, useCallback,
|
|
2
|
-
import { useAiContext } from "../context/AiProvider";
|
|
1
|
+
import { useState, useCallback, useMemo } from "react";
|
|
2
|
+
import { useAiContext, type AIModel } from "../context/AiProvider";
|
|
3
3
|
import {
|
|
4
4
|
toggleUserModel,
|
|
5
|
-
getAvailableModels,
|
|
6
|
-
getUserModels,
|
|
7
5
|
type ModelToggleOptions,
|
|
8
6
|
} from "../utils/modelManagement";
|
|
9
|
-
import {
|
|
10
|
-
getCached,
|
|
11
|
-
setCache,
|
|
12
|
-
isRateLimited,
|
|
13
|
-
getRateLimitResetTime,
|
|
14
|
-
} from "../utils/cache";
|
|
15
|
-
|
|
16
|
-
export interface AIModel {
|
|
17
|
-
id: string;
|
|
18
|
-
name: string;
|
|
19
|
-
description?: string;
|
|
20
|
-
provider: string;
|
|
21
|
-
category: "text" | "image" | "audio" | "video";
|
|
22
|
-
isActive?: boolean;
|
|
23
|
-
isPro?: boolean;
|
|
24
|
-
costPer1M?: number;
|
|
25
|
-
}
|
|
26
7
|
|
|
27
8
|
export interface UseModelManagementOptions extends ModelToggleOptions {
|
|
28
9
|
autoFetch?: boolean; // Charger automatiquement les données au mount
|
|
@@ -49,231 +30,99 @@ export interface UseModelManagementReturn {
|
|
|
49
30
|
|
|
50
31
|
/**
|
|
51
32
|
* Hook pour gérer les modèles IA d'un utilisateur
|
|
33
|
+
* Utilise les données du contexte pour éviter les appels API multiples
|
|
52
34
|
*/
|
|
53
35
|
export function useModelManagement(
|
|
54
36
|
options: UseModelManagementOptions = {}
|
|
55
37
|
): UseModelManagementReturn {
|
|
56
|
-
const {
|
|
57
|
-
const
|
|
38
|
+
const { category } = options;
|
|
39
|
+
const context = useAiContext();
|
|
58
40
|
|
|
59
|
-
const [availableModels, setAvailableModels] = useState<AIModel[]>([]);
|
|
60
|
-
const [userModels, setUserModels] = useState<string[]>([]);
|
|
61
41
|
const [loading, setLoading] = useState(false);
|
|
62
42
|
const [error, setError] = useState<string | null>(null);
|
|
63
|
-
const [apiUnavailable, setApiUnavailable] = useState(false);
|
|
64
|
-
|
|
65
|
-
// Utiliser baseUrl et apiKey du contexte avec memoization
|
|
66
|
-
const effectiveOptions = useMemo(
|
|
67
|
-
() => ({
|
|
68
|
-
baseUrl: options.baseUrl || baseUrl,
|
|
69
|
-
apiKey: options.apiKey || apiKeyId,
|
|
70
|
-
}),
|
|
71
|
-
[options.baseUrl, options.apiKey, baseUrl, apiKeyId]
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
const refreshModels = useCallback(async () => {
|
|
75
|
-
try {
|
|
76
|
-
setLoading(true);
|
|
77
|
-
setError(null);
|
|
78
|
-
|
|
79
|
-
// Check cache first (5 minutes TTL for models)
|
|
80
|
-
const cacheKey = `models_${category || "all"}`;
|
|
81
|
-
const cached = getCached<AIModel[]>(cacheKey, 300000);
|
|
82
|
-
if (cached) {
|
|
83
|
-
console.log("[useModelManagement] Using cached models");
|
|
84
|
-
setAvailableModels(cached);
|
|
85
|
-
setLoading(false);
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Check rate limit (max 5 calls per minute)
|
|
90
|
-
if (isRateLimited("models_fetch", 5, 60000)) {
|
|
91
|
-
const resetTime = getRateLimitResetTime("models_fetch");
|
|
92
|
-
const resetSeconds = Math.ceil(resetTime / 1000);
|
|
93
|
-
throw new Error(
|
|
94
|
-
`Rate limit exceeded. Please wait ${resetSeconds}s before trying again.`
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
console.log(
|
|
99
|
-
"[useModelManagement] Fetching available models with options:",
|
|
100
|
-
{
|
|
101
|
-
apiKey: effectiveOptions.apiKey
|
|
102
|
-
? effectiveOptions.apiKey.substring(0, 10) + "..."
|
|
103
|
-
: "none",
|
|
104
|
-
baseUrl: effectiveOptions.baseUrl || "default",
|
|
105
|
-
}
|
|
106
|
-
);
|
|
107
43
|
|
|
108
|
-
|
|
109
|
-
|
|
44
|
+
// Utiliser les données du contexte si disponibles
|
|
45
|
+
const useContextData =
|
|
46
|
+
(!options.baseUrl || options.baseUrl === context.baseUrl) &&
|
|
47
|
+
(!options.apiKey || options.apiKey === context.apiKeyId);
|
|
110
48
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
49
|
+
// Filtrer par catégorie si nécessaire
|
|
50
|
+
const filteredModels = useMemo(() => {
|
|
51
|
+
if (!useContextData) return [];
|
|
52
|
+
return category
|
|
53
|
+
? context.availableModels.filter((m) => m.category === category)
|
|
54
|
+
: context.availableModels;
|
|
55
|
+
}, [useContextData, category, context.availableModels]);
|
|
114
56
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
console.log(
|
|
119
|
-
"[useModelManagement] Set filtered models:",
|
|
120
|
-
filteredModels.length
|
|
121
|
-
);
|
|
122
|
-
} catch (err) {
|
|
123
|
-
const errorMessage =
|
|
124
|
-
err instanceof Error ? err.message : "Erreur inconnue";
|
|
125
|
-
console.error(
|
|
126
|
-
"[useModelManagement] Error fetching available models:",
|
|
127
|
-
errorMessage
|
|
128
|
-
);
|
|
129
|
-
setError(errorMessage);
|
|
130
|
-
// En cas d'erreur 404 (API non disponible), utiliser un array vide
|
|
131
|
-
if (errorMessage.includes("404") || errorMessage.includes("Not Found")) {
|
|
132
|
-
setAvailableModels([]);
|
|
133
|
-
}
|
|
134
|
-
} finally {
|
|
135
|
-
setLoading(false);
|
|
57
|
+
const refreshModels = useCallback(async () => {
|
|
58
|
+
if (useContextData) {
|
|
59
|
+
await context.refetchProviders();
|
|
136
60
|
}
|
|
137
|
-
}, [
|
|
61
|
+
}, [useContextData, context]);
|
|
138
62
|
|
|
139
63
|
const refreshUserModels = useCallback(async () => {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
console.log(
|
|
143
|
-
"[useModelManagement] Skipping user models fetch - API marked as unavailable"
|
|
144
|
-
);
|
|
145
|
-
return;
|
|
64
|
+
if (useContextData) {
|
|
65
|
+
await context.refetchUserModels();
|
|
146
66
|
}
|
|
147
|
-
|
|
148
|
-
try {
|
|
149
|
-
setLoading(true);
|
|
150
|
-
setError(null);
|
|
151
|
-
|
|
152
|
-
console.log("[useModelManagement] Fetching user models with options:", {
|
|
153
|
-
apiKey: effectiveOptions.apiKey
|
|
154
|
-
? effectiveOptions.apiKey.substring(0, 10) + "..."
|
|
155
|
-
: "none",
|
|
156
|
-
baseUrl: effectiveOptions.baseUrl || "default",
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
const models = await getUserModels(effectiveOptions);
|
|
160
|
-
console.log("[useModelManagement] Got user models:", models);
|
|
161
|
-
setUserModels(models);
|
|
162
|
-
} catch (err) {
|
|
163
|
-
const errorMessage =
|
|
164
|
-
err instanceof Error ? err.message : "Erreur inconnue";
|
|
165
|
-
console.error(
|
|
166
|
-
"[useModelManagement] Error fetching user models:",
|
|
167
|
-
errorMessage
|
|
168
|
-
);
|
|
169
|
-
setError(errorMessage);
|
|
170
|
-
// En cas d'erreur 404 (API non disponible), utiliser un array vide et ne pas retry
|
|
171
|
-
if (errorMessage.includes("404") || errorMessage.includes("Not Found")) {
|
|
172
|
-
setUserModels([]);
|
|
173
|
-
setApiUnavailable(true);
|
|
174
|
-
console.warn(
|
|
175
|
-
"[useModelManagement] User models API not available (404), disabling further requests"
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
} finally {
|
|
179
|
-
setLoading(false);
|
|
180
|
-
}
|
|
181
|
-
}, [effectiveOptions, apiUnavailable]);
|
|
67
|
+
}, [useContextData, context]);
|
|
182
68
|
|
|
183
69
|
const toggleModel = useCallback(
|
|
184
70
|
async (modelId: string, isActive?: boolean) => {
|
|
185
|
-
const currentlyActive = userModels.includes(modelId);
|
|
71
|
+
const currentlyActive = context.userModels.includes(modelId);
|
|
186
72
|
const targetState = isActive !== undefined ? isActive : !currentlyActive;
|
|
187
73
|
|
|
188
74
|
try {
|
|
189
75
|
setLoading(true);
|
|
190
76
|
setError(null);
|
|
191
77
|
|
|
78
|
+
const effectiveOptions = {
|
|
79
|
+
baseUrl: options.baseUrl || context.baseUrl,
|
|
80
|
+
apiKey: options.apiKey || context.apiKeyId,
|
|
81
|
+
};
|
|
82
|
+
|
|
192
83
|
await toggleUserModel(modelId, targetState, effectiveOptions);
|
|
193
84
|
|
|
194
|
-
//
|
|
195
|
-
|
|
196
|
-
setUserModels((prev) => [
|
|
197
|
-
...prev.filter((id) => id !== modelId),
|
|
198
|
-
modelId,
|
|
199
|
-
]);
|
|
200
|
-
} else {
|
|
201
|
-
setUserModels((prev) => prev.filter((id) => id !== modelId));
|
|
202
|
-
}
|
|
85
|
+
// Rafraîchir les modèles utilisateur depuis le contexte
|
|
86
|
+
await context.refetchUserModels();
|
|
203
87
|
} catch (err) {
|
|
204
|
-
|
|
88
|
+
const errorMessage =
|
|
89
|
+
err instanceof Error ? err.message : "Erreur inconnue";
|
|
90
|
+
console.error(
|
|
91
|
+
"[useModelManagement] Error toggling model:",
|
|
92
|
+
errorMessage
|
|
93
|
+
);
|
|
94
|
+
setError(errorMessage);
|
|
205
95
|
throw err;
|
|
206
96
|
} finally {
|
|
207
97
|
setLoading(false);
|
|
208
98
|
}
|
|
209
99
|
},
|
|
210
|
-
[
|
|
100
|
+
[context, options.baseUrl, options.apiKey]
|
|
211
101
|
);
|
|
212
102
|
|
|
213
|
-
// Helpers
|
|
214
103
|
const isModelActive = useCallback(
|
|
215
104
|
(modelId: string) => {
|
|
216
|
-
return userModels.includes(modelId);
|
|
105
|
+
return context.userModels.includes(modelId);
|
|
217
106
|
},
|
|
218
|
-
[userModels]
|
|
107
|
+
[context.userModels]
|
|
219
108
|
);
|
|
220
109
|
|
|
221
110
|
const getActiveModels = useCallback(() => {
|
|
222
|
-
return
|
|
223
|
-
|
|
111
|
+
return filteredModels.filter((model) =>
|
|
112
|
+
context.userModels.includes(model.id)
|
|
113
|
+
);
|
|
114
|
+
}, [filteredModels, context.userModels]);
|
|
224
115
|
|
|
225
116
|
const getInactiveModels = useCallback(() => {
|
|
226
|
-
return
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
useEffect(() => {
|
|
231
|
-
const isExternalProxy =
|
|
232
|
-
effectiveOptions.baseUrl &&
|
|
233
|
-
effectiveOptions.baseUrl.includes("/api/lastbrain");
|
|
234
|
-
|
|
235
|
-
console.log("[useModelManagement] useEffect triggered:", {
|
|
236
|
-
autoFetch,
|
|
237
|
-
hasApiKey: !!effectiveOptions.apiKey,
|
|
238
|
-
hasBaseUrl: !!effectiveOptions.baseUrl,
|
|
239
|
-
isExternalProxy,
|
|
240
|
-
apiUnavailable,
|
|
241
|
-
apiKeyPreview: effectiveOptions.apiKey
|
|
242
|
-
? effectiveOptions.apiKey.substring(0, 10) + "..."
|
|
243
|
-
: "none",
|
|
244
|
-
baseUrl: effectiveOptions.baseUrl || "none",
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
// Auto-fetch si autoFetch est activé ET qu'on a soit une apiKey soit un proxy externe ET API disponible
|
|
248
|
-
if (
|
|
249
|
-
autoFetch &&
|
|
250
|
-
!apiUnavailable &&
|
|
251
|
-
(effectiveOptions.apiKey || isExternalProxy)
|
|
252
|
-
) {
|
|
253
|
-
console.log("[useModelManagement] Starting auto-fetch...");
|
|
254
|
-
Promise.all([refreshModels(), refreshUserModels()]);
|
|
255
|
-
} else if (autoFetch && !effectiveOptions.apiKey && !isExternalProxy) {
|
|
256
|
-
console.warn(
|
|
257
|
-
"[useModelManagement] autoFetch is enabled but no apiKey or baseUrl provided. Skipping automatic fetch."
|
|
258
|
-
);
|
|
259
|
-
} else if (autoFetch && apiUnavailable) {
|
|
260
|
-
console.log(
|
|
261
|
-
"[useModelManagement] autoFetch skipped - API marked as unavailable"
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
|
-
}, [
|
|
265
|
-
autoFetch,
|
|
266
|
-
refreshModels,
|
|
267
|
-
refreshUserModels,
|
|
268
|
-
effectiveOptions.apiKey,
|
|
269
|
-
effectiveOptions.baseUrl,
|
|
270
|
-
apiUnavailable,
|
|
271
|
-
]);
|
|
117
|
+
return filteredModels.filter(
|
|
118
|
+
(model) => !context.userModels.includes(model.id)
|
|
119
|
+
);
|
|
120
|
+
}, [filteredModels, context.userModels]);
|
|
272
121
|
|
|
273
122
|
return {
|
|
274
|
-
availableModels,
|
|
275
|
-
userModels,
|
|
276
|
-
loading,
|
|
123
|
+
availableModels: filteredModels,
|
|
124
|
+
userModels: context.userModels,
|
|
125
|
+
loading: context.loadingProviders || context.loadingUserModels || loading,
|
|
277
126
|
error,
|
|
278
127
|
toggleModel,
|
|
279
128
|
refreshModels,
|
|
@@ -27,12 +27,16 @@ export async function toggleUserModel(
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const isPublicApi = baseUrl && baseUrl.includes("/api/public/v1");
|
|
30
|
+
const isExternalProxy = baseUrl && baseUrl.includes("/api/lastbrain");
|
|
30
31
|
|
|
32
|
+
// Route mapping pour toggle
|
|
31
33
|
const endpoint = isPublicApi
|
|
32
34
|
? `${baseUrl}/ai/user/models/toggle`
|
|
33
|
-
:
|
|
34
|
-
? `${baseUrl}/
|
|
35
|
-
:
|
|
35
|
+
: isExternalProxy
|
|
36
|
+
? `${baseUrl}/ai/user/models/toggle` // Gateway mappe automatiquement
|
|
37
|
+
: baseUrl
|
|
38
|
+
? `${baseUrl}/auth/ai-models-toggle`
|
|
39
|
+
: `/api/ai/auth/ai-models-toggle`;
|
|
36
40
|
|
|
37
41
|
const response = await fetch(endpoint, {
|
|
38
42
|
method: "PUT",
|