@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiChipLabel.d.ts","sourceRoot":"","sources":["../../src/components/AiChipLabel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAS/D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,OAAmB,EACnB,SAAS,EACT,KAAK,EAAE,WAAW,GACnB,EAAE,gBAAgB,2CAgClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,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,WAAW,CAAC,EAC1B,KAAU,EACV,QAAQ,EACR,WAAoE,EACpE,OAAO,EACP,QAAQ,EACR,eAAuB,EACvB,SAAS,EACT,YAAY,EACZ,aAAa,EACb,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,GACvB,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"AiChipLabel.d.ts","sourceRoot":"","sources":["../../src/components/AiChipLabel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAS/D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,OAAmB,EACnB,SAAS,EACT,KAAK,EAAE,WAAW,GACnB,EAAE,gBAAgB,2CAgClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,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,WAAW,CAAC,EAC1B,KAAU,EACV,QAAQ,EACR,WAAoE,EACpE,OAAO,EACP,QAAQ,EACR,eAAuB,EACvB,SAAS,EACT,YAAY,EACZ,aAAa,EACb,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,GACvB,EAAE,gBAAgB,2CAkMlB"}
|
|
@@ -42,7 +42,11 @@ export function AiChipInput({ value = [], onChange, placeholder = "Tapez et appu
|
|
|
42
42
|
const baseUrl = propBaseUrl ?? aiContext.baseUrl;
|
|
43
43
|
const apiKeyId = propApiKeyId ?? aiContext.apiKeyId;
|
|
44
44
|
// Hooks pour l'IA avec les valeurs du contexte
|
|
45
|
-
const { models } = useAiModels({
|
|
45
|
+
const { models } = useAiModels({
|
|
46
|
+
baseUrl,
|
|
47
|
+
apiKeyId,
|
|
48
|
+
modelType: "text-or-language",
|
|
49
|
+
});
|
|
46
50
|
const { generateText } = useAiCallText({ baseUrl, apiKeyId });
|
|
47
51
|
const addChip = (text) => {
|
|
48
52
|
if (!text.trim())
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiContextButton.d.ts","sourceRoot":"","sources":["../../src/components/AiContextButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAU5C,MAAM,WAAW,oBACf,SACE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC,EACrC,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IAEvE,WAAW,EAAE,GAAG,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,CACT,MAAM,EAAE,MAAM,EACd,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,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,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,eAAe,CAAC,EAC9B,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,EACtB,MAAgB,EAChB,WAAW,EACX,kBAAyC,EACzC,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,gBAA0C,EAC1C,YAAY,EACZ,aAAa,EACb,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,GAAG,WAAW,EACf,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"AiContextButton.d.ts","sourceRoot":"","sources":["../../src/components/AiContextButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAU5C,MAAM,WAAW,oBACf,SACE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC,EACrC,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IAEvE,WAAW,EAAE,GAAG,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,CACT,MAAM,EAAE,MAAM,EACd,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,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,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,eAAe,CAAC,EAC9B,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,EACtB,MAAgB,EAChB,WAAW,EACX,kBAAyC,EACzC,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,gBAA0C,EAC1C,YAAY,EACZ,aAAa,EACb,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,GAAG,WAAW,EACf,EAAE,oBAAoB,2CA8ftB"}
|
|
@@ -24,6 +24,7 @@ export function AiContextButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId,
|
|
|
24
24
|
const { models, loading: modelsLoading } = useAiModels({
|
|
25
25
|
baseUrl,
|
|
26
26
|
apiKeyId,
|
|
27
|
+
modelType: "text-or-language",
|
|
27
28
|
});
|
|
28
29
|
const { generateText: callText, loading } = useAiCallText({
|
|
29
30
|
baseUrl,
|
|
@@ -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;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAU5C,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,
|
|
1
|
+
{"version":3,"file":"AiImageButton.d.ts","sourceRoot":"","sources":["../../src/components/AiImageButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAU5C,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,2CAgYpB"}
|
|
@@ -19,8 +19,13 @@ export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, ui
|
|
|
19
19
|
const aiContext = useAiContext();
|
|
20
20
|
const baseUrl = propBaseUrl ?? aiContext.baseUrl;
|
|
21
21
|
const apiKeyId = propApiKeyId ?? aiContext.apiKeyId;
|
|
22
|
-
|
|
22
|
+
// Récupérer uniquement les modèles image
|
|
23
|
+
const { models } = useAiModels({ baseUrl, apiKeyId, modelType: "image" });
|
|
23
24
|
const { generateImage, loading } = useAiCallImage({ baseUrl, apiKeyId });
|
|
25
|
+
console.log("[AiImageButton] Models received:", {
|
|
26
|
+
count: models.length,
|
|
27
|
+
models: models.map((m) => ({ id: m.id, name: m.name, type: m.type })),
|
|
28
|
+
});
|
|
24
29
|
const handleOpenPanel = () => {
|
|
25
30
|
setIsOpen(true);
|
|
26
31
|
};
|
|
@@ -189,7 +194,15 @@ export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, ui
|
|
|
189
194
|
} }), _jsx("span", { style: { letterSpacing: "0.025em" }, children: "G\u00E9n\u00E9ration..." })] })) : (_jsxs(_Fragment, { children: [_jsx(ImageIcon, { size: 18, style: {
|
|
190
195
|
color: "white",
|
|
191
196
|
filter: "drop-shadow(0 0 2px rgba(255,255,255,0.2))",
|
|
192
|
-
} }), _jsx("span", { style: { letterSpacing: "0.025em" }, children: children || "Générer une image" })] })) }), isOpen && (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: handleClosePanel, onSubmit: handleSubmit, uiMode: uiMode, models:
|
|
197
|
+
} }), _jsx("span", { style: { letterSpacing: "0.025em" }, children: children || "Générer une image" })] })) }), isOpen && (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: handleClosePanel, onSubmit: handleSubmit, uiMode: uiMode, models: (() => {
|
|
198
|
+
const filteredModels = models.filter((m) => m.type === "image");
|
|
199
|
+
console.log("[AiImageButton] Passing to AiPromptPanel:", {
|
|
200
|
+
originalCount: models.length,
|
|
201
|
+
filteredCount: filteredModels.length,
|
|
202
|
+
models: filteredModels,
|
|
203
|
+
});
|
|
204
|
+
return filteredModels;
|
|
205
|
+
})() }))] }), showImageCard && generatedImage && (_jsxs("div", { className: "relative", style: {
|
|
193
206
|
maxWidth: "320px",
|
|
194
207
|
borderRadius: "12px",
|
|
195
208
|
padding: "16px",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiInput.d.ts","sourceRoot":"","sources":["../../src/components/AiInput.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAoB,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAE1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQ5C,MAAM,WAAW,YACf,SACE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,SAAS,CAAC;IACxD,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC5B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,QAAgB,EAChB,qBAA6B,EAC7B,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,UAAU,EACd,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"AiInput.d.ts","sourceRoot":"","sources":["../../src/components/AiInput.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAoB,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAE1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQ5C,MAAM,WAAW,YACf,SACE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,SAAS,CAAC;IACxD,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC5B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,QAAgB,EAChB,qBAA6B,EAC7B,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,UAAU,EACd,EAAE,YAAY,2CAiLd"}
|
|
@@ -15,7 +15,11 @@ export function AiInput({ baseUrl, apiKeyId, uiMode = "modal", context, model, p
|
|
|
15
15
|
const [isButtonHovered, setIsButtonHovered] = useState(false);
|
|
16
16
|
const inputRef = useRef(null);
|
|
17
17
|
const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
|
|
18
|
-
const { models } = useAiModels({
|
|
18
|
+
const { models } = useAiModels({
|
|
19
|
+
baseUrl,
|
|
20
|
+
apiKeyId,
|
|
21
|
+
modelType: "text-or-language",
|
|
22
|
+
});
|
|
19
23
|
const { generateText, loading } = useAiCallText({ baseUrl, apiKeyId });
|
|
20
24
|
const hasConfiguration = Boolean(model && prompt);
|
|
21
25
|
const handleOpenPanel = () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import type { ModelRef } from "@lastbrain/ai-ui-core";
|
|
3
3
|
import type { UiMode } from "../types";
|
|
4
|
-
import { type AIModel } from "../
|
|
4
|
+
import { type AIModel } from "../context/AiProvider";
|
|
5
5
|
export interface AiPromptPanelProps {
|
|
6
6
|
isOpen: boolean;
|
|
7
7
|
onClose: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiPromptPanel.d.ts","sourceRoot":"","sources":["../../src/components/AiPromptPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"AiPromptPanel.d.ts","sourceRoot":"","sources":["../../src/components/AiPromptPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AASvC,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGrD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,SAAS,CAAC;IAE1D,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,IAAI,CAAC;IAExB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3C,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,2CActD"}
|
|
@@ -539,11 +539,15 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode: _uiMode = "m
|
|
|
539
539
|
maxWidth: "600px",
|
|
540
540
|
maxHeight: "80vh",
|
|
541
541
|
overflow: "auto",
|
|
542
|
-
}, children: [_jsxs("div", { style: aiStyles.modalHeader, children: [_jsx("h2", { style: aiStyles.modalTitle, children: "Gestion des mod\u00E8les IA" }), _jsx("button", { style: aiStyles.modalCloseButton, onClick: () => setIsModelManagementOpen(false), "aria-label": "Close", children: "\u00D7" })] }), _jsxs("div", { style: aiStyles.modalBody, children: [
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
542
|
+
}, children: [_jsxs("div", { style: aiStyles.modalHeader, children: [_jsx("h2", { style: aiStyles.modalTitle, children: "Gestion des mod\u00E8les IA" }), _jsx("button", { style: aiStyles.modalCloseButton, onClick: () => setIsModelManagementOpen(false), "aria-label": "Close", children: "\u00D7" })] }), _jsxs("div", { style: aiStyles.modalBody, children: [_jsxs("div", { style: { marginBottom: "16px" }, children: [_jsx("p", { style: {
|
|
543
|
+
fontSize: "14px",
|
|
544
|
+
color: "#6b7280",
|
|
545
|
+
margin: "0 0 16px 0",
|
|
546
|
+
}, children: "Activez ou d\u00E9sactivez les mod\u00E8les selon vos besoins" }), _jsxs("p", { style: {
|
|
547
|
+
fontSize: "12px",
|
|
548
|
+
color: "#9ca3af",
|
|
549
|
+
margin: "0",
|
|
550
|
+
}, children: [effectiveAvailableModels.filter((m) => m.category === "text").length, " ", "mod\u00E8les disponibles \u2022", " ", effectiveUserModels.filter((id) => effectiveAvailableModels.some((m) => m.id === id && m.category === "text")).length, " ", "activ\u00E9s"] })] }), _jsx("div", { style: {
|
|
547
551
|
display: "flex",
|
|
548
552
|
flexDirection: "column",
|
|
549
553
|
gap: "12px",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiSelect.d.ts","sourceRoot":"","sources":["../../src/components/AiSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQ5C,MAAM,WAAW,aACf,SACE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,CAAC;IAC1D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,GAAG,WAAW,EACf,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"AiSelect.d.ts","sourceRoot":"","sources":["../../src/components/AiSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQ5C,MAAM,WAAW,aACf,SACE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,CAAC;IAC1D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,GAAG,WAAW,EACf,EAAE,aAAa,2CAqFf"}
|
|
@@ -11,7 +11,11 @@ export function AiSelect({ baseUrl, apiKeyId, uiMode = "modal", context, model,
|
|
|
11
11
|
const [isOpen, setIsOpen] = useState(false);
|
|
12
12
|
const [isFocused, setIsFocused] = useState(false);
|
|
13
13
|
const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
|
|
14
|
-
const { models } = useAiModels({
|
|
14
|
+
const { models } = useAiModels({
|
|
15
|
+
baseUrl,
|
|
16
|
+
apiKeyId,
|
|
17
|
+
modelType: "text-or-language",
|
|
18
|
+
});
|
|
15
19
|
const { generateText, loading } = useAiCallText({ baseUrl, apiKeyId });
|
|
16
20
|
const handleOpenPanel = () => {
|
|
17
21
|
setIsOpen(true);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiTextarea.d.ts","sourceRoot":"","sources":["../../src/components/AiTextarea.tsx"],"names":[],"mappings":"AAEA,OAAc,EAIZ,KAAK,sBAAsB,EAC5B,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQ5C,MAAM,WAAW,eACf,SACE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB,IAAI,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,EAAE,SAAS,CAAC;IAC9D,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,QAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,aAAa,EACjB,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"AiTextarea.d.ts","sourceRoot":"","sources":["../../src/components/AiTextarea.tsx"],"names":[],"mappings":"AAEA,OAAc,EAIZ,KAAK,sBAAsB,EAC5B,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQ5C,MAAM,WAAW,eACf,SACE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB,IAAI,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,EAAE,SAAS,CAAC;IAC9D,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,QAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,aAAa,EACjB,EAAE,eAAe,2CAkMjB"}
|
|
@@ -17,7 +17,11 @@ export function AiTextarea({ baseUrl, apiKeyId, uiMode = "modal", context, model
|
|
|
17
17
|
const [isButtonHovered, setIsButtonHovered] = useState(false);
|
|
18
18
|
const textareaRef = useRef(null);
|
|
19
19
|
const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
|
|
20
|
-
const { models } = useAiModels({
|
|
20
|
+
const { models } = useAiModels({
|
|
21
|
+
baseUrl,
|
|
22
|
+
apiKeyId,
|
|
23
|
+
modelType: "text-or-language",
|
|
24
|
+
});
|
|
21
25
|
const { generateText, loading } = useAiCallText({ baseUrl, apiKeyId });
|
|
22
26
|
const hasConfiguration = Boolean(model && prompt);
|
|
23
27
|
const handleOpenPanel = () => {
|
|
@@ -1,9 +1,37 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import type { UiMode } from "../types";
|
|
3
|
+
import type { ModelRef } from "@lastbrain/ai-ui-core";
|
|
4
|
+
export interface AIModel {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
provider: string;
|
|
9
|
+
category: "text" | "image" | "audio" | "video";
|
|
10
|
+
isActive?: boolean;
|
|
11
|
+
isPro?: boolean;
|
|
12
|
+
costPer1M?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface ProviderData {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
models: ModelRef[];
|
|
19
|
+
}
|
|
3
20
|
export interface AiContextValue {
|
|
4
21
|
baseUrl: string;
|
|
5
22
|
apiKeyId: string;
|
|
6
23
|
uiMode: UiMode;
|
|
24
|
+
providers: ProviderData[];
|
|
25
|
+
allModels: ModelRef[];
|
|
26
|
+
availableModels: AIModel[];
|
|
27
|
+
userModels: string[];
|
|
28
|
+
loadingProviders: boolean;
|
|
29
|
+
loadingUserModels: boolean;
|
|
30
|
+
refetchProviders: () => Promise<void>;
|
|
31
|
+
refetchUserModels: () => Promise<void>;
|
|
32
|
+
getModelsByType: (type: "text" | "language" | "image" | "embed") => ModelRef[];
|
|
33
|
+
getTextModels: () => ModelRef[];
|
|
34
|
+
getImageModels: () => ModelRef[];
|
|
7
35
|
}
|
|
8
36
|
declare const AiContext: import("react").Context<AiContextValue | undefined>;
|
|
9
37
|
export interface AiProviderProps {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiProvider.d.ts","sourceRoot":"","sources":["../../src/context/AiProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"AiProvider.d.ts","sourceRoot":"","sources":["../../src/context/AiProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAItD,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,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,QAAQ,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IAEf,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,eAAe,EAAE,OAAO,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAC;IAErB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,OAAO,CAAC;IAE3B,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvC,eAAe,EAAE,CACf,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,KAC1C,QAAQ,EAAE,CAAC;IAChB,aAAa,EAAE,MAAM,QAAQ,EAAE,CAAC;IAChC,cAAc,EAAE,MAAM,QAAQ,EAAE,CAAC;CAClC;AAED,QAAA,MAAM,SAAS,qDAAuD,CAAC;AAEvE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,QAAQ,GACT,EAAE,eAAe,2CAwLjB;AAED,wBAAgB,YAAY,IAAI,cAAc,CAM7C;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -1,12 +1,170 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { createContext, useContext } from "react";
|
|
3
|
+
import { createContext, useContext, useState, useEffect, useCallback, useRef, } from "react";
|
|
4
|
+
import { createClient } from "@lastbrain/ai-ui-core";
|
|
5
|
+
import { getAvailableModels, getUserModels } from "../utils/modelManagement";
|
|
4
6
|
const AiContext = createContext(undefined);
|
|
5
7
|
export function AiProvider({ baseUrl, apiKeyId, uiMode = "modal", children, }) {
|
|
8
|
+
const [providers, setProviders] = useState([]);
|
|
9
|
+
const [allModels, setAllModels] = useState([]);
|
|
10
|
+
const [availableModels, setAvailableModels] = useState([]);
|
|
11
|
+
const [userModels, setUserModels] = useState([]);
|
|
12
|
+
const [loadingProviders, setLoadingProviders] = useState(false);
|
|
13
|
+
const [loadingUserModels, setLoadingUserModels] = useState(false);
|
|
14
|
+
// Flags pour éviter les appels multiples et les boucles infinies
|
|
15
|
+
const isFetchingProviders = useRef(false);
|
|
16
|
+
const isFetchingUserModels = useRef(false);
|
|
17
|
+
const hasFetchedProviders = useRef(false);
|
|
18
|
+
const hasFetchedUserModels = useRef(false);
|
|
19
|
+
const providersAvailable = useRef(true); // false si 404
|
|
20
|
+
const userModelsAvailable = useRef(true); // false si 404
|
|
21
|
+
// Récupérer les providers et leurs modèles + available models en parallèle
|
|
22
|
+
const fetchProviders = useCallback(async () => {
|
|
23
|
+
// Éviter les appels multiples
|
|
24
|
+
if (isFetchingProviders.current) {
|
|
25
|
+
console.log("[AiProvider] Already fetching providers, skipping");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// Si déjà fetch et non disponible, ne pas réessayer
|
|
29
|
+
if (hasFetchedProviders.current && !providersAvailable.current) {
|
|
30
|
+
console.log("[AiProvider] Providers API not available (404), skipping");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
isFetchingProviders.current = true;
|
|
34
|
+
setLoadingProviders(true);
|
|
35
|
+
try {
|
|
36
|
+
console.log("[AiProvider] Fetching providers from:", baseUrl);
|
|
37
|
+
// Utiliser createClient pour avoir buildUrl qui gère les routes correctement
|
|
38
|
+
const client = createClient({ baseUrl, apiKeyId });
|
|
39
|
+
// Fetch providers et available models en parallèle
|
|
40
|
+
const [providersData, availableModelsData] = await Promise.all([
|
|
41
|
+
client
|
|
42
|
+
.getModels()
|
|
43
|
+
.then((models) => {
|
|
44
|
+
// getModels retourne directement les modèles, pas les providers
|
|
45
|
+
// On doit reconstruire la structure providers
|
|
46
|
+
return { providers: [{ id: "default", name: "Default", models }] };
|
|
47
|
+
})
|
|
48
|
+
.catch((error) => {
|
|
49
|
+
console.error("[AiProvider] Error fetching models:", error);
|
|
50
|
+
if (error.message?.includes("404")) {
|
|
51
|
+
providersAvailable.current = false;
|
|
52
|
+
}
|
|
53
|
+
return { providers: [] };
|
|
54
|
+
}),
|
|
55
|
+
getAvailableModels({ baseUrl, apiKey: apiKeyId }).catch((error) => {
|
|
56
|
+
console.warn("[AiProvider] Could not fetch available models:", error);
|
|
57
|
+
return [];
|
|
58
|
+
}),
|
|
59
|
+
]);
|
|
60
|
+
console.log("[AiProvider] Providers data received:", providersData);
|
|
61
|
+
if (providersData.providers && Array.isArray(providersData.providers)) {
|
|
62
|
+
setProviders(providersData.providers);
|
|
63
|
+
// Extraire tous les modèles
|
|
64
|
+
const models = [];
|
|
65
|
+
for (const provider of providersData.providers) {
|
|
66
|
+
if (provider.models && Array.isArray(provider.models)) {
|
|
67
|
+
models.push(...provider.models);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
console.log("[AiProvider] Extracted models:", models.length, models);
|
|
71
|
+
setAllModels(models);
|
|
72
|
+
}
|
|
73
|
+
// Stocker available models
|
|
74
|
+
console.log("[AiProvider] Available models:", availableModelsData.length);
|
|
75
|
+
setAvailableModels(availableModelsData);
|
|
76
|
+
hasFetchedProviders.current = true;
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
console.error("[AiProvider] Error fetching providers:", error);
|
|
80
|
+
// En cas d'erreur, utiliser des valeurs vides
|
|
81
|
+
setProviders([]);
|
|
82
|
+
setAllModels([]);
|
|
83
|
+
setAvailableModels([]);
|
|
84
|
+
hasFetchedProviders.current = true;
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
setLoadingProviders(false);
|
|
88
|
+
isFetchingProviders.current = false;
|
|
89
|
+
}
|
|
90
|
+
}, [baseUrl, apiKeyId]); // Retirer loadingProviders des dépendances
|
|
91
|
+
// Récupérer les modèles activés par l'utilisateur
|
|
92
|
+
const fetchUserModels = useCallback(async () => {
|
|
93
|
+
// Éviter les appels multiples
|
|
94
|
+
if (isFetchingUserModels.current) {
|
|
95
|
+
console.log("[AiProvider] Already fetching user models, skipping");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// Si déjà fetch et non disponible, ne pas réessayer
|
|
99
|
+
if (hasFetchedUserModels.current && !userModelsAvailable.current) {
|
|
100
|
+
console.log("[AiProvider] User models API not available (404), skipping");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
isFetchingUserModels.current = true;
|
|
104
|
+
setLoadingUserModels(true);
|
|
105
|
+
try {
|
|
106
|
+
const models = await getUserModels({ baseUrl, apiKey: apiKeyId });
|
|
107
|
+
setUserModels(models);
|
|
108
|
+
hasFetchedUserModels.current = true;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error("[AiProvider] Error fetching user models:", error);
|
|
112
|
+
// En cas d'erreur 404, ne pas logger comme erreur critique
|
|
113
|
+
if (error instanceof Error && error.message.includes("404")) {
|
|
114
|
+
console.warn("[AiProvider] User models API not available (404)");
|
|
115
|
+
userModelsAvailable.current = false;
|
|
116
|
+
setUserModels([]);
|
|
117
|
+
}
|
|
118
|
+
hasFetchedUserModels.current = true;
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
setLoadingUserModels(false);
|
|
122
|
+
isFetchingUserModels.current = false;
|
|
123
|
+
}
|
|
124
|
+
}, [baseUrl, apiKeyId]); // Retirer loadingUserModels des dépendances
|
|
125
|
+
// Récupérer les données au montage du provider
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
fetchProviders(); // Fetch providers + available models en même temps
|
|
128
|
+
fetchUserModels();
|
|
129
|
+
}, [fetchProviders, fetchUserModels]);
|
|
130
|
+
// Helpers pour filtrer les modèles par type
|
|
131
|
+
const getModelsByType = useCallback((type) => {
|
|
132
|
+
const filtered = allModels.filter((model) => model.type === type);
|
|
133
|
+
console.log(`[AiProvider] getModelsByType(${type}):`, {
|
|
134
|
+
total: allModels.length,
|
|
135
|
+
filtered: filtered.length,
|
|
136
|
+
models: filtered.map((m) => ({ id: m.id, name: m.name, type: m.type })),
|
|
137
|
+
});
|
|
138
|
+
return filtered;
|
|
139
|
+
}, [allModels]);
|
|
140
|
+
const getTextModels = useCallback(() => {
|
|
141
|
+
return allModels.filter((model) => model.type === "text" || model.type === "language");
|
|
142
|
+
}, [allModels]);
|
|
143
|
+
const getImageModels = useCallback(() => {
|
|
144
|
+
const imageModels = allModels.filter((model) => model.type === "image");
|
|
145
|
+
console.log("[AiProvider] getImageModels:", {
|
|
146
|
+
totalModels: allModels.length,
|
|
147
|
+
imageModels: imageModels.length,
|
|
148
|
+
allTypes: allModels.map((m) => ({ id: m.id, type: m.type })),
|
|
149
|
+
imageModelsList: imageModels.map((m) => ({ id: m.id, name: m.name })),
|
|
150
|
+
});
|
|
151
|
+
return imageModels;
|
|
152
|
+
}, [allModels]);
|
|
6
153
|
const value = {
|
|
7
154
|
baseUrl,
|
|
8
155
|
apiKeyId,
|
|
9
156
|
uiMode,
|
|
157
|
+
providers,
|
|
158
|
+
allModels,
|
|
159
|
+
availableModels,
|
|
160
|
+
userModels,
|
|
161
|
+
loadingProviders,
|
|
162
|
+
loadingUserModels,
|
|
163
|
+
refetchProviders: fetchProviders,
|
|
164
|
+
refetchUserModels: fetchUserModels,
|
|
165
|
+
getModelsByType,
|
|
166
|
+
getTextModels,
|
|
167
|
+
getImageModels,
|
|
10
168
|
};
|
|
11
169
|
return _jsx(AiContext.Provider, { value: value, children: children });
|
|
12
170
|
}
|
|
@@ -2,12 +2,17 @@ import type { ModelRef } from "@lastbrain/ai-ui-core";
|
|
|
2
2
|
export interface UseAiModelsOptions {
|
|
3
3
|
baseUrl?: string;
|
|
4
4
|
apiKeyId?: string;
|
|
5
|
+
modelType?: "text" | "language" | "image" | "embed" | "text-or-language";
|
|
5
6
|
}
|
|
6
7
|
export interface UseAiModelsResult {
|
|
7
|
-
models: ModelRef[]
|
|
8
|
+
models: ModelRef[];
|
|
8
9
|
loading: boolean;
|
|
9
10
|
error: Error | null;
|
|
10
11
|
refetch: () => void;
|
|
11
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Hook pour récupérer les modèles disponibles
|
|
15
|
+
* Utilise les données du contexte pour éviter les appels API multiples
|
|
16
|
+
*/
|
|
12
17
|
export declare function useAiModels(options?: UseAiModelsOptions): UseAiModelsResult;
|
|
13
18
|
//# sourceMappingURL=useAiModels.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAiModels.d.ts","sourceRoot":"","sources":["../../src/hooks/useAiModels.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"useAiModels.d.ts","sourceRoot":"","sources":["../../src/hooks/useAiModels.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,kBAAkB,CAAC;CAC1E;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CA+F3E"}
|
|
@@ -1,32 +1,79 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { useMemo, useCallback } from "react";
|
|
3
|
+
import { useAiContext } from "../context/AiProvider";
|
|
4
|
+
/**
|
|
5
|
+
* Hook pour récupérer les modèles disponibles
|
|
6
|
+
* Utilise les données du contexte pour éviter les appels API multiples
|
|
7
|
+
*/
|
|
4
8
|
export function useAiModels(options) {
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
const context = useAiContext();
|
|
10
|
+
// Si les options ne correspondent pas au contexte, on peut faire un appel direct
|
|
11
|
+
// Mais dans la plupart des cas, on utilise le contexte
|
|
12
|
+
const useContextData = (!options?.baseUrl || options.baseUrl === context.baseUrl) &&
|
|
13
|
+
(!options?.apiKeyId || options.apiKeyId === context.apiKeyId);
|
|
14
|
+
// Filtrer les modèles selon le type demandé
|
|
15
|
+
const filteredModels = useMemo(() => {
|
|
16
|
+
console.log("[useAiModels] Filtering models:", {
|
|
17
|
+
useContextData,
|
|
18
|
+
allModelsLength: context.allModels.length,
|
|
19
|
+
modelType: options?.modelType,
|
|
20
|
+
loading: context.loadingProviders,
|
|
21
|
+
});
|
|
22
|
+
if (!useContextData) {
|
|
23
|
+
console.log("[useAiModels] Not using context data");
|
|
24
|
+
return [];
|
|
15
25
|
}
|
|
16
|
-
|
|
17
|
-
|
|
26
|
+
// Pendant le chargement, retourner un tableau vide
|
|
27
|
+
if (context.loadingProviders) {
|
|
28
|
+
console.log("[useAiModels] Still loading...");
|
|
29
|
+
return [];
|
|
18
30
|
}
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
// Si pas de modèles après le chargement
|
|
32
|
+
if (!context.allModels.length) {
|
|
33
|
+
console.log("[useAiModels] No models in context");
|
|
34
|
+
return [];
|
|
21
35
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
36
|
+
if (!options?.modelType) {
|
|
37
|
+
console.log("[useAiModels] Returning all models:", context.allModels.length);
|
|
38
|
+
return context.allModels;
|
|
39
|
+
}
|
|
40
|
+
// Cas spécial: text ou language
|
|
41
|
+
if (options.modelType === "text-or-language") {
|
|
42
|
+
const textModels = context.getTextModels();
|
|
43
|
+
console.log("[useAiModels] Returning text models:", textModels.length);
|
|
44
|
+
return textModels;
|
|
45
|
+
}
|
|
46
|
+
// Cas spécial: image
|
|
47
|
+
if (options.modelType === "image") {
|
|
48
|
+
const imageModels = context.getImageModels();
|
|
49
|
+
console.log("[useAiModels] Returning image models:", imageModels.length, imageModels);
|
|
50
|
+
return imageModels;
|
|
51
|
+
}
|
|
52
|
+
const filtered = context.getModelsByType(options.modelType);
|
|
53
|
+
console.log(`[useAiModels] Returning ${options.modelType} models:`, filtered.length);
|
|
54
|
+
return filtered;
|
|
55
|
+
return filtered;
|
|
56
|
+
}, [useContextData, context, options?.modelType]);
|
|
57
|
+
const refetch = useCallback(() => {
|
|
58
|
+
if (useContextData) {
|
|
59
|
+
context.refetchProviders();
|
|
60
|
+
}
|
|
61
|
+
}, [useContextData, context]);
|
|
62
|
+
if (useContextData) {
|
|
63
|
+
return {
|
|
64
|
+
models: filteredModels,
|
|
65
|
+
loading: context.loadingProviders,
|
|
66
|
+
error: null,
|
|
67
|
+
refetch,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// Fallback: si les options ne correspondent pas, retourner des valeurs vides
|
|
71
|
+
// (cas rare, la plupart du temps on utilise le contexte)
|
|
72
|
+
console.log("[useAiModels] Using fallback (no context match)");
|
|
26
73
|
return {
|
|
27
|
-
models,
|
|
28
|
-
loading,
|
|
29
|
-
error,
|
|
30
|
-
refetch:
|
|
74
|
+
models: [],
|
|
75
|
+
loading: false,
|
|
76
|
+
error: new Error("useAiModels called with different baseUrl/apiKeyId than context"),
|
|
77
|
+
refetch: () => { },
|
|
31
78
|
};
|
|
32
79
|
}
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
+
import { type AIModel } from "../context/AiProvider";
|
|
1
2
|
import { type ModelToggleOptions } from "../utils/modelManagement";
|
|
2
|
-
export interface AIModel {
|
|
3
|
-
id: string;
|
|
4
|
-
name: string;
|
|
5
|
-
description?: string;
|
|
6
|
-
provider: string;
|
|
7
|
-
category: "text" | "image" | "audio" | "video";
|
|
8
|
-
isActive?: boolean;
|
|
9
|
-
isPro?: boolean;
|
|
10
|
-
costPer1M?: number;
|
|
11
|
-
}
|
|
12
3
|
export interface UseModelManagementOptions extends ModelToggleOptions {
|
|
13
4
|
autoFetch?: boolean;
|
|
14
5
|
category?: "text" | "image" | "audio" | "video";
|
|
@@ -27,6 +18,7 @@ export interface UseModelManagementReturn {
|
|
|
27
18
|
}
|
|
28
19
|
/**
|
|
29
20
|
* Hook pour gérer les modèles IA d'un utilisateur
|
|
21
|
+
* Utilise les données du contexte pour éviter les appels API multiples
|
|
30
22
|
*/
|
|
31
23
|
export declare function useModelManagement(options?: UseModelManagementOptions): UseModelManagementReturn;
|
|
32
24
|
//# sourceMappingURL=useModelManagement.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useModelManagement.d.ts","sourceRoot":"","sources":["../../src/hooks/useModelManagement.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useModelManagement.d.ts","sourceRoot":"","sources":["../../src/hooks/useModelManagement.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAElC,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;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,yBAA8B,GACtC,wBAAwB,CAiG1B"}
|