@burtson-labs/bandit-engine 2.0.44 → 2.0.49

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 (54) hide show
  1. package/README.md +7 -5
  2. package/dist/{aiProviderStore-UQI33C5E.mjs → aiProviderStore-3N3VE6D4.mjs} +2 -2
  3. package/dist/chat-647M6BRG.mjs +15 -0
  4. package/dist/chat-provider.js +45 -10
  5. package/dist/chat-provider.js.map +1 -1
  6. package/dist/chat-provider.mjs +6 -6
  7. package/dist/{chunk-UXE67LR7.mjs → chunk-6WZUQHZT.mjs} +11 -7
  8. package/dist/chunk-6WZUQHZT.mjs.map +1 -0
  9. package/dist/{chunk-QV4ELNLP.mjs → chunk-7HXARU5R.mjs} +58 -19
  10. package/dist/chunk-7HXARU5R.mjs.map +1 -0
  11. package/dist/{chunk-XUBYA5I7.mjs → chunk-7ZDS33S2.mjs} +34 -6
  12. package/dist/chunk-7ZDS33S2.mjs.map +1 -0
  13. package/dist/{chunk-SBNENBUQ.mjs → chunk-AXFX2HUK.mjs} +12 -12
  14. package/dist/{chunk-SBNENBUQ.mjs.map → chunk-AXFX2HUK.mjs.map} +1 -1
  15. package/dist/{chunk-54ZQ3FSN.mjs → chunk-BENL3EF2.mjs} +7 -4
  16. package/dist/chunk-BENL3EF2.mjs.map +1 -0
  17. package/dist/{chunk-RTQDQ6TC.mjs → chunk-EHNWQ4T3.mjs} +2 -2
  18. package/dist/{chunk-KBKWVG7X.mjs → chunk-HKJTRBWC.mjs} +5 -5
  19. package/dist/{chunk-JRGCRBWE.mjs → chunk-JCLL7AGP.mjs} +63 -45
  20. package/dist/chunk-JCLL7AGP.mjs.map +1 -0
  21. package/dist/{chunk-ERV7GLY3.mjs → chunk-TVF45U7B.mjs} +5 -5
  22. package/dist/{chunk-H4PBQ5LJ.mjs → chunk-VL3CMSDO.mjs} +4 -4
  23. package/dist/cli.js +44 -44
  24. package/dist/cli.js.map +1 -1
  25. package/dist/{gateway-5yt_3QDP.d.mts → gateway-oScD5tvE.d.mts} +4 -3
  26. package/dist/{gateway-5yt_3QDP.d.ts → gateway-oScD5tvE.d.ts} +4 -3
  27. package/dist/index.d.mts +2 -2
  28. package/dist/index.d.ts +2 -2
  29. package/dist/index.js +159 -67
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +10 -10
  32. package/dist/management/management.js +159 -67
  33. package/dist/management/management.js.map +1 -1
  34. package/dist/management/management.mjs +8 -8
  35. package/dist/modals/chat-modal/chat-modal.js +53 -18
  36. package/dist/modals/chat-modal/chat-modal.js.map +1 -1
  37. package/dist/modals/chat-modal/chat-modal.mjs +5 -5
  38. package/dist/{modelStore-UMJBDSEF.mjs → modelStore-XWFHNTBT.mjs} +2 -2
  39. package/dist/public-types.d.mts +2 -1
  40. package/dist/public-types.d.ts +2 -1
  41. package/package.json +1 -1
  42. package/dist/chat-7U633EWN.mjs +0 -15
  43. package/dist/chunk-54ZQ3FSN.mjs.map +0 -1
  44. package/dist/chunk-JRGCRBWE.mjs.map +0 -1
  45. package/dist/chunk-QV4ELNLP.mjs.map +0 -1
  46. package/dist/chunk-UXE67LR7.mjs.map +0 -1
  47. package/dist/chunk-XUBYA5I7.mjs.map +0 -1
  48. /package/dist/{aiProviderStore-UQI33C5E.mjs.map → aiProviderStore-3N3VE6D4.mjs.map} +0 -0
  49. /package/dist/{chat-7U633EWN.mjs.map → chat-647M6BRG.mjs.map} +0 -0
  50. /package/dist/{chunk-RTQDQ6TC.mjs.map → chunk-EHNWQ4T3.mjs.map} +0 -0
  51. /package/dist/{chunk-KBKWVG7X.mjs.map → chunk-HKJTRBWC.mjs.map} +0 -0
  52. /package/dist/{chunk-ERV7GLY3.mjs.map → chunk-TVF45U7B.mjs.map} +0 -0
  53. /package/dist/{chunk-H4PBQ5LJ.mjs.map → chunk-VL3CMSDO.mjs.map} +0 -0
  54. /package/dist/{modelStore-UMJBDSEF.mjs.map → modelStore-XWFHNTBT.mjs.map} +0 -0
package/dist/index.mjs CHANGED
@@ -1,24 +1,24 @@
1
1
  import {
2
2
  chat_default
3
- } from "./chunk-QV4ELNLP.mjs";
3
+ } from "./chunk-7HXARU5R.mjs";
4
4
  import {
5
5
  chat_provider_default
6
- } from "./chunk-KBKWVG7X.mjs";
6
+ } from "./chunk-HKJTRBWC.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-JRGCRBWE.mjs";
14
- import "./chunk-H4PBQ5LJ.mjs";
15
- import "./chunk-RTQDQ6TC.mjs";
13
+ } from "./chunk-JCLL7AGP.mjs";
14
+ import "./chunk-VL3CMSDO.mjs";
15
+ import "./chunk-EHNWQ4T3.mjs";
16
16
  import {
17
17
  defineCustomElement
18
18
  } from "./chunk-IXIM7BNO.mjs";
19
19
  import {
20
20
  chat_modal_default
21
- } from "./chunk-ERV7GLY3.mjs";
21
+ } from "./chunk-TVF45U7B.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-SBNENBUQ.mjs";
39
+ } from "./chunk-AXFX2HUK.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-UXE67LR7.mjs";
59
+ } from "./chunk-6WZUQHZT.mjs";
60
60
  import {
61
61
  usePackageSettingsStore
62
- } from "./chunk-XUBYA5I7.mjs";
63
- import "./chunk-54ZQ3FSN.mjs";
62
+ } from "./chunk-7ZDS33S2.mjs";
63
+ import "./chunk-BENL3EF2.mjs";
64
64
  import {
65
65
  DebugLogger,
66
66
  debugLogger
@@ -1655,7 +1655,7 @@ var init_gateway_service = __esm({
1655
1655
  * Chat completion using the gateway API
1656
1656
  */
1657
1657
  chat(request) {
1658
- const endpoint = request.provider === "ollama" ? `/api/${request.provider}/chat` : request.provider ? `/api/${request.provider}/chat/completions` : "/api/chat/completions";
1658
+ const endpoint = request.provider === "ollama" ? `/api/${request.provider}/chat` : request.provider === "playground" ? "/api/playground/chat/completions" : request.provider ? `/api/${request.provider}/chat/completions` : "/api/chat/completions";
1659
1659
  const fallbackEndpoint = request.provider === "bandit" ? "/completions" : null;
1660
1660
  const normalizedModel = request.provider === "bandit" ? (() => {
1661
1661
  const trimmed = (request.model ?? "").replace(/^bandit:/, "").trim();
@@ -2626,6 +2626,9 @@ var init_gateway_provider = __esm({
2626
2626
  case "ollama":
2627
2627
  this.providerSpecificService = new OllamaGatewayService(gatewayUrl, tokenFactory);
2628
2628
  break;
2629
+ case "playground":
2630
+ this.providerSpecificService = null;
2631
+ break;
2629
2632
  default:
2630
2633
  debugLogger.warn("Unknown provider for gateway, using generic gateway service", {
2631
2634
  provider: this.config.provider
@@ -2656,7 +2659,7 @@ var init_gateway_provider = __esm({
2656
2659
  images: request.images
2657
2660
  };
2658
2661
  }
2659
- } else if (["openai", "azure-openai", "anthropic", "bandit"].includes(this.config.provider || "")) {
2662
+ } else if (["openai", "azure-openai", "anthropic", "bandit", "playground"].includes(this.config.provider || "")) {
2660
2663
  if (lastUserMessageIndex !== -1) {
2661
2664
  const currentMessage = messages[lastUserMessageIndex];
2662
2665
  const contentArray = [
@@ -2703,7 +2706,7 @@ var init_gateway_provider = __esm({
2703
2706
  stream: request.stream,
2704
2707
  hasImages: !!(request.images && request.images.length > 0),
2705
2708
  imageCount: request.images?.length || 0,
2706
- imageStrategy: this.config.provider === "ollama" ? "message-level-array" : ["openai", "azure-openai", "anthropic"].includes(this.config.provider || "") ? "structured-content" : "top-level-fallback",
2709
+ imageStrategy: this.config.provider === "ollama" ? "message-level-array" : ["openai", "azure-openai", "anthropic", "playground"].includes(this.config.provider || "") ? "structured-content" : "top-level-fallback",
2707
2710
  finalMessages: messages.map((m) => ({
2708
2711
  role: m.role,
2709
2712
  hasImages: Array.isArray(m.images) && m.images.length > 0,
@@ -6820,6 +6823,27 @@ var init_modelStore = __esm({
6820
6823
  });
6821
6824
  }
6822
6825
  }
6826
+ (async () => {
6827
+ const storeConfigs6 = [{ name: "config", keyPath: "id" }];
6828
+ try {
6829
+ const existing = await indexedDBService_default.get("banditConfig", 1, "config", "main", storeConfigs6);
6830
+ await indexedDBService_default.put(
6831
+ "banditConfig",
6832
+ 1,
6833
+ "config",
6834
+ {
6835
+ ...existing,
6836
+ id: "main",
6837
+ model: { ...existing?.model ?? {}, selectedModel: modelName }
6838
+ },
6839
+ storeConfigs6
6840
+ );
6841
+ } catch (err) {
6842
+ debugLogger.warn("setSelectedModel: failed to persist selected model", {
6843
+ error: err instanceof Error ? err.message : String(err)
6844
+ });
6845
+ }
6846
+ })();
6823
6847
  },
6824
6848
  saveModel: async () => {
6825
6849
  const state = get();
@@ -6829,7 +6853,8 @@ var init_modelStore = __esm({
6829
6853
  tagline: state.tagline,
6830
6854
  systemPrompt: state.systemPrompt,
6831
6855
  commands: state.commands,
6832
- avatarBase64: state.avatarBase64 ?? void 0
6856
+ // Ensure avatar changes are persisted even when cleared
6857
+ avatarBase64: state.avatarBase64 ?? null
6833
6858
  };
6834
6859
  await indexedDBService_default.put("banditConfig", 1, "config", { id: newModel.name, model: newModel }, storeConfigs6);
6835
6860
  const exists = state.availableModels.find((m) => m.name === newModel.name);
@@ -6856,7 +6881,12 @@ var init_modelStore = __esm({
6856
6881
  debugLogger.info("initModels: starting initialization");
6857
6882
  set({ isLoading: true, isInitializing: true });
6858
6883
  const storeConfigs6 = [{ name: "config", keyPath: "id" }];
6859
- const entries = await indexedDBService_default.getAll("banditConfig", 1, "config", storeConfigs6);
6884
+ const entries = await indexedDBService_default.getAll(
6885
+ "banditConfig",
6886
+ 1,
6887
+ "config",
6888
+ storeConfigs6
6889
+ );
6860
6890
  const mainEntry = entries.find((entry) => entry.id === "main");
6861
6891
  const modelEntries = entries.filter((entry) => entry.id !== "main" && entry.id !== "deletedModels");
6862
6892
  const deletedEntry = await indexedDBService_default.get("banditConfig", 1, "config", "deletedModels", storeConfigs6);
@@ -6866,13 +6896,14 @@ var init_modelStore = __esm({
6866
6896
  if (modelEntries.length > 0) {
6867
6897
  debugLogger.info("Loading models from IndexedDB");
6868
6898
  allModels = modelEntries.map((entry) => {
6869
- const modelData = entry.model?.name ? entry.model : entry;
6899
+ const modelData = entry.model ?? entry;
6870
6900
  return {
6871
6901
  name: modelData.name,
6872
6902
  tagline: modelData.tagline || "",
6873
6903
  systemPrompt: modelData.systemPrompt || "",
6874
6904
  commands: modelData.commands ?? [],
6875
- avatarBase64: modelData.avatarBase64 ?? null
6905
+ // Fall back to legacy top-level avatar when the nested model config omitted it
6906
+ avatarBase64: modelData.avatarBase64 ?? entry.avatarBase64 ?? null
6876
6907
  };
6877
6908
  }).filter((m) => m.name && !deletedModelNames.includes(m.name));
6878
6909
  const preferences = usePreferencesStore.getState().preferences;
@@ -8072,6 +8103,9 @@ function ensureDeviceId() {
8072
8103
  return (0, import_uuid4.v4)();
8073
8104
  }
8074
8105
  }
8106
+ function getPackageDefaultAdvancedKnowledgeSync() {
8107
+ return usePackageSettingsStore.getState().settings?.advancedKnowledgeSyncDefaultEnabled;
8108
+ }
8075
8109
  function mapConversationToDTO(conversation) {
8076
8110
  const updatedAtIso = (conversation.updatedAt ?? /* @__PURE__ */ new Date()).toISOString();
8077
8111
  const createdAtIso = conversation.createdAt ? conversation.createdAt.toISOString() : null;
@@ -8418,7 +8452,8 @@ function applyPreference(preference, set, getState, options) {
8418
8452
  const override = options?.override ?? {};
8419
8453
  const preferenceVectorFlag = preference.isAdvancedVectorFeaturesEnabled;
8420
8454
  const overrideVectorFlag = override.isAdvancedVectorFeaturesEnabled;
8421
- const resolvedVectorFlag = preferenceVectorFlag !== void 0 ? preferenceVectorFlag : overrideVectorFlag !== void 0 ? overrideVectorFlag : current.isAdvancedVectorFeaturesEnabled ?? false;
8455
+ const packageDefaultVectorFlag = getPackageDefaultAdvancedKnowledgeSync();
8456
+ const resolvedVectorFlag = preferenceVectorFlag !== void 0 ? preferenceVectorFlag : overrideVectorFlag !== void 0 ? overrideVectorFlag : packageDefaultVectorFlag !== void 0 ? packageDefaultVectorFlag : current.isAdvancedVectorFeaturesEnabled ?? false;
8422
8457
  set({
8423
8458
  syncEnabled: preference.syncEnabled,
8424
8459
  status: preference.syncEnabled ? "idle" : "disabled",
@@ -8522,7 +8557,7 @@ var init_conversationSyncStore = __esm({
8522
8557
  cursor: null,
8523
8558
  lastError: null,
8524
8559
  keepLocalOnly: false,
8525
- isAdvancedVectorFeaturesEnabled: false,
8560
+ isAdvancedVectorFeaturesEnabled: getPackageDefaultAdvancedKnowledgeSync() ?? false,
8526
8561
  conflicts: null,
8527
8562
  deviceId: ensureDeviceId(),
8528
8563
  pendingConversationUpserts: /* @__PURE__ */ new Set(),
@@ -8646,7 +8681,7 @@ var init_conversationSyncStore = __esm({
8646
8681
  await get().runSync({ force: true });
8647
8682
  }
8648
8683
  } catch (error) {
8649
- const message = error instanceof Error ? error.message : "Failed to update advanced vector setting";
8684
+ const message = error instanceof Error ? error.message : "Failed to update advanced knowledge setting";
8650
8685
  debugLogger.error("conversationSyncStore: setAdvancedVectorFeaturesEnabled failed", { error: message });
8651
8686
  set({ status: "error", lastError: message });
8652
8687
  throw error;
@@ -13974,7 +14009,7 @@ var init_memory_modal = __esm({
13974
14009
  children: [
13975
14010
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_material8.Box, { sx: { display: "flex", alignItems: "center", gap: 0.75 }, children: [
13976
14011
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_material8.Typography, { variant: "h6", sx: { fontWeight: 600 }, children: "Memory" }),
13977
- shouldUseVectorForMemories && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_material8.Tooltip, { title: "Memories are stored in an AI vector database with semantic search capabilities", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
14012
+ shouldUseVectorForMemories && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_material8.Tooltip, { title: "Memories stay in your private knowledge space for faster, more accurate answers.", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
13978
14013
  import_material8.Typography,
13979
14014
  {
13980
14015
  variant: "caption",
@@ -13989,7 +14024,7 @@ var init_memory_modal = __esm({
13989
14024
  textTransform: "uppercase",
13990
14025
  cursor: "help"
13991
14026
  },
13992
- children: "Vector"
14027
+ children: "Synced"
13993
14028
  }
13994
14029
  ) })
13995
14030
  ] }),
@@ -14088,7 +14123,7 @@ var init_memory_modal = __esm({
14088
14123
  onClick: () => setBulkImportOpen(true),
14089
14124
  startIcon: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_CloudSync.default, {}),
14090
14125
  sx: { textTransform: "none", borderRadius: 2, fontSize: "0.75rem" },
14091
- children: "Import to Vector"
14126
+ children: "Import to workspace"
14092
14127
  }
14093
14128
  ),
14094
14129
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
@@ -14330,7 +14365,7 @@ var init_memory_modal = __esm({
14330
14365
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_material8.Typography, { variant: "body2", sx: {
14331
14366
  color: (0, import_styles3.alpha)(theme.palette.text.secondary, 0.7),
14332
14367
  maxWidth: 280
14333
- }, children: selectedTab === "user" ? shouldUseVectorForMemories ? "Start by adding something you'd like me to remember. Your memories will be stored in the AI vector database for intelligent retrieval." : "Start by adding something you'd like me to remember about you or your preferences." : shouldUseVectorForMemories ? "Auto memories are created automatically based on our conversations and stored in the vector database for semantic search." : "Auto memories are created automatically based on our conversations." })
14368
+ }, children: selectedTab === "user" ? shouldUseVectorForMemories ? "Start by adding something you'd like me to remember. Your memories will be kept in a private workspace for quick recall." : "Start by adding something you'd like me to remember about you or your preferences." : shouldUseVectorForMemories ? "Auto memories are created automatically based on our conversations and kept in your private workspace for better answers." : "Auto memories are created automatically based on our conversations." })
14334
14369
  ] }) : filteredMemories.map((memory) => {
14335
14370
  const isSelected = selectedIds.includes(memory.id);
14336
14371
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react14.default.Fragment, { children: [
@@ -14602,7 +14637,7 @@ var init_memory_modal = __esm({
14602
14637
  size: "small",
14603
14638
  value: newMemory,
14604
14639
  onChange: (e) => setNewMemory(e.target.value),
14605
- placeholder: shouldUseVectorForMemories ? `Add a new ${selectedTab} memory to vector database...` : `Add a new ${selectedTab} memory...`,
14640
+ placeholder: shouldUseVectorForMemories ? `Add a new ${selectedTab} memory to your workspace...` : `Add a new ${selectedTab} memory...`,
14606
14641
  onKeyDown: (e) => {
14607
14642
  if (e.key === "Enter" && !e.shiftKey && newMemory.trim()) {
14608
14643
  e.preventDefault();
@@ -14842,15 +14877,15 @@ var init_memory_modal = __esm({
14842
14877
  gap: 1
14843
14878
  }, children: [
14844
14879
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_CloudSync.default, { color: "primary" }),
14845
- "Import Memories to Vector Database"
14880
+ "Import Memories to Secure Workspace"
14846
14881
  ] }),
14847
14882
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_material8.DialogContent, { sx: { py: 2 }, children: !importProgress.isImporting ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_material8.Box, { children: [
14848
14883
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_material8.Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: [
14849
14884
  "This will import all your local memories (",
14850
14885
  entries.length,
14851
- " memories) to the vector database for enhanced semantic search capabilities."
14886
+ " memories) to your secure workspace for faster, more reliable answers."
14852
14887
  ] }),
14853
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_material8.Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: "\u2022 Memories will be added to your vector storage \u2022 Local memories will remain unchanged \u2022 You can switch between local and vector storage anytime" }),
14888
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_material8.Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: "\u2022 Memories will be added to your synced workspace \u2022 Local memories will remain unchanged \u2022 You can switch between synced and local storage anytime" }),
14854
14889
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_material8.Typography, { variant: "body2", color: "primary", sx: { fontWeight: 500 }, children: [
14855
14890
  "Ready to import ",
14856
14891
  entries.length,
@@ -19168,6 +19203,7 @@ var init_custom_logo = __esm({
19168
19203
  init_chat();
19169
19204
  init_brandingService();
19170
19205
  init_debugLogger();
19206
+ init_util();
19171
19207
  import_jsx_runtime26 = require("react/jsx-runtime");
19172
19208
  Logo = ({ visible, atTop = false }) => {
19173
19209
  const theme = (0, import_styles19.useTheme)();
@@ -19181,7 +19217,20 @@ var init_custom_logo = __esm({
19181
19217
  const brandingData = await brandingService_default.getBranding();
19182
19218
  if (brandingData) {
19183
19219
  setLogoBase64(brandingData.logoBase64 || null);
19184
- setHasTransparentLogo(brandingData.hasTransparentLogo ?? true);
19220
+ if (brandingData.logoBase64) {
19221
+ try {
19222
+ const detected = await detectTransparency(brandingData.logoBase64);
19223
+ const isPng = brandingData.logoBase64.startsWith("data:image/png");
19224
+ const finalTransparent = detected || isPng || brandingData.hasTransparentLogo === true;
19225
+ setHasTransparentLogo(finalTransparent);
19226
+ } catch {
19227
+ const isPng = brandingData.logoBase64.startsWith("data:image/png");
19228
+ const finalTransparent = brandingData.hasTransparentLogo === true || isPng;
19229
+ setHasTransparentLogo(finalTransparent);
19230
+ }
19231
+ } else {
19232
+ setHasTransparentLogo(brandingData.hasTransparentLogo ?? true);
19233
+ }
19185
19234
  }
19186
19235
  } catch (e) {
19187
19236
  debugLogger.error("Failed to load branding from service", { error: e });
@@ -19191,7 +19240,7 @@ var init_custom_logo = __esm({
19191
19240
  };
19192
19241
  loadBranding();
19193
19242
  }, []);
19194
- return logoBase64 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_jsx_runtime26.Fragment, { children: loading ? null : hasTransparentLogo ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
19243
+ return logoBase64 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_jsx_runtime26.Fragment, { children: loading ? null : hasTransparentLogo !== false ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
19195
19244
  import_material27.Box,
19196
19245
  {
19197
19246
  component: "img",
@@ -19203,7 +19252,8 @@ var init_custom_logo = __esm({
19203
19252
  maxWidth: 600,
19204
19253
  aspectRatio: "1 / 1",
19205
19254
  margin: "0 auto",
19206
- mt: atTop ? 2 : 6
19255
+ mt: atTop ? 2 : 6,
19256
+ display: "block"
19207
19257
  }
19208
19258
  }
19209
19259
  ) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
@@ -19245,8 +19295,8 @@ var init_chat_scroll_to_bottom_button = __esm({
19245
19295
  drawerOpen = false,
19246
19296
  isMobile = false
19247
19297
  }) => {
19248
- const verticalBuffer = isMobile ? 36 : 56;
19249
- const bottomOffset = Math.max(inputHeight + verticalBuffer, verticalBuffer + 72);
19298
+ const verticalBuffer = isMobile ? 28 : 48;
19299
+ const bottomOffset = Math.max(inputHeight + verticalBuffer, verticalBuffer + 64);
19250
19300
  return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
19251
19301
  import_material28.IconButton,
19252
19302
  {
@@ -19262,9 +19312,12 @@ var init_chat_scroll_to_bottom_button = __esm({
19262
19312
  borderColor: (theme) => theme.palette.divider,
19263
19313
  zIndex: (theme) => Math.max(theme.zIndex.modal + 1, 1400),
19264
19314
  boxShadow: 3,
19265
- transition: "bottom 0.3s ease, left 0.3s ease-in-out",
19315
+ transition: "bottom 0.25s ease, left 0.3s ease-in-out, transform 0.2s ease",
19266
19316
  "&:hover": {
19267
19317
  bgcolor: (theme) => theme.palette.action.hover
19318
+ },
19319
+ "&:active": {
19320
+ transform: "translateX(-50%) translateY(1px)"
19268
19321
  }
19269
19322
  },
19270
19323
  children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ArrowDownward.default, { sx: { color: "inherit" } })
@@ -26441,9 +26494,18 @@ var init_chat_app_bar = __esm({
26441
26494
  const currentModel = useModelStore((s) => s.availableModels.find((m) => m.name === selectedModel));
26442
26495
  const currentAvatar = currentModel?.avatarBase64 || modelAvatars3[selectedModel] || banditHead5;
26443
26496
  const pendingModelAvatar = useModelStore.getState().availableModels.find((m) => m.name === pendingModel)?.avatarBase64 || modelAvatars3[pendingModel || ""] || banditHead5;
26497
+ const resolvedHomeUrl = preferences.homeUrl?.trim() || packageSettings?.homeUrl?.trim() || "";
26498
+ const homeTooltip = (() => {
26499
+ if (!resolvedHomeUrl) return "Home";
26500
+ try {
26501
+ return `Home (${new URL(resolvedHomeUrl).hostname})`;
26502
+ } catch {
26503
+ return "Home";
26504
+ }
26505
+ })();
26444
26506
  function goToHome() {
26445
- if (preferences.homeUrl && preferences.homeUrl.trim()) {
26446
- window.location.href = preferences.homeUrl;
26507
+ if (resolvedHomeUrl) {
26508
+ window.location.href = resolvedHomeUrl;
26447
26509
  return;
26448
26510
  }
26449
26511
  if (typeof window !== "undefined") {
@@ -26506,7 +26568,7 @@ var init_chat_app_bar = __esm({
26506
26568
  }
26507
26569
  },
26508
26570
  children: [
26509
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_material40.Tooltip, { title: preferences.homeUrl && preferences.homeUrl.trim() ? `Home (${new URL(preferences.homeUrl).hostname})` : "Home", arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
26571
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_material40.Tooltip, { title: homeTooltip, arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
26510
26572
  import_material40.IconButton,
26511
26573
  {
26512
26574
  onClick: goToHome,
@@ -26790,9 +26852,15 @@ var init_chat_app_bar = __esm({
26790
26852
  (async () => {
26791
26853
  try {
26792
26854
  const storeConfigs6 = [{ name: "config", keyPath: "id" }];
26793
- const current = await indexedDBService_default.get("banditConfig", 1, "config", "main", storeConfigs6);
26855
+ const current = await indexedDBService_default.get(
26856
+ "banditConfig",
26857
+ 1,
26858
+ "config",
26859
+ "main",
26860
+ storeConfigs6
26861
+ );
26794
26862
  const updated = {
26795
- ...current,
26863
+ ...current ?? {},
26796
26864
  id: "main",
26797
26865
  model: {
26798
26866
  ...current?.model || {},
@@ -26984,9 +27052,15 @@ var init_chat_app_bar = __esm({
26984
27052
  (async () => {
26985
27053
  try {
26986
27054
  const storeConfigs6 = [{ name: "config", keyPath: "id" }];
26987
- const current = await indexedDBService_default.get("banditConfig", 1, "config", "main", storeConfigs6);
27055
+ const current = await indexedDBService_default.get(
27056
+ "banditConfig",
27057
+ 1,
27058
+ "config",
27059
+ "main",
27060
+ storeConfigs6
27061
+ );
26988
27062
  const updated = {
26989
- ...current,
27063
+ ...current ?? {},
26990
27064
  id: "main",
26991
27065
  model: {
26992
27066
  ...current?.model || {},
@@ -33771,7 +33845,7 @@ var PreferencesTab = ({
33771
33845
  await setAdvancedVectorFeaturesEnabled(enabled);
33772
33846
  if (showSnackbar) {
33773
33847
  showSnackbar(
33774
- enabled ? "Advanced vector features enabled for this account." : "Advanced vector features disabled.",
33848
+ enabled ? "Advanced knowledge sync enabled for this account." : "Advanced knowledge sync disabled.",
33775
33849
  "success"
33776
33850
  );
33777
33851
  }
@@ -34056,8 +34130,8 @@ var PreferencesTab = ({
34056
34130
  }
34057
34131
  ),
34058
34132
  label: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material19.Box, { textAlign: "left", children: [
34059
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material19.Typography, { variant: "body1", sx: { fontWeight: 600, color: "text.primary" }, children: "Advanced vector features" }),
34060
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material19.Typography, { variant: "body2", color: "text.secondary", children: "Keep semantic search, vector memories, and related context in sync across devices" })
34133
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material19.Typography, { variant: "body1", sx: { fontWeight: 600, color: "text.primary" }, children: "Advanced knowledge sync" }),
34134
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material19.Typography, { variant: "body2", color: "text.secondary", children: "Keep richer search, saved memories, and context in sync across devices" })
34061
34135
  ] }),
34062
34136
  sx: { alignSelf: { xs: "flex-start", sm: "center" } }
34063
34137
  }
@@ -34627,6 +34701,7 @@ var LogoCropper = ({
34627
34701
  canvas.width = outputWidth;
34628
34702
  canvas.height = outputHeight;
34629
34703
  ctx.save();
34704
+ ctx.clearRect(0, 0, outputWidth, outputHeight);
34630
34705
  const scaleX = outputWidth / cropDims.width;
34631
34706
  const scaleY = outputHeight / cropDims.height;
34632
34707
  ctx.translate(outputWidth / 2, outputHeight / 2);
@@ -35667,30 +35742,29 @@ var defaultSteps = [
35667
35742
  },
35668
35743
  {
35669
35744
  id: "embed",
35670
- title: "Creating Vectors",
35671
- description: "Neural networks are encoding knowledge into searchable vectors...",
35745
+ title: "Making It Searchable",
35746
+ description: "We turn the content into a private, searchable index...",
35672
35747
  icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons_material4.Memory, {}),
35673
35748
  duration: 10
35674
35749
  },
35675
35750
  {
35676
35751
  id: "optimize",
35677
35752
  title: "Optimizing Search",
35678
- description: "AI algorithms are organizing data for lightning-fast retrieval...",
35753
+ description: "Organizing everything for quick, reliable answers...",
35679
35754
  icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons_material4.AutoAwesome, {}),
35680
35755
  duration: 8
35681
35756
  }
35682
35757
  ];
35683
35758
  var cleverMessages = [
35684
- "\u{1F977} Digital ninjas are working their magic...",
35685
- "\u{1F916} AI robots are crunching your data...",
35686
- "\u26A1 Neural networks firing at maximum capacity...",
35687
- "\u{1F9E0} Machine learning models deep in thought...",
35688
- "\u{1F52E} AI wizards casting knowledge spells...",
35689
- "\u2699\uFE0F Quantum processors spinning up...",
35690
- "\u{1F680} Algorithms achieving warp speed...",
35691
- "\u{1F4AB} Creating digital memories from your content...",
35692
- "\u{1F3AF} Precision-targeting knowledge patterns...",
35693
- "\u{1F31F} Transforming text into searchable stardust..."
35759
+ "\u{1F977} Keeping your content safe while we set things up...",
35760
+ "\u{1F916} Getting everything ready for fast answers...",
35761
+ "\u26A1 Tidying the data so responses stay consistent...",
35762
+ "\u{1F9E0} Remembering the important parts for you...",
35763
+ "\u{1F512} Locking in privacy before we share results...",
35764
+ "\u{1F680} Optimizing for quick, reliable lookups...",
35765
+ "\u{1F4AB} Turning this into searchable knowledge...",
35766
+ "\u{1F3AF} Focusing on the details that matter to you...",
35767
+ "\u{1F31F} Making sure it stays available when you need it..."
35694
35768
  ];
35695
35769
  var ProcessingOverlay = ({
35696
35770
  open,
@@ -36279,16 +36353,16 @@ var KnowledgeTab = ({
36279
36353
  const handleDocumentUpload = async (files) => {
36280
36354
  if (shouldUseVector) {
36281
36355
  showProcessing(
36282
- "Uploading to Vector Database",
36356
+ "Uploading to Secure Workspace",
36283
36357
  [
36284
- "\u{1F977} Digital ninjas securing your documents...",
36285
- "\u{1F916} AI robots reading and understanding content...",
36286
- "\u26A1 Neural networks encoding knowledge vectors...",
36287
- "\u{1F9E0} Machine learning creating searchable memories...",
36288
- "\u{1F52E} AI wizards optimizing semantic search...",
36289
- "\u{1F680} Vector embeddings achieving light speed...",
36290
- "\u{1F4AB} Transforming documents into intelligent data...",
36291
- "\u{1F3AF} Precision-targeting knowledge patterns..."
36358
+ "\u{1F977} Keeping your documents private while we prepare them...",
36359
+ "\u{1F916} Reading the content so answers stay accurate...",
36360
+ "\u26A1 Turning pages into a searchable index...",
36361
+ "\u{1F9E0} Remembering highlights for quick recall...",
36362
+ "\u{1F52E} Organizing everything so search feels instant...",
36363
+ "\u{1F680} Optimizing for fast, consistent responses...",
36364
+ "\u{1F4AB} Transforming documents into trusted knowledge...",
36365
+ "\u{1F3AF} Focusing on the details that matter most..."
36292
36366
  ]
36293
36367
  );
36294
36368
  try {
@@ -36362,7 +36436,7 @@ var KnowledgeTab = ({
36362
36436
  progress: 100,
36363
36437
  status: "success"
36364
36438
  })));
36365
- const message = result.usedVector ? `Successfully uploaded ${files.length} document(s) to vector database` : result.error ? `Upload completed with warnings: ${result.error}` : `Successfully uploaded ${files.length} document(s)`;
36439
+ const message = result.usedVector ? `Successfully uploaded ${files.length} document(s) to your secure workspace` : result.error ? `Upload completed with warnings: ${result.error}` : `Successfully uploaded ${files.length} document(s)`;
36366
36440
  setSnackbarMessage(message);
36367
36441
  setSnackbarSeverity(result.error ? "warning" : "success");
36368
36442
  setShowSnackbar(true);
@@ -36423,7 +36497,7 @@ var KnowledgeTab = ({
36423
36497
  progress: 100,
36424
36498
  status: "success"
36425
36499
  })));
36426
- const message = result.usedVector ? `Successfully uploaded ${files.length} document(s) to vector database` : result.error ? `Upload completed with warnings: ${result.error}` : `Successfully uploaded ${files.length} document(s)`;
36500
+ const message = result.usedVector ? `Successfully uploaded ${files.length} document(s) to your secure workspace` : result.error ? `Upload completed with warnings: ${result.error}` : `Successfully uploaded ${files.length} document(s)`;
36427
36501
  setSnackbarMessage(message);
36428
36502
  setSnackbarSeverity(result.error ? "warning" : "success");
36429
36503
  setShowSnackbar(true);
@@ -36601,7 +36675,7 @@ var KnowledgeTab = ({
36601
36675
  shouldUseVector && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
36602
36676
  import_material23.Chip,
36603
36677
  {
36604
- label: "Vector DB",
36678
+ label: "Synced",
36605
36679
  color: "primary",
36606
36680
  size: "small",
36607
36681
  sx: { ml: 1 }
@@ -36618,7 +36692,7 @@ var KnowledgeTab = ({
36618
36692
  sx: { fontSize: { xs: "0.95rem", sm: "1rem" }, lineHeight: 1.5 },
36619
36693
  children: [
36620
36694
  "Add documents to your private knowledge base. Files are securely stored ",
36621
- shouldUseVector ? "in the vector database" : "locally in your browser",
36695
+ shouldUseVector ? "in your private workspace" : "locally in your browser",
36622
36696
  "."
36623
36697
  ]
36624
36698
  }
@@ -36954,7 +37028,7 @@ var KnowledgeTab = ({
36954
37028
  filteredAndSortedDocuments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material23.Card, { sx: { textAlign: "center", py: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_material23.CardContent, { children: [
36955
37029
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Folder.default, { sx: { fontSize: 64, color: "text.secondary", mb: 2 } }),
36956
37030
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material23.Typography, { variant: "h6", color: "text.secondary", gutterBottom: true, children: "No Documents Yet" }),
36957
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material23.Typography, { variant: "body2", color: "text.secondary", children: shouldUseVector ? "Upload and embed your first document to get started with advanced vector search" : "Upload your first document to get started" })
37031
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material23.Typography, { variant: "body2", color: "text.secondary", children: shouldUseVector ? "Upload and embed your first document to get started with advanced search" : "Upload your first document to get started" })
36958
37032
  ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_material23.Box, { children: [
36959
37033
  /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_material23.Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: [
36960
37034
  "Showing ",
@@ -36963,7 +37037,7 @@ var KnowledgeTab = ({
36963
37037
  shouldUseVector ? vectorDocuments.length : documents.length,
36964
37038
  " documents",
36965
37039
  searchQuery && ` for "${searchQuery}"`,
36966
- shouldUseVector && ` (Vector Database)`
37040
+ shouldUseVector && ` (Synced workspace)`
36967
37041
  ] }),
36968
37042
  viewMode === "grid" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
36969
37043
  import_material23.Box,
@@ -39750,6 +39824,7 @@ var Management = () => {
39750
39824
  name: modelToSave.name,
39751
39825
  tagline: modelToSave.tagline,
39752
39826
  systemPrompt: modelToSave.systemPrompt,
39827
+ avatarBase64: modelToSave.avatarBase64 || void 0,
39753
39828
  selectedModel: modelToSave.name
39754
39829
  }
39755
39830
  };
@@ -39802,6 +39877,19 @@ var Management = () => {
39802
39877
  try {
39803
39878
  const storeConfigs6 = [{ name: "config", keyPath: "id" }];
39804
39879
  debugLogger.info("Saving branding data to IndexedDB");
39880
+ let finalHasTransparentLogo = hasTransparentLogo;
39881
+ if (logoBase64) {
39882
+ try {
39883
+ const detected = await detectTransparency(logoBase64);
39884
+ const isPng = logoBase64.startsWith("data:image/png");
39885
+ finalHasTransparentLogo = detected || isPng;
39886
+ debugLogger.debug("SaveBranding transparency check", { detected, isPng, finalHasTransparentLogo });
39887
+ } catch (err) {
39888
+ const isPng = logoBase64.startsWith("data:image/png");
39889
+ finalHasTransparentLogo = finalHasTransparentLogo ?? isPng ?? true;
39890
+ debugLogger.warn("SaveBranding transparency check failed, using fallback", { error: err, finalHasTransparentLogo });
39891
+ }
39892
+ }
39805
39893
  const current = await indexedDBService_default.get(
39806
39894
  "banditConfig",
39807
39895
  1,
@@ -39817,7 +39905,7 @@ var Management = () => {
39817
39905
  logoBase64,
39818
39906
  brandingText,
39819
39907
  theme,
39820
- hasTransparentLogo,
39908
+ hasTransparentLogo: finalHasTransparentLogo,
39821
39909
  userSaved: true
39822
39910
  // Mark as user-saved to protect from CDN overrides
39823
39911
  }
@@ -39856,9 +39944,11 @@ var Management = () => {
39856
39944
  setLogoBase64(base64);
39857
39945
  debugLogger.debug("Starting transparency detection for uploaded image");
39858
39946
  try {
39947
+ const isPng = base64.startsWith("data:image/png");
39859
39948
  const isTransparent = await detectTransparency(base64);
39860
- setHasTransparentLogo(isTransparent);
39861
- debugLogger.debug("Transparency detection result saved", { isTransparent });
39949
+ const finalTransparent = isTransparent || isPng;
39950
+ setHasTransparentLogo(finalTransparent);
39951
+ debugLogger.debug("Transparency detection result saved", { isTransparent, finalTransparent });
39862
39952
  } catch (err) {
39863
39953
  debugLogger.error("Failed to detect transparency", { error: err });
39864
39954
  }
@@ -40071,7 +40161,8 @@ var Management = () => {
40071
40161
  name: modelName2,
40072
40162
  tagline: typeof parsedModel.tagline === "string" ? parsedModel.tagline : void 0,
40073
40163
  systemPrompt: typeof parsedModel.systemPrompt === "string" ? parsedModel.systemPrompt : void 0,
40074
- selectedModel: typeof parsedModel.selectedModel === "string" ? parsedModel.selectedModel : void 0
40164
+ selectedModel: typeof parsedModel.selectedModel === "string" ? parsedModel.selectedModel : void 0,
40165
+ avatarBase64: typeof parsedModel.avatarBase64 === "string" ? parsedModel.avatarBase64 : parsedModel.avatarBase64 === null ? void 0 : void 0
40075
40166
  };
40076
40167
  const entry = {
40077
40168
  id: modelName2,
@@ -40079,7 +40170,8 @@ var Management = () => {
40079
40170
  name: modelName2,
40080
40171
  tagline: sanitizedModel.tagline,
40081
40172
  systemPrompt: sanitizedModel.systemPrompt,
40082
- avatarBase64: typeof parsedModel.avatarBase64 === "string" ? parsedModel.avatarBase64 : void 0
40173
+ // Normalize to match StoredBanditConfigRecord (string | undefined)
40174
+ avatarBase64: sanitizedModel.avatarBase64 ?? void 0
40083
40175
  };
40084
40176
  await indexedDBService_default.put("banditConfig", 1, "config", entry, storeConfigs6);
40085
40177
  }