@burtson-labs/bandit-engine 2.0.160 → 2.0.161

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 (49) hide show
  1. package/README.md +78 -77
  2. package/dist/chat-3JAV77HO.mjs +16 -0
  3. package/dist/chat-provider.js +195 -111
  4. package/dist/chat-provider.js.map +1 -1
  5. package/dist/chat-provider.mjs +5 -5
  6. package/dist/{chunk-LTWMMHFT.mjs → chunk-EOMOOMUC.mjs} +1819 -3259
  7. package/dist/chunk-EOMOOMUC.mjs.map +1 -0
  8. package/dist/{chunk-TKSOJGHX.mjs → chunk-FSRMNQRN.mjs} +61 -60
  9. package/dist/chunk-FSRMNQRN.mjs.map +1 -0
  10. package/dist/{chunk-PDQT564P.mjs → chunk-MIDYEQOS.mjs} +2 -2
  11. package/dist/chunk-PFKKGJAQ.mjs +390 -0
  12. package/dist/chunk-PFKKGJAQ.mjs.map +1 -0
  13. package/dist/{chunk-LFQH6M6B.mjs → chunk-QPXG4A5C.mjs} +5 -5
  14. package/dist/chunk-QPXG4A5C.mjs.map +1 -0
  15. package/dist/{chunk-P6SLB5RC.mjs → chunk-QXITTH2X.mjs} +2 -2
  16. package/dist/{chunk-MHF76C2F.mjs → chunk-TTAORNWI.mjs} +1342 -1221
  17. package/dist/chunk-TTAORNWI.mjs.map +1 -0
  18. package/dist/{chunk-XTB6ZLUI.mjs → chunk-WQEBTH2R.mjs} +7 -2
  19. package/dist/{chunk-XTB6ZLUI.mjs.map → chunk-WQEBTH2R.mjs.map} +1 -1
  20. package/dist/{chunk-PXCIDXRP.mjs → chunk-X65A3NED.mjs} +5 -5
  21. package/dist/{chunk-IABD4L6K.mjs → chunk-XC7HDKFW.mjs} +3840 -4456
  22. package/dist/chunk-XC7HDKFW.mjs.map +1 -0
  23. package/dist/index.d.mts +85 -2
  24. package/dist/index.d.ts +85 -2
  25. package/dist/index.js +7994 -9837
  26. package/dist/index.js.map +1 -1
  27. package/dist/index.mjs +23 -14
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/management/management.js +7595 -9447
  30. package/dist/management/management.js.map +1 -1
  31. package/dist/management/management.mjs +8 -8
  32. package/dist/modals/chat-modal/chat-modal.js +1656 -3299
  33. package/dist/modals/chat-modal/chat-modal.js.map +1 -1
  34. package/dist/modals/chat-modal/chat-modal.mjs +4 -4
  35. package/dist/{modelStore-NMCRL3FR.mjs → modelStore-FGUGOWTL.mjs} +2 -2
  36. package/package.json +4 -2
  37. package/dist/chat-4BOIV4VP.mjs +0 -16
  38. package/dist/chunk-IABD4L6K.mjs.map +0 -1
  39. package/dist/chunk-LFQH6M6B.mjs.map +0 -1
  40. package/dist/chunk-LNGF2XAZ.mjs +0 -311
  41. package/dist/chunk-LNGF2XAZ.mjs.map +0 -1
  42. package/dist/chunk-LTWMMHFT.mjs.map +0 -1
  43. package/dist/chunk-MHF76C2F.mjs.map +0 -1
  44. package/dist/chunk-TKSOJGHX.mjs.map +0 -1
  45. /package/dist/{chat-4BOIV4VP.mjs.map → chat-3JAV77HO.mjs.map} +0 -0
  46. /package/dist/{chunk-PDQT564P.mjs.map → chunk-MIDYEQOS.mjs.map} +0 -0
  47. /package/dist/{chunk-P6SLB5RC.mjs.map → chunk-QXITTH2X.mjs.map} +0 -0
  48. /package/dist/{chunk-PXCIDXRP.mjs.map → chunk-X65A3NED.mjs.map} +0 -0
  49. /package/dist/{modelStore-NMCRL3FR.mjs.map → modelStore-FGUGOWTL.mjs.map} +0 -0
@@ -619,6 +619,8 @@ var init_preferencesStore = __esm({
619
619
  usePreferencesStore = (0, import_zustand4.create)((set, get) => ({
620
620
  preferences: defaultPreferences,
621
621
  isLoaded: false,
622
+ saveState: "idle",
623
+ lastSavedAt: null,
622
624
  setPreferences: (newPreferences) => {
623
625
  const sanitized = sanitizePreferences(newPreferences);
624
626
  set((state) => ({
@@ -661,6 +663,7 @@ var init_preferencesStore = __esm({
661
663
  }
662
664
  },
663
665
  savePreferences: async () => {
666
+ set({ saveState: "saving" });
664
667
  try {
665
668
  const { preferences } = get();
666
669
  const storeConfigs6 = [{ name: "config", keyPath: "id" }];
@@ -669,8 +672,10 @@ var init_preferencesStore = __esm({
669
672
  preferences
670
673
  }, storeConfigs6);
671
674
  debugLogger.debug("Preferences saved to IndexedDB");
675
+ set({ saveState: "saved", lastSavedAt: Date.now() });
672
676
  } catch (error) {
673
677
  debugLogger.error("Failed to save preferences to IndexedDB", { error });
678
+ set({ saveState: "error" });
674
679
  }
675
680
  },
676
681
  exportPreferences: () => {
@@ -6674,6 +6679,16 @@ var discoverMcpTools = async (id) => parse(await fetch(`${gatewayBase()}/mcp/ser
6674
6679
 
6675
6680
  // src/store/mcpToolsStore.ts
6676
6681
  var sanitizeMcpToolName = (raw) => raw.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").slice(0, 60);
6682
+ var STORE_CONFIGS = [{ name: "config", keyPath: "id" }];
6683
+ var readChoices = (value) => {
6684
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
6685
+ const out = {};
6686
+ for (const [id, on] of Object.entries(value)) {
6687
+ if (typeof on === "boolean") out[id] = on;
6688
+ }
6689
+ return out;
6690
+ };
6691
+ var withChoice = (tool, choices) => Object.prototype.hasOwnProperty.call(choices, tool.id) && tool.enabled !== choices[tool.id] ? { ...tool, enabled: choices[tool.id] } : tool;
6677
6692
  var healthCheckTool = {
6678
6693
  id: "health-check",
6679
6694
  name: "check_gateway_health",
@@ -6787,130 +6802,199 @@ var createFileTool = {
6787
6802
  isBuiltIn: true
6788
6803
  };
6789
6804
  var defaultTools = [healthCheckTool, webSearchTool, webFetchTool, imageGenerationTool, createFileTool];
6790
- var useMCPToolsStore = (0, import_zustand11.create)((set, get) => ({
6791
- tools: defaultTools,
6792
- isLoaded: false,
6793
- addTool: (toolData) => {
6794
- const newTool = {
6795
- ...toolData,
6796
- id: `tool-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
6797
- };
6798
- set((state) => ({
6799
- tools: [...state.tools, newTool]
6800
- }));
6801
- get().saveTools();
6802
- },
6803
- updateTool: (id, updates) => {
6804
- set((state) => ({
6805
- tools: state.tools.map(
6806
- (tool) => tool.id === id ? { ...tool, ...updates } : tool
6807
- )
6808
- }));
6809
- get().saveTools();
6810
- },
6811
- deleteTool: (id) => {
6812
- set((state) => ({
6813
- tools: state.tools.filter((tool) => tool.id !== id || tool.isBuiltIn)
6814
- }));
6815
- get().saveTools();
6816
- },
6817
- toggleTool: (id) => {
6818
- set((state) => ({
6819
- tools: state.tools.map(
6820
- (tool) => tool.id === id ? { ...tool, enabled: !tool.enabled } : tool
6821
- )
6822
- }));
6823
- get().saveTools();
6824
- },
6825
- getEnabledTools: () => {
6826
- return get().tools.filter((tool) => tool.enabled);
6827
- },
6828
- loadTools: async () => {
6829
- try {
6830
- const storeConfigs6 = [{ name: "config", keyPath: "id" }];
6831
- const data = await indexedDBService_default.get("banditConfig", 1, "config", "mcpTools", storeConfigs6);
6832
- if (data?.tools && Array.isArray(data.tools)) {
6833
- const savedTools = data.tools;
6834
- const builtInIds = defaultTools.map((t) => t.id);
6835
- const customTools = savedTools.filter(
6836
- (tool) => !tool.isBuiltIn && !builtInIds.includes(tool.id)
6837
- );
6838
- set({
6839
- tools: [...defaultTools, ...customTools],
6840
- isLoaded: true
6841
- });
6842
- debugLogger.info("MCP tools loaded from IndexedDB", {
6843
- totalTools: defaultTools.length + customTools.length,
6844
- builtInTools: defaultTools.length,
6845
- customTools: customTools.length
6846
- });
6847
- } else {
6848
- set({ isLoaded: true });
6849
- await get().saveTools();
6850
- debugLogger.info("Default MCP tools initialized");
6851
- }
6852
- } catch (error) {
6853
- debugLogger.error("Failed to load MCP tools from IndexedDB", { error });
6854
- set({ isLoaded: true });
6855
- }
6856
- },
6857
- saveTools: async () => {
6805
+ var useMCPToolsStore = (0, import_zustand11.create)((set, get) => {
6806
+ const persist = async () => {
6807
+ const { tools, choices } = get();
6808
+ const customTools = tools.filter((tool) => !tool.isBuiltIn && !tool.mcpServerId);
6809
+ await indexedDBService_default.put("banditConfig", 1, "config", {
6810
+ id: "mcpTools",
6811
+ tools: customTools,
6812
+ choices
6813
+ }, STORE_CONFIGS);
6814
+ debugLogger.debug("MCP tools saved to IndexedDB", { toolCount: customTools.length, choices: Object.keys(choices).length });
6815
+ };
6816
+ const persistQuietly = async () => {
6858
6817
  try {
6859
- const { tools } = get();
6860
- const storeConfigs6 = [{ name: "config", keyPath: "id" }];
6861
- const customTools = tools.filter((tool) => !tool.isBuiltIn && !tool.mcpServerId);
6862
- await indexedDBService_default.put("banditConfig", 1, "config", {
6863
- id: "mcpTools",
6864
- tools: customTools
6865
- }, storeConfigs6);
6866
- debugLogger.debug("MCP tools saved to IndexedDB", { toolCount: customTools.length });
6818
+ await persist();
6867
6819
  } catch (error) {
6868
6820
  debugLogger.error("Failed to save MCP tools to IndexedDB", { error });
6869
6821
  }
6870
- },
6871
- // Discover the user's connected MCP servers' tools from the gateway and merge
6872
- // them into the tool list (so the model can call them). Replaces any prior
6873
- // MCP-server tools; best-effort — a single unreachable server is skipped.
6874
- loadMcpServerTools: async () => {
6875
- let servers;
6876
- try {
6877
- servers = await listMcpServers();
6878
- } catch (error) {
6879
- debugLogger.warn("Could not list MCP servers", { error: String(error) });
6880
- return;
6881
- }
6882
- const collected = [];
6883
- for (const server of servers.filter((s) => s.enabled)) {
6822
+ };
6823
+ return {
6824
+ tools: defaultTools,
6825
+ isLoaded: false,
6826
+ choices: {},
6827
+ saveState: "idle",
6828
+ lastSavedAt: null,
6829
+ addTool: (toolData) => {
6830
+ const newTool = {
6831
+ ...toolData,
6832
+ id: `tool-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
6833
+ };
6834
+ set((state) => ({
6835
+ tools: [...state.tools, newTool]
6836
+ }));
6837
+ get().saveTools();
6838
+ },
6839
+ updateTool: (id, updates) => {
6840
+ set((state) => ({
6841
+ tools: state.tools.map(
6842
+ (tool) => tool.id === id ? { ...tool, ...updates } : tool
6843
+ )
6844
+ }));
6845
+ get().saveTools();
6846
+ },
6847
+ deleteTool: (id) => {
6848
+ set((state) => ({
6849
+ tools: state.tools.filter((tool) => tool.id !== id || tool.isBuiltIn)
6850
+ }));
6851
+ get().saveTools();
6852
+ },
6853
+ toggleTool: async (id) => {
6854
+ const tool = get().tools.find((t) => t.id === id);
6855
+ if (!tool) return false;
6856
+ const enabled = !tool.enabled;
6857
+ set((state) => ({
6858
+ tools: state.tools.map((t) => t.id === id ? { ...t, enabled } : t),
6859
+ choices: { ...state.choices, [id]: enabled }
6860
+ }));
6861
+ return get().saveTools();
6862
+ },
6863
+ getEnabledTools: () => {
6864
+ return get().tools.filter((tool) => tool.enabled);
6865
+ },
6866
+ loadTools: async () => {
6867
+ try {
6868
+ const data = await indexedDBService_default.get("banditConfig", 1, "config", "mcpTools", STORE_CONFIGS);
6869
+ if (data?.tools && Array.isArray(data.tools)) {
6870
+ const choices = { ...readChoices(data.choices), ...get().choices };
6871
+ const savedTools = data.tools;
6872
+ const builtInIds = defaultTools.map((t) => t.id);
6873
+ const customTools = savedTools.filter(
6874
+ (tool) => !tool.isBuiltIn && !builtInIds.includes(tool.id)
6875
+ );
6876
+ const discovered = get().tools.filter((t) => t.mcpServerId);
6877
+ set({
6878
+ tools: [...defaultTools, ...customTools, ...discovered].map((t) => withChoice(t, choices)),
6879
+ choices,
6880
+ isLoaded: true
6881
+ });
6882
+ debugLogger.info("MCP tools loaded from IndexedDB", {
6883
+ totalTools: defaultTools.length + customTools.length,
6884
+ builtInTools: defaultTools.length,
6885
+ customTools: customTools.length,
6886
+ choices: Object.keys(choices).length
6887
+ });
6888
+ } else {
6889
+ set({ isLoaded: true });
6890
+ await persistQuietly();
6891
+ debugLogger.info("Default MCP tools initialized");
6892
+ }
6893
+ } catch (error) {
6894
+ debugLogger.error("Failed to load MCP tools from IndexedDB", { error });
6895
+ set({ isLoaded: true });
6896
+ }
6897
+ },
6898
+ saveTools: async () => {
6899
+ set({ saveState: "saving" });
6884
6900
  try {
6885
- const { tools } = await discoverMcpTools(server.id);
6886
- for (const t of tools) {
6887
- const fnName = sanitizeMcpToolName(`mcp_${server.name}_${t.name}`);
6888
- const schema = t.inputSchema && typeof t.inputSchema === "object" && t.inputSchema.type === "object" ? t.inputSchema : { type: "object", properties: {}, required: [] };
6889
- collected.push({
6890
- id: `mcp-${server.id}-${t.name}`,
6891
- name: fnName,
6892
- description: t.description || `${t.name} (via ${server.name})`,
6893
- enabled: true,
6901
+ await persist();
6902
+ set({ saveState: "saved", lastSavedAt: Date.now() });
6903
+ return true;
6904
+ } catch (error) {
6905
+ debugLogger.error("Failed to save MCP tools to IndexedDB", { error });
6906
+ set({ saveState: "error" });
6907
+ return false;
6908
+ }
6909
+ },
6910
+ syncControllerTools: (controllerTools) => {
6911
+ const { choices } = get();
6912
+ const next = [...get().tools];
6913
+ let changed = false;
6914
+ for (const ct of controllerTools) {
6915
+ const functionName = (ct.id || ct.name).replace(/[^a-zA-Z0-9_]/g, "_");
6916
+ const index = [
6917
+ next.findIndex((lt) => lt.function.name === functionName),
6918
+ next.findIndex((lt) => lt.function.name === ct.id),
6919
+ next.findIndex((lt) => lt.id === ct.id)
6920
+ ].find((i) => i >= 0) ?? -1;
6921
+ if (index < 0) {
6922
+ next.push({
6923
+ id: `tool-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
6924
+ name: functionName,
6925
+ description: ct.description,
6926
+ enabled: ct.isEnabled,
6894
6927
  type: "function",
6895
6928
  function: {
6896
- name: fnName,
6897
- description: t.description || `${t.name} \u2014 provided by the ${server.name} MCP server.`,
6898
- parameters: schema
6929
+ name: ct.id,
6930
+ // the controller id maps back to the tool
6931
+ description: ct.description,
6932
+ parameters: { type: "object", properties: {}, required: [] }
6899
6933
  },
6900
- mcpServerId: server.id,
6901
- mcpToolName: t.name
6934
+ endpoint: `/mcp/${ct.id}`,
6935
+ method: "GET",
6936
+ isBuiltIn: false
6902
6937
  });
6938
+ changed = true;
6939
+ continue;
6940
+ }
6941
+ const local = next[index];
6942
+ const enabled = Object.prototype.hasOwnProperty.call(choices, local.id) ? choices[local.id] : ct.isEnabled;
6943
+ if (local.enabled !== enabled) {
6944
+ next[index] = { ...local, enabled };
6945
+ changed = true;
6903
6946
  }
6947
+ }
6948
+ if (!changed) return;
6949
+ set({ tools: next });
6950
+ void persistQuietly();
6951
+ },
6952
+ // Discover the user's connected MCP servers' tools from the gateway and merge
6953
+ // them into the tool list (so the model can call them). Replaces any prior
6954
+ // MCP-server tools; best-effort — a single unreachable server is skipped.
6955
+ loadMcpServerTools: async () => {
6956
+ let servers;
6957
+ try {
6958
+ servers = await listMcpServers();
6904
6959
  } catch (error) {
6905
- debugLogger.warn("Failed to discover tools for MCP server", { server: server.name, error: String(error) });
6960
+ debugLogger.warn("Could not list MCP servers", { error: String(error) });
6961
+ return;
6906
6962
  }
6963
+ const collected = [];
6964
+ for (const server of servers.filter((s) => s.enabled)) {
6965
+ try {
6966
+ const { tools } = await discoverMcpTools(server.id);
6967
+ for (const t of tools) {
6968
+ const fnName = sanitizeMcpToolName(`mcp_${server.name}_${t.name}`);
6969
+ const schema = t.inputSchema && typeof t.inputSchema === "object" && t.inputSchema.type === "object" ? t.inputSchema : { type: "object", properties: {}, required: [] };
6970
+ const id = `mcp-${server.id}-${t.name}`;
6971
+ const { choices } = get();
6972
+ collected.push({
6973
+ id,
6974
+ name: fnName,
6975
+ description: t.description || `${t.name} (via ${server.name})`,
6976
+ enabled: Object.prototype.hasOwnProperty.call(choices, id) ? choices[id] : true,
6977
+ type: "function",
6978
+ function: {
6979
+ name: fnName,
6980
+ description: t.description || `${t.name} \u2014 provided by the ${server.name} MCP server.`,
6981
+ parameters: schema
6982
+ },
6983
+ mcpServerId: server.id,
6984
+ mcpToolName: t.name
6985
+ });
6986
+ }
6987
+ } catch (error) {
6988
+ debugLogger.warn("Failed to discover tools for MCP server", { server: server.name, error: String(error) });
6989
+ }
6990
+ }
6991
+ set((state) => ({
6992
+ tools: [...state.tools.filter((t) => !t.mcpServerId), ...collected]
6993
+ }));
6994
+ debugLogger.info("MCP server tools loaded", { count: collected.length });
6907
6995
  }
6908
- set((state) => ({
6909
- tools: [...state.tools.filter((t) => !t.mcpServerId), ...collected]
6910
- }));
6911
- debugLogger.info("MCP server tools loaded", { count: collected.length });
6912
- }
6913
- }));
6996
+ };
6997
+ });
6914
6998
 
6915
6999
  // src/chat/hooks/useKnowledgeStore.tsx
6916
7000
  var import_react4 = require("react");