@burtson-labs/bandit-engine 2.1.4 → 2.1.7

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 (56) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/ProjectsPane-E5D72PUG.mjs +866 -0
  3. package/dist/ProjectsPane-E5D72PUG.mjs.map +1 -0
  4. package/dist/{SchedulesTab-YZG3P2GW.mjs → SchedulesTab-AKJ6WFZV.mjs} +5 -4
  5. package/dist/SchedulesTab-AKJ6WFZV.mjs.map +1 -0
  6. package/dist/chat-MI4IL3WK.mjs +19 -0
  7. package/dist/chunk-2HFSBPOE.mjs +163 -0
  8. package/dist/chunk-2HFSBPOE.mjs.map +1 -0
  9. package/dist/{chunk-W2D454CZ.mjs → chunk-4NHPLHXU.mjs} +3550 -4872
  10. package/dist/chunk-4NHPLHXU.mjs.map +1 -0
  11. package/dist/{chunk-PSI7RQ54.mjs → chunk-4NUQYUZH.mjs} +7 -2
  12. package/dist/chunk-4NUQYUZH.mjs.map +1 -0
  13. package/dist/{chunk-62H3OLTV.mjs → chunk-5URP2E5V.mjs} +20 -26
  14. package/dist/chunk-5URP2E5V.mjs.map +1 -0
  15. package/dist/chunk-HS62C62A.mjs +22 -0
  16. package/dist/chunk-HS62C62A.mjs.map +1 -0
  17. package/dist/{chunk-4LLCLYLH.mjs → chunk-K7SQWDNF.mjs} +1 -1
  18. package/dist/{chunk-4LLCLYLH.mjs.map → chunk-K7SQWDNF.mjs.map} +1 -1
  19. package/dist/{chunk-6CSFKF34.mjs → chunk-KWOUXBSF.mjs} +3 -3
  20. package/dist/chunk-MAKXJD7A.mjs +233 -0
  21. package/dist/chunk-MAKXJD7A.mjs.map +1 -0
  22. package/dist/chunk-SQJ4OKWM.mjs +3567 -0
  23. package/dist/chunk-SQJ4OKWM.mjs.map +1 -0
  24. package/dist/chunk-WBKTQJNX.mjs +21 -0
  25. package/dist/chunk-WBKTQJNX.mjs.map +1 -0
  26. package/dist/image-compare-NW5VCP4Q.mjs +74 -0
  27. package/dist/image-compare-NW5VCP4Q.mjs.map +1 -0
  28. package/dist/image-edit-acknowledgement-RZPQYKYJ.mjs +54 -0
  29. package/dist/image-edit-acknowledgement-RZPQYKYJ.mjs.map +1 -0
  30. package/dist/index.d.mts +18 -3
  31. package/dist/index.d.ts +18 -3
  32. package/dist/index.js +8173 -4832
  33. package/dist/index.js.map +1 -1
  34. package/dist/index.mjs +367 -338
  35. package/dist/index.mjs.map +1 -1
  36. package/dist/modelStore-YNANSWCN.mjs +9 -0
  37. package/dist/{public-ByjnoHLe.d.mts → public-Tq2Pmw9m.d.mts} +44 -2
  38. package/dist/{public-ByjnoHLe.d.ts → public-Tq2Pmw9m.d.ts} +44 -2
  39. package/dist/public-types.d.mts +1 -1
  40. package/dist/public-types.d.ts +1 -1
  41. package/dist/{schedule-confirm-card-N4TKLEHL.mjs → schedule-confirm-card-D4K76HEA.mjs} +8 -5
  42. package/dist/schedule-confirm-card-D4K76HEA.mjs.map +1 -0
  43. package/docs/package-settings.md +25 -0
  44. package/package.json +1 -1
  45. package/dist/SchedulesTab-YZG3P2GW.mjs.map +0 -1
  46. package/dist/chat-W7MDFESE.mjs +0 -15
  47. package/dist/chunk-62H3OLTV.mjs.map +0 -1
  48. package/dist/chunk-LMAQWR7Z.mjs +0 -388
  49. package/dist/chunk-LMAQWR7Z.mjs.map +0 -1
  50. package/dist/chunk-PSI7RQ54.mjs.map +0 -1
  51. package/dist/chunk-W2D454CZ.mjs.map +0 -1
  52. package/dist/modelStore-FIVOSLFY.mjs +0 -9
  53. package/dist/schedule-confirm-card-N4TKLEHL.mjs.map +0 -1
  54. /package/dist/{chat-W7MDFESE.mjs.map → chat-MI4IL3WK.mjs.map} +0 -0
  55. /package/dist/{chunk-6CSFKF34.mjs.map → chunk-KWOUXBSF.mjs.map} +0 -0
  56. /package/dist/{modelStore-FIVOSLFY.mjs.map → modelStore-YNANSWCN.mjs.map} +0 -0
package/dist/index.mjs CHANGED
@@ -1,9 +1,6 @@
1
1
  import {
2
2
  CHUNK_SECONDS,
3
- DEFAULT_TIER_FEATURES,
4
3
  DocumentCard_default,
5
- FeatureFlagContext,
6
- FeatureFlagProvider,
7
4
  FeedbackModal,
8
5
  IS_STORE_BUILD,
9
6
  MAX_RECORDING_BYTES,
@@ -11,7 +8,6 @@ import {
11
8
  MeetingNotesError,
12
9
  NotificationProvider,
13
10
  NotificationService,
14
- OSS_DEFAULT_FEATURES,
15
11
  SpeechToTextError,
16
12
  StashError,
17
13
  StreamingTTSClient,
@@ -24,7 +20,6 @@ import {
24
20
  addMcpServer,
25
21
  ai_response_text_field_default,
26
22
  banditDarkTheme,
27
- brandingService_default,
28
23
  brandingThemeKey,
29
24
  chat_default,
30
25
  chunkTranscript,
@@ -41,9 +36,7 @@ import {
41
36
  getStreamingTTSClient,
42
37
  getTTSState,
43
38
  isMeetingFile,
44
- isNativeShell,
45
39
  isRecordingFile,
46
- isStandalonePwa,
47
40
  isTenantAccent,
48
41
  isTranscriptFileName,
49
42
  knowledge_file_modal_default,
@@ -51,7 +44,6 @@ import {
51
44
  looksLikeTranscript,
52
45
  meetingNotesErrorMessage,
53
46
  memory_modal_default,
54
- newId,
55
47
  notesToHtml,
56
48
  notesToMarkdown,
57
49
  notificationService,
@@ -59,7 +51,6 @@ import {
59
51
  parseNotesJson,
60
52
  parseTranscript,
61
53
  pauseTTS,
62
- predefinedThemes,
63
54
  registry_default,
64
55
  resolveAvatar,
65
56
  resumeTTS,
@@ -75,12 +66,7 @@ import {
75
66
  transcribeRecording,
76
67
  transcriptToText,
77
68
  updateMcpServer,
78
- useAIQueryStore,
79
- useConversationStore,
80
69
  useConversationSyncStore,
81
- useFeatureFlag,
82
- useFeatureVisibility,
83
- useFeatures,
84
70
  useGlobalTTS,
85
71
  useKnowledgeStore,
86
72
  useKnowledgeStore2,
@@ -88,36 +74,13 @@ import {
88
74
  useMemoryStore,
89
75
  useNotification,
90
76
  useNotificationService,
91
- useProjectStore,
92
77
  useTTS,
93
78
  useVectorStore,
94
79
  useVoiceStore,
95
80
  vectorDatabaseService,
96
81
  vectorMigrationService,
97
82
  voiceService
98
- } from "./chunk-W2D454CZ.mjs";
99
- import {
100
- indexedDBService_default,
101
- models,
102
- useModelStore,
103
- usePreferencesStore
104
- } from "./chunk-6CSFKF34.mjs";
105
- import {
106
- AIProviderFactory,
107
- GatewayService,
108
- useAIProviderStore
109
- } from "./chunk-GX4FVZNA.mjs";
110
- import {
111
- Agent,
112
- AlertTriangle,
113
- Cpu,
114
- CreditCard,
115
- Home,
116
- MessageCircle,
117
- Sparkles,
118
- Upload,
119
- Zap
120
- } from "./chunk-62H3OLTV.mjs";
83
+ } from "./chunk-4NHPLHXU.mjs";
121
84
  import {
122
85
  ManagementEmptyState,
123
86
  ManagementPageHeader,
@@ -150,6 +113,7 @@ import {
150
113
  FilePdf,
151
114
  FileText,
152
115
  FileUp,
116
+ Folder,
153
117
  FolderOpen,
154
118
  Globe,
155
119
  Grip,
@@ -192,11 +156,52 @@ import {
192
156
  X,
193
157
  ZoomIn,
194
158
  ZoomOut
195
- } from "./chunk-PSI7RQ54.mjs";
196
- import "./chunk-LMAQWR7Z.mjs";
159
+ } from "./chunk-4NUQYUZH.mjs";
160
+ import {
161
+ AIProviderFactory,
162
+ GatewayService,
163
+ useAIProviderStore
164
+ } from "./chunk-GX4FVZNA.mjs";
165
+ import {
166
+ DEFAULT_TIER_FEATURES,
167
+ FeatureFlagContext,
168
+ FeatureFlagProvider,
169
+ OSS_DEFAULT_FEATURES,
170
+ brandingService_default,
171
+ isNativeShell,
172
+ isStandalonePwa,
173
+ newId,
174
+ useAIQueryStore,
175
+ useConversationStore,
176
+ useFeatureFlag,
177
+ useFeatureVisibility,
178
+ useFeatures,
179
+ useProjectStore
180
+ } from "./chunk-SQJ4OKWM.mjs";
181
+ import {
182
+ indexedDBService_default,
183
+ models,
184
+ useModelStore,
185
+ usePreferencesStore
186
+ } from "./chunk-KWOUXBSF.mjs";
187
+ import "./chunk-WBKTQJNX.mjs";
188
+ import "./chunk-HS62C62A.mjs";
189
+ import "./chunk-MAKXJD7A.mjs";
190
+ import {
191
+ Agent,
192
+ AlertTriangle,
193
+ Cpu,
194
+ CreditCard,
195
+ Home,
196
+ MessageCircle,
197
+ Sparkles,
198
+ Upload,
199
+ Zap
200
+ } from "./chunk-5URP2E5V.mjs";
201
+ import "./chunk-2HFSBPOE.mjs";
197
202
  import {
198
203
  usePackageSettingsStore
199
- } from "./chunk-4LLCLYLH.mjs";
204
+ } from "./chunk-K7SQWDNF.mjs";
200
205
  import {
201
206
  AUTH_TOKEN_CHANGED_EVENT,
202
207
  TOKEN_KEY,
@@ -4235,9 +4240,9 @@ var PersonalitiesTab = ({
4235
4240
  handleSaveModel,
4236
4241
  handleResetModel,
4237
4242
  restoreDefaultModelsAndConfig,
4238
- restoreBanditModels,
4239
4243
  showSnackbar,
4240
- createRequest
4244
+ createRequest,
4245
+ webConsole = false
4241
4246
  }) => {
4242
4247
  const theme = useTheme7();
4243
4248
  const isMobile = useMediaQuery4(theme.breakpoints.down("sm"));
@@ -4392,6 +4397,10 @@ var PersonalitiesTab = ({
4392
4397
  showSnackbar(`Added the ${mood} mood to the prompt.`, "success");
4393
4398
  }
4394
4399
  };
4400
+ const activatePersonality = (model) => {
4401
+ setSelectedModel(model.name);
4402
+ showSnackbar?.(`${model.name} now answers new chats.`, "success");
4403
+ };
4395
4404
  const handleDeletePersonality = (modelNameToDelete) => {
4396
4405
  const nameToDelete = modelNameToDelete || localSelectedModel.selectedModel;
4397
4406
  if (!nameToDelete) {
@@ -5126,6 +5135,7 @@ var PersonalitiesTab = ({
5126
5135
  ]
5127
5136
  }
5128
5137
  ),
5138
+ webConsole && availableModels.length > 0 && /* @__PURE__ */ jsx10(Typography5, { variant: "body2", color: "text.secondary", sx: { mb: 1.5 }, children: "The active personality answers new chats. Choosing one to edit, or saving one, also makes it active." }),
5129
5139
  availableModels.length === 0 ? /* @__PURE__ */ jsx10(
5130
5140
  ManagementEmptyState,
5131
5141
  {
@@ -5163,15 +5173,27 @@ var PersonalitiesTab = ({
5163
5173
  }
5164
5174
  ),
5165
5175
  /* @__PURE__ */ jsxs6(Box8, { sx: { flex: 1, minWidth: 0 }, children: [
5166
- /* @__PURE__ */ jsx10(
5167
- Typography5,
5168
- {
5169
- variant: "body2",
5170
- sx: { fontWeight: 600, lineHeight: 1.2 },
5171
- noWrap: true,
5172
- children: model.name
5173
- }
5174
- ),
5176
+ /* @__PURE__ */ jsxs6(Stack, { direction: "row", alignItems: "center", spacing: 1, sx: { minWidth: 0 }, children: [
5177
+ /* @__PURE__ */ jsx10(
5178
+ Typography5,
5179
+ {
5180
+ variant: "body2",
5181
+ sx: { fontWeight: 600, lineHeight: 1.2 },
5182
+ noWrap: true,
5183
+ children: model.name
5184
+ }
5185
+ ),
5186
+ webConsole && model.name === selectedModel && /* @__PURE__ */ jsx10(
5187
+ Chip3,
5188
+ {
5189
+ label: "Active",
5190
+ size: "small",
5191
+ color: "primary",
5192
+ variant: "outlined",
5193
+ sx: { height: 20, fontSize: "0.7rem" }
5194
+ }
5195
+ )
5196
+ ] }),
5175
5197
  /* @__PURE__ */ jsx10(
5176
5198
  Typography5,
5177
5199
  {
@@ -5192,6 +5214,19 @@ var PersonalitiesTab = ({
5192
5214
  width: { xs: "100%", sm: "auto" }
5193
5215
  },
5194
5216
  children: [
5217
+ webConsole && model.name !== selectedModel && /* @__PURE__ */ jsx10(
5218
+ Button4,
5219
+ {
5220
+ variant: "text",
5221
+ "aria-label": `Use ${model.name}`,
5222
+ onClick: () => activatePersonality(model),
5223
+ sx: {
5224
+ flex: { xs: 1, sm: "initial" },
5225
+ minHeight: { xs: 44, sm: "auto" }
5226
+ },
5227
+ children: "Use"
5228
+ }
5229
+ ),
5195
5230
  /* @__PURE__ */ jsx10(
5196
5231
  Button4,
5197
5232
  {
@@ -5483,7 +5518,8 @@ var PreferencesTab = ({
5483
5518
  packageSettings,
5484
5519
  updatePreference,
5485
5520
  handleSavePreferences,
5486
- showSnackbar
5521
+ showSnackbar,
5522
+ showDiagnostics = false
5487
5523
  }) => {
5488
5524
  const theme = useTheme8();
5489
5525
  const isMobile = useMediaQuery5(theme.breakpoints.down("sm"));
@@ -6627,7 +6663,7 @@ var PreferencesTab = ({
6627
6663
  ]
6628
6664
  }
6629
6665
  ),
6630
- /* @__PURE__ */ jsx11(ViewportDiagnostics, {})
6666
+ showDiagnostics && /* @__PURE__ */ jsx11(ViewportDiagnostics, {})
6631
6667
  ] }) });
6632
6668
  };
6633
6669
  var ViewportDiagnostics = () => {
@@ -7411,11 +7447,14 @@ var BrandingTab = ({
7411
7447
  "Failed to reset branding settings"
7412
7448
  );
7413
7449
  const handleImport = async (event) => {
7450
+ const input = event.target;
7414
7451
  try {
7415
7452
  await handleImportConfig(event);
7416
7453
  notify("Branding configuration imported", "success");
7417
7454
  } catch {
7418
7455
  notify("Failed to import branding configuration", "error");
7456
+ } finally {
7457
+ input.value = "";
7419
7458
  }
7420
7459
  };
7421
7460
  const name = brandingText.trim() || "Bandit AI";
@@ -8361,8 +8400,7 @@ var KnowledgeTab = ({
8361
8400
  addDocuments,
8362
8401
  removeDocument,
8363
8402
  loadDocuments,
8364
- clearAllDocuments,
8365
- isLimitedAdmin = false
8403
+ clearAllDocuments
8366
8404
  }) => {
8367
8405
  const muiTheme = useTheme11();
8368
8406
  const authStore = useAuthenticationStore();
@@ -8373,12 +8411,9 @@ var KnowledgeTab = ({
8373
8411
  const {
8374
8412
  isVectorEnabled,
8375
8413
  uploadDocument: uploadToVector,
8376
- searchDocuments: searchVectorDocuments,
8377
8414
  getKnowledgeDocumentsPage,
8378
8415
  downloadVectorFile,
8379
- getFilePreview,
8380
- refreshCompatibilityCheck,
8381
- initializeVectorService
8416
+ getFilePreview
8382
8417
  } = useVectorStore();
8383
8418
  const { showProcessing, hideProcessing, updateProgress, processingState } = useProcessingOverlay();
8384
8419
  const shouldUseVector = (features.isAdmin() || features.hasAdvancedSearch() || features.hasAdvancedMemories()) && isAdvancedVectorFeaturesEnabled && isVectorEnabled;
@@ -8459,7 +8494,7 @@ var KnowledgeTab = ({
8459
8494
  hiddenCount: page.hiddenCount
8460
8495
  });
8461
8496
  } catch (error) {
8462
- console.error("Failed to load vector documents:", error);
8497
+ debugLogger.error("Failed to load vector documents", { error });
8463
8498
  setVectorLoadError(error instanceof Error ? error.message : String(error));
8464
8499
  } finally {
8465
8500
  setLoadingVectorDocs(false);
@@ -8636,7 +8671,7 @@ var KnowledgeTab = ({
8636
8671
  await loadVectorDocuments();
8637
8672
  return { success: true, usedVector: true };
8638
8673
  } catch (error) {
8639
- console.error("Error uploading to vector database:", error);
8674
+ debugLogger.error("Error uploading to vector database", { error });
8640
8675
  hideProcessing();
8641
8676
  try {
8642
8677
  await addDocuments(files);
@@ -8704,7 +8739,7 @@ var KnowledgeTab = ({
8704
8739
  try {
8705
8740
  await loadDocuments();
8706
8741
  } catch (loadError) {
8707
- console.error("Failed to reload documents after upload", loadError);
8742
+ debugLogger.error("Failed to reload documents after upload", { error: loadError });
8708
8743
  }
8709
8744
  }, 100);
8710
8745
  } else {
@@ -8732,7 +8767,7 @@ var KnowledgeTab = ({
8732
8767
  );
8733
8768
  setSnackbarSeverity("error");
8734
8769
  setShowSnackbar(true);
8735
- console.error("Failed to add documents", err);
8770
+ debugLogger.error("Failed to add documents", { error: err });
8736
8771
  } finally {
8737
8772
  if (e.target) {
8738
8773
  e.target.value = "";
@@ -8775,7 +8810,7 @@ var KnowledgeTab = ({
8775
8810
  try {
8776
8811
  await loadDocuments();
8777
8812
  } catch (loadError) {
8778
- console.error("Failed to reload documents after drop", loadError);
8813
+ debugLogger.error("Failed to reload documents after drop", { error: loadError });
8779
8814
  }
8780
8815
  }, 100);
8781
8816
  } else {
@@ -8803,7 +8838,7 @@ var KnowledgeTab = ({
8803
8838
  );
8804
8839
  setSnackbarSeverity("error");
8805
8840
  setShowSnackbar(true);
8806
- console.error("Drag/drop failed", err);
8841
+ debugLogger.error("Drag/drop failed", { error: err });
8807
8842
  }
8808
8843
  };
8809
8844
  const handleDragOver = (e) => {
@@ -8834,7 +8869,7 @@ var KnowledgeTab = ({
8834
8869
  URL.revokeObjectURL(url);
8835
8870
  }
8836
8871
  } catch (error) {
8837
- console.error("Download failed:", error);
8872
+ debugLogger.error("Download failed", { error });
8838
8873
  setSnackbarMessage(
8839
8874
  `Couldn't download ${doc.name}: ${error instanceof Error ? error.message : "unknown error"}`
8840
8875
  );
@@ -8861,7 +8896,7 @@ var KnowledgeTab = ({
8861
8896
  setShowSnackbar(true);
8862
8897
  }
8863
8898
  } catch (error) {
8864
- console.error("Failed to get preview:", error);
8899
+ debugLogger.error("Failed to get preview", { error });
8865
8900
  setSnackbarMessage(
8866
8901
  `Couldn't preview ${doc.name}: ${error instanceof Error ? error.message : "unknown error"}`
8867
8902
  );
@@ -11465,6 +11500,23 @@ import {
11465
11500
  useTheme as useTheme13
11466
11501
  } from "@mui/material";
11467
11502
  import { Fragment as Fragment7, jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
11503
+ var BANDIT_DATABASES = {
11504
+ conversations: { db: "bandit-conversations", store: "conversations" },
11505
+ projects: { db: "bandit-projects", store: "projects" },
11506
+ knowledge: { db: "banditKnowledge", store: "documents" },
11507
+ memories: { db: "bandit-memory-db", store: "bandit-memory" },
11508
+ config: { db: "banditConfig", store: "config" },
11509
+ queryCache: { db: "ai-query-db", store: "ai-query" }
11510
+ };
11511
+ var LEGACY_DATABASES = [
11512
+ "bandit-knowledge",
11513
+ "knowledge",
11514
+ "banditConversations",
11515
+ "banditMemories",
11516
+ "bandit-memories",
11517
+ "banditAIQuery",
11518
+ "bandit-config"
11519
+ ];
11468
11520
  var DEFAULT_DISPLAY_QUOTA_BYTES = 1024 * 1024 * 1024;
11469
11521
  var MAX_DISPLAY_QUOTA_BYTES = 5 * 1024 * 1024 * 1024;
11470
11522
  var formatBytes = (bytes) => {
@@ -11488,171 +11540,101 @@ var getStorageQuota = async () => {
11488
11540
  }
11489
11541
  return { used: 0, quota: 0 };
11490
11542
  };
11543
+ var listExistingDatabases = async () => {
11544
+ try {
11545
+ if (typeof indexedDB === "undefined" || typeof indexedDB.databases !== "function") {
11546
+ return null;
11547
+ }
11548
+ const databases = await indexedDB.databases();
11549
+ return new Set(
11550
+ databases.map((db) => db.name).filter((name) => Boolean(name))
11551
+ );
11552
+ } catch (error) {
11553
+ debugLogger.warn("Could not list databases", { error });
11554
+ return null;
11555
+ }
11556
+ };
11491
11557
  var getIndexedDBSize = async () => {
11492
- const categories = [];
11493
11558
  try {
11494
11559
  debugLogger.info("Starting IndexedDB size estimation");
11495
- try {
11496
- const databases = await indexedDB.databases();
11497
- debugLogger.info("Available IndexedDB databases:", {
11498
- databases: databases.map((db) => ({ name: db.name, version: db.version }))
11499
- });
11500
- } catch (error) {
11501
- debugLogger.warn("Could not list databases", { error });
11502
- }
11503
- const conversationDbNames = [
11504
- "bandit-conversations",
11505
- "banditConversations",
11506
- "conversations"
11507
- ];
11508
- let chatSize = { size: 0, count: 0 };
11509
- let foundConversationDb = "";
11510
- for (const dbName of conversationDbNames) {
11511
- try {
11512
- const result = await estimateStoreSize(dbName, "conversations");
11513
- if (result.count > 0) {
11514
- chatSize = result;
11515
- foundConversationDb = dbName;
11516
- debugLogger.info(`Found conversations in database: ${dbName}`);
11517
- break;
11518
- }
11519
- } catch (error) {
11520
- debugLogger.warn(`Failed to check conversations in ${dbName}`, { error });
11521
- }
11522
- }
11523
- categories.push({
11524
- name: "Chat History",
11525
- icon: MessageSquare,
11526
- size: chatSize.size,
11527
- itemCount: chatSize.count,
11528
- description: "Conversation history and messages",
11529
- stores: foundConversationDb ? [`${foundConversationDb}.conversations`] : [],
11530
- canClear: chatSize.count > 0,
11531
- clearWarning: "This will permanently delete all your chat conversations and message history."
11532
- });
11533
- debugLogger.info(`Chat History category created:`, {
11534
- itemCount: chatSize.count,
11535
- size: chatSize.size,
11536
- canClear: chatSize.count > 0,
11537
- foundDb: foundConversationDb
11538
- });
11539
- const knowledgeDbNames = ["bandit-knowledge", "banditKnowledge", "knowledge"];
11540
- let knowledgeSize = { size: 0, count: 0 };
11541
- let foundKnowledgeDb = "";
11542
- for (const dbName of knowledgeDbNames) {
11543
- try {
11544
- const result = await estimateStoreSize(dbName, "documents");
11545
- debugLogger.info(`Knowledge database ${dbName} check result:`, {
11546
- size: result.size,
11547
- count: result.count,
11548
- sizeFormatted: `${(result.size / 1024).toFixed(2)} KB`
11549
- });
11550
- if (result.count > 0) {
11551
- knowledgeSize = result;
11552
- foundKnowledgeDb = dbName;
11553
- debugLogger.info(`Found knowledge documents in database: ${dbName}`, {
11554
- totalSize: result.size,
11555
- itemCount: result.count
11556
- });
11557
- break;
11558
- }
11559
- } catch (error) {
11560
- debugLogger.warn(`Failed to check knowledge in ${dbName}`, { error });
11561
- }
11562
- }
11563
- categories.push({
11564
- name: "Knowledge Documents",
11565
- icon: FileText,
11566
- size: knowledgeSize.size,
11567
- itemCount: knowledgeSize.count,
11568
- description: "Uploaded documents and their embeddings",
11569
- stores: foundKnowledgeDb ? [`${foundKnowledgeDb}.documents`] : [],
11570
- canClear: knowledgeSize.count > 0,
11571
- clearWarning: "This will remove all uploaded documents and their AI embeddings. You will need to re-upload documents."
11572
- });
11573
- debugLogger.info(`Knowledge Documents category created:`, {
11574
- itemCount: knowledgeSize.count,
11575
- size: knowledgeSize.size,
11576
- sizeFormatted: `${(knowledgeSize.size / 1024).toFixed(2)} KB`,
11577
- canClear: knowledgeSize.count > 0,
11578
- foundDb: foundKnowledgeDb
11579
- });
11580
- const memoryDbNames = ["bandit-memory-db", "banditMemories", "bandit-memories"];
11581
- let memorySize = { size: 0, count: 0 };
11582
- let foundMemoryDb = "";
11583
- for (const dbName of memoryDbNames) {
11584
- try {
11585
- const result = await estimateStoreSize(dbName, "memories");
11586
- if (result.count > 0) {
11587
- memorySize = result;
11588
- foundMemoryDb = dbName;
11589
- debugLogger.info(`Found memories in database: ${dbName}`);
11590
- break;
11591
- }
11592
- } catch (error) {
11593
- debugLogger.warn(`Failed to check memories in ${dbName}`, { error });
11594
- }
11595
- }
11596
- categories.push({
11597
- name: "AI Memories",
11598
- icon: User,
11599
- size: memorySize.size,
11600
- itemCount: memorySize.count,
11601
- description: "AI memory entries and learned patterns",
11602
- stores: foundMemoryDb ? [`${foundMemoryDb}.memories`] : [],
11603
- canClear: memorySize.count > 0,
11604
- clearWarning: "This will delete all AI memory entries and learned conversation patterns."
11605
- });
11606
- const configDbNames = ["banditConfig", "bandit-config"];
11607
- let configSize = { size: 0, count: 0 };
11608
- let foundConfigDb = "";
11609
- for (const dbName of configDbNames) {
11610
- try {
11611
- const result = await estimateStoreSize(dbName, "config");
11612
- if (result.count > 0) {
11613
- configSize = result;
11614
- foundConfigDb = dbName;
11615
- debugLogger.info(`Found config in database: ${dbName}`);
11616
- break;
11617
- }
11618
- } catch (error) {
11619
- debugLogger.warn(`Failed to check config in ${dbName}`, { error });
11620
- }
11621
- }
11622
- categories.push({
11623
- name: "App Settings & Models",
11624
- icon: Settings,
11625
- size: configSize.size,
11626
- itemCount: configSize.count,
11627
- description: "Custom models, app settings, and user preferences",
11628
- stores: foundConfigDb ? [`${foundConfigDb}.config`] : [],
11629
- canClear: configSize.count > 0,
11630
- clearWarning: "This will delete all custom AI models, app settings, themes, and preferences. The app will reset to defaults."
11631
- });
11632
- const queryDbNames = ["banditAIQuery", "ai-query-db"];
11633
- let querySize = { size: 0, count: 0 };
11634
- let foundQueryDb = "";
11635
- for (const dbName of queryDbNames) {
11636
- try {
11637
- const result = await estimateStoreSize(dbName, "queries");
11638
- if (result.count > 0) {
11639
- querySize = result;
11640
- foundQueryDb = dbName;
11641
- debugLogger.info(`Found AI queries in database: ${dbName}`);
11642
- break;
11560
+ const existing = await listExistingDatabases();
11561
+ const measure = async (target) => existing && !existing.has(target.db) ? { size: 0, count: 0 } : estimateStoreSize(target.db, target.store);
11562
+ const location = (target) => `${target.db}.${target.store}`;
11563
+ const [conversations, projects, knowledge, memories, config, queryCache] = await Promise.all([
11564
+ measure(BANDIT_DATABASES.conversations),
11565
+ measure(BANDIT_DATABASES.projects),
11566
+ measure(BANDIT_DATABASES.knowledge),
11567
+ measure(BANDIT_DATABASES.memories),
11568
+ measure(BANDIT_DATABASES.config),
11569
+ measure(BANDIT_DATABASES.queryCache)
11570
+ ]);
11571
+ const categories = [
11572
+ {
11573
+ name: "Chat History",
11574
+ icon: MessageSquare,
11575
+ size: conversations.size,
11576
+ itemCount: conversations.count,
11577
+ description: "Conversation history and messages",
11578
+ stores: [location(BANDIT_DATABASES.conversations)],
11579
+ canClear: conversations.count > 0,
11580
+ clearWarning: "This will permanently delete all your chat conversations and message history.",
11581
+ // Through the store, so the sidebar empties with it and sync sees the deletes.
11582
+ clear: () => useConversationStore.getState().clearAllConversations()
11583
+ },
11584
+ {
11585
+ name: "Projects",
11586
+ icon: Folder,
11587
+ size: projects.size,
11588
+ itemCount: projects.count,
11589
+ description: "Project names, colours and instructions",
11590
+ stores: [location(BANDIT_DATABASES.projects)],
11591
+ canClear: projects.count > 0,
11592
+ clearWarning: "This deletes every project. Conversations in them are kept, without a project.",
11593
+ clear: async () => {
11594
+ await clearStoreRows(BANDIT_DATABASES.projects.db, BANDIT_DATABASES.projects.store);
11595
+ await useProjectStore.getState().hydrate();
11643
11596
  }
11644
- } catch (error) {
11645
- debugLogger.warn(`Failed to check queries in ${dbName}`, { error });
11597
+ },
11598
+ {
11599
+ name: "Knowledge Documents",
11600
+ icon: FileText,
11601
+ size: knowledge.size,
11602
+ itemCount: knowledge.count,
11603
+ description: "Uploaded documents and their embeddings",
11604
+ stores: [location(BANDIT_DATABASES.knowledge)],
11605
+ canClear: knowledge.count > 0,
11606
+ clearWarning: "This will remove all uploaded documents and their AI embeddings. You will need to re-upload documents."
11607
+ },
11608
+ {
11609
+ name: "AI Memories",
11610
+ icon: User,
11611
+ size: memories.size,
11612
+ itemCount: memories.count,
11613
+ description: "What Bandit remembers from your chats (this browser's copy)",
11614
+ stores: [location(BANDIT_DATABASES.memories)],
11615
+ canClear: memories.count > 0,
11616
+ clearWarning: "This will delete all AI memory entries and learned conversation patterns.",
11617
+ clear: () => useMemoryStore.getState().clearMemories()
11618
+ },
11619
+ {
11620
+ name: "App Settings & Models",
11621
+ icon: Settings,
11622
+ size: config.size,
11623
+ itemCount: config.count,
11624
+ description: "Custom models, app settings, and user preferences",
11625
+ stores: [location(BANDIT_DATABASES.config)],
11626
+ canClear: config.count > 0,
11627
+ clearWarning: "This will delete all custom AI models, app settings, themes, and preferences. The app will reset to defaults."
11646
11628
  }
11647
- }
11648
- if (querySize.count > 0) {
11629
+ ];
11630
+ if (queryCache.count > 0) {
11649
11631
  categories.push({
11650
11632
  name: "AI Query Cache",
11651
11633
  icon: User,
11652
- size: querySize.size,
11653
- itemCount: querySize.count,
11634
+ size: queryCache.size,
11635
+ itemCount: queryCache.count,
11654
11636
  description: "Cached AI query results and responses",
11655
- stores: [`${foundQueryDb}.queries`],
11637
+ stores: [location(BANDIT_DATABASES.queryCache)],
11656
11638
  canClear: true,
11657
11639
  clearWarning: "This will delete all cached AI query results."
11658
11640
  });
@@ -11662,8 +11644,7 @@ var getIndexedDBSize = async () => {
11662
11644
  categories: categories.map((cat) => ({
11663
11645
  name: cat.name,
11664
11646
  itemCount: cat.itemCount,
11665
- canClear: cat.canClear,
11666
- storesLength: cat.stores.length
11647
+ canClear: cat.canClear
11667
11648
  }))
11668
11649
  });
11669
11650
  return categories;
@@ -11719,39 +11700,37 @@ var estimateStoreSize = async (dbName, storeName) => {
11719
11700
  return { size: 0, count: 0 };
11720
11701
  }
11721
11702
  };
11703
+ var clearStoreRows = async (dbName, storeName) => {
11704
+ const storeConfigs = [{ name: storeName, keyPath: "id" }];
11705
+ const items = await indexedDBService_default.getAll(dbName, 1, storeName, storeConfigs);
11706
+ const records = Array.isArray(items) ? items : [];
11707
+ for (const rawItem of records) {
11708
+ if (rawItem && typeof rawItem === "object") {
11709
+ const record = rawItem;
11710
+ const candidate = record["id"] ?? record["key"] ?? record["name"];
11711
+ if (typeof candidate === "string" && candidate.length > 0) {
11712
+ await indexedDBService_default.delete(dbName, 1, storeName, candidate, storeConfigs);
11713
+ }
11714
+ }
11715
+ }
11716
+ debugLogger.info(`Cleared ${records.length} items from ${dbName}.${storeName}`);
11717
+ };
11722
11718
  var clearStorageCategory = async (category) => {
11723
11719
  debugLogger.info(`Clearing storage category: ${category.name}`);
11720
+ if (category.clear) {
11721
+ await category.clear();
11722
+ return;
11723
+ }
11724
11724
  for (const storeSpec of category.stores) {
11725
+ const dot = storeSpec.indexOf(".");
11726
+ const dbName = dot > 0 ? storeSpec.slice(0, dot) : "";
11727
+ const storeName = dot > 0 ? storeSpec.slice(dot + 1) : "";
11728
+ if (!dbName || !storeName) {
11729
+ debugLogger.warn(`Invalid store specification: ${storeSpec}`);
11730
+ continue;
11731
+ }
11725
11732
  try {
11726
- const [dbName, storeName] = storeSpec.split(".");
11727
- debugLogger.info(`Clearing store: ${dbName}.${storeName}`);
11728
- if (!dbName || !storeName) {
11729
- debugLogger.warn(`Invalid store specification: ${storeSpec}`);
11730
- continue;
11731
- }
11732
- const storeConfigs = [{ name: storeName, keyPath: "id" }];
11733
- const items = await indexedDBService_default.getAll(dbName, 1, storeName, storeConfigs);
11734
- const records = Array.isArray(items) ? items : [];
11735
- if (records.length > 0) {
11736
- for (const rawItem of records) {
11737
- if (rawItem && typeof rawItem === "object") {
11738
- const record = rawItem;
11739
- const candidate = record["id"] ?? record["key"] ?? record["name"];
11740
- if (typeof candidate === "string" && candidate.length > 0) {
11741
- await indexedDBService_default.delete(
11742
- dbName,
11743
- 1,
11744
- storeName,
11745
- candidate,
11746
- storeConfigs
11747
- );
11748
- }
11749
- }
11750
- }
11751
- debugLogger.info(`Cleared ${records.length} items from ${dbName}.${storeName}`);
11752
- } else {
11753
- debugLogger.info(`No items found in ${dbName}.${storeName}`);
11754
- }
11733
+ await clearStoreRows(dbName, storeName);
11755
11734
  } catch (error) {
11756
11735
  debugLogger.error(`Failed to clear store: ${storeSpec}`, { error });
11757
11736
  }
@@ -11778,7 +11757,7 @@ var clearEntireDatabase = async (dbName) => {
11778
11757
  };
11779
11758
  });
11780
11759
  };
11781
- var StorageTab = ({ currentTheme }) => {
11760
+ var StorageTab = () => {
11782
11761
  const theme = useTheme13();
11783
11762
  const [storageQuota, setStorageQuota] = useState19({
11784
11763
  used: 0,
@@ -11927,18 +11906,8 @@ var StorageTab = ({ currentTheme }) => {
11927
11906
  setClearing(true);
11928
11907
  try {
11929
11908
  const databases = [
11930
- // Current databases
11931
- "banditConfig",
11932
- "bandit-knowledge",
11933
- "bandit-conversations",
11934
- "bandit-memory-db",
11935
- // Legacy/duplicate databases
11936
- "banditConversations",
11937
- "banditKnowledge",
11938
- "banditMemories",
11939
- "banditAIQuery",
11940
- "ai-query-db",
11941
- "knowledge"
11909
+ ...Object.values(BANDIT_DATABASES).map((target) => target.db),
11910
+ ...LEGACY_DATABASES
11942
11911
  ];
11943
11912
  for (const dbName of databases) {
11944
11913
  await clearEntireDatabase(dbName);
@@ -12197,7 +12166,7 @@ var StorageTab = ({ currentTheme }) => {
12197
12166
  compact: true,
12198
12167
  icon: /* @__PURE__ */ jsx18(Database, {}),
12199
12168
  title: "No stored data found",
12200
- description: "Bandit keeps conversations, knowledge documents, memories and settings in this browser. Nothing was found, either because it's empty or the databases couldn't be read.",
12169
+ description: "Bandit keeps conversations, projects, knowledge documents, memories and settings in this browser. Nothing was found, either because it's empty or the databases couldn't be read.",
12201
12170
  action: /* @__PURE__ */ jsx18(
12202
12171
  Button10,
12203
12172
  {
@@ -12727,7 +12696,6 @@ var ProviderTab = () => {
12727
12696
  type: config.type
12728
12697
  });
12729
12698
  } catch (error) {
12730
- console.error("Failed to save provider config to IndexedDB:", error);
12731
12699
  debugLogger.error("Failed to save provider config to IndexedDB:", { error });
12732
12700
  throw error;
12733
12701
  }
@@ -14563,6 +14531,11 @@ import {
14563
14531
  import { alpha as alpha3 } from "@mui/material/styles";
14564
14532
  import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
14565
14533
  var RAIL_WIDTH = 248;
14534
+ var GROUP_HEADINGS = [
14535
+ { group: "home", heading: null },
14536
+ { group: "you", heading: "You" },
14537
+ { group: "workspace", heading: "Workspace" }
14538
+ ];
14566
14539
  var controlRadius = (theme) => `${Math.max(Number(theme.shape.borderRadius) - 2, 4)}px`;
14567
14540
  var SECTION_ICONS = {
14568
14541
  overview: Home2,
@@ -14612,8 +14585,14 @@ function Navigation({
14612
14585
  onBackToChat,
14613
14586
  onBackHover,
14614
14587
  onOpenCommandPalette,
14588
+ grouped,
14615
14589
  onAfterSelect
14616
14590
  }) {
14591
+ const lists = grouped ? GROUP_HEADINGS.map(({ group, heading }) => ({
14592
+ key: group,
14593
+ heading,
14594
+ items: sections.filter((section) => section.group === group)
14595
+ })).filter((list) => list.items.length > 0) : [{ key: "all", heading: "Workspace", items: sections }];
14617
14596
  const subheaderSx = {
14618
14597
  bgcolor: "transparent",
14619
14598
  lineHeight: "28px",
@@ -14706,14 +14685,16 @@ function Navigation({
14706
14685
  "aria-label": "Management",
14707
14686
  sx: { flex: 1, overflowY: "auto", px: 1.5, pb: 2 },
14708
14687
  children: [
14709
- /* @__PURE__ */ jsx23(
14688
+ lists.map((list, index) => /* @__PURE__ */ jsx23(
14710
14689
  List5,
14711
14690
  {
14712
14691
  component: "div",
14713
14692
  dense: true,
14714
14693
  disablePadding: true,
14715
- subheader: /* @__PURE__ */ jsx23(ListSubheader, { component: "div", disableSticky: true, sx: subheaderSx, children: "Workspace" }),
14716
- children: sections.map((section) => {
14694
+ "aria-label": list.heading ?? void 0,
14695
+ sx: index > 0 && !list.heading ? { mt: 1 } : void 0,
14696
+ subheader: list.heading ? /* @__PURE__ */ jsx23(ListSubheader, { component: "div", disableSticky: true, sx: subheaderSx, children: list.heading }) : void 0,
14697
+ children: list.items.map((section) => {
14717
14698
  const Icon = SECTION_ICONS[section.id];
14718
14699
  const selected = section.id === active;
14719
14700
  return /* @__PURE__ */ jsxs19(
@@ -14743,8 +14724,9 @@ function Navigation({
14743
14724
  section.id
14744
14725
  );
14745
14726
  })
14746
- }
14747
- ),
14727
+ },
14728
+ list.key
14729
+ )),
14748
14730
  organizationLinks && organizationLinks.length > 0 && /* @__PURE__ */ jsx23(
14749
14731
  List5,
14750
14732
  {
@@ -15153,6 +15135,11 @@ function ManagementOverview({
15153
15135
 
15154
15136
  // src/management/shell/sections.ts
15155
15137
  import { useMemo as useMemo7 } from "react";
15138
+
15139
+ // src/management/shell/console.ts
15140
+ var managementConsoleVariant = () => IS_STORE_BUILD || isNativeShell() ? "native" : "web";
15141
+
15142
+ // src/management/shell/sections.ts
15156
15143
  var MANAGEMENT_SECTIONS = [
15157
15144
  {
15158
15145
  id: "overview",
@@ -15160,7 +15147,8 @@ var MANAGEMENT_SECTIONS = [
15160
15147
  description: "This workspace at a glance: personalities, knowledge, provider and appearance.",
15161
15148
  keywords: ["home", "summary", "dashboard"],
15162
15149
  requiresAdmin: true,
15163
- requiresFeature: "limitedAdminDashboard"
15150
+ requiresFeature: "limitedAdminDashboard",
15151
+ group: "home"
15164
15152
  },
15165
15153
  {
15166
15154
  id: "personalities",
@@ -15168,7 +15156,8 @@ var MANAGEMENT_SECTIONS = [
15168
15156
  description: "The assistants people chat with: their name, prompt, model and avatar.",
15169
15157
  keywords: ["models", "assistant", "prompt", "persona", "create personality"],
15170
15158
  requiresAdmin: true,
15171
- requiresFeature: "limitedAdminDashboard"
15159
+ requiresFeature: "limitedAdminDashboard",
15160
+ group: "workspace"
15172
15161
  },
15173
15162
  {
15174
15163
  id: "knowledge",
@@ -15176,7 +15165,8 @@ var MANAGEMENT_SECTIONS = [
15176
15165
  description: "Documents Bandit can answer from, and seed packs for new workspaces.",
15177
15166
  keywords: ["documents", "upload", "files", "seed packs", "rag"],
15178
15167
  requiresAdmin: true,
15179
- requiresFeature: "limitedAdminDashboard"
15168
+ requiresFeature: "limitedAdminDashboard",
15169
+ group: "workspace"
15180
15170
  },
15181
15171
  {
15182
15172
  id: "tools",
@@ -15184,7 +15174,8 @@ var MANAGEMENT_SECTIONS = [
15184
15174
  description: "Built-in tools and connected MCP servers the assistant can call.",
15185
15175
  keywords: ["mcp", "integrations", "servers", "functions"],
15186
15176
  requiresAdmin: true,
15187
- requiresFeature: "advancedSearch"
15177
+ requiresFeature: "advancedSearch",
15178
+ group: "workspace"
15188
15179
  },
15189
15180
  {
15190
15181
  id: "provider",
@@ -15192,7 +15183,8 @@ var MANAGEMENT_SECTIONS = [
15192
15183
  description: "The model backend that powers chat: gateway, OpenAI, Ollama and others.",
15193
15184
  keywords: ["engine", "model", "api key", "gateway", "ollama", "openai"],
15194
15185
  requiresAdmin: true,
15195
- requiresFeature: "advancedSearch"
15186
+ requiresFeature: "advancedSearch",
15187
+ group: "workspace"
15196
15188
  },
15197
15189
  {
15198
15190
  id: "storage",
@@ -15200,7 +15192,8 @@ var MANAGEMENT_SECTIONS = [
15200
15192
  description: "What this browser keeps locally, and how much room it takes.",
15201
15193
  keywords: ["indexeddb", "cache", "clear", "data"],
15202
15194
  requiresAdmin: true,
15203
- requiresFeature: "limitedAdminDashboard"
15195
+ requiresFeature: "limitedAdminDashboard",
15196
+ group: "workspace"
15204
15197
  },
15205
15198
  {
15206
15199
  id: "branding",
@@ -15208,7 +15201,8 @@ var MANAGEMENT_SECTIONS = [
15208
15201
  description: "Logo, name and theme for this workspace.",
15209
15202
  keywords: ["theme", "logo", "colors", "appearance", "change theme"],
15210
15203
  requiresAdmin: true,
15211
- requiresFeature: "limitedAdminDashboard"
15204
+ requiresFeature: "limitedAdminDashboard",
15205
+ group: "workspace"
15212
15206
  },
15213
15207
  {
15214
15208
  id: "schedules",
@@ -15216,7 +15210,8 @@ var MANAGEMENT_SECTIONS = [
15216
15210
  description: "Prompts Bandit runs for you on a schedule, with results in chat and by email.",
15217
15211
  keywords: ["scheduled tasks", "recurring", "cron", "daily", "weekly", "automation", "email", "reminder"],
15218
15212
  requiresAdmin: false,
15219
- requiresFeature: "limitedAdminDashboard"
15213
+ requiresFeature: "limitedAdminDashboard",
15214
+ group: "you"
15220
15215
  },
15221
15216
  {
15222
15217
  id: "preferences",
@@ -15224,10 +15219,52 @@ var MANAGEMENT_SECTIONS = [
15224
15219
  description: "Your own settings for this device. Changes save automatically.",
15225
15220
  keywords: ["settings", "memory", "voice", "features"],
15226
15221
  requiresAdmin: false,
15227
- requiresFeature: "limitedAdminDashboard"
15222
+ requiresFeature: "limitedAdminDashboard",
15223
+ group: "you"
15228
15224
  }
15229
15225
  ];
15230
15226
  var sectionById = (id) => MANAGEMENT_SECTIONS.find((s) => s.id === id) ?? MANAGEMENT_SECTIONS[0];
15227
+ var WEB_PRESENTATION = {
15228
+ personalities: {
15229
+ description: "Named assistants, each with its own instructions and avatar. The active one answers new chats."
15230
+ },
15231
+ tools: {
15232
+ label: "Tools & integrations",
15233
+ description: "Connected MCP servers, your Bandit Crew, and the built-in capabilities Bandit may use.",
15234
+ keywords: ["mcp", "integrations", "servers", "functions", "crew", "tools"]
15235
+ },
15236
+ provider: {
15237
+ description: "The model service chat requests go to. Gateway is the default; OpenAI, Ollama and others are options."
15238
+ },
15239
+ storage: {
15240
+ label: "Local data",
15241
+ description: "What this browser stores for Bandit, and how to clear it.",
15242
+ keywords: ["indexeddb", "cache", "clear", "data", "storage", "local data"]
15243
+ },
15244
+ branding: {
15245
+ label: "Appearance",
15246
+ description: "Name, logo, accent colour and light or dark mode for this workspace.",
15247
+ keywords: ["theme", "logo", "colors", "appearance", "branding", "change theme"]
15248
+ },
15249
+ preferences: {
15250
+ description: "Your settings on this device: conversation starters, memory, voice and sync. Changes save automatically."
15251
+ }
15252
+ };
15253
+ var WEB_ORDER = [
15254
+ "overview",
15255
+ "preferences",
15256
+ "schedules",
15257
+ "personalities",
15258
+ "knowledge",
15259
+ "tools",
15260
+ "branding",
15261
+ "provider",
15262
+ "storage"
15263
+ ];
15264
+ function presentManagementSections(sections, variant) {
15265
+ if (variant === "native") return [...sections];
15266
+ return sections.map((section) => ({ ...section, ...WEB_PRESENTATION[section.id] })).sort((a, b) => WEB_ORDER.indexOf(a.id) - WEB_ORDER.indexOf(b.id));
15267
+ }
15231
15268
  function isWorkspaceAdminRole(roles) {
15232
15269
  const platformAdminRoles = /* @__PURE__ */ new Set(["admin", "platform_admin"]);
15233
15270
  return roles.map((r) => r.toLowerCase()).some((r) => platformAdminRoles.has(r) || r.endsWith("-admin"));
@@ -15252,12 +15289,15 @@ function useManagementAccess() {
15252
15289
  return useMemo7(() => {
15253
15290
  const roles = (token ? authenticationService.parseJwtClaims(token)?.roles : void 0) ?? [];
15254
15291
  return {
15255
- sections: resolveManagementSections({
15256
- roles,
15257
- limitedAdminDashboard: limited,
15258
- adminDashboard: full,
15259
- advancedSearch: advanced
15260
- }),
15292
+ sections: presentManagementSections(
15293
+ resolveManagementSections({
15294
+ roles,
15295
+ limitedAdminDashboard: limited,
15296
+ adminDashboard: full,
15297
+ advancedSearch: advanced
15298
+ }),
15299
+ managementConsoleVariant()
15300
+ ),
15261
15301
  isWorkspaceAdmin: isWorkspaceAdminRole(roles),
15262
15302
  isLimitedAdmin: limited && !full
15263
15303
  };
@@ -15266,8 +15306,8 @@ function useManagementAccess() {
15266
15306
 
15267
15307
  // src/management/management.tsx
15268
15308
  import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
15269
- var preloadChatPage = () => import("./chat-W7MDFESE.mjs");
15270
- var SchedulesTab = lazy(() => import("./SchedulesTab-YZG3P2GW.mjs"));
15309
+ var preloadChatPage = () => import("./chat-MI4IL3WK.mjs");
15310
+ var SchedulesTab = lazy(() => import("./SchedulesTab-AKJ6WFZV.mjs"));
15271
15311
  var buildCapabilitiesUrl = (gatewayApiUrl) => {
15272
15312
  const trimmed = gatewayApiUrl.replace(/\/$/, "");
15273
15313
  if (trimmed.endsWith("/api")) {
@@ -15289,6 +15329,9 @@ var Management = ({
15289
15329
  const navigate = useNavigate2();
15290
15330
  const notificationService2 = useNotificationService();
15291
15331
  const isMobile = useMediaQuery7("(max-width:900px)");
15332
+ const consoleVariant = managementConsoleVariant();
15333
+ const webConsole = consoleVariant === "web";
15334
+ const showAssistantFab = !isMobile && !webConsole;
15292
15335
  const getOptimalFabLogo = async () => {
15293
15336
  const banditHead4 = "https://cdn.burtson.ai/images/bandit-head.png";
15294
15337
  try {
@@ -15314,16 +15357,12 @@ var Management = ({
15314
15357
  }
15315
15358
  };
15316
15359
  const {
15317
- name: modelName,
15318
15360
  setModelName,
15319
- tagline,
15320
15361
  setTagline,
15321
- systemPrompt,
15322
15362
  setSystemPrompt,
15323
15363
  availableModels,
15324
15364
  selectedModel,
15325
15365
  setSelectedModel,
15326
- saveModel,
15327
15366
  resetModel,
15328
15367
  hasTransparentLogo,
15329
15368
  setHasTransparentLogo
@@ -15331,7 +15370,7 @@ var Management = ({
15331
15370
  const [modalOpen, setModalOpen] = useState24(false);
15332
15371
  const banditHead3 = "https://cdn.burtson.ai/images/bandit-head.png";
15333
15372
  const [fabLogo, setFabLogo] = useState24(banditHead3);
15334
- const [logoFile, setLogoFile] = useState24(null);
15373
+ const [, setLogoFile] = useState24(null);
15335
15374
  const [logoBase64, setLogoBase64] = useState24(null);
15336
15375
  const [brandingText, setBrandingText] = useState24("");
15337
15376
  const [headerMode, setHeaderMode] = useState24("logo");
@@ -15520,15 +15559,13 @@ var Management = ({
15520
15559
  const handleOpenModal = () => setModalOpen(true);
15521
15560
  const handleCloseModal = () => setModalOpen(false);
15522
15561
  useEffect21(() => {
15523
- getOptimalFabLogo().then(setFabLogo);
15524
- }, []);
15525
- useEffect21(() => {
15562
+ if (!showAssistantFab) return;
15526
15563
  if (logoBase64) {
15527
15564
  setFabLogo(logoBase64);
15528
15565
  } else {
15529
15566
  getOptimalFabLogo().then(setFabLogo);
15530
15567
  }
15531
- }, [logoBase64]);
15568
+ }, [logoBase64, showAssistantFab]);
15532
15569
  const handleSaveModel = async () => {
15533
15570
  debugLogger.info("STARTING handleSaveModel", {
15534
15571
  modelName: localSelectedModel.name,
@@ -15827,7 +15864,7 @@ var Management = ({
15827
15864
  setLogoFile(null);
15828
15865
  setCustomAvatarBase64(null);
15829
15866
  setPresetAvatar(null);
15830
- getOptimalFabLogo().then(setFabLogo);
15867
+ if (showAssistantFab) getOptimalFabLogo().then(setFabLogo);
15831
15868
  try {
15832
15869
  const storeConfigs = [{ name: "config", keyPath: "id" }];
15833
15870
  const current = await indexedDBService_default.get(
@@ -15957,19 +15994,12 @@ var Management = ({
15957
15994
  debugLogger.error("Failed to restore default models and config", { error: err });
15958
15995
  }
15959
15996
  };
15960
- const restoreBanditModels = async () => {
15961
- try {
15962
- debugLogger.info("Restoring deleted Bandit models");
15963
- await useModelStore.getState().restoreDeletedBanditModels();
15964
- debugLogger.info("\u2705 Bandit models restored successfully");
15965
- } catch (err) {
15966
- debugLogger.error("Failed to restore Bandit models", { error: err });
15967
- }
15968
- };
15969
15997
  const handleImportConfig = (event) => {
15970
- if (event.target.files && event.target.files[0]) {
15971
- const file = event.target.files[0];
15998
+ const file = event.target.files?.[0];
15999
+ if (!file) return Promise.resolve();
16000
+ return new Promise((resolve, reject) => {
15972
16001
  const reader = new FileReader();
16002
+ reader.onerror = () => reject(reader.error ?? new Error("Could not read the file"));
15973
16003
  reader.onload = async function(e) {
15974
16004
  try {
15975
16005
  const data = JSON.parse(e.target?.result);
@@ -15978,7 +16008,7 @@ var Management = ({
15978
16008
  setHeaderMode(
15979
16009
  data.branding.headerMode || "logo"
15980
16010
  );
15981
- setTheme(data.branding.theme || "Dark");
16011
+ setTheme(data.branding.theme || "bandit-dark");
15982
16012
  setLogoBase64(data.branding.logoBase64 || null);
15983
16013
  setLogoFile(null);
15984
16014
  if (data.branding.hasTransparentLogo !== void 0) {
@@ -15992,21 +16022,21 @@ var Management = ({
15992
16022
  continue;
15993
16023
  }
15994
16024
  const parsedModel = model;
15995
- const modelName2 = typeof parsedModel.name === "string" ? parsedModel.name : "";
15996
- if (!modelName2) {
16025
+ const modelName = typeof parsedModel.name === "string" ? parsedModel.name : "";
16026
+ if (!modelName) {
15997
16027
  continue;
15998
16028
  }
15999
16029
  const sanitizedModel = {
16000
- name: modelName2,
16030
+ name: modelName,
16001
16031
  tagline: typeof parsedModel.tagline === "string" ? parsedModel.tagline : void 0,
16002
16032
  systemPrompt: typeof parsedModel.systemPrompt === "string" ? parsedModel.systemPrompt : void 0,
16003
16033
  selectedModel: typeof parsedModel.selectedModel === "string" ? parsedModel.selectedModel : void 0,
16004
16034
  avatarBase64: typeof parsedModel.avatarBase64 === "string" ? parsedModel.avatarBase64 : parsedModel.avatarBase64 === null ? void 0 : void 0
16005
16035
  };
16006
16036
  const entry = {
16007
- id: modelName2,
16037
+ id: modelName,
16008
16038
  model: sanitizedModel,
16009
- name: modelName2,
16039
+ name: modelName,
16010
16040
  tagline: sanitizedModel.tagline,
16011
16041
  systemPrompt: sanitizedModel.systemPrompt,
16012
16042
  // Normalize to match StoredBanditConfigRecord (string | undefined)
@@ -16060,12 +16090,14 @@ var Management = ({
16060
16090
  if (typeof initModels === "function") {
16061
16091
  await initModels();
16062
16092
  }
16093
+ resolve();
16063
16094
  } catch (e2) {
16064
16095
  debugLogger.error("Failed to import config", { error: e2 });
16096
+ reject(e2 instanceof Error ? e2 : new Error(String(e2)));
16065
16097
  }
16066
16098
  };
16067
16099
  reader.readAsText(file);
16068
- }
16100
+ });
16069
16101
  };
16070
16102
  useEffect21(() => {
16071
16103
  if (localSelectedModel.selectedModel && !availableModels.some((m) => m.name === localSelectedModel.selectedModel)) {
@@ -16130,8 +16162,11 @@ var Management = ({
16130
16162
  }, [currentTheme, onThemeChange]);
16131
16163
  const access = useManagementAccess();
16132
16164
  const sections = useMemo8(
16133
- () => sectionOverride ? MANAGEMENT_SECTIONS.filter((s) => sectionOverride.includes(s.id)) : access.sections,
16134
- [sectionOverride, access.sections]
16165
+ () => sectionOverride ? presentManagementSections(
16166
+ MANAGEMENT_SECTIONS.filter((s) => sectionOverride.includes(s.id)),
16167
+ consoleVariant
16168
+ ) : access.sections,
16169
+ [sectionOverride, access.sections, consoleVariant]
16135
16170
  );
16136
16171
  const defaultSection = sections.some((s) => s.id === "overview") ? "overview" : sections.some((s) => s.id === "preferences") ? "preferences" : sections[0]?.id ?? "preferences";
16137
16172
  const [ownSection, setOwnSection] = useState24(null);
@@ -16144,7 +16179,7 @@ var Management = ({
16144
16179
  },
16145
16180
  [onSectionChange]
16146
16181
  );
16147
- const activeDef = sectionById(active);
16182
+ const activeDef = sections.find((s) => s.id === active) ?? sectionById(active);
16148
16183
  const [createPersonalityRequest, setCreatePersonalityRequest] = useState24(0);
16149
16184
  const [pendingUpload, setPendingUpload] = useState24(0);
16150
16185
  useEffect21(() => {
@@ -16251,6 +16286,7 @@ var Management = ({
16251
16286
  onBackToChat: () => navigate(chatPath),
16252
16287
  onBackHover: preloadChatPage,
16253
16288
  onOpenCommandPalette,
16289
+ grouped: webConsole,
16254
16290
  isMobile,
16255
16291
  children: /* @__PURE__ */ jsx25(SectionSkeleton, {})
16256
16292
  }
@@ -16269,6 +16305,7 @@ var Management = ({
16269
16305
  onBackToChat: () => navigate(chatPath),
16270
16306
  onBackHover: preloadChatPage,
16271
16307
  onOpenCommandPalette,
16308
+ grouped: webConsole,
16272
16309
  isMobile,
16273
16310
  children: [
16274
16311
  notice,
@@ -16327,15 +16364,14 @@ var Management = ({
16327
16364
  handleSaveModel,
16328
16365
  handleResetModel,
16329
16366
  restoreDefaultModelsAndConfig,
16330
- restoreBanditModels,
16331
16367
  showSnackbar: showSnackbarMessage,
16332
- createRequest: createPersonalityRequest
16368
+ createRequest: createPersonalityRequest,
16369
+ webConsole
16333
16370
  }
16334
16371
  ),
16335
16372
  active === "branding" && /* @__PURE__ */ jsx25(
16336
16373
  BrandingTab_default,
16337
16374
  {
16338
- logoFile,
16339
16375
  logoBase64,
16340
16376
  brandingText,
16341
16377
  setBrandingText,
@@ -16343,16 +16379,10 @@ var Management = ({
16343
16379
  setHeaderMode,
16344
16380
  theme,
16345
16381
  setTheme,
16346
- predefinedThemes,
16347
16382
  handleLogoUpload,
16348
16383
  handleRestoreDefaults,
16349
16384
  handleExportConfig,
16350
16385
  handleImportConfig,
16351
- handleSaveBranding: async () => {
16352
- const ok = await handleSaveBranding();
16353
- if (ok) setBrandingBaseline(brandingValue);
16354
- return ok;
16355
- },
16356
16386
  setLogoFile,
16357
16387
  setLogoBase64
16358
16388
  }
@@ -16365,12 +16395,10 @@ var Management = ({
16365
16395
  removeDocument,
16366
16396
  loadDocuments,
16367
16397
  clearAllDocuments,
16368
- currentTheme,
16369
- isLimitedAdmin: access.isLimitedAdmin,
16370
16398
  seedPacksEnabled
16371
16399
  }
16372
16400
  ),
16373
- active === "storage" && /* @__PURE__ */ jsx25(StorageTab_default, { currentTheme }),
16401
+ active === "storage" && /* @__PURE__ */ jsx25(StorageTab_default, {}),
16374
16402
  active === "preferences" && /* @__PURE__ */ jsx25(
16375
16403
  PreferencesTab_default,
16376
16404
  {
@@ -16378,7 +16406,8 @@ var Management = ({
16378
16406
  updatePreference,
16379
16407
  packageSettings,
16380
16408
  handleSavePreferences,
16381
- showSnackbar: showSnackbarMessage
16409
+ showSnackbar: showSnackbarMessage,
16410
+ showDiagnostics: !webConsole
16382
16411
  }
16383
16412
  ),
16384
16413
  active === "provider" && /* @__PURE__ */ jsx25(ProviderTab, {}),
@@ -16414,7 +16443,7 @@ var Management = ({
16414
16443
  ]
16415
16444
  }
16416
16445
  ),
16417
- !isMobile && /* @__PURE__ */ jsx25(
16446
+ showAssistantFab && /* @__PURE__ */ jsx25(
16418
16447
  Fab2,
16419
16448
  {
16420
16449
  "aria-label": "Ask the assistant",
@@ -16436,7 +16465,7 @@ var Management = ({
16436
16465
  )
16437
16466
  }
16438
16467
  ),
16439
- !isMobile && /* @__PURE__ */ jsx25(chat_modal_default, { open: modalOpen, onClose: handleCloseModal })
16468
+ showAssistantFab && /* @__PURE__ */ jsx25(chat_modal_default, { open: modalOpen, onClose: handleCloseModal })
16440
16469
  ] });
16441
16470
  };
16442
16471
  var management_default = Management;