@burtson-labs/bandit-engine 2.0.40 → 2.0.42

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-XDC4SNJF.mjs} +5 -5
  4. package/dist/chat-provider.js +156 -106
  5. package/dist/chat-provider.js.map +1 -1
  6. package/dist/chat-provider.mjs +4 -4
  7. package/dist/{chunk-7KEBNVCO.mjs → chunk-4RCAVVDN.mjs} +15 -10
  8. package/dist/{chunk-7KEBNVCO.mjs.map → chunk-4RCAVVDN.mjs.map} +1 -1
  9. package/dist/{chunk-QJYPWWA5.mjs → chunk-54ZQ3FSN.mjs} +104 -61
  10. package/dist/chunk-54ZQ3FSN.mjs.map +1 -0
  11. package/dist/{chunk-26QQ4CLA.mjs → chunk-EOEI74X4.mjs} +4 -4
  12. package/dist/{chunk-6ELNWXKC.mjs → chunk-ERV7GLY3.mjs} +4 -4
  13. package/dist/{chunk-75W5VWPV.mjs → chunk-H4PBQ5LJ.mjs} +51 -46
  14. package/dist/chunk-H4PBQ5LJ.mjs.map +1 -0
  15. package/dist/{chunk-D3AGKOM6.mjs → chunk-KBKWVG7X.mjs} +3 -3
  16. package/dist/{chunk-VIYBZO5W.mjs → chunk-SBNENBUQ.mjs} +3 -3
  17. package/dist/{chunk-2ZCR2TDY.mjs → chunk-UXE67LR7.mjs} +8 -6
  18. package/dist/{chunk-2ZCR2TDY.mjs.map → chunk-UXE67LR7.mjs.map} +1 -1
  19. package/dist/cli.js +1 -1
  20. package/dist/cli.js.map +1 -1
  21. package/dist/index.js +164 -109
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.mjs +8 -8
  24. package/dist/management/management.js +164 -109
  25. package/dist/management/management.js.map +1 -1
  26. package/dist/management/management.mjs +6 -6
  27. package/dist/modals/chat-modal/chat-modal.js +108 -63
  28. package/dist/modals/chat-modal/chat-modal.js.map +1 -1
  29. package/dist/modals/chat-modal/chat-modal.mjs +4 -4
  30. package/docs/01_quickstart.md +10 -4
  31. package/docs/02_gateway_api.md +19 -3
  32. package/docs/03_provider_integration.md +5 -4
  33. package/docs/api_reference/media/02_gateway_api.md +19 -3
  34. package/docs/api_reference/media/README.md +3 -1
  35. package/package.json +1 -1
  36. package/dist/chunk-75W5VWPV.mjs.map +0 -1
  37. package/dist/chunk-QJYPWWA5.mjs.map +0 -1
  38. /package/dist/{aiProviderStore-JMA5RWX7.mjs.map → aiProviderStore-UQI33C5E.mjs.map} +0 -0
  39. /package/dist/{chat-JMWPOSQ4.mjs.map → chat-XDC4SNJF.mjs.map} +0 -0
  40. /package/dist/{chunk-26QQ4CLA.mjs.map → chunk-EOEI74X4.mjs.map} +0 -0
  41. /package/dist/{chunk-6ELNWXKC.mjs.map → chunk-ERV7GLY3.mjs.map} +0 -0
  42. /package/dist/{chunk-D3AGKOM6.mjs.map → chunk-KBKWVG7X.mjs.map} +0 -0
  43. /package/dist/{chunk-VIYBZO5W.mjs.map → chunk-SBNENBUQ.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-EOEI74X4.mjs";
4
4
  import {
5
5
  chat_provider_default
6
- } from "./chunk-D3AGKOM6.mjs";
6
+ } from "./chunk-KBKWVG7X.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-4RCAVVDN.mjs";
14
+ import "./chunk-H4PBQ5LJ.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-ERV7GLY3.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-SBNENBUQ.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-UXE67LR7.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
  */
@@ -8909,9 +8952,11 @@ var init_useVectorStore = __esm({
8909
8952
  setHasCompatibleProvider(false);
8910
8953
  return false;
8911
8954
  }
8912
- const isOllama = config.type === "ollama";
8913
- const isGatewayWithOllama = config.type === "gateway" && config.provider === "ollama";
8914
- const isCompatible = isOllama || isGatewayWithOllama;
8955
+ const vectorCapableProviders = /* @__PURE__ */ new Set(["ollama", "bandit"]);
8956
+ const isNativeOllama = config.type === "ollama";
8957
+ const hasVectorCapableProvider = typeof config.provider === "string" && vectorCapableProviders.has(config.provider);
8958
+ const isGatewayWithVectorSupport = config.type === "gateway" && hasVectorCapableProvider;
8959
+ const isCompatible = isNativeOllama || isGatewayWithVectorSupport;
8915
8960
  setHasCompatibleProvider(isCompatible);
8916
8961
  return isCompatible;
8917
8962
  } catch (error) {
@@ -38288,26 +38333,7 @@ var AIProviderInitService = class _AIProviderInitService {
38288
38333
  if (providerConfig.type === "anthropic" /* ANTHROPIC */) {
38289
38334
  providerConfig = this.convertAnthropicConfig(providerConfig, settings?.gatewayApiUrl);
38290
38335
  }
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
- }
38336
+ providerConfig = this.ensureTokenFactory(providerConfig);
38311
38337
  try {
38312
38338
  const { createProvider } = useAIProviderStore.getState();
38313
38339
  createProvider(providerConfig);
@@ -38335,27 +38361,7 @@ var AIProviderInitService = class _AIProviderInitService {
38335
38361
  if (providerConfig.type === "anthropic" /* ANTHROPIC */) {
38336
38362
  providerConfig = this.convertAnthropicConfig(providerConfig, settings.gatewayApiUrl);
38337
38363
  }
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
- }
38364
+ providerConfig = this.ensureTokenFactory(providerConfig);
38359
38365
  debugLogger.info("Using explicit AI provider config", providerConfig);
38360
38366
  } else {
38361
38367
  providerConfig = {
@@ -38467,9 +38473,10 @@ var AIProviderInitService = class _AIProviderInitService {
38467
38473
  */
38468
38474
  switchProvider(config) {
38469
38475
  try {
38476
+ const normalizedConfig = this.ensureTokenFactory({ ...config });
38470
38477
  const { switchProvider } = useAIProviderStore.getState();
38471
- switchProvider(config);
38472
- debugLogger.info(`Switched to AI provider: ${config.type}`);
38478
+ switchProvider(normalizedConfig);
38479
+ debugLogger.info(`Switched to AI provider: ${normalizedConfig.type}`);
38473
38480
  } catch (error) {
38474
38481
  debugLogger.error("Failed to switch AI provider:", { error });
38475
38482
  throw error;
@@ -38503,6 +38510,49 @@ var AIProviderInitService = class _AIProviderInitService {
38503
38510
  debugLogger.info("AI Provider Init: Converted direct Anthropic provider to gateway configuration");
38504
38511
  return normalized;
38505
38512
  }
38513
+ /**
38514
+ * Ensure providers that require auth have a token factory configured.
38515
+ * Handles both UI auth tokens and API key scenarios.
38516
+ */
38517
+ ensureTokenFactory(config) {
38518
+ if (config.type === "ollama" /* OLLAMA */ || config.type === "gateway" /* GATEWAY */) {
38519
+ const existingFactory = config.tokenFactory;
38520
+ if (existingFactory) {
38521
+ return config;
38522
+ }
38523
+ if (typeof config.apiKey === "string" && config.apiKey.trim() !== "") {
38524
+ const key = config.apiKey.trim();
38525
+ config.tokenFactory = () => key;
38526
+ debugLogger.info("AIProviderInit: Using API key for token factory", {
38527
+ type: config.type,
38528
+ hasKey: true
38529
+ });
38530
+ return config;
38531
+ }
38532
+ config.tokenFactory = () => {
38533
+ let token = authenticationService.getToken();
38534
+ if (!token && typeof localStorage !== "undefined") {
38535
+ try {
38536
+ token = localStorage.getItem("authToken");
38537
+ } catch {
38538
+ }
38539
+ }
38540
+ if (!token) {
38541
+ try {
38542
+ const { useAuthenticationStore: useAuthenticationStore2 } = require("../../store/authenticationStore");
38543
+ const authStore = useAuthenticationStore2.getState();
38544
+ token = authStore.token;
38545
+ } catch {
38546
+ }
38547
+ }
38548
+ debugLogger.info("AIProviderInit: Token factory resolved auth token", {
38549
+ hasToken: !!token
38550
+ });
38551
+ return token;
38552
+ };
38553
+ }
38554
+ return config;
38555
+ }
38506
38556
  };
38507
38557
  var aiProviderInitService = AIProviderInitService.getInstance();
38508
38558
 
@@ -38558,11 +38608,16 @@ var ProviderTab = () => {
38558
38608
  const trimmed = sanitized.defaultModel.trim();
38559
38609
  sanitized.defaultModel = trimmed || void 0;
38560
38610
  }
38611
+ if (typeof sanitized.apiKey === "string") {
38612
+ const trimmedKey = sanitized.apiKey.trim();
38613
+ sanitized.apiKey = trimmedKey || void 0;
38614
+ }
38561
38615
  return sanitized;
38562
38616
  }, []);
38563
38617
  const [providerConfig, setProviderConfig] = (0, import_react33.useState)({
38564
- type: "ollama",
38565
- baseUrl: "http://localhost:11434"
38618
+ type: "gateway",
38619
+ gatewayUrl: packageSettings?.gatewayApiUrl || "",
38620
+ provider: "bandit"
38566
38621
  });
38567
38622
  const [isProviderConfigOpen, setIsProviderConfigOpen] = (0, import_react33.useState)(false);
38568
38623
  const [snackbarMessage, setSnackbarMessage] = (0, import_react33.useState)("");
@@ -38698,7 +38753,7 @@ var ProviderTab = () => {
38698
38753
  setProviderConfig(applyDefaultModel({
38699
38754
  ...baseConfig,
38700
38755
  gatewayUrl: packageSettings?.gatewayApiUrl || "",
38701
- provider: "openai"
38756
+ provider: "bandit"
38702
38757
  }));
38703
38758
  break;
38704
38759
  case "playground" /* PLAYGROUND */: