@burtson-labs/bandit-engine 2.0.40 → 2.0.41

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.
Files changed (43) hide show
  1. package/README.md +14 -11
  2. package/dist/{aiProviderStore-JMA5RWX7.mjs → aiProviderStore-UQI33C5E.mjs} +2 -2
  3. package/dist/{chat-JMWPOSQ4.mjs → chat-T5ANWWYQ.mjs} +5 -5
  4. package/dist/chat-provider.js +151 -103
  5. package/dist/chat-provider.js.map +1 -1
  6. package/dist/chat-provider.mjs +4 -4
  7. package/dist/{chunk-D3AGKOM6.mjs → chunk-22EY3ZDC.mjs} +3 -3
  8. package/dist/{chunk-6ELNWXKC.mjs → chunk-3E57HLDV.mjs} +4 -4
  9. package/dist/{chunk-QJYPWWA5.mjs → chunk-54ZQ3FSN.mjs} +104 -61
  10. package/dist/chunk-54ZQ3FSN.mjs.map +1 -0
  11. package/dist/{chunk-7KEBNVCO.mjs → chunk-A6OBEF72.mjs} +15 -10
  12. package/dist/{chunk-7KEBNVCO.mjs.map → chunk-A6OBEF72.mjs.map} +1 -1
  13. package/dist/{chunk-2ZCR2TDY.mjs → chunk-CX3INLYJ.mjs} +3 -3
  14. package/dist/{chunk-VIYBZO5W.mjs → chunk-LYWVYBKU.mjs} +3 -3
  15. package/dist/{chunk-26QQ4CLA.mjs → chunk-QFNEHSY4.mjs} +4 -4
  16. package/dist/{chunk-75W5VWPV.mjs → chunk-WPWWWUD7.mjs} +51 -46
  17. package/dist/chunk-WPWWWUD7.mjs.map +1 -0
  18. package/dist/cli.js +1 -1
  19. package/dist/cli.js.map +1 -1
  20. package/dist/index.js +159 -106
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +8 -8
  23. package/dist/management/management.js +159 -106
  24. package/dist/management/management.js.map +1 -1
  25. package/dist/management/management.mjs +6 -6
  26. package/dist/modals/chat-modal/chat-modal.js +103 -60
  27. package/dist/modals/chat-modal/chat-modal.js.map +1 -1
  28. package/dist/modals/chat-modal/chat-modal.mjs +4 -4
  29. package/docs/01_quickstart.md +10 -4
  30. package/docs/02_gateway_api.md +19 -3
  31. package/docs/03_provider_integration.md +5 -4
  32. package/docs/api_reference/media/02_gateway_api.md +19 -3
  33. package/docs/api_reference/media/README.md +3 -1
  34. package/package.json +1 -1
  35. package/dist/chunk-75W5VWPV.mjs.map +0 -1
  36. package/dist/chunk-QJYPWWA5.mjs.map +0 -1
  37. /package/dist/{aiProviderStore-JMA5RWX7.mjs.map → aiProviderStore-UQI33C5E.mjs.map} +0 -0
  38. /package/dist/{chat-JMWPOSQ4.mjs.map → chat-T5ANWWYQ.mjs.map} +0 -0
  39. /package/dist/{chunk-D3AGKOM6.mjs.map → chunk-22EY3ZDC.mjs.map} +0 -0
  40. /package/dist/{chunk-6ELNWXKC.mjs.map → chunk-3E57HLDV.mjs.map} +0 -0
  41. /package/dist/{chunk-2ZCR2TDY.mjs.map → chunk-CX3INLYJ.mjs.map} +0 -0
  42. /package/dist/{chunk-VIYBZO5W.mjs.map → chunk-LYWVYBKU.mjs.map} +0 -0
  43. /package/dist/{chunk-26QQ4CLA.mjs.map → chunk-QFNEHSY4.mjs.map} +0 -0
package/dist/index.mjs CHANGED
@@ -1,24 +1,24 @@
1
1
  import {
2
2
  chat_default
3
- } from "./chunk-26QQ4CLA.mjs";
3
+ } from "./chunk-QFNEHSY4.mjs";
4
4
  import {
5
5
  chat_provider_default
6
- } from "./chunk-D3AGKOM6.mjs";
6
+ } from "./chunk-22EY3ZDC.mjs";
7
7
  import "./chunk-ONQMRE2G.mjs";
8
8
  import {
9
9
  management_default,
10
10
  useGatewayHealth,
11
11
  useGatewayMemory,
12
12
  useGatewayModels
13
- } from "./chunk-7KEBNVCO.mjs";
14
- import "./chunk-75W5VWPV.mjs";
13
+ } from "./chunk-A6OBEF72.mjs";
14
+ import "./chunk-WPWWWUD7.mjs";
15
15
  import "./chunk-RTQDQ6TC.mjs";
16
16
  import {
17
17
  defineCustomElement
18
18
  } from "./chunk-IXIM7BNO.mjs";
19
19
  import {
20
20
  chat_modal_default
21
- } from "./chunk-6ELNWXKC.mjs";
21
+ } from "./chunk-3E57HLDV.mjs";
22
22
  import {
23
23
  FeedbackButton,
24
24
  FeedbackModal,
@@ -36,7 +36,7 @@ import {
36
36
  useTTS,
37
37
  useVoiceStore,
38
38
  voiceService
39
- } from "./chunk-VIYBZO5W.mjs";
39
+ } from "./chunk-LYWVYBKU.mjs";
40
40
  import {
41
41
  DEFAULT_TIER_FEATURES,
42
42
  FeatureFlagContext,
@@ -56,11 +56,11 @@ import {
56
56
  useVectorStore,
57
57
  vectorDatabaseService,
58
58
  vectorMigrationService
59
- } from "./chunk-2ZCR2TDY.mjs";
59
+ } from "./chunk-CX3INLYJ.mjs";
60
60
  import {
61
61
  usePackageSettingsStore
62
62
  } from "./chunk-XUBYA5I7.mjs";
63
- import "./chunk-QJYPWWA5.mjs";
63
+ import "./chunk-54ZQ3FSN.mjs";
64
64
  import {
65
65
  DebugLogger,
66
66
  debugLogger
@@ -1656,61 +1656,15 @@ var init_gateway_service = __esm({
1656
1656
  */
1657
1657
  chat(request) {
1658
1658
  const endpoint = request.provider === "ollama" ? `/api/${request.provider}/chat` : request.provider ? `/api/${request.provider}/chat/completions` : "/api/chat/completions";
1659
- const url = `${this._baseUrl}${endpoint}`;
1659
+ const fallbackEndpoint = request.provider === "bandit" ? "/completions" : null;
1660
1660
  const normalizedModel = request.provider === "bandit" ? (() => {
1661
1661
  const trimmed = (request.model ?? "").replace(/^bandit:/, "").trim();
1662
1662
  return trimmed !== "" ? trimmed : "bandit-core-1";
1663
1663
  })() : request.model;
1664
- debugLogger.debug(`Gateway chat request to ${url} with provider: ${request.provider || "default"}`, {
1665
- model: normalizedModel,
1666
- messageCount: request.messages.length,
1667
- hasImages: !!(request.images && request.images.length > 0),
1668
- imageCount: request.images?.length || 0
1669
- });
1670
1664
  const requestBody = { ...request, model: normalizedModel, stream: request.stream !== false };
1671
1665
  return new import_rxjs6.Observable((observer) => {
1672
1666
  const controller = new AbortController();
1673
- const task = fetch(url, {
1674
- method: "POST",
1675
- headers: this._getHeaders(),
1676
- body: JSON.stringify(requestBody),
1677
- signal: controller.signal
1678
- });
1679
- task.then(async (response) => {
1680
- debugLogger.debug(`Gateway chat response status: ${response.status} for provider: ${request.provider || "default"}`);
1681
- if (!response.ok) {
1682
- let errorText = "";
1683
- let errorData = null;
1684
- try {
1685
- errorText = await response.text();
1686
- debugLogger.error("GatewayService chat error response body", {
1687
- status: response.status,
1688
- statusText: response.statusText,
1689
- url: response.url,
1690
- body: errorText
1691
- });
1692
- } catch (readError) {
1693
- debugLogger.error("GatewayService chat failed to read error response body", { error: readError });
1694
- errorText = `Request failed with status ${response.status}`;
1695
- }
1696
- try {
1697
- errorData = JSON.parse(errorText);
1698
- debugLogger.error("GatewayService chat parsed error payload", errorData);
1699
- } catch (parseError) {
1700
- debugLogger.error("GatewayService chat error payload was not valid JSON");
1701
- errorData = { message: errorText };
1702
- }
1703
- const error = this._createHttpError(
1704
- `POST ${url} failed: ${response.status} ${response.statusText ?? ""}`,
1705
- {
1706
- status: response.status,
1707
- statusText: response.statusText ?? "",
1708
- data: errorData,
1709
- url
1710
- }
1711
- );
1712
- throw error;
1713
- }
1667
+ const handleStreamingResponse = async (response) => {
1714
1668
  const reader = response.body?.getReader();
1715
1669
  const decoder = new TextDecoder();
1716
1670
  let buffer = "";
@@ -1785,14 +1739,75 @@ var init_gateway_service = __esm({
1785
1739
  }).catch((err) => observer.error(err));
1786
1740
  };
1787
1741
  read();
1788
- }).catch((err) => {
1789
- debugLogger.error("GatewayService chat fetch error", {
1790
- error: err,
1791
- url,
1792
- provider: request.provider
1742
+ };
1743
+ const sendRequest = (targetEndpoint, allowFallback) => {
1744
+ const url = `${this._baseUrl}${targetEndpoint}`;
1745
+ debugLogger.debug(`Gateway chat request to ${url} with provider: ${request.provider || "default"}`, {
1746
+ model: normalizedModel,
1747
+ messageCount: request.messages.length,
1748
+ hasImages: !!(request.images && request.images.length > 0),
1749
+ imageCount: request.images?.length || 0
1793
1750
  });
1794
- observer.error(err);
1795
- });
1751
+ fetch(url, {
1752
+ method: "POST",
1753
+ headers: this._getHeaders(),
1754
+ body: JSON.stringify(requestBody),
1755
+ signal: controller.signal
1756
+ }).then(async (response) => {
1757
+ debugLogger.debug(`Gateway chat response status: ${response.status} for provider: ${request.provider || "default"}`);
1758
+ if (response.status === 404 && allowFallback && fallbackEndpoint) {
1759
+ debugLogger.warn("GatewayService chat endpoint returned 404, attempting fallback route", {
1760
+ provider: request.provider,
1761
+ attemptedEndpoint: targetEndpoint,
1762
+ fallbackEndpoint
1763
+ });
1764
+ sendRequest(fallbackEndpoint, false);
1765
+ return;
1766
+ }
1767
+ if (!response.ok) {
1768
+ let errorText = "";
1769
+ let errorData = null;
1770
+ try {
1771
+ errorText = await response.text();
1772
+ debugLogger.error("GatewayService chat error response body", {
1773
+ status: response.status,
1774
+ statusText: response.statusText,
1775
+ url: response.url,
1776
+ body: errorText
1777
+ });
1778
+ } catch (readError) {
1779
+ debugLogger.error("GatewayService chat failed to read error response body", { error: readError });
1780
+ errorText = `Request failed with status ${response.status}`;
1781
+ }
1782
+ try {
1783
+ errorData = JSON.parse(errorText);
1784
+ debugLogger.error("GatewayService chat parsed error payload", errorData);
1785
+ } catch (parseError) {
1786
+ debugLogger.error("GatewayService chat error payload was not valid JSON");
1787
+ errorData = { message: errorText };
1788
+ }
1789
+ const error = this._createHttpError(
1790
+ `POST ${url} failed: ${response.status} ${response.statusText ?? ""}`,
1791
+ {
1792
+ status: response.status,
1793
+ statusText: response.statusText ?? "",
1794
+ data: errorData,
1795
+ url
1796
+ }
1797
+ );
1798
+ throw error;
1799
+ }
1800
+ await handleStreamingResponse(response);
1801
+ }).catch((err) => {
1802
+ debugLogger.error("GatewayService chat fetch error", {
1803
+ error: err,
1804
+ url,
1805
+ provider: request.provider
1806
+ });
1807
+ observer.error(err);
1808
+ });
1809
+ };
1810
+ sendRequest(endpoint, true);
1796
1811
  return () => {
1797
1812
  try {
1798
1813
  controller.abort();
@@ -1925,18 +1940,46 @@ var init_gateway_service = __esm({
1925
1940
  );
1926
1941
  }
1927
1942
  _getHeaders() {
1928
- const token = this._tokenFactory();
1943
+ const rawToken2 = this._tokenFactory();
1929
1944
  const headers = {
1930
1945
  "Content-Type": "application/json"
1931
1946
  };
1932
- if (token && token.trim() !== "") {
1933
- headers["Authorization"] = `Bearer ${token}`;
1934
- debugLogger.debug("Authorization header set with token");
1935
- } else {
1947
+ if (!rawToken2) {
1936
1948
  debugLogger.warn("GatewayService: No token found, skipping Authorization header");
1949
+ return headers;
1950
+ }
1951
+ const token = rawToken2.trim();
1952
+ if (token === "") {
1953
+ debugLogger.warn("GatewayService: Token factory returned empty string");
1954
+ return headers;
1955
+ }
1956
+ if (/^(Bearer|ApiKey)\s+/i.test(token)) {
1957
+ headers["Authorization"] = token;
1958
+ debugLogger.debug("GatewayService: Authorization header set with explicit scheme");
1959
+ return headers;
1960
+ }
1961
+ if (this._isLikelyBanditApiKey(token)) {
1962
+ headers["Authorization"] = `ApiKey ${token}`;
1963
+ headers["X-Burtson-Api-Key"] = token;
1964
+ debugLogger.debug("GatewayService: Authorization header set using API key");
1965
+ return headers;
1937
1966
  }
1967
+ if (this._isLikelyJwt(token)) {
1968
+ headers["Authorization"] = `Bearer ${token}`;
1969
+ debugLogger.debug("GatewayService: Authorization header set using bearer token");
1970
+ return headers;
1971
+ }
1972
+ headers["Authorization"] = `Bearer ${token}`;
1973
+ debugLogger.debug("GatewayService: Authorization header defaulted to bearer scheme");
1938
1974
  return headers;
1939
1975
  }
1976
+ _isLikelyJwt(token) {
1977
+ const segments = token.split(".");
1978
+ return segments.length === 3 && segments.every((segment) => segment.length > 0);
1979
+ }
1980
+ _isLikelyBanditApiKey(value) {
1981
+ return /^bai_[a-z0-9]{10,}$/i.test(value);
1982
+ }
1940
1983
  /**
1941
1984
  * Submit feedback to the gateway API
1942
1985
  */
@@ -38288,26 +38331,7 @@ var AIProviderInitService = class _AIProviderInitService {
38288
38331
  if (providerConfig.type === "anthropic" /* ANTHROPIC */) {
38289
38332
  providerConfig = this.convertAnthropicConfig(providerConfig, settings?.gatewayApiUrl);
38290
38333
  }
38291
- if ((providerConfig.type === "ollama" /* OLLAMA */ || providerConfig.type === "gateway" /* GATEWAY */) && !providerConfig.tokenFactory) {
38292
- providerConfig.tokenFactory = () => {
38293
- let token = authenticationService.getToken();
38294
- if (!token) {
38295
- token = localStorage.getItem("authToken");
38296
- }
38297
- if (!token) {
38298
- try {
38299
- const { useAuthenticationStore: useAuthenticationStore2 } = require("../../store/authenticationStore");
38300
- const authStore = useAuthenticationStore2.getState();
38301
- token = authStore.token;
38302
- } catch (e) {
38303
- }
38304
- }
38305
- debugLogger.info("AI Provider Init: IndexedDB config token factory", {
38306
- hasToken: !!token
38307
- });
38308
- return token;
38309
- };
38310
- }
38334
+ providerConfig = this.ensureTokenFactory(providerConfig);
38311
38335
  try {
38312
38336
  const { createProvider } = useAIProviderStore.getState();
38313
38337
  createProvider(providerConfig);
@@ -38335,27 +38359,7 @@ var AIProviderInitService = class _AIProviderInitService {
38335
38359
  if (providerConfig.type === "anthropic" /* ANTHROPIC */) {
38336
38360
  providerConfig = this.convertAnthropicConfig(providerConfig, settings.gatewayApiUrl);
38337
38361
  }
38338
- if (providerConfig.type === "ollama" /* OLLAMA */ && !providerConfig.tokenFactory) {
38339
- providerConfig.tokenFactory = () => {
38340
- let token = authenticationService.getToken();
38341
- if (!token) {
38342
- token = localStorage.getItem("authToken");
38343
- }
38344
- if (!token) {
38345
- try {
38346
- const { useAuthenticationStore: useAuthenticationStore2 } = require("../../store/authenticationStore");
38347
- const authStore = useAuthenticationStore2.getState();
38348
- token = authStore.token;
38349
- } catch (e) {
38350
- }
38351
- }
38352
- debugLogger.info("AIProviderInit: Explicit config tokenFactory", {
38353
- hasToken: !!token,
38354
- localStorage: !!localStorage.getItem("authToken")
38355
- });
38356
- return token;
38357
- };
38358
- }
38362
+ providerConfig = this.ensureTokenFactory(providerConfig);
38359
38363
  debugLogger.info("Using explicit AI provider config", providerConfig);
38360
38364
  } else {
38361
38365
  providerConfig = {
@@ -38467,9 +38471,10 @@ var AIProviderInitService = class _AIProviderInitService {
38467
38471
  */
38468
38472
  switchProvider(config) {
38469
38473
  try {
38474
+ const normalizedConfig = this.ensureTokenFactory({ ...config });
38470
38475
  const { switchProvider } = useAIProviderStore.getState();
38471
- switchProvider(config);
38472
- debugLogger.info(`Switched to AI provider: ${config.type}`);
38476
+ switchProvider(normalizedConfig);
38477
+ debugLogger.info(`Switched to AI provider: ${normalizedConfig.type}`);
38473
38478
  } catch (error) {
38474
38479
  debugLogger.error("Failed to switch AI provider:", { error });
38475
38480
  throw error;
@@ -38503,6 +38508,49 @@ var AIProviderInitService = class _AIProviderInitService {
38503
38508
  debugLogger.info("AI Provider Init: Converted direct Anthropic provider to gateway configuration");
38504
38509
  return normalized;
38505
38510
  }
38511
+ /**
38512
+ * Ensure providers that require auth have a token factory configured.
38513
+ * Handles both UI auth tokens and API key scenarios.
38514
+ */
38515
+ ensureTokenFactory(config) {
38516
+ if (config.type === "ollama" /* OLLAMA */ || config.type === "gateway" /* GATEWAY */) {
38517
+ const existingFactory = config.tokenFactory;
38518
+ if (existingFactory) {
38519
+ return config;
38520
+ }
38521
+ if (typeof config.apiKey === "string" && config.apiKey.trim() !== "") {
38522
+ const key = config.apiKey.trim();
38523
+ config.tokenFactory = () => key;
38524
+ debugLogger.info("AIProviderInit: Using API key for token factory", {
38525
+ type: config.type,
38526
+ hasKey: true
38527
+ });
38528
+ return config;
38529
+ }
38530
+ config.tokenFactory = () => {
38531
+ let token = authenticationService.getToken();
38532
+ if (!token && typeof localStorage !== "undefined") {
38533
+ try {
38534
+ token = localStorage.getItem("authToken");
38535
+ } catch {
38536
+ }
38537
+ }
38538
+ if (!token) {
38539
+ try {
38540
+ const { useAuthenticationStore: useAuthenticationStore2 } = require("../../store/authenticationStore");
38541
+ const authStore = useAuthenticationStore2.getState();
38542
+ token = authStore.token;
38543
+ } catch {
38544
+ }
38545
+ }
38546
+ debugLogger.info("AIProviderInit: Token factory resolved auth token", {
38547
+ hasToken: !!token
38548
+ });
38549
+ return token;
38550
+ };
38551
+ }
38552
+ return config;
38553
+ }
38506
38554
  };
38507
38555
  var aiProviderInitService = AIProviderInitService.getInstance();
38508
38556
 
@@ -38558,11 +38606,16 @@ var ProviderTab = () => {
38558
38606
  const trimmed = sanitized.defaultModel.trim();
38559
38607
  sanitized.defaultModel = trimmed || void 0;
38560
38608
  }
38609
+ if (typeof sanitized.apiKey === "string") {
38610
+ const trimmedKey = sanitized.apiKey.trim();
38611
+ sanitized.apiKey = trimmedKey || void 0;
38612
+ }
38561
38613
  return sanitized;
38562
38614
  }, []);
38563
38615
  const [providerConfig, setProviderConfig] = (0, import_react33.useState)({
38564
- type: "ollama",
38565
- baseUrl: "http://localhost:11434"
38616
+ type: "gateway",
38617
+ gatewayUrl: packageSettings?.gatewayApiUrl || "",
38618
+ provider: "bandit"
38566
38619
  });
38567
38620
  const [isProviderConfigOpen, setIsProviderConfigOpen] = (0, import_react33.useState)(false);
38568
38621
  const [snackbarMessage, setSnackbarMessage] = (0, import_react33.useState)("");
@@ -38698,7 +38751,7 @@ var ProviderTab = () => {
38698
38751
  setProviderConfig(applyDefaultModel({
38699
38752
  ...baseConfig,
38700
38753
  gatewayUrl: packageSettings?.gatewayApiUrl || "",
38701
- provider: "openai"
38754
+ provider: "bandit"
38702
38755
  }));
38703
38756
  break;
38704
38757
  case "playground" /* PLAYGROUND */: