@burtson-labs/bandit-engine 2.0.42 → 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-EOEI74X4.mjs → chunk-7HXARU5R.mjs} +101 -37
  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-4RCAVVDN.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 +45 -45
  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 +199 -76
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +10 -10
  32. package/dist/management/management.js +199 -76
  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 +2 -2
  42. package/dist/chat-XDC4SNJF.mjs +0 -15
  43. package/dist/chunk-4RCAVVDN.mjs.map +0 -1
  44. package/dist/chunk-54ZQ3FSN.mjs.map +0 -1
  45. package/dist/chunk-EOEI74X4.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-XDC4SNJF.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.js CHANGED
@@ -859,6 +859,27 @@ var init_modelStore = __esm({
859
859
  });
860
860
  }
861
861
  }
862
+ (async () => {
863
+ const storeConfigs6 = [{ name: "config", keyPath: "id" }];
864
+ try {
865
+ const existing = await indexedDBService_default.get("banditConfig", 1, "config", "main", storeConfigs6);
866
+ await indexedDBService_default.put(
867
+ "banditConfig",
868
+ 1,
869
+ "config",
870
+ {
871
+ ...existing,
872
+ id: "main",
873
+ model: { ...existing?.model ?? {}, selectedModel: modelName }
874
+ },
875
+ storeConfigs6
876
+ );
877
+ } catch (err) {
878
+ debugLogger.warn("setSelectedModel: failed to persist selected model", {
879
+ error: err instanceof Error ? err.message : String(err)
880
+ });
881
+ }
882
+ })();
862
883
  },
863
884
  saveModel: async () => {
864
885
  const state = get();
@@ -868,7 +889,8 @@ var init_modelStore = __esm({
868
889
  tagline: state.tagline,
869
890
  systemPrompt: state.systemPrompt,
870
891
  commands: state.commands,
871
- avatarBase64: state.avatarBase64 ?? void 0
892
+ // Ensure avatar changes are persisted even when cleared
893
+ avatarBase64: state.avatarBase64 ?? null
872
894
  };
873
895
  await indexedDBService_default.put("banditConfig", 1, "config", { id: newModel.name, model: newModel }, storeConfigs6);
874
896
  const exists = state.availableModels.find((m) => m.name === newModel.name);
@@ -895,7 +917,12 @@ var init_modelStore = __esm({
895
917
  debugLogger.info("initModels: starting initialization");
896
918
  set({ isLoading: true, isInitializing: true });
897
919
  const storeConfigs6 = [{ name: "config", keyPath: "id" }];
898
- const entries = await indexedDBService_default.getAll("banditConfig", 1, "config", storeConfigs6);
920
+ const entries = await indexedDBService_default.getAll(
921
+ "banditConfig",
922
+ 1,
923
+ "config",
924
+ storeConfigs6
925
+ );
899
926
  const mainEntry = entries.find((entry) => entry.id === "main");
900
927
  const modelEntries = entries.filter((entry) => entry.id !== "main" && entry.id !== "deletedModels");
901
928
  const deletedEntry = await indexedDBService_default.get("banditConfig", 1, "config", "deletedModels", storeConfigs6);
@@ -905,13 +932,14 @@ var init_modelStore = __esm({
905
932
  if (modelEntries.length > 0) {
906
933
  debugLogger.info("Loading models from IndexedDB");
907
934
  allModels = modelEntries.map((entry) => {
908
- const modelData = entry.model?.name ? entry.model : entry;
935
+ const modelData = entry.model ?? entry;
909
936
  return {
910
937
  name: modelData.name,
911
938
  tagline: modelData.tagline || "",
912
939
  systemPrompt: modelData.systemPrompt || "",
913
940
  commands: modelData.commands ?? [],
914
- avatarBase64: modelData.avatarBase64 ?? null
941
+ // Fall back to legacy top-level avatar when the nested model config omitted it
942
+ avatarBase64: modelData.avatarBase64 ?? entry.avatarBase64 ?? null
915
943
  };
916
944
  }).filter((m) => m.name && !deletedModelNames.includes(m.name));
917
945
  const preferences = usePreferencesStore.getState().preferences;
@@ -2140,6 +2168,9 @@ function ensureDeviceId() {
2140
2168
  return (0, import_uuid3.v4)();
2141
2169
  }
2142
2170
  }
2171
+ function getPackageDefaultAdvancedKnowledgeSync() {
2172
+ return usePackageSettingsStore.getState().settings?.advancedKnowledgeSyncDefaultEnabled;
2173
+ }
2143
2174
  function mapConversationToDTO(conversation) {
2144
2175
  const updatedAtIso = (conversation.updatedAt ?? /* @__PURE__ */ new Date()).toISOString();
2145
2176
  const createdAtIso = conversation.createdAt ? conversation.createdAt.toISOString() : null;
@@ -2486,7 +2517,8 @@ function applyPreference(preference, set, getState, options) {
2486
2517
  const override = options?.override ?? {};
2487
2518
  const preferenceVectorFlag = preference.isAdvancedVectorFeaturesEnabled;
2488
2519
  const overrideVectorFlag = override.isAdvancedVectorFeaturesEnabled;
2489
- const resolvedVectorFlag = preferenceVectorFlag !== void 0 ? preferenceVectorFlag : overrideVectorFlag !== void 0 ? overrideVectorFlag : current.isAdvancedVectorFeaturesEnabled ?? false;
2520
+ const packageDefaultVectorFlag = getPackageDefaultAdvancedKnowledgeSync();
2521
+ const resolvedVectorFlag = preferenceVectorFlag !== void 0 ? preferenceVectorFlag : overrideVectorFlag !== void 0 ? overrideVectorFlag : packageDefaultVectorFlag !== void 0 ? packageDefaultVectorFlag : current.isAdvancedVectorFeaturesEnabled ?? false;
2490
2522
  set({
2491
2523
  syncEnabled: preference.syncEnabled,
2492
2524
  status: preference.syncEnabled ? "idle" : "disabled",
@@ -2590,7 +2622,7 @@ var init_conversationSyncStore = __esm({
2590
2622
  cursor: null,
2591
2623
  lastError: null,
2592
2624
  keepLocalOnly: false,
2593
- isAdvancedVectorFeaturesEnabled: false,
2625
+ isAdvancedVectorFeaturesEnabled: getPackageDefaultAdvancedKnowledgeSync() ?? false,
2594
2626
  conflicts: null,
2595
2627
  deviceId: ensureDeviceId(),
2596
2628
  pendingConversationUpserts: /* @__PURE__ */ new Set(),
@@ -2714,7 +2746,7 @@ var init_conversationSyncStore = __esm({
2714
2746
  await get().runSync({ force: true });
2715
2747
  }
2716
2748
  } catch (error) {
2717
- const message = error instanceof Error ? error.message : "Failed to update advanced vector setting";
2749
+ const message = error instanceof Error ? error.message : "Failed to update advanced knowledge setting";
2718
2750
  debugLogger.error("conversationSyncStore: setAdvancedVectorFeaturesEnabled failed", { error: message });
2719
2751
  set({ status: "error", lastError: message });
2720
2752
  throw error;
@@ -4467,7 +4499,7 @@ var init_gateway_service = __esm({
4467
4499
  * Chat completion using the gateway API
4468
4500
  */
4469
4501
  chat(request) {
4470
- const endpoint = request.provider === "ollama" ? `/api/${request.provider}/chat` : request.provider ? `/api/${request.provider}/chat/completions` : "/api/chat/completions";
4502
+ 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";
4471
4503
  const fallbackEndpoint = request.provider === "bandit" ? "/completions" : null;
4472
4504
  const normalizedModel = request.provider === "bandit" ? (() => {
4473
4505
  const trimmed = (request.model ?? "").replace(/^bandit:/, "").trim();
@@ -5438,6 +5470,9 @@ var init_gateway_provider = __esm({
5438
5470
  case "ollama":
5439
5471
  this.providerSpecificService = new OllamaGatewayService(gatewayUrl, tokenFactory);
5440
5472
  break;
5473
+ case "playground":
5474
+ this.providerSpecificService = null;
5475
+ break;
5441
5476
  default:
5442
5477
  debugLogger.warn("Unknown provider for gateway, using generic gateway service", {
5443
5478
  provider: this.config.provider
@@ -5468,7 +5503,7 @@ var init_gateway_provider = __esm({
5468
5503
  images: request.images
5469
5504
  };
5470
5505
  }
5471
- } else if (["openai", "azure-openai", "anthropic", "bandit"].includes(this.config.provider || "")) {
5506
+ } else if (["openai", "azure-openai", "anthropic", "bandit", "playground"].includes(this.config.provider || "")) {
5472
5507
  if (lastUserMessageIndex !== -1) {
5473
5508
  const currentMessage = messages[lastUserMessageIndex];
5474
5509
  const contentArray = [
@@ -5515,7 +5550,7 @@ var init_gateway_provider = __esm({
5515
5550
  stream: request.stream,
5516
5551
  hasImages: !!(request.images && request.images.length > 0),
5517
5552
  imageCount: request.images?.length || 0,
5518
- imageStrategy: this.config.provider === "ollama" ? "message-level-array" : ["openai", "azure-openai", "anthropic"].includes(this.config.provider || "") ? "structured-content" : "top-level-fallback",
5553
+ imageStrategy: this.config.provider === "ollama" ? "message-level-array" : ["openai", "azure-openai", "anthropic", "playground"].includes(this.config.provider || "") ? "structured-content" : "top-level-fallback",
5519
5554
  finalMessages: messages.map((m) => ({
5520
5555
  role: m.role,
5521
5556
  hasImages: Array.isArray(m.images) && m.images.length > 0,
@@ -10549,6 +10584,7 @@ var init_custom_logo = __esm({
10549
10584
  init_chat();
10550
10585
  init_brandingService();
10551
10586
  init_debugLogger();
10587
+ init_util();
10552
10588
  import_jsx_runtime4 = require("react/jsx-runtime");
10553
10589
  Logo = ({ visible, atTop = false }) => {
10554
10590
  const theme = (0, import_styles.useTheme)();
@@ -10562,7 +10598,20 @@ var init_custom_logo = __esm({
10562
10598
  const brandingData = await brandingService_default.getBranding();
10563
10599
  if (brandingData) {
10564
10600
  setLogoBase64(brandingData.logoBase64 || null);
10565
- setHasTransparentLogo(brandingData.hasTransparentLogo ?? true);
10601
+ if (brandingData.logoBase64) {
10602
+ try {
10603
+ const detected = await detectTransparency(brandingData.logoBase64);
10604
+ const isPng = brandingData.logoBase64.startsWith("data:image/png");
10605
+ const finalTransparent = detected || isPng || brandingData.hasTransparentLogo === true;
10606
+ setHasTransparentLogo(finalTransparent);
10607
+ } catch {
10608
+ const isPng = brandingData.logoBase64.startsWith("data:image/png");
10609
+ const finalTransparent = brandingData.hasTransparentLogo === true || isPng;
10610
+ setHasTransparentLogo(finalTransparent);
10611
+ }
10612
+ } else {
10613
+ setHasTransparentLogo(brandingData.hasTransparentLogo ?? true);
10614
+ }
10566
10615
  }
10567
10616
  } catch (e) {
10568
10617
  debugLogger.error("Failed to load branding from service", { error: e });
@@ -10572,7 +10621,7 @@ var init_custom_logo = __esm({
10572
10621
  };
10573
10622
  loadBranding();
10574
10623
  }, []);
10575
- return logoBase64 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: loading ? null : hasTransparentLogo ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
10624
+ return logoBase64 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: loading ? null : hasTransparentLogo !== false ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
10576
10625
  import_material2.Box,
10577
10626
  {
10578
10627
  component: "img",
@@ -10584,7 +10633,8 @@ var init_custom_logo = __esm({
10584
10633
  maxWidth: 600,
10585
10634
  aspectRatio: "1 / 1",
10586
10635
  margin: "0 auto",
10587
- mt: atTop ? 2 : 6
10636
+ mt: atTop ? 2 : 6,
10637
+ display: "block"
10588
10638
  }
10589
10639
  }
10590
10640
  ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
@@ -10626,8 +10676,8 @@ var init_chat_scroll_to_bottom_button = __esm({
10626
10676
  drawerOpen = false,
10627
10677
  isMobile = false
10628
10678
  }) => {
10629
- const verticalBuffer = isMobile ? 36 : 56;
10630
- const bottomOffset = Math.max(inputHeight + verticalBuffer, verticalBuffer + 72);
10679
+ const verticalBuffer = isMobile ? 28 : 48;
10680
+ const bottomOffset = Math.max(inputHeight + verticalBuffer, verticalBuffer + 64);
10631
10681
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
10632
10682
  import_material3.IconButton,
10633
10683
  {
@@ -10643,9 +10693,12 @@ var init_chat_scroll_to_bottom_button = __esm({
10643
10693
  borderColor: (theme) => theme.palette.divider,
10644
10694
  zIndex: (theme) => Math.max(theme.zIndex.modal + 1, 1400),
10645
10695
  boxShadow: 3,
10646
- transition: "bottom 0.3s ease, left 0.3s ease-in-out",
10696
+ transition: "bottom 0.25s ease, left 0.3s ease-in-out, transform 0.2s ease",
10647
10697
  "&:hover": {
10648
10698
  bgcolor: (theme) => theme.palette.action.hover
10699
+ },
10700
+ "&:active": {
10701
+ transform: "translateX(-50%) translateY(1px)"
10649
10702
  }
10650
10703
  },
10651
10704
  children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_ArrowDownward.default, { sx: { color: "inherit" } })
@@ -15660,7 +15713,7 @@ var init_memory_modal = __esm({
15660
15713
  children: [
15661
15714
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material11.Box, { sx: { display: "flex", alignItems: "center", gap: 0.75 }, children: [
15662
15715
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material11.Typography, { variant: "h6", sx: { fontWeight: 600 }, children: "Memory" }),
15663
- shouldUseVectorForMemories && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material11.Tooltip, { title: "Memories are stored in an AI vector database with semantic search capabilities", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
15716
+ shouldUseVectorForMemories && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material11.Tooltip, { title: "Memories stay in your private knowledge space for faster, more accurate answers.", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
15664
15717
  import_material11.Typography,
15665
15718
  {
15666
15719
  variant: "caption",
@@ -15675,7 +15728,7 @@ var init_memory_modal = __esm({
15675
15728
  textTransform: "uppercase",
15676
15729
  cursor: "help"
15677
15730
  },
15678
- children: "Vector"
15731
+ children: "Synced"
15679
15732
  }
15680
15733
  ) })
15681
15734
  ] }),
@@ -15774,7 +15827,7 @@ var init_memory_modal = __esm({
15774
15827
  onClick: () => setBulkImportOpen(true),
15775
15828
  startIcon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_CloudSync.default, {}),
15776
15829
  sx: { textTransform: "none", borderRadius: 2, fontSize: "0.75rem" },
15777
- children: "Import to Vector"
15830
+ children: "Import to workspace"
15778
15831
  }
15779
15832
  ),
15780
15833
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
@@ -16016,7 +16069,7 @@ var init_memory_modal = __esm({
16016
16069
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material11.Typography, { variant: "body2", sx: {
16017
16070
  color: (0, import_styles6.alpha)(theme.palette.text.secondary, 0.7),
16018
16071
  maxWidth: 280
16019
- }, 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." })
16072
+ }, 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." })
16020
16073
  ] }) : filteredMemories.map((memory) => {
16021
16074
  const isSelected = selectedIds.includes(memory.id);
16022
16075
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react17.default.Fragment, { children: [
@@ -16288,7 +16341,7 @@ var init_memory_modal = __esm({
16288
16341
  size: "small",
16289
16342
  value: newMemory,
16290
16343
  onChange: (e) => setNewMemory(e.target.value),
16291
- placeholder: shouldUseVectorForMemories ? `Add a new ${selectedTab} memory to vector database...` : `Add a new ${selectedTab} memory...`,
16344
+ placeholder: shouldUseVectorForMemories ? `Add a new ${selectedTab} memory to your workspace...` : `Add a new ${selectedTab} memory...`,
16292
16345
  onKeyDown: (e) => {
16293
16346
  if (e.key === "Enter" && !e.shiftKey && newMemory.trim()) {
16294
16347
  e.preventDefault();
@@ -16528,15 +16581,15 @@ var init_memory_modal = __esm({
16528
16581
  gap: 1
16529
16582
  }, children: [
16530
16583
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_CloudSync.default, { color: "primary" }),
16531
- "Import Memories to Vector Database"
16584
+ "Import Memories to Secure Workspace"
16532
16585
  ] }),
16533
16586
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material11.DialogContent, { sx: { py: 2 }, children: !importProgress.isImporting ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material11.Box, { children: [
16534
16587
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material11.Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: [
16535
16588
  "This will import all your local memories (",
16536
16589
  entries.length,
16537
- " memories) to the vector database for enhanced semantic search capabilities."
16590
+ " memories) to your secure workspace for faster, more reliable answers."
16538
16591
  ] }),
16539
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material11.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" }),
16592
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material11.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" }),
16540
16593
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material11.Typography, { variant: "body2", color: "primary", sx: { fontWeight: 500 }, children: [
16541
16594
  "Ready to import ",
16542
16595
  entries.length,
@@ -22290,6 +22343,24 @@ var init_project_header = __esm({
22290
22343
  }
22291
22344
  });
22292
22345
 
22346
+ // src/config/tooltips.ts
22347
+ var TOOLTIP_COPY, tooltip;
22348
+ var init_tooltips = __esm({
22349
+ "src/config/tooltips.ts"() {
22350
+ "use strict";
22351
+ TOOLTIP_COPY = {
22352
+ openNavigation: "Open navigation",
22353
+ closeNavigation: "Close navigation",
22354
+ manageProjects: "Manage projects",
22355
+ conversationOptions: "Open conversation options",
22356
+ closeConversationsPanel: "Close conversations panel",
22357
+ clearSearch: "Clear search",
22358
+ addProject: "Add new project"
22359
+ };
22360
+ tooltip = (key) => TOOLTIP_COPY[key];
22361
+ }
22362
+ });
22363
+
22293
22364
  // src/chat/conversation-drawer.tsx
22294
22365
  var import_react28, import_material19, import_icons_material7, import_icons_material8, import_styles13, import_jsx_runtime21, BANDIT_AVATAR, coerceOptionalString, deriveInitials, ConversationDrawer, conversation_drawer_default;
22295
22366
  var init_conversation_drawer = __esm({
@@ -22309,6 +22380,7 @@ var init_conversation_drawer = __esm({
22309
22380
  init_simple_conversation_item();
22310
22381
  init_project_header();
22311
22382
  init_debugLogger();
22383
+ init_tooltips();
22312
22384
  import_jsx_runtime21 = require("react/jsx-runtime");
22313
22385
  BANDIT_AVATAR = "https://cdn.burtson.ai/images/bandit-head.png";
22314
22386
  coerceOptionalString = (value) => {
@@ -22585,11 +22657,12 @@ var init_conversation_drawer = __esm({
22585
22657
  gap: 1
22586
22658
  },
22587
22659
  children: [
22588
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
22660
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_material19.Tooltip, { title: tooltip("manageProjects"), arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
22589
22661
  import_material19.IconButton,
22590
22662
  {
22591
22663
  onClick: () => setProjectManagementOpen(true),
22592
22664
  size: "small",
22665
+ "aria-label": tooltip("manageProjects"),
22593
22666
  sx: {
22594
22667
  color: theme.palette.text.secondary,
22595
22668
  "&:hover": {
@@ -22599,12 +22672,13 @@ var init_conversation_drawer = __esm({
22599
22672
  },
22600
22673
  children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons_material7.Folder, {})
22601
22674
  }
22602
- ),
22603
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
22675
+ ) }),
22676
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_material19.Tooltip, { title: tooltip("conversationOptions"), arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
22604
22677
  import_material19.IconButton,
22605
22678
  {
22606
22679
  onClick: handleMenuOpen,
22607
22680
  size: "small",
22681
+ "aria-label": tooltip("conversationOptions"),
22608
22682
  sx: {
22609
22683
  color: theme.palette.text.secondary,
22610
22684
  "&:hover": {
@@ -22614,8 +22688,8 @@ var init_conversation_drawer = __esm({
22614
22688
  },
22615
22689
  children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons_material7.MoreVert, {})
22616
22690
  }
22617
- ),
22618
- isMobile && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
22691
+ ) }),
22692
+ isMobile && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_material19.Tooltip, { title: tooltip("closeConversationsPanel"), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
22619
22693
  import_material19.IconButton,
22620
22694
  {
22621
22695
  onClick: (e) => {
@@ -22624,6 +22698,7 @@ var init_conversation_drawer = __esm({
22624
22698
  onClose();
22625
22699
  },
22626
22700
  size: "small",
22701
+ "aria-label": tooltip("closeConversationsPanel"),
22627
22702
  sx: {
22628
22703
  color: theme.palette.text.secondary,
22629
22704
  "&:hover": {
@@ -22633,7 +22708,7 @@ var init_conversation_drawer = __esm({
22633
22708
  },
22634
22709
  children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons_material7.Close, {})
22635
22710
  }
22636
- )
22711
+ ) })
22637
22712
  ]
22638
22713
  }
22639
22714
  ),
@@ -22648,16 +22723,17 @@ var init_conversation_drawer = __esm({
22648
22723
  variant: "outlined",
22649
22724
  InputProps: {
22650
22725
  startAdornment: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_material19.InputAdornment, { position: "start", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons_material7.Search, { fontSize: "small", sx: { color: theme.palette.text.secondary } }) }),
22651
- endAdornment: searchQuery && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_material19.InputAdornment, { position: "end", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
22726
+ endAdornment: searchQuery && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_material19.InputAdornment, { position: "end", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_material19.Tooltip, { title: tooltip("clearSearch"), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
22652
22727
  import_material19.IconButton,
22653
22728
  {
22654
22729
  onClick: handleSearchClear,
22655
22730
  size: "small",
22656
22731
  edge: "end",
22732
+ "aria-label": tooltip("clearSearch"),
22657
22733
  sx: { color: theme.palette.text.secondary },
22658
22734
  children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons_material7.Clear, { fontSize: "small" })
22659
22735
  }
22660
- ) })
22736
+ ) }) })
22661
22737
  },
22662
22738
  sx: {
22663
22739
  "& .MuiOutlinedInput-root": {
@@ -22732,7 +22808,15 @@ var init_conversation_drawer = __esm({
22732
22808
  children: "New Project"
22733
22809
  }
22734
22810
  ),
22735
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_material19.IconButton, { size: "small", sx: { color: theme.palette.success.main }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons_material8.Add, { fontSize: "small" }) })
22811
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_material19.Tooltip, { title: tooltip("addProject"), arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
22812
+ import_material19.IconButton,
22813
+ {
22814
+ size: "small",
22815
+ "aria-label": tooltip("addProject"),
22816
+ sx: { color: theme.palette.success.main },
22817
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons_material8.Add, { fontSize: "small" })
22818
+ }
22819
+ ) })
22736
22820
  ]
22737
22821
  }
22738
22822
  ),
@@ -24171,9 +24255,18 @@ var init_chat_app_bar = __esm({
24171
24255
  const currentModel = useModelStore((s) => s.availableModels.find((m) => m.name === selectedModel));
24172
24256
  const currentAvatar = currentModel?.avatarBase64 || modelAvatars2[selectedModel] || banditHead3;
24173
24257
  const pendingModelAvatar = useModelStore.getState().availableModels.find((m) => m.name === pendingModel)?.avatarBase64 || modelAvatars2[pendingModel || ""] || banditHead3;
24258
+ const resolvedHomeUrl = preferences.homeUrl?.trim() || packageSettings?.homeUrl?.trim() || "";
24259
+ const homeTooltip = (() => {
24260
+ if (!resolvedHomeUrl) return "Home";
24261
+ try {
24262
+ return `Home (${new URL(resolvedHomeUrl).hostname})`;
24263
+ } catch {
24264
+ return "Home";
24265
+ }
24266
+ })();
24174
24267
  function goToHome() {
24175
- if (preferences.homeUrl && preferences.homeUrl.trim()) {
24176
- window.location.href = preferences.homeUrl;
24268
+ if (resolvedHomeUrl) {
24269
+ window.location.href = resolvedHomeUrl;
24177
24270
  return;
24178
24271
  }
24179
24272
  if (typeof window !== "undefined") {
@@ -24236,7 +24329,7 @@ var init_chat_app_bar = __esm({
24236
24329
  }
24237
24330
  },
24238
24331
  children: [
24239
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_material22.Tooltip, { title: preferences.homeUrl && preferences.homeUrl.trim() ? `Home (${new URL(preferences.homeUrl).hostname})` : "Home", arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
24332
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_material22.Tooltip, { title: homeTooltip, arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
24240
24333
  import_material22.IconButton,
24241
24334
  {
24242
24335
  onClick: goToHome,
@@ -24520,9 +24613,15 @@ var init_chat_app_bar = __esm({
24520
24613
  (async () => {
24521
24614
  try {
24522
24615
  const storeConfigs6 = [{ name: "config", keyPath: "id" }];
24523
- const current = await indexedDBService_default.get("banditConfig", 1, "config", "main", storeConfigs6);
24616
+ const current = await indexedDBService_default.get(
24617
+ "banditConfig",
24618
+ 1,
24619
+ "config",
24620
+ "main",
24621
+ storeConfigs6
24622
+ );
24524
24623
  const updated = {
24525
- ...current,
24624
+ ...current ?? {},
24526
24625
  id: "main",
24527
24626
  model: {
24528
24627
  ...current?.model || {},
@@ -24714,9 +24813,15 @@ var init_chat_app_bar = __esm({
24714
24813
  (async () => {
24715
24814
  try {
24716
24815
  const storeConfigs6 = [{ name: "config", keyPath: "id" }];
24717
- const current = await indexedDBService_default.get("banditConfig", 1, "config", "main", storeConfigs6);
24816
+ const current = await indexedDBService_default.get(
24817
+ "banditConfig",
24818
+ 1,
24819
+ "config",
24820
+ "main",
24821
+ storeConfigs6
24822
+ );
24718
24823
  const updated = {
24719
- ...current,
24824
+ ...current ?? {},
24720
24825
  id: "main",
24721
24826
  model: {
24722
24827
  ...current?.model || {},
@@ -34645,7 +34750,7 @@ var PreferencesTab = ({
34645
34750
  await setAdvancedVectorFeaturesEnabled(enabled);
34646
34751
  if (showSnackbar) {
34647
34752
  showSnackbar(
34648
- enabled ? "Advanced vector features enabled for this account." : "Advanced vector features disabled.",
34753
+ enabled ? "Advanced knowledge sync enabled for this account." : "Advanced knowledge sync disabled.",
34649
34754
  "success"
34650
34755
  );
34651
34756
  }
@@ -34930,8 +35035,8 @@ var PreferencesTab = ({
34930
35035
  }
34931
35036
  ),
34932
35037
  label: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_material37.Box, { textAlign: "left", children: [
34933
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_material37.Typography, { variant: "body1", sx: { fontWeight: 600, color: "text.primary" }, children: "Advanced vector features" }),
34934
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_material37.Typography, { variant: "body2", color: "text.secondary", children: "Keep semantic search, vector memories, and related context in sync across devices" })
35038
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_material37.Typography, { variant: "body1", sx: { fontWeight: 600, color: "text.primary" }, children: "Advanced knowledge sync" }),
35039
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_material37.Typography, { variant: "body2", color: "text.secondary", children: "Keep richer search, saved memories, and context in sync across devices" })
34935
35040
  ] }),
34936
35041
  sx: { alignSelf: { xs: "flex-start", sm: "center" } }
34937
35042
  }
@@ -35501,6 +35606,7 @@ var LogoCropper = ({
35501
35606
  canvas.width = outputWidth;
35502
35607
  canvas.height = outputHeight;
35503
35608
  ctx.save();
35609
+ ctx.clearRect(0, 0, outputWidth, outputHeight);
35504
35610
  const scaleX = outputWidth / cropDims.width;
35505
35611
  const scaleY = outputHeight / cropDims.height;
35506
35612
  ctx.translate(outputWidth / 2, outputHeight / 2);
@@ -36541,30 +36647,29 @@ var defaultSteps = [
36541
36647
  },
36542
36648
  {
36543
36649
  id: "embed",
36544
- title: "Creating Vectors",
36545
- description: "Neural networks are encoding knowledge into searchable vectors...",
36650
+ title: "Making It Searchable",
36651
+ description: "We turn the content into a private, searchable index...",
36546
36652
  icon: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_icons_material12.Memory, {}),
36547
36653
  duration: 10
36548
36654
  },
36549
36655
  {
36550
36656
  id: "optimize",
36551
36657
  title: "Optimizing Search",
36552
- description: "AI algorithms are organizing data for lightning-fast retrieval...",
36658
+ description: "Organizing everything for quick, reliable answers...",
36553
36659
  icon: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_icons_material12.AutoAwesome, {}),
36554
36660
  duration: 8
36555
36661
  }
36556
36662
  ];
36557
36663
  var cleverMessages = [
36558
- "\u{1F977} Digital ninjas are working their magic...",
36559
- "\u{1F916} AI robots are crunching your data...",
36560
- "\u26A1 Neural networks firing at maximum capacity...",
36561
- "\u{1F9E0} Machine learning models deep in thought...",
36562
- "\u{1F52E} AI wizards casting knowledge spells...",
36563
- "\u2699\uFE0F Quantum processors spinning up...",
36564
- "\u{1F680} Algorithms achieving warp speed...",
36565
- "\u{1F4AB} Creating digital memories from your content...",
36566
- "\u{1F3AF} Precision-targeting knowledge patterns...",
36567
- "\u{1F31F} Transforming text into searchable stardust..."
36664
+ "\u{1F977} Keeping your content safe while we set things up...",
36665
+ "\u{1F916} Getting everything ready for fast answers...",
36666
+ "\u26A1 Tidying the data so responses stay consistent...",
36667
+ "\u{1F9E0} Remembering the important parts for you...",
36668
+ "\u{1F512} Locking in privacy before we share results...",
36669
+ "\u{1F680} Optimizing for quick, reliable lookups...",
36670
+ "\u{1F4AB} Turning this into searchable knowledge...",
36671
+ "\u{1F3AF} Focusing on the details that matter to you...",
36672
+ "\u{1F31F} Making sure it stays available when you need it..."
36568
36673
  ];
36569
36674
  var ProcessingOverlay = ({
36570
36675
  open,
@@ -37153,16 +37258,16 @@ var KnowledgeTab = ({
37153
37258
  const handleDocumentUpload = async (files) => {
37154
37259
  if (shouldUseVector) {
37155
37260
  showProcessing(
37156
- "Uploading to Vector Database",
37261
+ "Uploading to Secure Workspace",
37157
37262
  [
37158
- "\u{1F977} Digital ninjas securing your documents...",
37159
- "\u{1F916} AI robots reading and understanding content...",
37160
- "\u26A1 Neural networks encoding knowledge vectors...",
37161
- "\u{1F9E0} Machine learning creating searchable memories...",
37162
- "\u{1F52E} AI wizards optimizing semantic search...",
37163
- "\u{1F680} Vector embeddings achieving light speed...",
37164
- "\u{1F4AB} Transforming documents into intelligent data...",
37165
- "\u{1F3AF} Precision-targeting knowledge patterns..."
37263
+ "\u{1F977} Keeping your documents private while we prepare them...",
37264
+ "\u{1F916} Reading the content so answers stay accurate...",
37265
+ "\u26A1 Turning pages into a searchable index...",
37266
+ "\u{1F9E0} Remembering highlights for quick recall...",
37267
+ "\u{1F52E} Organizing everything so search feels instant...",
37268
+ "\u{1F680} Optimizing for fast, consistent responses...",
37269
+ "\u{1F4AB} Transforming documents into trusted knowledge...",
37270
+ "\u{1F3AF} Focusing on the details that matter most..."
37166
37271
  ]
37167
37272
  );
37168
37273
  try {
@@ -37236,7 +37341,7 @@ var KnowledgeTab = ({
37236
37341
  progress: 100,
37237
37342
  status: "success"
37238
37343
  })));
37239
- 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)`;
37344
+ 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)`;
37240
37345
  setSnackbarMessage(message);
37241
37346
  setSnackbarSeverity(result.error ? "warning" : "success");
37242
37347
  setShowSnackbar(true);
@@ -37297,7 +37402,7 @@ var KnowledgeTab = ({
37297
37402
  progress: 100,
37298
37403
  status: "success"
37299
37404
  })));
37300
- 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)`;
37405
+ 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)`;
37301
37406
  setSnackbarMessage(message);
37302
37407
  setSnackbarSeverity(result.error ? "warning" : "success");
37303
37408
  setShowSnackbar(true);
@@ -37475,7 +37580,7 @@ var KnowledgeTab = ({
37475
37580
  shouldUseVector && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
37476
37581
  import_material41.Chip,
37477
37582
  {
37478
- label: "Vector DB",
37583
+ label: "Synced",
37479
37584
  color: "primary",
37480
37585
  size: "small",
37481
37586
  sx: { ml: 1 }
@@ -37492,7 +37597,7 @@ var KnowledgeTab = ({
37492
37597
  sx: { fontSize: { xs: "0.95rem", sm: "1rem" }, lineHeight: 1.5 },
37493
37598
  children: [
37494
37599
  "Add documents to your private knowledge base. Files are securely stored ",
37495
- shouldUseVector ? "in the vector database" : "locally in your browser",
37600
+ shouldUseVector ? "in your private workspace" : "locally in your browser",
37496
37601
  "."
37497
37602
  ]
37498
37603
  }
@@ -37828,7 +37933,7 @@ var KnowledgeTab = ({
37828
37933
  filteredAndSortedDocuments.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_material41.Card, { sx: { textAlign: "center", py: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_material41.CardContent, { children: [
37829
37934
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_Folder.default, { sx: { fontSize: 64, color: "text.secondary", mb: 2 } }),
37830
37935
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_material41.Typography, { variant: "h6", color: "text.secondary", gutterBottom: true, children: "No Documents Yet" }),
37831
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_material41.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" })
37936
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_material41.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" })
37832
37937
  ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_material41.Box, { children: [
37833
37938
  /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_material41.Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: [
37834
37939
  "Showing ",
@@ -37837,7 +37942,7 @@ var KnowledgeTab = ({
37837
37942
  shouldUseVector ? vectorDocuments.length : documents.length,
37838
37943
  " documents",
37839
37944
  searchQuery && ` for "${searchQuery}"`,
37840
- shouldUseVector && ` (Vector Database)`
37945
+ shouldUseVector && ` (Synced workspace)`
37841
37946
  ] }),
37842
37947
  viewMode === "grid" ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
37843
37948
  import_material41.Box,
@@ -40347,6 +40452,7 @@ var Management = () => {
40347
40452
  name: modelToSave.name,
40348
40453
  tagline: modelToSave.tagline,
40349
40454
  systemPrompt: modelToSave.systemPrompt,
40455
+ avatarBase64: modelToSave.avatarBase64 || void 0,
40350
40456
  selectedModel: modelToSave.name
40351
40457
  }
40352
40458
  };
@@ -40399,6 +40505,19 @@ var Management = () => {
40399
40505
  try {
40400
40506
  const storeConfigs6 = [{ name: "config", keyPath: "id" }];
40401
40507
  debugLogger.info("Saving branding data to IndexedDB");
40508
+ let finalHasTransparentLogo = hasTransparentLogo;
40509
+ if (logoBase64) {
40510
+ try {
40511
+ const detected = await detectTransparency(logoBase64);
40512
+ const isPng = logoBase64.startsWith("data:image/png");
40513
+ finalHasTransparentLogo = detected || isPng;
40514
+ debugLogger.debug("SaveBranding transparency check", { detected, isPng, finalHasTransparentLogo });
40515
+ } catch (err) {
40516
+ const isPng = logoBase64.startsWith("data:image/png");
40517
+ finalHasTransparentLogo = finalHasTransparentLogo ?? isPng ?? true;
40518
+ debugLogger.warn("SaveBranding transparency check failed, using fallback", { error: err, finalHasTransparentLogo });
40519
+ }
40520
+ }
40402
40521
  const current = await indexedDBService_default.get(
40403
40522
  "banditConfig",
40404
40523
  1,
@@ -40414,7 +40533,7 @@ var Management = () => {
40414
40533
  logoBase64,
40415
40534
  brandingText,
40416
40535
  theme,
40417
- hasTransparentLogo,
40536
+ hasTransparentLogo: finalHasTransparentLogo,
40418
40537
  userSaved: true
40419
40538
  // Mark as user-saved to protect from CDN overrides
40420
40539
  }
@@ -40453,9 +40572,11 @@ var Management = () => {
40453
40572
  setLogoBase64(base64);
40454
40573
  debugLogger.debug("Starting transparency detection for uploaded image");
40455
40574
  try {
40575
+ const isPng = base64.startsWith("data:image/png");
40456
40576
  const isTransparent = await detectTransparency(base64);
40457
- setHasTransparentLogo(isTransparent);
40458
- debugLogger.debug("Transparency detection result saved", { isTransparent });
40577
+ const finalTransparent = isTransparent || isPng;
40578
+ setHasTransparentLogo(finalTransparent);
40579
+ debugLogger.debug("Transparency detection result saved", { isTransparent, finalTransparent });
40459
40580
  } catch (err) {
40460
40581
  debugLogger.error("Failed to detect transparency", { error: err });
40461
40582
  }
@@ -40668,7 +40789,8 @@ var Management = () => {
40668
40789
  name: modelName2,
40669
40790
  tagline: typeof parsedModel.tagline === "string" ? parsedModel.tagline : void 0,
40670
40791
  systemPrompt: typeof parsedModel.systemPrompt === "string" ? parsedModel.systemPrompt : void 0,
40671
- selectedModel: typeof parsedModel.selectedModel === "string" ? parsedModel.selectedModel : void 0
40792
+ selectedModel: typeof parsedModel.selectedModel === "string" ? parsedModel.selectedModel : void 0,
40793
+ avatarBase64: typeof parsedModel.avatarBase64 === "string" ? parsedModel.avatarBase64 : parsedModel.avatarBase64 === null ? void 0 : void 0
40672
40794
  };
40673
40795
  const entry = {
40674
40796
  id: modelName2,
@@ -40676,7 +40798,8 @@ var Management = () => {
40676
40798
  name: modelName2,
40677
40799
  tagline: sanitizedModel.tagline,
40678
40800
  systemPrompt: sanitizedModel.systemPrompt,
40679
- avatarBase64: typeof parsedModel.avatarBase64 === "string" ? parsedModel.avatarBase64 : void 0
40801
+ // Normalize to match StoredBanditConfigRecord (string | undefined)
40802
+ avatarBase64: sanitizedModel.avatarBase64 ?? void 0
40680
40803
  };
40681
40804
  await indexedDBService_default.put("banditConfig", 1, "config", entry, storeConfigs6);
40682
40805
  }