@lastbrain/ai-ui-react 1.0.37 → 1.0.39
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/AiPromptPanel.js +1 -6
- package/dist/components/ErrorToast.js +14 -14
- package/dist/components/LBConnectButton.d.ts +20 -0
- package/dist/components/LBConnectButton.d.ts.map +1 -0
- package/dist/components/LBConnectButton.js +87 -0
- package/dist/components/LBKeyPicker.d.ts +10 -0
- package/dist/components/LBKeyPicker.d.ts.map +1 -0
- package/dist/components/LBKeyPicker.js +61 -0
- package/dist/context/LBAuthProvider.d.ts +38 -0
- package/dist/context/LBAuthProvider.d.ts.map +1 -0
- package/dist/context/LBAuthProvider.js +194 -0
- package/dist/hooks/useAiModels.d.ts.map +1 -1
- package/dist/hooks/useAiModels.js +1 -2
- package/dist/hooks/useLB.d.ts +5 -0
- package/dist/hooks/useLB.d.ts.map +1 -0
- package/dist/hooks/useLB.js +5 -0
- package/dist/hooks/usePrompts.d.ts.map +1 -1
- package/dist/hooks/usePrompts.js +12 -3
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/package.json +2 -2
- package/src/components/AiPromptPanel.tsx +5 -6
- package/src/components/ErrorToast.tsx +16 -16
- package/src/components/LBConnectButton.tsx +230 -0
- package/src/components/LBKeyPicker.tsx +145 -0
- package/src/context/LBAuthProvider.tsx +269 -0
- package/src/hooks/useAiModels.ts +1 -2
- package/src/hooks/useLB.ts +7 -0
- package/src/hooks/usePrompts.ts +13 -3
- package/src/index.ts +4 -0
|
@@ -279,7 +279,6 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode: _uiMode = "m
|
|
|
279
279
|
position: "sticky",
|
|
280
280
|
top: 0,
|
|
281
281
|
zIndex: 5,
|
|
282
|
-
background: "var(--ai-bg-primary, #1f2937)",
|
|
283
282
|
borderBottom: "1px solid var(--ai-border-primary, #374151)",
|
|
284
283
|
backdropFilter: "blur(8px)",
|
|
285
284
|
}, children: [_jsx("h2", { style: aiStyles.modalTitle, children: showPromptLibrary ? "Select a Prompt" : "AI Prompt Configuration" }), _jsx("button", { style: {
|
|
@@ -530,7 +529,6 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode: _uiMode = "m
|
|
|
530
529
|
position: "sticky",
|
|
531
530
|
bottom: 0,
|
|
532
531
|
zIndex: 5,
|
|
533
|
-
background: "var(--ai-bg-primary, #1f2937)",
|
|
534
532
|
borderTop: "1px solid var(--ai-border-primary, #374151)",
|
|
535
533
|
backdropFilter: "blur(8px)",
|
|
536
534
|
}, children: [_jsx("button", { onClick: handleClose, onMouseEnter: () => setIsCancelHovered(true), onMouseLeave: () => setIsCancelHovered(false), style: {
|
|
@@ -561,7 +559,6 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode: _uiMode = "m
|
|
|
561
559
|
overflow: "hidden",
|
|
562
560
|
display: "flex",
|
|
563
561
|
flexDirection: "column",
|
|
564
|
-
background: "var(--ai-bg-primary, #1f2937)",
|
|
565
562
|
boxShadow: "0 20px 40px rgba(0, 0, 0, 0.5)",
|
|
566
563
|
}, children: [_jsxs("div", { style: aiStyles.modalHeader, children: [_jsx("h2", { style: aiStyles.modalTitle, children: "Gestion des mod\u00E8les IA" }), _jsx("button", { style: aiStyles.modalCloseButton, onClick: () => {
|
|
567
564
|
setIsModelManagementOpen(false);
|
|
@@ -662,9 +659,7 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode: _uiMode = "m
|
|
|
662
659
|
}, children: [_jsx("span", { style: {
|
|
663
660
|
fontWeight: "600",
|
|
664
661
|
fontSize: "15px",
|
|
665
|
-
color:
|
|
666
|
-
? "#10b981"
|
|
667
|
-
: "var(--ai-text-primary, #f3f4f6)",
|
|
662
|
+
color: "var(--ai-text-secondary, #6b7280)",
|
|
668
663
|
letterSpacing: "-0.01em",
|
|
669
664
|
}, children: modelData.name }), modelData.isPro && (_jsx("span", { style: {
|
|
670
665
|
padding: "3px 10px",
|
|
@@ -7,6 +7,19 @@ export function ErrorToast({ error, position = "bottom-right", onComplete, }) {
|
|
|
7
7
|
const [isClosing, setIsClosing] = useState(false);
|
|
8
8
|
const fadeTimeoutRef = useRef(null);
|
|
9
9
|
const autoCloseTimeoutRef = useRef(null);
|
|
10
|
+
const handleClose = () => {
|
|
11
|
+
if (isClosing)
|
|
12
|
+
return;
|
|
13
|
+
// Clear auto-close timeout if user closes manually
|
|
14
|
+
if (autoCloseTimeoutRef.current) {
|
|
15
|
+
window.clearTimeout(autoCloseTimeoutRef.current);
|
|
16
|
+
}
|
|
17
|
+
setIsClosing(true);
|
|
18
|
+
fadeTimeoutRef.current = window.setTimeout(() => {
|
|
19
|
+
setIsVisible(false);
|
|
20
|
+
onComplete?.();
|
|
21
|
+
}, 200);
|
|
22
|
+
};
|
|
10
23
|
useEffect(() => {
|
|
11
24
|
if (error) {
|
|
12
25
|
// Show toast immediately
|
|
@@ -27,20 +40,7 @@ export function ErrorToast({ error, position = "bottom-right", onComplete, }) {
|
|
|
27
40
|
window.clearTimeout(autoCloseTimeoutRef.current);
|
|
28
41
|
}
|
|
29
42
|
};
|
|
30
|
-
}, [error]);
|
|
31
|
-
const handleClose = () => {
|
|
32
|
-
if (isClosing)
|
|
33
|
-
return;
|
|
34
|
-
// Clear auto-close timeout if user closes manually
|
|
35
|
-
if (autoCloseTimeoutRef.current) {
|
|
36
|
-
window.clearTimeout(autoCloseTimeoutRef.current);
|
|
37
|
-
}
|
|
38
|
-
setIsClosing(true);
|
|
39
|
-
fadeTimeoutRef.current = window.setTimeout(() => {
|
|
40
|
-
setIsVisible(false);
|
|
41
|
-
onComplete?.();
|
|
42
|
-
}, 200);
|
|
43
|
-
};
|
|
43
|
+
}, [error, handleClose]);
|
|
44
44
|
if (!error)
|
|
45
45
|
return null;
|
|
46
46
|
const getPositionStyles = () => {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
interface LBConnectButtonProps {
|
|
2
|
+
/** Texte du bouton */
|
|
3
|
+
label?: string;
|
|
4
|
+
/** Classe CSS personnalisée */
|
|
5
|
+
className?: string;
|
|
6
|
+
/** Callback après connexion réussie */
|
|
7
|
+
onConnected?: () => void;
|
|
8
|
+
/** Callback à l'ouverture de la modal */
|
|
9
|
+
onOpenModal?: () => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function LBConnectButton({ label, className, onConnected, onOpenModal, }: LBConnectButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
/**
|
|
13
|
+
* Modal d'authentification LastBrain
|
|
14
|
+
*/
|
|
15
|
+
interface LBAuthModalProps {
|
|
16
|
+
onClose: (success: boolean) => void;
|
|
17
|
+
}
|
|
18
|
+
declare function LBAuthModal({ onClose }: LBAuthModalProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export { LBAuthModal };
|
|
20
|
+
//# sourceMappingURL=LBConnectButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LBConnectButton.d.ts","sourceRoot":"","sources":["../../src/components/LBConnectButton.tsx"],"names":[],"mappings":"AAUA,UAAU,oBAAoB;IAC5B,sBAAsB;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAAC,EAC9B,KAAkC,EAClC,SAAc,EACd,WAAW,EACX,WAAW,GACZ,EAAE,oBAAoB,2CA0CtB;AAED;;GAEG;AACH,UAAU,gBAAgB;IACxB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACrC;AAED,iBAAS,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE,gBAAgB,2CAsJjD;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Bouton de connexion LastBrain
|
|
5
|
+
* Ouvre la modal d'authentification
|
|
6
|
+
*/
|
|
7
|
+
import React from "react";
|
|
8
|
+
import { useLB } from "../context/LBAuthProvider";
|
|
9
|
+
export function LBConnectButton({ label = "Se connecter à LastBrain", className = "", onConnected, onOpenModal, }) {
|
|
10
|
+
const { status, user, logout } = useLB();
|
|
11
|
+
const [showModal, setShowModal] = React.useState(false);
|
|
12
|
+
const handleClick = () => {
|
|
13
|
+
if (status === "ready" && user) {
|
|
14
|
+
// Déjà connecté, proposer de se déconnecter
|
|
15
|
+
logout();
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
// Pas connecté, ouvrir la modal
|
|
19
|
+
setShowModal(true);
|
|
20
|
+
onOpenModal?.();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const handleModalClose = (success) => {
|
|
24
|
+
setShowModal(false);
|
|
25
|
+
if (success) {
|
|
26
|
+
onConnected?.();
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
return (_jsxs(_Fragment, { children: [_jsx("button", { onClick: handleClick, className: className ||
|
|
30
|
+
"px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700", disabled: status === "loading", children: status === "loading"
|
|
31
|
+
? "Chargement..."
|
|
32
|
+
: status === "ready" && user
|
|
33
|
+
? `Connecté (${user.email})`
|
|
34
|
+
: label }), showModal && _jsx(LBAuthModal, { onClose: handleModalClose })] }));
|
|
35
|
+
}
|
|
36
|
+
function LBAuthModal({ onClose }) {
|
|
37
|
+
const { login, fetchApiKeys, selectApiKey, status } = useLB();
|
|
38
|
+
const [step, setStep] = React.useState("login");
|
|
39
|
+
const [email, setEmail] = React.useState("");
|
|
40
|
+
const [password, setPassword] = React.useState("");
|
|
41
|
+
const [error, setError] = React.useState("");
|
|
42
|
+
const [loading, setLoading] = React.useState(false);
|
|
43
|
+
const [accessToken, setAccessToken] = React.useState("");
|
|
44
|
+
const [apiKeys, setApiKeys] = React.useState([]);
|
|
45
|
+
const handleLogin = async (e) => {
|
|
46
|
+
e.preventDefault();
|
|
47
|
+
setError("");
|
|
48
|
+
setLoading(true);
|
|
49
|
+
try {
|
|
50
|
+
const result = await login(email, password);
|
|
51
|
+
setAccessToken(result.accessToken);
|
|
52
|
+
// Récupérer les clés API
|
|
53
|
+
const keys = await fetchApiKeys(result.accessToken);
|
|
54
|
+
setApiKeys(keys);
|
|
55
|
+
if (keys.length === 0) {
|
|
56
|
+
setError("Aucune clé API active trouvée. Créez-en une dans votre dashboard LastBrain.");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Passer à l'étape de sélection
|
|
60
|
+
setStep("select-key");
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
setError(err instanceof Error ? err.message : "Échec de la connexion");
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
setLoading(false);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const handleSelectKey = async (apiKeyId) => {
|
|
70
|
+
setError("");
|
|
71
|
+
setLoading(true);
|
|
72
|
+
try {
|
|
73
|
+
await selectApiKey(accessToken, apiKeyId);
|
|
74
|
+
onClose(true); // Succès
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
setError(err instanceof Error ? err.message : "Échec de la sélection");
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
setLoading(false);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
return (_jsx("div", { className: "fixed inset-0 bg-black/50 flex items-center justify-center z-50", children: _jsxs("div", { className: "bg-white dark:bg-gray-800 rounded-lg p-6 max-w-md w-full mx-4", children: [_jsxs("div", { className: "flex justify-between items-center mb-4", children: [_jsx("h2", { className: "text-xl font-bold", children: step === "login"
|
|
84
|
+
? "Connexion LastBrain"
|
|
85
|
+
: "Sélectionner une clé API" }), _jsx("button", { onClick: () => onClose(false), className: "text-gray-500 hover:text-gray-700", children: "\u2715" })] }), step === "login" ? (_jsxs("form", { onSubmit: handleLogin, className: "space-y-4", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium mb-1", children: "Email" }), _jsx("input", { type: "email", value: email, onChange: (e) => setEmail(e.target.value), className: "w-full px-3 py-2 border rounded dark:bg-gray-700", required: true, autoFocus: true })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-sm font-medium mb-1", children: "Mot de passe" }), _jsx("input", { type: "password", value: password, onChange: (e) => setPassword(e.target.value), className: "w-full px-3 py-2 border rounded dark:bg-gray-700", required: true })] }), error && _jsx("div", { className: "text-red-600 text-sm", children: error }), _jsx("button", { type: "submit", disabled: loading, className: "w-full px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50", children: loading ? "Connexion..." : "Se connecter" }), _jsxs("p", { className: "text-sm text-gray-600 dark:text-gray-400 text-center", children: ["Pas encore de compte ?", " ", _jsx("a", { href: "https://lastbrain.io/signup", target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:underline", children: "Cr\u00E9er un compte" })] })] })) : (_jsxs("div", { className: "space-y-4", children: [_jsx("p", { className: "text-sm text-gray-600 dark:text-gray-400", children: "S\u00E9lectionnez une cl\u00E9 API pour cr\u00E9er une session de 72h" }), _jsx("div", { className: "space-y-2", children: apiKeys.map((key) => (_jsxs("button", { onClick: () => handleSelectKey(key.id), disabled: !key.isActive || loading, className: "w-full text-left px-4 py-3 border rounded hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed", children: [_jsx("div", { className: "font-medium", children: key.name }), _jsxs("div", { className: "text-sm text-gray-500", children: [key.keyPrefix, "..."] }), !key.isActive && (_jsx("div", { className: "text-xs text-red-600", children: "Inactive" }))] }, key.id))) }), error && _jsx("div", { className: "text-red-600 text-sm", children: error })] }))] }) }));
|
|
86
|
+
}
|
|
87
|
+
export { LBAuthModal };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LBApiKey } from "@lastbrain/ai-ui-core";
|
|
2
|
+
interface LBKeyPickerProps {
|
|
3
|
+
/** Classe CSS personnalisée */
|
|
4
|
+
className?: string;
|
|
5
|
+
/** Callback après changement de clé */
|
|
6
|
+
onKeyChanged?: (key: LBApiKey) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function LBKeyPicker({ className, onKeyChanged, }: LBKeyPickerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=LBKeyPicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LBKeyPicker.d.ts","sourceRoot":"","sources":["../../src/components/LBKeyPicker.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,UAAU,gBAAgB;IACxB,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;CACxC;AAED,wBAAgB,WAAW,CAAC,EAC1B,SAAc,EACd,YAAY,GACb,EAAE,gBAAgB,kDA2HlB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Composant LBKeyPicker
|
|
5
|
+
* Permet de changer de clé API sans se reconnecter
|
|
6
|
+
*/
|
|
7
|
+
import { useEffect, useState } from "react";
|
|
8
|
+
import { useLB } from "../hooks/useLB";
|
|
9
|
+
export function LBKeyPicker({ className = "", onKeyChanged, }) {
|
|
10
|
+
const { status, selectedKey, fetchApiKeys, selectApiKey, accessToken } = useLB();
|
|
11
|
+
const [apiKeys, setApiKeys] = useState([]);
|
|
12
|
+
const [loading, setLoading] = useState(false);
|
|
13
|
+
const [error, setError] = useState("");
|
|
14
|
+
const [showDropdown, setShowDropdown] = useState(false);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (status === "ready" && accessToken) {
|
|
17
|
+
loadKeys();
|
|
18
|
+
}
|
|
19
|
+
}, [status, accessToken]);
|
|
20
|
+
const loadKeys = async () => {
|
|
21
|
+
if (!accessToken)
|
|
22
|
+
return;
|
|
23
|
+
try {
|
|
24
|
+
setLoading(true);
|
|
25
|
+
const keys = await fetchApiKeys(accessToken);
|
|
26
|
+
setApiKeys(keys);
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
setError("Impossible de charger les clés API");
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
setLoading(false);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const handleSelectKey = async (keyId) => {
|
|
36
|
+
if (!accessToken)
|
|
37
|
+
return;
|
|
38
|
+
try {
|
|
39
|
+
setLoading(true);
|
|
40
|
+
setError("");
|
|
41
|
+
await selectApiKey(accessToken, keyId);
|
|
42
|
+
const selectedApiKey = apiKeys.find((k) => k.id === keyId);
|
|
43
|
+
if (selectedApiKey) {
|
|
44
|
+
onKeyChanged?.(selectedApiKey);
|
|
45
|
+
}
|
|
46
|
+
setShowDropdown(false);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
setError(err instanceof Error ? err.message : "Échec du changement de clé");
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
setLoading(false);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
if (status !== "ready" || !selectedKey) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return (_jsxs("div", { className: `relative ${className}`, children: [_jsxs("button", { onClick: () => setShowDropdown(!showDropdown), disabled: loading, className: "px-4 py-2 border rounded hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-50 flex items-center gap-2", children: [_jsxs("span", { className: "font-mono text-sm", children: [selectedKey.keyPrefix, "..."] }), _jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })] }), showDropdown && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-10", onClick: () => setShowDropdown(false) }), _jsxs("div", { className: "absolute right-0 mt-2 w-64 bg-white dark:bg-gray-800 border rounded-lg shadow-lg z-20", children: [_jsxs("div", { className: "p-2", children: [_jsx("div", { className: "text-sm font-medium text-gray-700 dark:text-gray-300 px-3 py-2", children: "Changer de cl\u00E9 API" }), _jsx("div", { className: "space-y-1", children: apiKeys.map((key) => (_jsxs("button", { onClick: () => handleSelectKey(key.id), disabled: !key.isActive || loading || key.id === selectedKey.id, className: `w-full text-left px-3 py-2 rounded text-sm ${key.id === selectedKey.id
|
|
59
|
+
? "bg-blue-100 dark:bg-blue-900"
|
|
60
|
+
: "hover:bg-gray-100 dark:hover:bg-gray-700"} disabled:opacity-50 disabled:cursor-not-allowed`, children: [_jsx("div", { className: "font-medium", children: key.name }), _jsxs("div", { className: "text-xs text-gray-500 font-mono", children: [key.keyPrefix, "..."] }), !key.isActive && (_jsx("div", { className: "text-xs text-red-600", children: "Inactive" }))] }, key.id))) })] }), error && (_jsx("div", { className: "px-3 py-2 text-xs text-red-600 border-t", children: error }))] })] }))] }));
|
|
61
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider d'authentification LastBrain
|
|
3
|
+
* Gère l'état de connexion, la session et les appels IA
|
|
4
|
+
*/
|
|
5
|
+
import { type ReactNode } from "react";
|
|
6
|
+
import type { LBAuthState, LBApiKey, LBLoginResult } from "@lastbrain/ai-ui-core";
|
|
7
|
+
interface LBProviderProps {
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
/** URL de l'API LastBrain (ex: https://api.lastbrain.io) */
|
|
10
|
+
baseUrl?: string;
|
|
11
|
+
/** URL du proxy local (ex: /api/lb) */
|
|
12
|
+
proxyUrl?: string;
|
|
13
|
+
/** Fonction appelée lors des changements d'état */
|
|
14
|
+
onStatusChange?: (status: LBAuthState["status"]) => void;
|
|
15
|
+
}
|
|
16
|
+
interface LBContextValue extends LBAuthState {
|
|
17
|
+
/** Fonction de connexion */
|
|
18
|
+
login: (email: string, password: string) => Promise<LBLoginResult>;
|
|
19
|
+
/** Fonction de déconnexion */
|
|
20
|
+
logout: () => Promise<void>;
|
|
21
|
+
/** Récupère les clés API de l'utilisateur */
|
|
22
|
+
fetchApiKeys: (accessToken: string) => Promise<LBApiKey[]>;
|
|
23
|
+
/** Sélectionne une clé API et crée une session */
|
|
24
|
+
selectApiKey: (accessToken: string, apiKeyId: string) => Promise<void>;
|
|
25
|
+
/** Recharge l'état de la session */
|
|
26
|
+
refreshSession: () => Promise<void>;
|
|
27
|
+
/** Clés API disponibles */
|
|
28
|
+
apiKeys: LBApiKey[];
|
|
29
|
+
/** Access token temporaire (après login) */
|
|
30
|
+
accessToken?: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function LBProvider({ children, baseUrl: _baseUrl, proxyUrl, onStatusChange, }: LBProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
/**
|
|
34
|
+
* Hook pour accéder au contexte LastBrain
|
|
35
|
+
*/
|
|
36
|
+
export declare function useLB(): LBContextValue;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=LBAuthProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LBAuthProvider.d.ts","sourceRoot":"","sources":["../../src/context/LBAuthProvider.tsx"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EAER,aAAa,EAEd,MAAM,uBAAuB,CAAC;AAE/B,UAAU,eAAe;IACvB,QAAQ,EAAE,SAAS,CAAC;IACpB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;CAC1D;AAED,UAAU,cAAe,SAAQ,WAAW;IAC1C,4BAA4B;IAC5B,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;IACnE,8BAA8B;IAC9B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,6CAA6C;IAC7C,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC3D,kDAAkD;IAClD,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,oCAAoC;IACpC,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,2BAA2B;IAC3B,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,OAAO,EAAE,QAAoB,EAC7B,QAAoB,EACpB,cAAc,GACf,EAAE,eAAe,2CAwMjB;AAED;;GAEG;AACH,wBAAgB,KAAK,IAAI,cAAc,CAMtC"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Provider d'authentification LastBrain
|
|
5
|
+
* Gère l'état de connexion, la session et les appels IA
|
|
6
|
+
*/
|
|
7
|
+
import { createContext, useContext, useEffect, useCallback, useState, } from "react";
|
|
8
|
+
const LBContext = createContext(undefined);
|
|
9
|
+
export function LBProvider({ children, baseUrl: _baseUrl = "/api/lb", proxyUrl = "/api/lb", onStatusChange, }) {
|
|
10
|
+
const [state, setState] = useState({
|
|
11
|
+
status: "loading",
|
|
12
|
+
});
|
|
13
|
+
const [apiKeys, setApiKeys] = useState([]);
|
|
14
|
+
const [accessToken, setAccessToken] = useState();
|
|
15
|
+
/**
|
|
16
|
+
* Vérifie si une session existe au chargement
|
|
17
|
+
*/
|
|
18
|
+
const checkSession = useCallback(async () => {
|
|
19
|
+
try {
|
|
20
|
+
const response = await fetch(`${proxyUrl}/auth/session/verify`, {
|
|
21
|
+
credentials: "include",
|
|
22
|
+
});
|
|
23
|
+
if (response.ok) {
|
|
24
|
+
const session = await response.json();
|
|
25
|
+
setState({
|
|
26
|
+
status: "ready",
|
|
27
|
+
session,
|
|
28
|
+
user: {
|
|
29
|
+
id: session.userId,
|
|
30
|
+
email: "", // Sera rempli par une autre requête si nécessaire
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
onStatusChange?.("ready");
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
setState({ status: "needs_auth" });
|
|
37
|
+
onStatusChange?.("needs_auth");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.error("[LBProvider] Session check failed:", error);
|
|
42
|
+
setState({ status: "needs_auth" });
|
|
43
|
+
onStatusChange?.("needs_auth");
|
|
44
|
+
}
|
|
45
|
+
}, [proxyUrl, onStatusChange]);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
checkSession();
|
|
48
|
+
}, [checkSession]);
|
|
49
|
+
/**
|
|
50
|
+
* Connexion utilisateur
|
|
51
|
+
*/
|
|
52
|
+
const login = useCallback(async (email, password) => {
|
|
53
|
+
try {
|
|
54
|
+
setState((prev) => ({ ...prev, status: "loading" }));
|
|
55
|
+
const response = await fetch(`${proxyUrl}/auth/login`, {
|
|
56
|
+
method: "POST",
|
|
57
|
+
headers: { "Content-Type": "application/json" },
|
|
58
|
+
body: JSON.stringify({ email, password }),
|
|
59
|
+
credentials: "include",
|
|
60
|
+
});
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
const error = await response.json();
|
|
63
|
+
throw new Error(error.message || "Login failed");
|
|
64
|
+
}
|
|
65
|
+
const result = await response.json();
|
|
66
|
+
setAccessToken(result.accessToken);
|
|
67
|
+
setState({
|
|
68
|
+
status: "ready",
|
|
69
|
+
user: result.user,
|
|
70
|
+
});
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
const message = error instanceof Error ? error.message : "Login failed";
|
|
75
|
+
setState({
|
|
76
|
+
status: "error",
|
|
77
|
+
error: message,
|
|
78
|
+
});
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
}, [proxyUrl]);
|
|
82
|
+
/**
|
|
83
|
+
* Récupère les clés API de l'utilisateur
|
|
84
|
+
*/
|
|
85
|
+
const fetchApiKeys = useCallback(async (token) => {
|
|
86
|
+
try {
|
|
87
|
+
const response = await fetch(`${proxyUrl}/user/api-keys`, {
|
|
88
|
+
headers: {
|
|
89
|
+
Authorization: `Bearer ${token}`,
|
|
90
|
+
},
|
|
91
|
+
credentials: "include",
|
|
92
|
+
});
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
throw new Error("Failed to fetch API keys");
|
|
95
|
+
}
|
|
96
|
+
const keys = await response.json();
|
|
97
|
+
setApiKeys(keys);
|
|
98
|
+
return keys;
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error("[LBProvider] Failed to fetch API keys:", error);
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}, [proxyUrl]);
|
|
105
|
+
/**
|
|
106
|
+
* Sélectionne une clé API et crée une session
|
|
107
|
+
*/
|
|
108
|
+
const selectApiKey = useCallback(async (token, apiKeyId) => {
|
|
109
|
+
try {
|
|
110
|
+
setState((prev) => ({ ...prev, status: "loading" }));
|
|
111
|
+
const response = await fetch(`${proxyUrl}/auth/session`, {
|
|
112
|
+
method: "POST",
|
|
113
|
+
headers: {
|
|
114
|
+
"Content-Type": "application/json",
|
|
115
|
+
Authorization: `Bearer ${token}`,
|
|
116
|
+
},
|
|
117
|
+
body: JSON.stringify({ api_key_id: apiKeyId }),
|
|
118
|
+
credentials: "include",
|
|
119
|
+
});
|
|
120
|
+
if (!response.ok) {
|
|
121
|
+
throw new Error("Failed to create session");
|
|
122
|
+
}
|
|
123
|
+
const sessionResult = await response.json();
|
|
124
|
+
setState({
|
|
125
|
+
status: "ready",
|
|
126
|
+
user: state.user,
|
|
127
|
+
selectedKey: sessionResult.apiKey,
|
|
128
|
+
session: {
|
|
129
|
+
sessionToken: sessionResult.sessionToken,
|
|
130
|
+
userId: state.user?.id || "",
|
|
131
|
+
apiKeyId,
|
|
132
|
+
expiresAt: Date.now() + sessionResult.expiresIn * 1000,
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
setAccessToken(undefined); // Nettoyer l'access token temporaire
|
|
136
|
+
onStatusChange?.("ready");
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
const message = error instanceof Error ? error.message : "Failed to select API key";
|
|
140
|
+
setState({
|
|
141
|
+
status: "error",
|
|
142
|
+
error: message,
|
|
143
|
+
});
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
}, [proxyUrl, state.user, onStatusChange]);
|
|
147
|
+
/**
|
|
148
|
+
* Déconnexion
|
|
149
|
+
*/
|
|
150
|
+
const logout = useCallback(async () => {
|
|
151
|
+
try {
|
|
152
|
+
await fetch(`${proxyUrl}/auth/session/logout`, {
|
|
153
|
+
method: "POST",
|
|
154
|
+
credentials: "include",
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
console.error("[LBProvider] Logout failed:", error);
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
setState({ status: "needs_auth" });
|
|
162
|
+
setApiKeys([]);
|
|
163
|
+
setAccessToken(undefined);
|
|
164
|
+
onStatusChange?.("needs_auth");
|
|
165
|
+
}
|
|
166
|
+
}, [proxyUrl, onStatusChange]);
|
|
167
|
+
/**
|
|
168
|
+
* Recharge la session
|
|
169
|
+
*/
|
|
170
|
+
const refreshSession = useCallback(async () => {
|
|
171
|
+
await checkSession();
|
|
172
|
+
}, [checkSession]);
|
|
173
|
+
const value = {
|
|
174
|
+
...state,
|
|
175
|
+
login,
|
|
176
|
+
logout,
|
|
177
|
+
fetchApiKeys,
|
|
178
|
+
selectApiKey,
|
|
179
|
+
refreshSession,
|
|
180
|
+
apiKeys,
|
|
181
|
+
accessToken,
|
|
182
|
+
};
|
|
183
|
+
return _jsx(LBContext.Provider, { value: value, children: children });
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Hook pour accéder au contexte LastBrain
|
|
187
|
+
*/
|
|
188
|
+
export function useLB() {
|
|
189
|
+
const context = useContext(LBContext);
|
|
190
|
+
if (!context) {
|
|
191
|
+
throw new Error("useLB must be used within LBProvider");
|
|
192
|
+
}
|
|
193
|
+
return context;
|
|
194
|
+
}
|
|
@@ -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;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,
|
|
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,CA8F3E"}
|
|
@@ -52,8 +52,7 @@ export function useAiModels(options) {
|
|
|
52
52
|
const filtered = context.getModelsByType(options.modelType);
|
|
53
53
|
console.log(`[useAiModels] Returning ${options.modelType} models:`, filtered.length);
|
|
54
54
|
return filtered;
|
|
55
|
-
|
|
56
|
-
}, [useContextData, context, options?.modelType]);
|
|
55
|
+
}, [useContextData, context, options]);
|
|
57
56
|
const refetch = useCallback(() => {
|
|
58
57
|
if (useContextData) {
|
|
59
58
|
context.refetchProviders();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLB.d.ts","sourceRoot":"","sources":["../../src/hooks/useLB.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePrompts.d.ts","sourceRoot":"","sources":["../../src/hooks/usePrompts.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAa,SAAQ,MAAM;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,YAAY,EAAE,CACZ,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,YAAY,GAAG,YAAY,CAAC,KACnD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5B,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5E,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,aAAa,EAAE,CACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,KAClC,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB;AAED,wBAAgB,UAAU,IAAI,gBAAgB,
|
|
1
|
+
{"version":3,"file":"usePrompts.d.ts","sourceRoot":"","sources":["../../src/hooks/usePrompts.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAa,SAAQ,MAAM;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,YAAY,EAAE,CACZ,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,YAAY,GAAG,YAAY,CAAC,KACnD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5B,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5E,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,aAAa,EAAE,CACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,KAClC,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB;AAED,wBAAgB,UAAU,IAAI,gBAAgB,CAgS7C"}
|
package/dist/hooks/usePrompts.js
CHANGED
|
@@ -23,7 +23,10 @@ export function usePrompts() {
|
|
|
23
23
|
// Check cache first (60 seconds TTL)
|
|
24
24
|
const cached = getCached(cacheKey, 60000);
|
|
25
25
|
if (cached) {
|
|
26
|
-
console.log("[usePrompts] Using cached data",
|
|
26
|
+
console.log("[usePrompts] Using cached data:", {
|
|
27
|
+
count: cached.length,
|
|
28
|
+
prompts: cached,
|
|
29
|
+
});
|
|
27
30
|
setPrompts(cached);
|
|
28
31
|
setLoading(false);
|
|
29
32
|
return;
|
|
@@ -76,6 +79,12 @@ export function usePrompts() {
|
|
|
76
79
|
credentials: isExternalProxy ? "include" : "same-origin",
|
|
77
80
|
});
|
|
78
81
|
const data = await response.json();
|
|
82
|
+
console.log("[usePrompts] Server response:", {
|
|
83
|
+
ok: response.ok,
|
|
84
|
+
status: response.status,
|
|
85
|
+
promptsCount: data.prompts?.length || 0,
|
|
86
|
+
data,
|
|
87
|
+
});
|
|
79
88
|
if (response.ok) {
|
|
80
89
|
const promptsData = data.prompts || [];
|
|
81
90
|
setPrompts(promptsData);
|
|
@@ -92,7 +101,7 @@ export function usePrompts() {
|
|
|
92
101
|
finally {
|
|
93
102
|
setLoading(false);
|
|
94
103
|
}
|
|
95
|
-
}, [baseUrl]);
|
|
104
|
+
}, [baseUrl, apiKeyId]);
|
|
96
105
|
const createPrompt = useCallback(async (data) => {
|
|
97
106
|
try {
|
|
98
107
|
setError(null);
|
|
@@ -223,7 +232,7 @@ export function usePrompts() {
|
|
|
223
232
|
credentials: isExternalProxy ? "include" : "same-origin",
|
|
224
233
|
});
|
|
225
234
|
}
|
|
226
|
-
catch
|
|
235
|
+
catch {
|
|
227
236
|
// Silent fail for stats
|
|
228
237
|
}
|
|
229
238
|
}, [baseUrl, apiKeyId]);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from "./types";
|
|
2
2
|
export * from "./context/AiProvider";
|
|
3
|
+
export * from "./context/LBAuthProvider";
|
|
3
4
|
export * from "./hooks/useAiClient";
|
|
4
5
|
export * from "./hooks/useAiModels";
|
|
5
6
|
export * from "./hooks/useAiStatus";
|
|
@@ -7,6 +8,7 @@ export * from "./hooks/useAiCallText";
|
|
|
7
8
|
export * from "./hooks/useAiCallImage";
|
|
8
9
|
export * from "./hooks/usePrompts";
|
|
9
10
|
export * from "./hooks/useModelManagement";
|
|
11
|
+
export * from "./hooks/useLB";
|
|
10
12
|
export * from "./components/AiPromptPanel";
|
|
11
13
|
export * from "./components/AiModelSelect";
|
|
12
14
|
export * from "./components/AiInput";
|
|
@@ -17,6 +19,8 @@ export * from "./components/AiImageButton";
|
|
|
17
19
|
export * from "./components/AiContextButton";
|
|
18
20
|
export * from "./components/AiSettingsButton";
|
|
19
21
|
export * from "./components/AiStatusButton";
|
|
22
|
+
export * from "./components/LBConnectButton";
|
|
23
|
+
export * from "./components/LBKeyPicker";
|
|
20
24
|
export * from "./components/ErrorToast";
|
|
21
25
|
export * from "./components/UsageToast";
|
|
22
26
|
export * from "./utils/modelManagement";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AAGxB,cAAc,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AAGxB,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AAGzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,eAAe,CAAC;AAG9B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AAGzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,eAAe,CAAC;AAG9B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
export * from "./types";
|
|
3
3
|
// Context
|
|
4
4
|
export * from "./context/AiProvider";
|
|
5
|
+
export * from "./context/LBAuthProvider";
|
|
5
6
|
// Hooks
|
|
6
7
|
export * from "./hooks/useAiClient";
|
|
7
8
|
export * from "./hooks/useAiModels";
|
|
@@ -10,6 +11,7 @@ export * from "./hooks/useAiCallText";
|
|
|
10
11
|
export * from "./hooks/useAiCallImage";
|
|
11
12
|
export * from "./hooks/usePrompts";
|
|
12
13
|
export * from "./hooks/useModelManagement";
|
|
14
|
+
export * from "./hooks/useLB";
|
|
13
15
|
// Components
|
|
14
16
|
export * from "./components/AiPromptPanel";
|
|
15
17
|
export * from "./components/AiModelSelect";
|
|
@@ -21,6 +23,8 @@ export * from "./components/AiImageButton";
|
|
|
21
23
|
export * from "./components/AiContextButton";
|
|
22
24
|
export * from "./components/AiSettingsButton";
|
|
23
25
|
export * from "./components/AiStatusButton";
|
|
26
|
+
export * from "./components/LBConnectButton";
|
|
27
|
+
export * from "./components/LBKeyPicker";
|
|
24
28
|
// Toast system
|
|
25
29
|
export * from "./components/ErrorToast";
|
|
26
30
|
export * from "./components/UsageToast";
|