@burtson-labs/bandit-engine 2.0.165 → 2.0.167
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/README.md +4 -1
- package/dist/aiProviderStore-HY5G4QAK.mjs +8 -0
- package/dist/chat-6N5B7A7F.mjs +15 -0
- package/dist/chat-provider.js +175 -109
- package/dist/chat-provider.js.map +1 -1
- package/dist/chat-provider.mjs +6 -7
- package/dist/{chunk-FEIDGXVR.mjs → chunk-46OGYEME.mjs} +24 -6
- package/dist/{chunk-FEIDGXVR.mjs.map → chunk-46OGYEME.mjs.map} +1 -1
- package/dist/{chunk-ASWUEAWM.mjs → chunk-5BZWJQ5O.mjs} +2 -2
- package/dist/{chunk-LKGBO5OP.mjs → chunk-CABOLDNR.mjs} +12 -84
- package/dist/chunk-CABOLDNR.mjs.map +1 -0
- package/dist/{chunk-NGGTQVGX.mjs → chunk-E5WMDLE3.mjs} +3 -3
- package/dist/{chunk-J6LSSK3G.mjs → chunk-GRPTCHFN.mjs} +149 -41
- package/dist/chunk-GRPTCHFN.mjs.map +1 -0
- package/dist/{chunk-RLW4RBIR.mjs → chunk-KDIL5WUL.mjs} +4 -4
- package/dist/{chunk-6VDL4SLX.mjs → chunk-N4BQ6HKL.mjs} +5 -5
- package/dist/{chunk-RNCASZ2Y.mjs → chunk-PK3LFBGC.mjs} +10 -10
- package/dist/{chunk-WSUUW7T2.mjs → chunk-SHYNXDRO.mjs} +10 -7
- package/dist/chunk-SHYNXDRO.mjs.map +1 -0
- package/dist/{chunk-2EM4ATKI.mjs → chunk-SZJB5FLZ.mjs} +2 -2
- package/dist/{chunk-2EM4ATKI.mjs.map → chunk-SZJB5FLZ.mjs.map} +1 -1
- package/dist/{chunk-QHGGV4KJ.mjs → chunk-US4TG745.mjs} +6 -6
- package/dist/index.d.mts +94 -3
- package/dist/index.d.ts +94 -3
- package/dist/index.js +191 -130
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +21 -20
- package/dist/index.mjs.map +1 -1
- package/dist/management/management.js +162 -120
- package/dist/management/management.js.map +1 -1
- package/dist/management/management.mjs +9 -10
- package/dist/{memoryUtils-2FVXDSS6.mjs → memoryUtils-HGCYEUCD.mjs} +1 -3
- package/dist/{memoryUtils-2FVXDSS6.mjs.map → memoryUtils-HGCYEUCD.mjs.map} +1 -1
- package/dist/modals/chat-modal/chat-modal.js +149 -30
- package/dist/modals/chat-modal/chat-modal.js.map +1 -1
- package/dist/modals/chat-modal/chat-modal.mjs +5 -6
- package/dist/modelStore-TFNX4GEC.mjs +8 -0
- package/dist/{public-0EYmtpGD.d.mts → public-DJa4Db00.d.mts} +9 -0
- package/dist/{public-0EYmtpGD.d.ts → public-DJa4Db00.d.ts} +9 -0
- package/dist/public-types.d.mts +1 -1
- package/dist/public-types.d.ts +1 -1
- package/dist/shared/custom-element.mjs +0 -1
- package/docs/03_provider_integration.md +5 -2
- package/package.json +1 -1
- package/dist/aiProviderStore-M4BVEKUB.mjs +0 -9
- package/dist/chat-EMKHB23B.mjs +0 -16
- package/dist/chunk-BJTO5JO5.mjs +0 -11
- package/dist/chunk-J6LSSK3G.mjs.map +0 -1
- package/dist/chunk-LKGBO5OP.mjs.map +0 -1
- package/dist/chunk-WSUUW7T2.mjs.map +0 -1
- package/dist/modelStore-7YYELPF6.mjs +0 -9
- package/dist/modelStore-7YYELPF6.mjs.map +0 -1
- /package/dist/{aiProviderStore-M4BVEKUB.mjs.map → aiProviderStore-HY5G4QAK.mjs.map} +0 -0
- /package/dist/{chat-EMKHB23B.mjs.map → chat-6N5B7A7F.mjs.map} +0 -0
- /package/dist/{chunk-ASWUEAWM.mjs.map → chunk-5BZWJQ5O.mjs.map} +0 -0
- /package/dist/{chunk-NGGTQVGX.mjs.map → chunk-E5WMDLE3.mjs.map} +0 -0
- /package/dist/{chunk-RLW4RBIR.mjs.map → chunk-KDIL5WUL.mjs.map} +0 -0
- /package/dist/{chunk-6VDL4SLX.mjs.map → chunk-N4BQ6HKL.mjs.map} +0 -0
- /package/dist/{chunk-RNCASZ2Y.mjs.map → chunk-PK3LFBGC.mjs.map} +0 -0
- /package/dist/{chunk-QHGGV4KJ.mjs.map → chunk-US4TG745.mjs.map} +0 -0
- /package/dist/{chunk-BJTO5JO5.mjs.map → modelStore-TFNX4GEC.mjs.map} +0 -0
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
markdownSanitizeSchema,
|
|
7
7
|
maybeHandleFileLinkClick,
|
|
8
8
|
renderLowlightChildren
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KDIL5WUL.mjs";
|
|
10
10
|
|
|
11
11
|
// src/components/StreamingMarkdown.tsx
|
|
12
12
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
@@ -513,4 +513,4 @@ export {
|
|
|
513
513
|
isNativeShell,
|
|
514
514
|
isStandalonePwa
|
|
515
515
|
};
|
|
516
|
-
//# sourceMappingURL=chunk-
|
|
516
|
+
//# sourceMappingURL=chunk-5BZWJQ5O.mjs.map
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
indexedDBService_default,
|
|
3
3
|
usePackageSettingsStore
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SZJB5FLZ.mjs";
|
|
5
5
|
import {
|
|
6
6
|
authenticationService,
|
|
7
7
|
useAIProviderStore
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-GRPTCHFN.mjs";
|
|
9
9
|
import {
|
|
10
10
|
debugLogger
|
|
11
11
|
} from "./chunk-HNXPDIWC.mjs";
|
|
12
|
-
import {
|
|
13
|
-
__require
|
|
14
|
-
} from "./chunk-BJTO5JO5.mjs";
|
|
15
12
|
|
|
16
13
|
// src/services/ai-provider-init.service.ts
|
|
14
|
+
var sessionTokenFactory = (label) => () => {
|
|
15
|
+
const token = authenticationService.getToken();
|
|
16
|
+
debugLogger.info(`AIProviderInit: ${label}`, { hasToken: !!token });
|
|
17
|
+
return token;
|
|
18
|
+
};
|
|
17
19
|
var AIProviderInitService = class _AIProviderInitService {
|
|
18
20
|
static instance;
|
|
19
21
|
constructor() {
|
|
@@ -93,25 +95,7 @@ var AIProviderInitService = class _AIProviderInitService {
|
|
|
93
95
|
providerConfig = {
|
|
94
96
|
type: "ollama" /* OLLAMA */,
|
|
95
97
|
baseUrl: settings.ollamaUrl,
|
|
96
|
-
tokenFactory: (
|
|
97
|
-
let token = authenticationService.getToken();
|
|
98
|
-
if (!token) {
|
|
99
|
-
token = localStorage.getItem("authToken");
|
|
100
|
-
}
|
|
101
|
-
if (!token) {
|
|
102
|
-
try {
|
|
103
|
-
const { useAuthenticationStore } = __require("../../store/authenticationStore");
|
|
104
|
-
const authStore = useAuthenticationStore.getState();
|
|
105
|
-
token = authStore.token;
|
|
106
|
-
} catch (e) {
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
debugLogger.info("AIProviderInit: Token factory called", {
|
|
110
|
-
hasToken: !!token,
|
|
111
|
-
localStorage: !!localStorage.getItem("authToken")
|
|
112
|
-
});
|
|
113
|
-
return token;
|
|
114
|
-
}
|
|
98
|
+
tokenFactory: sessionTokenFactory("Token factory called")
|
|
115
99
|
};
|
|
116
100
|
debugLogger.info("Using legacy Ollama config", providerConfig);
|
|
117
101
|
}
|
|
@@ -134,25 +118,7 @@ var AIProviderInitService = class _AIProviderInitService {
|
|
|
134
118
|
const fallbackConfig = {
|
|
135
119
|
type: "ollama" /* OLLAMA */,
|
|
136
120
|
baseUrl: settings.ollamaUrl || "http://localhost:11434",
|
|
137
|
-
tokenFactory: ()
|
|
138
|
-
let token = authenticationService.getToken();
|
|
139
|
-
if (!token) {
|
|
140
|
-
token = localStorage.getItem("authToken");
|
|
141
|
-
}
|
|
142
|
-
if (!token) {
|
|
143
|
-
try {
|
|
144
|
-
const { useAuthenticationStore } = __require("../../store/authenticationStore");
|
|
145
|
-
const authStore = useAuthenticationStore.getState();
|
|
146
|
-
token = authStore.token;
|
|
147
|
-
} catch (e) {
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
debugLogger.info("AIProviderInit: Fallback tokenFactory", {
|
|
151
|
-
hasToken: !!token,
|
|
152
|
-
localStorage: !!localStorage.getItem("authToken")
|
|
153
|
-
});
|
|
154
|
-
return token;
|
|
155
|
-
}
|
|
121
|
+
tokenFactory: sessionTokenFactory("Fallback tokenFactory")
|
|
156
122
|
};
|
|
157
123
|
const { createProvider } = useAIProviderStore.getState();
|
|
158
124
|
createProvider(fallbackConfig);
|
|
@@ -165,25 +131,7 @@ var AIProviderInitService = class _AIProviderInitService {
|
|
|
165
131
|
const localFallbackConfig = {
|
|
166
132
|
type: "ollama" /* OLLAMA */,
|
|
167
133
|
baseUrl: "http://localhost:11434",
|
|
168
|
-
tokenFactory: (
|
|
169
|
-
let token = authenticationService.getToken();
|
|
170
|
-
if (!token) {
|
|
171
|
-
token = localStorage.getItem("authToken");
|
|
172
|
-
}
|
|
173
|
-
if (!token) {
|
|
174
|
-
try {
|
|
175
|
-
const { useAuthenticationStore } = __require("../../store/authenticationStore");
|
|
176
|
-
const authStore = useAuthenticationStore.getState();
|
|
177
|
-
token = authStore.token;
|
|
178
|
-
} catch (e) {
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
debugLogger.info("AIProviderInit: Local fallback tokenFactory", {
|
|
182
|
-
hasToken: !!token,
|
|
183
|
-
localStorage: !!localStorage.getItem("authToken")
|
|
184
|
-
});
|
|
185
|
-
return token;
|
|
186
|
-
}
|
|
134
|
+
tokenFactory: sessionTokenFactory("Local fallback tokenFactory")
|
|
187
135
|
};
|
|
188
136
|
const { createProvider } = useAIProviderStore.getState();
|
|
189
137
|
createProvider(localFallbackConfig);
|
|
@@ -255,27 +203,7 @@ var AIProviderInitService = class _AIProviderInitService {
|
|
|
255
203
|
});
|
|
256
204
|
return config;
|
|
257
205
|
}
|
|
258
|
-
config.tokenFactory = (
|
|
259
|
-
let token = authenticationService.getToken();
|
|
260
|
-
if (!token && typeof localStorage !== "undefined") {
|
|
261
|
-
try {
|
|
262
|
-
token = localStorage.getItem("authToken");
|
|
263
|
-
} catch {
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
if (!token) {
|
|
267
|
-
try {
|
|
268
|
-
const { useAuthenticationStore } = __require("../../store/authenticationStore");
|
|
269
|
-
const authStore = useAuthenticationStore.getState();
|
|
270
|
-
token = authStore.token;
|
|
271
|
-
} catch {
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
debugLogger.info("AIProviderInit: Token factory resolved auth token", {
|
|
275
|
-
hasToken: !!token
|
|
276
|
-
});
|
|
277
|
-
return token;
|
|
278
|
-
};
|
|
206
|
+
config.tokenFactory = sessionTokenFactory("Token factory resolved auth token");
|
|
279
207
|
}
|
|
280
208
|
return config;
|
|
281
209
|
}
|
|
@@ -285,4 +213,4 @@ var aiProviderInitService = AIProviderInitService.getInstance();
|
|
|
285
213
|
export {
|
|
286
214
|
aiProviderInitService
|
|
287
215
|
};
|
|
288
|
-
//# sourceMappingURL=chunk-
|
|
216
|
+
//# sourceMappingURL=chunk-CABOLDNR.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/ai-provider-init.service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025 Burtson Labs LLC.\n * SPDX-License-Identifier: BUSL-1.1\n * See LICENSE for the applicable terms.\n */\n\n\nimport { useAIProviderStore } from \"../store/aiProviderStore\";\nimport { usePackageSettingsStore } from \"../store/packageSettingsStore\";\nimport { AIProviderConfig, AIProviderType } from \"./ai-provider/types/common.types\";\nimport { authenticationService } from \"./auth/authenticationService\";\nimport { debugLogger } from \"./logging/debugLogger\";\nimport indexedDBService from \"./indexedDB/indexedDBService\";\n\ntype StoredAIProviderConfig = AIProviderConfig & { id?: string };\n\n/**\n * The signed-in user's access token for provider calls. authenticationService\n * is the single source of truth: depending on the host it reads localStorage,\n * the in-memory session (HttpOnly-cookie web sessions) or the token restored\n * from native secure storage. Nothing here reads Web Storage directly — in\n * memory mode a token must never be looked for there.\n */\nconst sessionTokenFactory = (label: string) => (): string | null => {\n const token = authenticationService.getToken();\n debugLogger.info(`AIProviderInit: ${label}`, { hasToken: !!token });\n return token;\n};\n\n/**\n * Service to initialize AI providers based on package settings\n */\nexport class AIProviderInitService {\n private static instance: AIProviderInitService;\n\n private constructor() {}\n\n static getInstance(): AIProviderInitService {\n if (!AIProviderInitService.instance) {\n AIProviderInitService.instance = new AIProviderInitService();\n }\n return AIProviderInitService.instance;\n }\n\n /**\n * Initialize AI provider from package settings\n * Provides backward compatibility with existing Ollama settings\n */\n async initializeFromSettings(): Promise<void> {\n const settings = usePackageSettingsStore.getState().settings;\n if (!settings) {\n debugLogger.warn(\"No package settings found, cannot initialize AI provider\");\n return;\n }\n\n let providerConfig: AIProviderConfig;\n\n debugLogger.info(\"AI Provider Init: Starting initialization\", { \n hasSettings: !!settings,\n hasAiProvider: !!settings.aiProvider,\n ollamaUrl: settings.ollamaUrl\n });\n\n const isPlaygroundEnvironment =\n settings.playgroundMode === true ||\n settings.aiProvider?.type === AIProviderType.PLAYGROUND ||\n (settings.gatewayApiUrl?.toLowerCase()?.startsWith(\"playground://\") ?? false) ||\n (typeof window !== \"undefined\" && window.location.pathname.includes(\"/playground\"));\n\n // First, try to load provider configuration from IndexedDB\n if (isPlaygroundEnvironment) {\n debugLogger.info(\"AI Provider Init: Playground environment detected, bypassing saved provider config\");\n } else {\n try {\n const savedConfig = await indexedDBService.get<StoredAIProviderConfig>(\n 'banditConfig', \n 1, \n 'config', \n 'aiProvider',\n [{ name: 'config', keyPath: 'id' }]\n );\n \n if (savedConfig) {\n debugLogger.info('AI Provider Init: Found saved config in IndexedDB', { type: savedConfig.type });\n \n // Filter out the 'id' property that was added for IndexedDB storage\n const { id: _id, ...configWithoutId } = savedConfig;\n providerConfig = { ...configWithoutId };\n if (providerConfig.type === AIProviderType.ANTHROPIC) {\n providerConfig = this.convertAnthropicConfig(providerConfig, settings?.gatewayApiUrl);\n }\n\n // Ensure tokenFactory is present for providers that need it\n providerConfig = this.ensureTokenFactory(providerConfig);\n \n // Initialize the provider with saved config\n try {\n const { createProvider } = useAIProviderStore.getState();\n createProvider(providerConfig);\n \n const provider = useAIProviderStore.getState().provider;\n if (provider) {\n try {\n await provider.validateServiceAvailability({ timeoutMs: 5000 });\n debugLogger.info(`AI Provider initialized and validated from IndexedDB: ${providerConfig.type}`);\n } catch (validationError) {\n debugLogger.warn(`AI Provider created but validation failed`, { error: validationError });\n }\n }\n return; // Successfully initialized from IndexedDB\n } catch (error) {\n debugLogger.error(\"Failed to initialize saved provider config, falling back to package settings\", { error });\n }\n }\n \n debugLogger.info('AI Provider Init: No saved config found, using package settings');\n } catch (error) {\n debugLogger.warn('AI Provider Init: Failed to load from IndexedDB, using package settings', { error });\n }\n }\n\n // Fallback to package settings if no saved config found\n if (settings.aiProvider) {\n providerConfig = { ...settings.aiProvider };\n if (providerConfig.type === AIProviderType.ANTHROPIC) {\n providerConfig = this.convertAnthropicConfig(providerConfig, settings.gatewayApiUrl);\n }\n \n providerConfig = this.ensureTokenFactory(providerConfig);\n \n debugLogger.info(\"Using explicit AI provider config\", providerConfig);\n } else {\n // Fall back to legacy Ollama settings for backward compatibility\n providerConfig = {\n type: AIProviderType.OLLAMA,\n baseUrl: settings.ollamaUrl,\n tokenFactory: sessionTokenFactory(\"Token factory called\")\n };\n debugLogger.info(\"Using legacy Ollama config\", providerConfig);\n }\n\n try {\n // First validate if the service is available\n const { createProvider } = useAIProviderStore.getState();\n \n // Try to create and validate the provider\n createProvider(providerConfig);\n \n // Test provider availability\n const provider = useAIProviderStore.getState().provider;\n if (provider) {\n try {\n await provider.validateServiceAvailability({ timeoutMs: 5000 });\n debugLogger.info(`AI Provider initialized and validated: ${providerConfig.type}`);\n } catch (validationError) {\n debugLogger.warn(`AI Provider created but validation failed:`, { error: validationError });\n // Provider is created but may not be fully available - this is ok for offline scenarios\n }\n }\n } catch (error) {\n debugLogger.error(\"Failed to initialize AI provider:\", { error });\n \n // Try to fall back to default Ollama if initial provider fails\n if (providerConfig.type !== AIProviderType.OLLAMA) {\n try {\n const fallbackConfig: AIProviderConfig = {\n type: AIProviderType.OLLAMA,\n baseUrl: settings.ollamaUrl || 'http://localhost:11434',\n tokenFactory: sessionTokenFactory(\"Fallback tokenFactory\")\n };\n const { createProvider } = useAIProviderStore.getState();\n createProvider(fallbackConfig);\n debugLogger.info(\"Fallback to Ollama provider successful\");\n } catch (fallbackError) {\n debugLogger.error(\"Failed to initialize fallback Ollama provider:\", { error: fallbackError });\n }\n } else {\n // If Ollama provider fails, try localhost as ultimate fallback\n try {\n const localFallbackConfig: AIProviderConfig = {\n type: AIProviderType.OLLAMA,\n baseUrl: 'http://localhost:11434',\n tokenFactory: sessionTokenFactory(\"Local fallback tokenFactory\")\n };\n const { createProvider } = useAIProviderStore.getState();\n createProvider(localFallbackConfig);\n debugLogger.info(\"Fallback to localhost Ollama provider successful\");\n } catch (localFallbackError) {\n debugLogger.error(\"All provider initialization attempts failed:\", { error: localFallbackError });\n }\n }\n }\n }\n\n /**\n * Switch to a different AI provider\n */\n switchProvider(config: AIProviderConfig): void {\n try {\n const normalizedConfig = this.ensureTokenFactory({ ...config });\n const { switchProvider } = useAIProviderStore.getState();\n switchProvider(normalizedConfig);\n debugLogger.info(`Switched to AI provider: ${normalizedConfig.type}`);\n } catch (error) {\n debugLogger.error(\"Failed to switch AI provider:\", { error });\n throw error;\n }\n }\n\n /**\n * Get the current provider type\n */\n getCurrentProviderType(): string | null {\n const provider = useAIProviderStore.getState().provider;\n return provider ? provider.getProviderType() : null;\n }\n\n /**\n * Check if a provider is initialized\n */\n isProviderInitialized(): boolean {\n return useAIProviderStore.getState().provider !== null;\n }\n\n private convertAnthropicConfig(config: AIProviderConfig, gatewayUrl?: string | null): AIProviderConfig {\n if (config.type !== AIProviderType.ANTHROPIC) {\n return config;\n }\n\n const defaultModel = typeof config.defaultModel === 'string' && config.defaultModel.trim()\n ? config.defaultModel.trim()\n : 'claude-3-5-sonnet-latest';\n\n const normalized: AIProviderConfig = {\n type: AIProviderType.GATEWAY,\n gatewayUrl: gatewayUrl || config.gatewayUrl || '',\n provider: 'anthropic',\n defaultModel,\n tokenFactory: config.tokenFactory\n };\n\n debugLogger.info('AI Provider Init: Converted direct Anthropic provider to gateway configuration');\n return normalized;\n }\n\n /**\n * Ensure providers that require auth have a token factory configured.\n * Handles both UI auth tokens and API key scenarios.\n */\n private ensureTokenFactory(config: AIProviderConfig): AIProviderConfig {\n if (config.type === AIProviderType.OLLAMA || config.type === AIProviderType.GATEWAY) {\n const existingFactory = config.tokenFactory;\n if (existingFactory) {\n return config;\n }\n\n // Prefer explicit API key if provided\n if (typeof config.apiKey === 'string' && config.apiKey.trim() !== '') {\n const key = config.apiKey.trim();\n config.tokenFactory = () => key;\n debugLogger.info(\"AIProviderInit: Using API key for token factory\", {\n type: config.type,\n hasKey: true\n });\n return config;\n }\n\n // Fallback to the signed-in session (UI sessions)\n config.tokenFactory = sessionTokenFactory(\"Token factory resolved auth token\");\n }\n\n return config;\n }\n}\n\nexport const aiProviderInitService = AIProviderInitService.getInstance();\n"],"mappings":"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","names":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
indexedDBService_default,
|
|
3
3
|
usePackageSettingsStore
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SZJB5FLZ.mjs";
|
|
5
5
|
import {
|
|
6
6
|
authenticationService
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GRPTCHFN.mjs";
|
|
8
8
|
import {
|
|
9
9
|
debugLogger
|
|
10
10
|
} from "./chunk-HNXPDIWC.mjs";
|
|
@@ -387,4 +387,4 @@ export {
|
|
|
387
387
|
discoverMcpTools,
|
|
388
388
|
useMCPToolsStore
|
|
389
389
|
};
|
|
390
|
-
//# sourceMappingURL=chunk-
|
|
390
|
+
//# sourceMappingURL=chunk-E5WMDLE3.mjs.map
|
|
@@ -1060,25 +1060,36 @@ import { catchError as catchError2, from as from5, lastValueFrom as lastValueFro
|
|
|
1060
1060
|
// src/store/authenticationStore.ts
|
|
1061
1061
|
import { create } from "zustand";
|
|
1062
1062
|
var TOKEN_KEY = "authToken";
|
|
1063
|
-
var
|
|
1064
|
-
var user = null;
|
|
1065
|
-
var rawToken = localStorage.getItem(TOKEN_KEY);
|
|
1066
|
-
if (rawToken) {
|
|
1063
|
+
var decodeClaims = (token) => {
|
|
1067
1064
|
try {
|
|
1068
|
-
const base64Url =
|
|
1065
|
+
const base64Url = token.split(".")[1];
|
|
1069
1066
|
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
|
1070
1067
|
const jsonPayload = decodeURIComponent(
|
|
1071
1068
|
atob(base64).split("").map((c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)).join("")
|
|
1072
1069
|
);
|
|
1073
|
-
|
|
1074
|
-
if (decoded.exp * 1e3 > Date.now()) {
|
|
1075
|
-
validToken = rawToken;
|
|
1076
|
-
user = decoded;
|
|
1077
|
-
}
|
|
1070
|
+
return JSON.parse(jsonPayload);
|
|
1078
1071
|
} catch {
|
|
1079
|
-
|
|
1080
|
-
user = null;
|
|
1072
|
+
return null;
|
|
1081
1073
|
}
|
|
1074
|
+
};
|
|
1075
|
+
var validOrNull = (raw) => {
|
|
1076
|
+
if (!raw) return null;
|
|
1077
|
+
const decoded = decodeClaims(raw);
|
|
1078
|
+
return decoded && decoded.exp * 1e3 > Date.now() ? raw : null;
|
|
1079
|
+
};
|
|
1080
|
+
var readLegacyStorage = () => {
|
|
1081
|
+
try {
|
|
1082
|
+
return typeof localStorage === "undefined" ? null : localStorage.getItem(TOKEN_KEY);
|
|
1083
|
+
} catch {
|
|
1084
|
+
return null;
|
|
1085
|
+
}
|
|
1086
|
+
};
|
|
1087
|
+
var validToken = null;
|
|
1088
|
+
var user = null;
|
|
1089
|
+
var rawToken = readLegacyStorage();
|
|
1090
|
+
if (rawToken) {
|
|
1091
|
+
validToken = validOrNull(rawToken);
|
|
1092
|
+
user = validToken ? decodeClaims(validToken) : null;
|
|
1082
1093
|
}
|
|
1083
1094
|
var useAuthenticationStore = create((set) => ({
|
|
1084
1095
|
token: validToken,
|
|
@@ -1086,16 +1097,10 @@ var useAuthenticationStore = create((set) => ({
|
|
|
1086
1097
|
authError: null,
|
|
1087
1098
|
setToken: (token) => {
|
|
1088
1099
|
if (token) {
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
atob(base64).split("").map((c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)).join("")
|
|
1094
|
-
);
|
|
1095
|
-
const user2 = JSON.parse(jsonPayload);
|
|
1096
|
-
localStorage.setItem(TOKEN_KEY, token);
|
|
1097
|
-
set({ token, authError: null, user: user2 });
|
|
1098
|
-
} catch {
|
|
1100
|
+
const decoded = decodeClaims(token);
|
|
1101
|
+
if (decoded) {
|
|
1102
|
+
set({ token, authError: null, user: decoded });
|
|
1103
|
+
} else {
|
|
1099
1104
|
set({ token: null, authError: "Invalid token", user: null });
|
|
1100
1105
|
}
|
|
1101
1106
|
} else {
|
|
@@ -1103,23 +1108,11 @@ var useAuthenticationStore = create((set) => ({
|
|
|
1103
1108
|
}
|
|
1104
1109
|
},
|
|
1105
1110
|
clearToken: () => {
|
|
1106
|
-
localStorage.removeItem(TOKEN_KEY);
|
|
1107
1111
|
set({ token: null, authError: null, user: null });
|
|
1108
1112
|
}
|
|
1109
1113
|
}));
|
|
1110
1114
|
var readPersistedToken = () => {
|
|
1111
|
-
|
|
1112
|
-
const raw = localStorage.getItem(TOKEN_KEY);
|
|
1113
|
-
if (!raw) return null;
|
|
1114
|
-
const base64 = raw.split(".")[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
1115
|
-
const json = decodeURIComponent(
|
|
1116
|
-
atob(base64).split("").map((c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)).join("")
|
|
1117
|
-
);
|
|
1118
|
-
const decoded = JSON.parse(json);
|
|
1119
|
-
return decoded.exp * 1e3 > Date.now() ? raw : null;
|
|
1120
|
-
} catch {
|
|
1121
|
-
return null;
|
|
1122
|
-
}
|
|
1115
|
+
return validOrNull(readLegacyStorage()) ?? validOrNull(useAuthenticationStore.getState().token);
|
|
1123
1116
|
};
|
|
1124
1117
|
|
|
1125
1118
|
// src/services/auth/authenticationService.ts
|
|
@@ -1133,21 +1126,103 @@ function emitAuthTokenChanged(token) {
|
|
|
1133
1126
|
detail: { token }
|
|
1134
1127
|
}));
|
|
1135
1128
|
}
|
|
1129
|
+
var readLocalStorage = () => {
|
|
1130
|
+
try {
|
|
1131
|
+
return typeof localStorage === "undefined" ? null : localStorage.getItem(TOKEN_KEY2);
|
|
1132
|
+
} catch {
|
|
1133
|
+
return null;
|
|
1134
|
+
}
|
|
1135
|
+
};
|
|
1136
|
+
var writeLocalStorage = (token) => {
|
|
1137
|
+
try {
|
|
1138
|
+
if (typeof localStorage === "undefined") return;
|
|
1139
|
+
if (token) localStorage.setItem(TOKEN_KEY2, token);
|
|
1140
|
+
else localStorage.removeItem(TOKEN_KEY2);
|
|
1141
|
+
} catch {
|
|
1142
|
+
}
|
|
1143
|
+
};
|
|
1136
1144
|
var AuthenticationService = class {
|
|
1145
|
+
storageMode = "localStorage";
|
|
1146
|
+
persistence = null;
|
|
1147
|
+
handlers = {};
|
|
1148
|
+
/** Bumped on every setToken/clearToken; async flows compare it to detect a superseded session. */
|
|
1149
|
+
revision = 0;
|
|
1150
|
+
refreshInFlight = null;
|
|
1151
|
+
lastPersist = Promise.resolve();
|
|
1152
|
+
/**
|
|
1153
|
+
* Pick the storage contract for this host. Call once at boot, before the
|
|
1154
|
+
* first `setToken`. Switching modes never moves a token by itself: the
|
|
1155
|
+
* host migrates (e.g. reads the legacy localStorage value, then clears it).
|
|
1156
|
+
*/
|
|
1157
|
+
configureSession(config) {
|
|
1158
|
+
this.storageMode = config.storage;
|
|
1159
|
+
this.persistence = config.persistence ?? null;
|
|
1160
|
+
this.handlers = config.handlers ?? {};
|
|
1161
|
+
}
|
|
1162
|
+
getStorageMode() {
|
|
1163
|
+
return this.storageMode;
|
|
1164
|
+
}
|
|
1165
|
+
getSessionRevision() {
|
|
1166
|
+
return this.revision;
|
|
1167
|
+
}
|
|
1137
1168
|
getToken() {
|
|
1138
|
-
|
|
1139
|
-
|
|
1169
|
+
if (this.storageMode === "memory") {
|
|
1170
|
+
return useAuthenticationStore.getState().token;
|
|
1171
|
+
}
|
|
1172
|
+
return readLocalStorage();
|
|
1140
1173
|
}
|
|
1141
1174
|
setToken(token) {
|
|
1142
|
-
|
|
1175
|
+
this.revision += 1;
|
|
1176
|
+
if (this.storageMode === "localStorage") {
|
|
1177
|
+
writeLocalStorage(token);
|
|
1178
|
+
} else {
|
|
1179
|
+
writeLocalStorage(null);
|
|
1180
|
+
}
|
|
1143
1181
|
useAuthenticationStore.getState().setToken(token);
|
|
1182
|
+
this.mirror(() => this.persistence?.write(token));
|
|
1144
1183
|
emitAuthTokenChanged(token);
|
|
1145
1184
|
}
|
|
1146
1185
|
clearToken() {
|
|
1147
|
-
|
|
1186
|
+
this.revision += 1;
|
|
1187
|
+
const current = this.getToken() ?? useAuthenticationStore.getState().token;
|
|
1188
|
+
try {
|
|
1189
|
+
this.handlers.beforeClear?.(current);
|
|
1190
|
+
} catch (error) {
|
|
1191
|
+
debugLogger.warn("Auth beforeClear handler failed", { error });
|
|
1192
|
+
}
|
|
1193
|
+
writeLocalStorage(null);
|
|
1148
1194
|
useAuthenticationStore.getState().clearToken();
|
|
1195
|
+
this.mirror(() => this.persistence?.clear());
|
|
1149
1196
|
emitAuthTokenChanged(null);
|
|
1150
1197
|
}
|
|
1198
|
+
/** True when the host registered a silent refresh path. */
|
|
1199
|
+
canRefresh() {
|
|
1200
|
+
return typeof this.handlers.refresh === "function";
|
|
1201
|
+
}
|
|
1202
|
+
/**
|
|
1203
|
+
* Ask the host for a fresh token. Concurrent callers share one attempt.
|
|
1204
|
+
* Resolves false when no refresh path exists or it did not produce a token.
|
|
1205
|
+
*/
|
|
1206
|
+
tryRefresh() {
|
|
1207
|
+
const refresh = this.handlers.refresh;
|
|
1208
|
+
if (!refresh) return Promise.resolve(false);
|
|
1209
|
+
if (this.refreshInFlight) return this.refreshInFlight;
|
|
1210
|
+
this.refreshInFlight = (async () => {
|
|
1211
|
+
try {
|
|
1212
|
+
return await refresh();
|
|
1213
|
+
} catch (error) {
|
|
1214
|
+
debugLogger.warn("Auth refresh handler failed", { error });
|
|
1215
|
+
return false;
|
|
1216
|
+
} finally {
|
|
1217
|
+
this.refreshInFlight = null;
|
|
1218
|
+
}
|
|
1219
|
+
})();
|
|
1220
|
+
return this.refreshInFlight;
|
|
1221
|
+
}
|
|
1222
|
+
/** Resolves once the most recent persistence write/clear has settled. */
|
|
1223
|
+
whenPersisted() {
|
|
1224
|
+
return this.lastPersist;
|
|
1225
|
+
}
|
|
1151
1226
|
isAuthenticated() {
|
|
1152
1227
|
const token = useAuthenticationStore.getState().token;
|
|
1153
1228
|
return !!token && !this.isTokenExpired(token);
|
|
@@ -1177,6 +1252,16 @@ var AuthenticationService = class {
|
|
|
1177
1252
|
return null;
|
|
1178
1253
|
}
|
|
1179
1254
|
}
|
|
1255
|
+
mirror(run) {
|
|
1256
|
+
const attempt = (async () => {
|
|
1257
|
+
try {
|
|
1258
|
+
await run();
|
|
1259
|
+
} catch (error) {
|
|
1260
|
+
debugLogger.warn("Auth token persistence failed", { error });
|
|
1261
|
+
}
|
|
1262
|
+
})();
|
|
1263
|
+
this.lastPersist = attempt;
|
|
1264
|
+
}
|
|
1180
1265
|
};
|
|
1181
1266
|
var authenticationService = new AuthenticationService();
|
|
1182
1267
|
|
|
@@ -1221,13 +1306,35 @@ var GatewayService = class {
|
|
|
1221
1306
|
});
|
|
1222
1307
|
instance.interceptors.response.use(
|
|
1223
1308
|
(response) => response,
|
|
1224
|
-
(error) => {
|
|
1309
|
+
async (error) => {
|
|
1310
|
+
const retried = await this._retryAfterRefresh(instance, error);
|
|
1311
|
+
if (retried) return retried;
|
|
1225
1312
|
this._handleAuthFailure(error);
|
|
1226
1313
|
return Promise.reject(this._normalizeAxiosError(error));
|
|
1227
1314
|
}
|
|
1228
1315
|
);
|
|
1229
1316
|
return instance;
|
|
1230
1317
|
}
|
|
1318
|
+
/**
|
|
1319
|
+
* A bare 401 on a host with a silent refresh path (HttpOnly refresh cookie,
|
|
1320
|
+
* native device token) usually means the access token aged out mid-session.
|
|
1321
|
+
* Refresh once and replay the request with the new token instead of
|
|
1322
|
+
* signing the user out; a failed refresh falls through to the sign-out path.
|
|
1323
|
+
*/
|
|
1324
|
+
async _retryAfterRefresh(instance, error) {
|
|
1325
|
+
const config = error.config;
|
|
1326
|
+
if (!config || config._banditAuthRetried || error.response?.status !== 401) return null;
|
|
1327
|
+
if (!authenticationService.canRefresh()) return null;
|
|
1328
|
+
const data = error.response?.data;
|
|
1329
|
+
if (data?.code && data.code !== "TOKEN_EXPIRED") return null;
|
|
1330
|
+
try {
|
|
1331
|
+
if (!await authenticationService.tryRefresh()) return null;
|
|
1332
|
+
} catch {
|
|
1333
|
+
return null;
|
|
1334
|
+
}
|
|
1335
|
+
config._banditAuthRetried = true;
|
|
1336
|
+
return instance.request(config);
|
|
1337
|
+
}
|
|
1231
1338
|
_normalizeAxiosError(error) {
|
|
1232
1339
|
if (error.response) {
|
|
1233
1340
|
return this._createHttpError(
|
|
@@ -3148,10 +3255,11 @@ var useAIProviderStore = create2((set, get) => ({
|
|
|
3148
3255
|
export {
|
|
3149
3256
|
useAuthenticationStore,
|
|
3150
3257
|
readPersistedToken,
|
|
3258
|
+
TOKEN_KEY2 as TOKEN_KEY,
|
|
3151
3259
|
AUTH_TOKEN_CHANGED_EVENT,
|
|
3152
3260
|
authenticationService,
|
|
3153
3261
|
GatewayService,
|
|
3154
3262
|
AIProviderFactory,
|
|
3155
3263
|
useAIProviderStore
|
|
3156
3264
|
};
|
|
3157
|
-
//# sourceMappingURL=chunk-
|
|
3265
|
+
//# sourceMappingURL=chunk-GRPTCHFN.mjs.map
|