@lastbrain/ai-ui-react 1.0.47 → 1.0.48
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/AiStatusButton.d.ts.map +1 -1
- package/dist/components/AiStatusButton.js +57 -7
- package/dist/context/LBAuthProvider.d.ts +3 -1
- package/dist/context/LBAuthProvider.d.ts.map +1 -1
- package/dist/context/LBAuthProvider.js +5 -3
- package/package.json +2 -2
- package/src/components/AiStatusButton.tsx +81 -13
- package/src/context/LBAuthProvider.tsx +7 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiStatusButton.d.ts","sourceRoot":"","sources":["../../src/components/AiStatusButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"AiStatusButton.d.ts","sourceRoot":"","sources":["../../src/components/AiStatusButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAoBtD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,OAAe,EACf,SAAc,GACf,EAAE,mBAAmB,2CAiiCrB"}
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useRef, useLayoutEffect } from "react";
|
|
4
4
|
import { createPortal } from "react-dom";
|
|
5
|
-
import { BarChart3, Settings, FileText, History as HistoryIcon, FolderPlus, Power, LogOut, Key, } from "lucide-react";
|
|
5
|
+
import { BarChart3, Settings, FileText, History as HistoryIcon, FolderPlus, Power, LogOut, Key, RefreshCw, } from "lucide-react";
|
|
6
6
|
import { aiStyles, calculateTooltipPosition } from "../styles/inline";
|
|
7
7
|
import { useLB } from "../context/LBAuthProvider";
|
|
8
|
+
import { useAiContext } from "../context/AiProvider";
|
|
8
9
|
import { LBSigninModal } from "./LBSigninModal";
|
|
9
10
|
import { LBApiKeySelector } from "./LBApiKeySelector";
|
|
10
11
|
export function AiStatusButton({ status, loading = false, className = "", }) {
|
|
@@ -30,6 +31,16 @@ export function AiStatusButton({ status, loading = false, className = "", }) {
|
|
|
30
31
|
user = undefined;
|
|
31
32
|
logout = undefined;
|
|
32
33
|
}
|
|
34
|
+
// Récupérer refetchProviders depuis AiProvider si disponible
|
|
35
|
+
let refetchProviders;
|
|
36
|
+
try {
|
|
37
|
+
const aiContext = useAiContext();
|
|
38
|
+
refetchProviders = aiContext.refetchProviders;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// AiProvider n'est pas disponible, ignorer
|
|
42
|
+
refetchProviders = undefined;
|
|
43
|
+
}
|
|
33
44
|
const [showSigninModal, setShowSigninModal] = useState(false);
|
|
34
45
|
const [showApiKeySelector, setShowApiKeySelector] = useState(false);
|
|
35
46
|
const formatNumber = (value) => typeof value === "number" ? value.toLocaleString() : "0";
|
|
@@ -281,6 +292,10 @@ export function AiStatusButton({ status, loading = false, className = "", }) {
|
|
|
281
292
|
}, title: "New Folder", children: _jsx(FolderPlus, { size: 18 }) }), _jsx("button", { onClick: async () => {
|
|
282
293
|
if (logout) {
|
|
283
294
|
await logout();
|
|
295
|
+
// Refresh provider data after logout
|
|
296
|
+
if (refetchProviders) {
|
|
297
|
+
await refetchProviders();
|
|
298
|
+
}
|
|
284
299
|
}
|
|
285
300
|
setShowTooltip(false);
|
|
286
301
|
}, style: {
|
|
@@ -354,12 +369,39 @@ export function AiStatusButton({ status, loading = false, className = "", }) {
|
|
|
354
369
|
textOverflow: "ellipsis",
|
|
355
370
|
}, children: status.user.email })] }) })), _jsxs("div", { style: {
|
|
356
371
|
...aiStyles.tooltipSection,
|
|
357
|
-
...(status.user?.email
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
372
|
+
...(status.user?.email ? {} : aiStyles.tooltipSectionFirst),
|
|
373
|
+
}, children: [_jsxs("div", { style: aiStyles.tooltipRow, children: [_jsx("span", { style: aiStyles.tooltipLabel, children: "API Key:" }), _jsxs("div", { style: {
|
|
374
|
+
display: "flex",
|
|
375
|
+
alignItems: "center",
|
|
376
|
+
gap: "8px",
|
|
377
|
+
}, children: [_jsx("span", { style: aiStyles.tooltipValue, children: status.apiKey?.name || status.api_key?.name || "Unknown" }), apiKeys.length > 1 && selectApiKeyWithToken && (_jsx("button", { onClick: (e) => {
|
|
378
|
+
e.stopPropagation();
|
|
379
|
+
setShowApiKeySelector(true);
|
|
380
|
+
}, style: {
|
|
381
|
+
background: "rgba(139, 92, 246, 0.1)",
|
|
382
|
+
border: "1px solid rgba(139, 92, 246, 0.3)",
|
|
383
|
+
borderRadius: "50%",
|
|
384
|
+
width: "24px",
|
|
385
|
+
height: "24px",
|
|
386
|
+
display: "flex",
|
|
387
|
+
alignItems: "center",
|
|
388
|
+
justifyContent: "center",
|
|
389
|
+
cursor: "pointer",
|
|
390
|
+
padding: 0,
|
|
391
|
+
transition: "all 0.2s ease",
|
|
392
|
+
}, onMouseEnter: (e) => {
|
|
393
|
+
e.currentTarget.style.background =
|
|
394
|
+
"rgba(139, 92, 246, 0.2)";
|
|
395
|
+
e.currentTarget.style.borderColor =
|
|
396
|
+
"rgba(139, 92, 246, 0.5)";
|
|
397
|
+
}, onMouseLeave: (e) => {
|
|
398
|
+
e.currentTarget.style.background =
|
|
399
|
+
"rgba(139, 92, 246, 0.1)";
|
|
400
|
+
e.currentTarget.style.borderColor =
|
|
401
|
+
"rgba(139, 92, 246, 0.3)";
|
|
402
|
+
}, title: "Change API Key", children: _jsx(RefreshCw, { size: 12, style: { color: "rgba(139, 92, 246, 1)" } }) }))] })] }), _jsxs("div", { style: aiStyles.tooltipRow, children: [_jsx("span", { style: aiStyles.tooltipLabel, children: "Env:" }), _jsx("span", { style: aiStyles.tooltipValue, children: status.apiKey?.env || status.api_key?.env || "N/A" })] }), _jsxs("div", { style: aiStyles.tooltipRow, children: [_jsx("span", { style: aiStyles.tooltipLabel, children: "Rate Limit:" }), _jsxs("span", { style: aiStyles.tooltipValue, children: [status.apiKey?.rate_limit_rpm ||
|
|
403
|
+
status.api_key?.rate_limit_rpm ||
|
|
404
|
+
0, " ", "req/min"] })] })] }), _jsxs("div", { style: aiStyles.tooltipSection, children: [_jsx("div", { style: aiStyles.tooltipSubtitle, children: "Balance" }), _jsxs("div", { style: aiStyles.tooltipRow, children: [_jsx("span", { style: aiStyles.tooltipLabel, children: "Total:" }), _jsxs("span", { style: aiStyles.tooltipValue, children: ["$", formatFixed(balanceUsed, 6), " / $", formatNumber(balanceTotal)] }), renderUsageCircle(balancePercentage)] })] }), _jsxs("div", { style: aiStyles.tooltipSection, children: [_jsx("div", { style: aiStyles.tooltipSubtitle, children: "Storage" }), _jsxs("div", { style: aiStyles.tooltipRow, children: [_jsx("span", { style: aiStyles.tooltipLabel, children: "Total:" }), _jsxs("span", { style: aiStyles.tooltipValue, children: [formatStorage(storageUsed), " /", " ", formatStorage(storageAllocated)] }), renderUsageCircle(storagePercentage)] })] }), _jsxs("div", { style: {
|
|
363
405
|
...aiStyles.tooltipActions,
|
|
364
406
|
width: "100%",
|
|
365
407
|
flexDirection: "row",
|
|
@@ -479,6 +521,10 @@ export function AiStatusButton({ status, loading = false, className = "", }) {
|
|
|
479
521
|
try {
|
|
480
522
|
await logout();
|
|
481
523
|
setShowTooltip(false);
|
|
524
|
+
// Refresh provider data after logout
|
|
525
|
+
if (refetchProviders) {
|
|
526
|
+
await refetchProviders();
|
|
527
|
+
}
|
|
482
528
|
}
|
|
483
529
|
catch (error) {
|
|
484
530
|
console.error("Logout failed:", error);
|
|
@@ -506,6 +552,10 @@ export function AiStatusButton({ status, loading = false, className = "", }) {
|
|
|
506
552
|
await selectApiKeyWithToken(keyId);
|
|
507
553
|
setShowApiKeySelector(false);
|
|
508
554
|
setShowTooltip(false);
|
|
555
|
+
// Refresh provider data after API key selection
|
|
556
|
+
if (refetchProviders) {
|
|
557
|
+
await refetchProviders();
|
|
558
|
+
}
|
|
509
559
|
}
|
|
510
560
|
catch (error) {
|
|
511
561
|
console.error("Failed to select API key:", error);
|
|
@@ -12,6 +12,8 @@ interface LBProviderProps {
|
|
|
12
12
|
proxyUrl?: string;
|
|
13
13
|
/** Fonction appelée lors des changements d'état */
|
|
14
14
|
onStatusChange?: (status: LBAuthState["status"]) => void;
|
|
15
|
+
/** Fonction appelée après signin/logout pour refresh les providers */
|
|
16
|
+
onAuthChange?: () => void;
|
|
15
17
|
}
|
|
16
18
|
interface LBContextValue extends LBAuthState {
|
|
17
19
|
/** Fonction de connexion */
|
|
@@ -35,7 +37,7 @@ interface LBContextValue extends LBAuthState {
|
|
|
35
37
|
/** Access token temporaire (après login) */
|
|
36
38
|
accessToken?: string;
|
|
37
39
|
}
|
|
38
|
-
export declare function LBProvider({ children, baseUrl: _baseUrl, proxyUrl, onStatusChange, }: LBProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
40
|
+
export declare function LBProvider({ children, baseUrl: _baseUrl, proxyUrl, onStatusChange, onAuthChange, }: LBProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
39
41
|
/**
|
|
40
42
|
* Hook pour accéder au contexte LastBrain
|
|
41
43
|
*/
|
|
@@ -1 +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,EAIT,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;
|
|
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,EAIT,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;IACzD,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,UAAU,cAAe,SAAQ,WAAW;IAC1C,4BAA4B;IAC5B,KAAK,EAAE,CACL,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC;QACX,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,iBAAiB,CAAC,EAAE,OAAO,CAAC;KAC7B,CAAC,CAAC;IACH,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,gEAAgE;IAChE,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,mDAAmD;IACnD,qBAAqB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,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,QAA2B,EACpC,QAA2B,EAC3B,cAAc,EACd,YAAY,GACb,EAAE,eAAe,2CA4UjB;AAED;;GAEG;AACH,wBAAgB,KAAK,IAAI,cAAc,CAMtC"}
|
|
@@ -6,7 +6,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
6
6
|
*/
|
|
7
7
|
import { createContext, useContext, useEffect, useCallback, useState, } from "react";
|
|
8
8
|
const LBContext = createContext(undefined);
|
|
9
|
-
export function LBProvider({ children, baseUrl: _baseUrl = "/api/lastbrain", proxyUrl = "/api/lastbrain", onStatusChange, }) {
|
|
9
|
+
export function LBProvider({ children, baseUrl: _baseUrl = "/api/lastbrain", proxyUrl = "/api/lastbrain", onStatusChange, onAuthChange, }) {
|
|
10
10
|
const [state, setState] = useState({
|
|
11
11
|
status: "loading",
|
|
12
12
|
});
|
|
@@ -114,6 +114,7 @@ export function LBProvider({ children, baseUrl: _baseUrl = "/api/lastbrain", pro
|
|
|
114
114
|
setAccessToken(undefined); // Nettoyer l'access token temporaire
|
|
115
115
|
setApiKeys([]); // Nettoyer les clés API temporaires
|
|
116
116
|
onStatusChange?.("ready");
|
|
117
|
+
onAuthChange?.(); // Refresh provider after signin
|
|
117
118
|
}
|
|
118
119
|
catch (error) {
|
|
119
120
|
const message = error instanceof Error ? error.message : "Failed to select API key";
|
|
@@ -123,7 +124,7 @@ export function LBProvider({ children, baseUrl: _baseUrl = "/api/lastbrain", pro
|
|
|
123
124
|
});
|
|
124
125
|
throw error;
|
|
125
126
|
}
|
|
126
|
-
}, [proxyUrl, state.user, onStatusChange]);
|
|
127
|
+
}, [proxyUrl, state.user, onStatusChange, onAuthChange]);
|
|
127
128
|
/**
|
|
128
129
|
* Connexion utilisateur (étape 1 : login)
|
|
129
130
|
* Retourne le token et les clés API sans créer de session
|
|
@@ -248,8 +249,9 @@ export function LBProvider({ children, baseUrl: _baseUrl = "/api/lastbrain", pro
|
|
|
248
249
|
setApiKeys([]);
|
|
249
250
|
setAccessToken(undefined);
|
|
250
251
|
onStatusChange?.("needs_auth");
|
|
252
|
+
onAuthChange?.(); // Refresh provider after logout
|
|
251
253
|
}
|
|
252
|
-
}, [proxyUrl, onStatusChange]);
|
|
254
|
+
}, [proxyUrl, onStatusChange, onAuthChange]);
|
|
253
255
|
/**
|
|
254
256
|
* Recharge la session
|
|
255
257
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lastbrain/ai-ui-react",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.48",
|
|
4
4
|
"description": "Headless React components for LastBrain AI UI Kit",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"lucide-react": "^0.257.0",
|
|
51
|
-
"@lastbrain/ai-ui-core": "1.0.
|
|
51
|
+
"@lastbrain/ai-ui-core": "1.0.39"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/react": "^19.2.0",
|
|
@@ -12,9 +12,11 @@ import {
|
|
|
12
12
|
Power,
|
|
13
13
|
LogOut,
|
|
14
14
|
Key,
|
|
15
|
+
RefreshCw,
|
|
15
16
|
} from "lucide-react";
|
|
16
17
|
import { aiStyles, calculateTooltipPosition } from "../styles/inline";
|
|
17
18
|
import { useLB } from "../context/LBAuthProvider";
|
|
19
|
+
import { useAiContext } from "../context/AiProvider";
|
|
18
20
|
import { LBSigninModal } from "./LBSigninModal";
|
|
19
21
|
import { LBApiKeySelector } from "./LBApiKeySelector";
|
|
20
22
|
|
|
@@ -35,9 +37,7 @@ export function AiStatusButton({
|
|
|
35
37
|
let logout: (() => Promise<void>) | undefined;
|
|
36
38
|
let apiKeys: any[] = [];
|
|
37
39
|
let accessToken: string | undefined;
|
|
38
|
-
let selectApiKeyWithToken:
|
|
39
|
-
| ((apiKeyId: string) => Promise<void>)
|
|
40
|
-
| undefined;
|
|
40
|
+
let selectApiKeyWithToken: ((apiKeyId: string) => Promise<void>) | undefined;
|
|
41
41
|
|
|
42
42
|
try {
|
|
43
43
|
const lbContext = useLB();
|
|
@@ -54,6 +54,16 @@ export function AiStatusButton({
|
|
|
54
54
|
logout = undefined;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
// Récupérer refetchProviders depuis AiProvider si disponible
|
|
58
|
+
let refetchProviders: (() => Promise<void>) | undefined;
|
|
59
|
+
try {
|
|
60
|
+
const aiContext = useAiContext();
|
|
61
|
+
refetchProviders = aiContext.refetchProviders;
|
|
62
|
+
} catch {
|
|
63
|
+
// AiProvider n'est pas disponible, ignorer
|
|
64
|
+
refetchProviders = undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
57
67
|
const [showSigninModal, setShowSigninModal] = useState(false);
|
|
58
68
|
const [showApiKeySelector, setShowApiKeySelector] = useState(false);
|
|
59
69
|
|
|
@@ -540,6 +550,10 @@ export function AiStatusButton({
|
|
|
540
550
|
onClick={async () => {
|
|
541
551
|
if (logout) {
|
|
542
552
|
await logout();
|
|
553
|
+
// Refresh provider data after logout
|
|
554
|
+
if (refetchProviders) {
|
|
555
|
+
await refetchProviders();
|
|
556
|
+
}
|
|
543
557
|
}
|
|
544
558
|
setShowTooltip(false);
|
|
545
559
|
}}
|
|
@@ -704,29 +718,75 @@ export function AiStatusButton({
|
|
|
704
718
|
<div
|
|
705
719
|
style={{
|
|
706
720
|
...aiStyles.tooltipSection,
|
|
707
|
-
...(status.user?.email
|
|
708
|
-
? {}
|
|
709
|
-
: aiStyles.tooltipSectionFirst),
|
|
721
|
+
...(status.user?.email ? {} : aiStyles.tooltipSectionFirst),
|
|
710
722
|
}}
|
|
711
723
|
>
|
|
712
724
|
<div style={aiStyles.tooltipRow}>
|
|
713
725
|
<span style={aiStyles.tooltipLabel}>API Key:</span>
|
|
714
|
-
<
|
|
715
|
-
{
|
|
716
|
-
|
|
717
|
-
"
|
|
718
|
-
|
|
726
|
+
<div
|
|
727
|
+
style={{
|
|
728
|
+
display: "flex",
|
|
729
|
+
alignItems: "center",
|
|
730
|
+
gap: "8px",
|
|
731
|
+
}}
|
|
732
|
+
>
|
|
733
|
+
<span style={aiStyles.tooltipValue}>
|
|
734
|
+
{status.apiKey?.name || status.api_key?.name || "Unknown"}
|
|
735
|
+
</span>
|
|
736
|
+
{apiKeys.length > 1 && selectApiKeyWithToken && (
|
|
737
|
+
<button
|
|
738
|
+
onClick={(e) => {
|
|
739
|
+
e.stopPropagation();
|
|
740
|
+
setShowApiKeySelector(true);
|
|
741
|
+
}}
|
|
742
|
+
style={{
|
|
743
|
+
background: "rgba(139, 92, 246, 0.1)",
|
|
744
|
+
border: "1px solid rgba(139, 92, 246, 0.3)",
|
|
745
|
+
borderRadius: "50%",
|
|
746
|
+
width: "24px",
|
|
747
|
+
height: "24px",
|
|
748
|
+
display: "flex",
|
|
749
|
+
alignItems: "center",
|
|
750
|
+
justifyContent: "center",
|
|
751
|
+
cursor: "pointer",
|
|
752
|
+
padding: 0,
|
|
753
|
+
transition: "all 0.2s ease",
|
|
754
|
+
}}
|
|
755
|
+
onMouseEnter={(e) => {
|
|
756
|
+
e.currentTarget.style.background =
|
|
757
|
+
"rgba(139, 92, 246, 0.2)";
|
|
758
|
+
e.currentTarget.style.borderColor =
|
|
759
|
+
"rgba(139, 92, 246, 0.5)";
|
|
760
|
+
}}
|
|
761
|
+
onMouseLeave={(e) => {
|
|
762
|
+
e.currentTarget.style.background =
|
|
763
|
+
"rgba(139, 92, 246, 0.1)";
|
|
764
|
+
e.currentTarget.style.borderColor =
|
|
765
|
+
"rgba(139, 92, 246, 0.3)";
|
|
766
|
+
}}
|
|
767
|
+
title="Change API Key"
|
|
768
|
+
>
|
|
769
|
+
<RefreshCw
|
|
770
|
+
size={12}
|
|
771
|
+
style={{ color: "rgba(139, 92, 246, 1)" }}
|
|
772
|
+
/>
|
|
773
|
+
</button>
|
|
774
|
+
)}
|
|
775
|
+
</div>
|
|
719
776
|
</div>
|
|
720
777
|
<div style={aiStyles.tooltipRow}>
|
|
721
778
|
<span style={aiStyles.tooltipLabel}>Env:</span>
|
|
722
779
|
<span style={aiStyles.tooltipValue}>
|
|
723
|
-
{status.api_key?.env || "N/A"}
|
|
780
|
+
{status.apiKey?.env || status.api_key?.env || "N/A"}
|
|
724
781
|
</span>
|
|
725
782
|
</div>
|
|
726
783
|
<div style={aiStyles.tooltipRow}>
|
|
727
784
|
<span style={aiStyles.tooltipLabel}>Rate Limit:</span>
|
|
728
785
|
<span style={aiStyles.tooltipValue}>
|
|
729
|
-
{status.
|
|
786
|
+
{status.apiKey?.rate_limit_rpm ||
|
|
787
|
+
status.api_key?.rate_limit_rpm ||
|
|
788
|
+
0}{" "}
|
|
789
|
+
req/min
|
|
730
790
|
</span>
|
|
731
791
|
</div>
|
|
732
792
|
</div>
|
|
@@ -965,6 +1025,10 @@ export function AiStatusButton({
|
|
|
965
1025
|
try {
|
|
966
1026
|
await logout();
|
|
967
1027
|
setShowTooltip(false);
|
|
1028
|
+
// Refresh provider data after logout
|
|
1029
|
+
if (refetchProviders) {
|
|
1030
|
+
await refetchProviders();
|
|
1031
|
+
}
|
|
968
1032
|
} catch (error) {
|
|
969
1033
|
console.error("Logout failed:", error);
|
|
970
1034
|
}
|
|
@@ -1010,6 +1074,10 @@ export function AiStatusButton({
|
|
|
1010
1074
|
await selectApiKeyWithToken(keyId);
|
|
1011
1075
|
setShowApiKeySelector(false);
|
|
1012
1076
|
setShowTooltip(false);
|
|
1077
|
+
// Refresh provider data after API key selection
|
|
1078
|
+
if (refetchProviders) {
|
|
1079
|
+
await refetchProviders();
|
|
1080
|
+
}
|
|
1013
1081
|
} catch (error) {
|
|
1014
1082
|
console.error("Failed to select API key:", error);
|
|
1015
1083
|
}
|
|
@@ -29,6 +29,8 @@ interface LBProviderProps {
|
|
|
29
29
|
proxyUrl?: string;
|
|
30
30
|
/** Fonction appelée lors des changements d'état */
|
|
31
31
|
onStatusChange?: (status: LBAuthState["status"]) => void;
|
|
32
|
+
/** Fonction appelée après signin/logout pour refresh les providers */
|
|
33
|
+
onAuthChange?: () => void;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
interface LBContextValue extends LBAuthState {
|
|
@@ -64,6 +66,7 @@ export function LBProvider({
|
|
|
64
66
|
baseUrl: _baseUrl = "/api/lastbrain",
|
|
65
67
|
proxyUrl = "/api/lastbrain",
|
|
66
68
|
onStatusChange,
|
|
69
|
+
onAuthChange,
|
|
67
70
|
}: LBProviderProps) {
|
|
68
71
|
const [state, setState] = useState<LBAuthState>({
|
|
69
72
|
status: "loading",
|
|
@@ -195,6 +198,7 @@ export function LBProvider({
|
|
|
195
198
|
setAccessToken(undefined); // Nettoyer l'access token temporaire
|
|
196
199
|
setApiKeys([]); // Nettoyer les clés API temporaires
|
|
197
200
|
onStatusChange?.("ready");
|
|
201
|
+
onAuthChange?.(); // Refresh provider after signin
|
|
198
202
|
} catch (error) {
|
|
199
203
|
const message =
|
|
200
204
|
error instanceof Error ? error.message : "Failed to select API key";
|
|
@@ -205,7 +209,7 @@ export function LBProvider({
|
|
|
205
209
|
throw error;
|
|
206
210
|
}
|
|
207
211
|
},
|
|
208
|
-
[proxyUrl, state.user, onStatusChange]
|
|
212
|
+
[proxyUrl, state.user, onStatusChange, onAuthChange]
|
|
209
213
|
);
|
|
210
214
|
|
|
211
215
|
/**
|
|
@@ -371,8 +375,9 @@ export function LBProvider({
|
|
|
371
375
|
setApiKeys([]);
|
|
372
376
|
setAccessToken(undefined);
|
|
373
377
|
onStatusChange?.("needs_auth");
|
|
378
|
+
onAuthChange?.(); // Refresh provider after logout
|
|
374
379
|
}
|
|
375
|
-
}, [proxyUrl, onStatusChange]);
|
|
380
|
+
}, [proxyUrl, onStatusChange, onAuthChange]);
|
|
376
381
|
|
|
377
382
|
/**
|
|
378
383
|
* Recharge la session
|