@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.
@@ -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;AAkBtD,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,2CA+9BrB"}
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
- : aiStyles.tooltipSectionFirst),
360
- }, children: [_jsxs("div", { style: aiStyles.tooltipRow, children: [_jsx("span", { style: aiStyles.tooltipLabel, children: "API Key:" }), _jsx("span", { style: aiStyles.tooltipValue, children: status.apiKey?.name ||
361
- status.api_key?.name ||
362
- "N/A" })] }), _jsxs("div", { style: aiStyles.tooltipRow, children: [_jsx("span", { style: aiStyles.tooltipLabel, children: "Env:" }), _jsx("span", { style: aiStyles.tooltipValue, children: 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.api_key?.rate_limit_rpm || 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: {
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;CAC1D;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,GACf,EAAE,eAAe,2CA0UjB;AAED;;GAEG;AACH,wBAAgB,KAAK,IAAI,cAAc,CAMtC"}
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.47",
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.38"
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
- <span style={aiStyles.tooltipValue}>
715
- {status.apiKey?.name ||
716
- status.api_key?.name ||
717
- "N/A"}
718
- </span>
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.api_key?.rate_limit_rpm || 0} req/min
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