@burtson-labs/bandit-engine 2.0.50 → 2.0.52

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 (37) hide show
  1. package/dist/{chat-CQWZOJH4.mjs → chat-YWYLVKXX.mjs} +5 -5
  2. package/dist/chat-provider.js +254 -22
  3. package/dist/chat-provider.js.map +1 -1
  4. package/dist/chat-provider.mjs +3 -3
  5. package/dist/{chunk-VL3CMSDO.mjs → chunk-37PEP5JK.mjs} +2 -2
  6. package/dist/{chunk-AXFX2HUK.mjs → chunk-M3BEAMCC.mjs} +2 -2
  7. package/dist/{chunk-HKJTRBWC.mjs → chunk-MH7WFWCP.mjs} +34 -3
  8. package/dist/chunk-MH7WFWCP.mjs.map +1 -0
  9. package/dist/{chunk-6WZUQHZT.mjs → chunk-QX6CO7TJ.mjs} +225 -23
  10. package/dist/chunk-QX6CO7TJ.mjs.map +1 -0
  11. package/dist/{chunk-TVF45U7B.mjs → chunk-RSSJADDD.mjs} +3 -3
  12. package/dist/{chunk-Q2N7CCZI.mjs → chunk-TSQCNHOX.mjs} +45 -6
  13. package/dist/chunk-TSQCNHOX.mjs.map +1 -0
  14. package/dist/{chunk-ZTTGERUG.mjs → chunk-Y5N3NSTU.mjs} +459 -180
  15. package/dist/chunk-Y5N3NSTU.mjs.map +1 -0
  16. package/dist/{chunk-KHKWYHXD.mjs → chunk-YZ2HJFPQ.mjs} +2 -2
  17. package/dist/cli.js +1 -1
  18. package/dist/cli.js.map +1 -1
  19. package/dist/index.js +747 -198
  20. package/dist/index.js.map +1 -1
  21. package/dist/index.mjs +8 -8
  22. package/dist/management/management.js +717 -198
  23. package/dist/management/management.js.map +1 -1
  24. package/dist/management/management.mjs +6 -6
  25. package/dist/modals/chat-modal/chat-modal.js +226 -22
  26. package/dist/modals/chat-modal/chat-modal.js.map +1 -1
  27. package/dist/modals/chat-modal/chat-modal.mjs +3 -3
  28. package/package.json +1 -1
  29. package/dist/chunk-6WZUQHZT.mjs.map +0 -1
  30. package/dist/chunk-HKJTRBWC.mjs.map +0 -1
  31. package/dist/chunk-Q2N7CCZI.mjs.map +0 -1
  32. package/dist/chunk-ZTTGERUG.mjs.map +0 -1
  33. /package/dist/{chat-CQWZOJH4.mjs.map → chat-YWYLVKXX.mjs.map} +0 -0
  34. /package/dist/{chunk-VL3CMSDO.mjs.map → chunk-37PEP5JK.mjs.map} +0 -0
  35. /package/dist/{chunk-AXFX2HUK.mjs.map → chunk-M3BEAMCC.mjs.map} +0 -0
  36. /package/dist/{chunk-TVF45U7B.mjs.map → chunk-RSSJADDD.mjs.map} +0 -0
  37. /package/dist/{chunk-KHKWYHXD.mjs.map → chunk-YZ2HJFPQ.mjs.map} +0 -0
@@ -6431,7 +6431,18 @@ async function saveStateToDB(state) {
6431
6431
  await indexedDBService_default.put(DB_NAME2, DB_VERSION, STORE_NAME2, state, storeConfigs2, STORAGE_KEY);
6432
6432
  }
6433
6433
  async function loadStateFromDB() {
6434
- return indexedDBService_default.get(DB_NAME2, DB_VERSION, STORE_NAME2, STORAGE_KEY, storeConfigs2);
6434
+ let timeoutId;
6435
+ const timeoutPromise = new Promise((resolve) => {
6436
+ timeoutId = window.setTimeout(() => resolve(void 0), 1200);
6437
+ });
6438
+ try {
6439
+ const getPromise = indexedDBService_default.get(DB_NAME2, DB_VERSION, STORE_NAME2, STORAGE_KEY, storeConfigs2).catch(() => void 0);
6440
+ return await Promise.race([getPromise, timeoutPromise]);
6441
+ } finally {
6442
+ if (timeoutId !== void 0) {
6443
+ window.clearTimeout(timeoutId);
6444
+ }
6445
+ }
6435
6446
  }
6436
6447
  var import_zustand6, DB_NAME2, STORE_NAME2, DB_VERSION, STORAGE_KEY, storeConfigs2, useAIQueryStore;
6437
6448
  var init_aiQueryStore = __esm({
@@ -6498,19 +6509,23 @@ var init_aiQueryStore = __esm({
6498
6509
  saveStateToDB(resetState);
6499
6510
  },
6500
6511
  hydrate: async () => {
6501
- const storedState = await loadStateFromDB();
6502
- if (storedState) {
6503
- set({
6504
- inputValue: storedState.inputValue ?? "",
6505
- response: storedState.response ?? "",
6506
- previousQuestion: storedState.previousQuestion ?? "",
6507
- position: storedState.position ?? { x: window.innerWidth / 2 - 300, y: window.innerHeight - 350 },
6508
- componentStatus: "Idle",
6509
- history: storedState.history ?? [],
6510
- apiKey: storedState.apiKey ?? "",
6511
- hydrated: true
6512
- });
6513
- } else {
6512
+ try {
6513
+ const storedState = await loadStateFromDB();
6514
+ if (storedState) {
6515
+ set({
6516
+ inputValue: storedState.inputValue ?? "",
6517
+ response: storedState.response ?? "",
6518
+ previousQuestion: storedState.previousQuestion ?? "",
6519
+ position: storedState.position ?? { x: window.innerWidth / 2 - 300, y: window.innerHeight - 350 },
6520
+ componentStatus: "Idle",
6521
+ history: storedState.history ?? [],
6522
+ apiKey: storedState.apiKey ?? "",
6523
+ hydrated: true
6524
+ });
6525
+ } else {
6526
+ set({ hydrated: true });
6527
+ }
6528
+ } catch {
6514
6529
  set({ hydrated: true });
6515
6530
  }
6516
6531
  }
@@ -7928,13 +7943,22 @@ var init_projectStore = __esm({
7928
7943
  });
7929
7944
 
7930
7945
  // src/services/auth/authenticationService.ts
7931
- var TOKEN_KEY2, AuthenticationService, authenticationService;
7946
+ function emitAuthTokenChanged(token) {
7947
+ if (typeof window === "undefined") {
7948
+ return;
7949
+ }
7950
+ window.dispatchEvent(new CustomEvent(AUTH_TOKEN_CHANGED_EVENT, {
7951
+ detail: { token }
7952
+ }));
7953
+ }
7954
+ var TOKEN_KEY2, AUTH_TOKEN_CHANGED_EVENT, AuthenticationService, authenticationService;
7932
7955
  var init_authenticationService = __esm({
7933
7956
  "src/services/auth/authenticationService.ts"() {
7934
7957
  "use strict";
7935
7958
  init_authenticationStore();
7936
7959
  init_debugLogger();
7937
7960
  TOKEN_KEY2 = "authToken";
7961
+ AUTH_TOKEN_CHANGED_EVENT = "bandit:auth-token-changed";
7938
7962
  AuthenticationService = class {
7939
7963
  getToken() {
7940
7964
  const token = localStorage.getItem(TOKEN_KEY2);
@@ -7943,10 +7967,12 @@ var init_authenticationService = __esm({
7943
7967
  setToken(token) {
7944
7968
  localStorage.setItem(TOKEN_KEY2, token);
7945
7969
  useAuthenticationStore.getState().setToken(token);
7970
+ emitAuthTokenChanged(token);
7946
7971
  }
7947
7972
  clearToken() {
7948
7973
  localStorage.removeItem(TOKEN_KEY2);
7949
7974
  useAuthenticationStore.getState().clearToken();
7975
+ emitAuthTokenChanged(null);
7950
7976
  }
7951
7977
  isAuthenticated() {
7952
7978
  const token = useAuthenticationStore.getState().token;
@@ -8103,9 +8129,99 @@ function ensureDeviceId() {
8103
8129
  return (0, import_uuid4.v4)();
8104
8130
  }
8105
8131
  }
8132
+ function getStoredSyncIdentity() {
8133
+ if (typeof window === "undefined") {
8134
+ return null;
8135
+ }
8136
+ try {
8137
+ return window.localStorage.getItem(SYNC_IDENTITY_STORAGE_KEY);
8138
+ } catch (error) {
8139
+ debugLogger.warn("conversationSyncStore: unable to read stored sync identity", { error });
8140
+ return null;
8141
+ }
8142
+ }
8143
+ function setStoredSyncIdentity(identity) {
8144
+ if (typeof window === "undefined") {
8145
+ return;
8146
+ }
8147
+ try {
8148
+ if (identity) {
8149
+ window.localStorage.setItem(SYNC_IDENTITY_STORAGE_KEY, identity);
8150
+ } else {
8151
+ window.localStorage.removeItem(SYNC_IDENTITY_STORAGE_KEY);
8152
+ }
8153
+ } catch (error) {
8154
+ debugLogger.warn("conversationSyncStore: unable to persist sync identity", { error });
8155
+ }
8156
+ }
8106
8157
  function getPackageDefaultAdvancedKnowledgeSync() {
8107
8158
  return usePackageSettingsStore.getState().settings?.advancedKnowledgeSyncDefaultEnabled;
8108
8159
  }
8160
+ function clearAutoSyncTimer() {
8161
+ if (autoSyncTimeout) {
8162
+ clearTimeout(autoSyncTimeout);
8163
+ autoSyncTimeout = null;
8164
+ }
8165
+ }
8166
+ function resolveAuthIdentity(token) {
8167
+ if (!token) {
8168
+ return null;
8169
+ }
8170
+ const claims = authenticationService.parseJwtClaims(token);
8171
+ if (claims?.sub) {
8172
+ return claims.sub;
8173
+ }
8174
+ if (claims?.email) {
8175
+ return `email:${claims.email.toLowerCase()}`;
8176
+ }
8177
+ return `token:${token.slice(0, 32)}`;
8178
+ }
8179
+ function buildQueueResetState() {
8180
+ return {
8181
+ pendingConversationUpserts: /* @__PURE__ */ new Set(),
8182
+ pendingConversationDeletes: /* @__PURE__ */ new Set(),
8183
+ pendingProjectUpserts: /* @__PURE__ */ new Set(),
8184
+ pendingProjectDeletes: /* @__PURE__ */ new Set(),
8185
+ conflicts: null,
8186
+ lastSyncAt: null,
8187
+ cursor: null,
8188
+ lastError: null,
8189
+ totalConversationsOnServer: void 0,
8190
+ totalProjectsOnServer: void 0,
8191
+ hasCompletedInitialUpload: false,
8192
+ warningConversations: [],
8193
+ oversizedConversations: []
8194
+ };
8195
+ }
8196
+ async function clearLocalStoresForIdentitySwitch(fromIdentity, toIdentity) {
8197
+ const conversationCount = useConversationStore.getState().conversations.length;
8198
+ const projectCount = useProjectStore.getState().projects.length;
8199
+ debugLogger.warn("conversationSyncStore: auth identity changed, clearing local conversation/project cache", {
8200
+ fromIdentity,
8201
+ toIdentity,
8202
+ conversationCount,
8203
+ projectCount
8204
+ });
8205
+ suppressTracking = true;
8206
+ try {
8207
+ await useConversationStore.getState().clearAllConversations();
8208
+ await indexedDBService_default.clear(
8209
+ PROJECT_DB_NAME,
8210
+ PROJECT_DB_VERSION,
8211
+ PROJECT_STORE_NAME,
8212
+ PROJECT_STORE_CONFIGS
8213
+ );
8214
+ useProjectStore.setState({ projects: [] });
8215
+ conversationsMeta = snapshotConversationMetaMap(useConversationStore.getState().conversations);
8216
+ projectsMeta = snapshotProjectMetaMap(useProjectStore.getState().projects);
8217
+ } catch (error) {
8218
+ debugLogger.error("conversationSyncStore: failed to clear local stores on auth switch", {
8219
+ error: error instanceof Error ? error.message : String(error)
8220
+ });
8221
+ } finally {
8222
+ suppressTracking = false;
8223
+ }
8224
+ }
8109
8225
  function mapConversationToDTO(conversation) {
8110
8226
  const updatedAtIso = (conversation.updatedAt ?? /* @__PURE__ */ new Date()).toISOString();
8111
8227
  const createdAtIso = conversation.createdAt ? conversation.createdAt.toISOString() : null;
@@ -8499,7 +8615,7 @@ function buildOversizedMessage(notices) {
8499
8615
  const names = notices.map((n) => `"${n.name || "Untitled"}"`).join(", ");
8500
8616
  return `Some conversations (${names}) are too large for Bandit Cloud. Start a new conversation or archive older turns to continue syncing.`;
8501
8617
  }
8502
- var import_zustand11, import_uuid4, DEVICE_STORAGE_KEY, PAYLOAD_VERSION, MAX_CONVERSATION_BYTES, WARN_CONVERSATION_BYTES, suppressTracking, conversationsMeta, projectsMeta, conversationUnsubscribe, projectUnsubscribe, autoSyncTimeout, AUTO_SYNC_DELAY_MS, useConversationSyncStore;
8618
+ var import_zustand11, import_uuid4, DEVICE_STORAGE_KEY, SYNC_IDENTITY_STORAGE_KEY, PAYLOAD_VERSION, MAX_CONVERSATION_BYTES, WARN_CONVERSATION_BYTES, PROJECT_DB_NAME, PROJECT_DB_VERSION, PROJECT_STORE_NAME, PROJECT_STORE_CONFIGS, suppressTracking, conversationsMeta, projectsMeta, conversationUnsubscribe, projectUnsubscribe, autoSyncTimeout, AUTO_SYNC_DELAY_MS, useConversationSyncStore;
8503
8619
  var init_conversationSyncStore = __esm({
8504
8620
  "src/store/conversationSyncStore.ts"() {
8505
8621
  "use strict";
@@ -8509,13 +8625,19 @@ var init_conversationSyncStore = __esm({
8509
8625
  init_projectStore();
8510
8626
  init_packageSettingsStore();
8511
8627
  init_authenticationService();
8628
+ init_indexedDBService();
8512
8629
  init_conversationSyncEvents();
8513
8630
  init_conversationSyncService();
8514
8631
  init_debugLogger();
8515
8632
  DEVICE_STORAGE_KEY = "banditConversationDeviceId";
8633
+ SYNC_IDENTITY_STORAGE_KEY = "banditConversationSyncIdentity";
8516
8634
  PAYLOAD_VERSION = 1;
8517
8635
  MAX_CONVERSATION_BYTES = 12 * 1024 * 1024;
8518
8636
  WARN_CONVERSATION_BYTES = 10 * 1024 * 1024;
8637
+ PROJECT_DB_NAME = "bandit-projects";
8638
+ PROJECT_DB_VERSION = 1;
8639
+ PROJECT_STORE_NAME = "projects";
8640
+ PROJECT_STORE_CONFIGS = [{ name: PROJECT_STORE_NAME, keyPath: "id" }];
8519
8641
  suppressTracking = false;
8520
8642
  conversationsMeta = /* @__PURE__ */ new Map();
8521
8643
  projectsMeta = /* @__PURE__ */ new Map();
@@ -8551,6 +8673,9 @@ var init_conversationSyncStore = __esm({
8551
8673
  }
8552
8674
  useConversationSyncStore = (0, import_zustand11.create)((set, get) => ({
8553
8675
  initialized: false,
8676
+ hasLoadedPreference: false,
8677
+ initializedForToken: null,
8678
+ initializedForIdentity: null,
8554
8679
  syncEnabled: false,
8555
8680
  status: "disabled",
8556
8681
  lastSyncAt: null,
@@ -8570,20 +8695,63 @@ var init_conversationSyncStore = __esm({
8570
8695
  warningConversations: [],
8571
8696
  oversizedConversations: [],
8572
8697
  async initialize() {
8573
- if (get().initialized) {
8574
- return;
8575
- }
8576
8698
  ensureTrackersInitialized();
8577
8699
  const gatewayUrl = usePackageSettingsStore.getState().settings?.gatewayApiUrl;
8700
+ const token = authenticationService.getToken();
8701
+ const tokenIdentity = resolveAuthIdentity(token);
8702
+ const current = get();
8703
+ const storedIdentity = getStoredSyncIdentity();
8704
+ const knownIdentity = current.initializedForIdentity ?? storedIdentity;
8705
+ if (current.initialized && current.hasLoadedPreference && knownIdentity && tokenIdentity && knownIdentity === tokenIdentity) {
8706
+ return;
8707
+ }
8708
+ const hasIdentitySwitch = Boolean(
8709
+ knownIdentity && tokenIdentity && knownIdentity !== tokenIdentity
8710
+ );
8711
+ if (hasIdentitySwitch) {
8712
+ clearAutoSyncTimer();
8713
+ set({
8714
+ ...buildQueueResetState(),
8715
+ syncEnabled: false,
8716
+ status: "disabled",
8717
+ hasLoadedPreference: false,
8718
+ initializedForToken: null,
8719
+ initializedForIdentity: tokenIdentity
8720
+ });
8721
+ await clearLocalStoresForIdentitySwitch(
8722
+ knownIdentity,
8723
+ tokenIdentity
8724
+ );
8725
+ setStoredSyncIdentity(tokenIdentity);
8726
+ }
8578
8727
  if (!gatewayUrl) {
8579
8728
  debugLogger.info("conversationSyncStore: gateway API URL not configured; sync disabled");
8580
- set({ initialized: true, status: "disabled", syncEnabled: false });
8729
+ if (tokenIdentity) {
8730
+ setStoredSyncIdentity(tokenIdentity);
8731
+ }
8732
+ set({
8733
+ ...buildQueueResetState(),
8734
+ initialized: true,
8735
+ hasLoadedPreference: false,
8736
+ initializedForToken: null,
8737
+ initializedForIdentity: tokenIdentity,
8738
+ status: "disabled",
8739
+ syncEnabled: false
8740
+ });
8581
8741
  return;
8582
8742
  }
8583
- const token = authenticationService.getToken();
8584
8743
  if (!token) {
8585
8744
  debugLogger.info("conversationSyncStore: no authentication token; sync disabled until login");
8586
- set({ initialized: true, status: "disabled", syncEnabled: false });
8745
+ clearAutoSyncTimer();
8746
+ set({
8747
+ ...buildQueueResetState(),
8748
+ initialized: true,
8749
+ hasLoadedPreference: false,
8750
+ initializedForToken: null,
8751
+ initializedForIdentity: null,
8752
+ status: "disabled",
8753
+ syncEnabled: false
8754
+ });
8587
8755
  return;
8588
8756
  }
8589
8757
  try {
@@ -8605,14 +8773,27 @@ var init_conversationSyncStore = __esm({
8605
8773
  isAdvancedVectorFeaturesEnabled: get().isAdvancedVectorFeaturesEnabled
8606
8774
  }
8607
8775
  });
8608
- set({ initialized: true });
8776
+ set({
8777
+ initialized: true,
8778
+ hasLoadedPreference: true,
8779
+ initializedForToken: token,
8780
+ initializedForIdentity: tokenIdentity
8781
+ });
8782
+ setStoredSyncIdentity(tokenIdentity);
8609
8783
  if (preference.syncEnabled) {
8610
8784
  await get().runSync({ force: true });
8611
8785
  }
8612
8786
  } catch (error) {
8613
8787
  const message = error instanceof Error ? error.message : "Failed to load conversation sync preference";
8614
8788
  debugLogger.error("conversationSyncStore: initialization failed", { error: message });
8615
- set({ initialized: true, status: "error", lastError: message });
8789
+ set({
8790
+ initialized: true,
8791
+ hasLoadedPreference: false,
8792
+ initializedForToken: null,
8793
+ initializedForIdentity: tokenIdentity,
8794
+ status: "error",
8795
+ lastError: message
8796
+ });
8616
8797
  }
8617
8798
  },
8618
8799
  async setSyncEnabled(enabled) {
@@ -8640,6 +8821,12 @@ var init_conversationSyncStore = __esm({
8640
8821
  isAdvancedVectorFeaturesEnabled
8641
8822
  }
8642
8823
  });
8824
+ set({
8825
+ hasLoadedPreference: true,
8826
+ initializedForToken: authenticationService.getToken(),
8827
+ initializedForIdentity: resolveAuthIdentity(authenticationService.getToken())
8828
+ });
8829
+ setStoredSyncIdentity(resolveAuthIdentity(authenticationService.getToken()));
8643
8830
  if (enabled) {
8644
8831
  set({ hasCompletedInitialUpload: false });
8645
8832
  }
@@ -8677,6 +8864,12 @@ var init_conversationSyncStore = __esm({
8677
8864
  isAdvancedVectorFeaturesEnabled: enabled
8678
8865
  }
8679
8866
  });
8867
+ set({
8868
+ hasLoadedPreference: true,
8869
+ initializedForToken: authenticationService.getToken(),
8870
+ initializedForIdentity: resolveAuthIdentity(authenticationService.getToken())
8871
+ });
8872
+ setStoredSyncIdentity(resolveAuthIdentity(authenticationService.getToken()));
8680
8873
  if (preference.syncEnabled && preference.isAdvancedVectorFeaturesEnabled) {
8681
8874
  await get().runSync({ force: true });
8682
8875
  }
@@ -8722,6 +8915,15 @@ var init_conversationSyncStore = __esm({
8722
8915
  debugLogger.error("conversationSyncStore: runSync error - missing auth token");
8723
8916
  return;
8724
8917
  }
8918
+ const tokenIdentity = resolveAuthIdentity(token);
8919
+ if (state.initializedForIdentity && tokenIdentity && state.initializedForIdentity !== tokenIdentity) {
8920
+ debugLogger.warn("conversationSyncStore: runSync aborted due auth identity mismatch; reinitializing", {
8921
+ initializedForIdentity: state.initializedForIdentity,
8922
+ tokenIdentity
8923
+ });
8924
+ await get().initialize();
8925
+ return;
8926
+ }
8725
8927
  const pendingConversationIds = Array.from(state.pendingConversationUpserts);
8726
8928
  const pendingConversationDeleteIds = Array.from(state.pendingConversationDeletes);
8727
8929
  const pendingProjectIds = Array.from(state.pendingProjectUpserts);
@@ -27975,6 +28177,22 @@ var init_chat2 = __esm({
27975
28177
  }, 500);
27976
28178
  }
27977
28179
  }, [history, pendingMessage]);
28180
+ (0, import_react55.useEffect)(() => {
28181
+ if (!brandingLoading && !themeLoading) {
28182
+ return;
28183
+ }
28184
+ const timeoutId = window.setTimeout(() => {
28185
+ if (brandingLoading || themeLoading) {
28186
+ debugLogger.warn("Chat: branding/theme load timed out, falling back to defaults");
28187
+ setBrandingLoading(false);
28188
+ setThemeLoading(false);
28189
+ if (!selectedTheme) {
28190
+ setSelectedTheme("bandit-dark");
28191
+ }
28192
+ }
28193
+ }, 2500);
28194
+ return () => window.clearTimeout(timeoutId);
28195
+ }, [brandingLoading, themeLoading, selectedTheme]);
27978
28196
  (0, import_react55.useEffect)(() => () => {
27979
28197
  if (logoFadeTimeoutRef.current) {
27980
28198
  window.clearTimeout(logoFadeTimeoutRef.current);
@@ -28692,7 +28910,30 @@ var init_chat2 = __esm({
28692
28910
  requestAnimationFrame(pump);
28693
28911
  }
28694
28912
  };
28695
- if (!hydrated || brandingLoading || themeLoading) return null;
28913
+ if (!hydrated || brandingLoading || themeLoading) {
28914
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_material46.ThemeProvider, { theme: banditTheme, children: [
28915
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_material46.CssBaseline, {}),
28916
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
28917
+ import_material46.Box,
28918
+ {
28919
+ sx: (theme) => ({
28920
+ minHeight: "100dvh",
28921
+ display: "flex",
28922
+ alignItems: "center",
28923
+ justifyContent: "center",
28924
+ flexDirection: "column",
28925
+ gap: 1.5,
28926
+ bgcolor: theme.palette.chat.shell,
28927
+ color: theme.palette.text.primary
28928
+ }),
28929
+ children: [
28930
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_material46.CircularProgress, { size: 32, thickness: 4 }),
28931
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_material46.Typography, { variant: "body2", color: "text.secondary", children: "Preparing your workspace..." })
28932
+ ]
28933
+ }
28934
+ )
28935
+ ] });
28936
+ }
28696
28937
  const userHasAccess = playgroundBypassAccess || ossMode || claims?.roles?.includes("super-user") || claims?.roles?.includes("admin");
28697
28938
  if (!userHasAccess) {
28698
28939
  return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_material46.ThemeProvider, { theme: banditTheme, children: [
@@ -32103,6 +32344,7 @@ var PersonalitiesTab = ({
32103
32344
  const [deleteDialogOpen, setDeleteDialogOpen] = (0, import_react24.useState)(false);
32104
32345
  const [personalityToDelete, setPersonalityToDelete] = (0, import_react24.useState)(null);
32105
32346
  const [clickedChips, setClickedChips] = (0, import_react24.useState)(/* @__PURE__ */ new Set());
32347
+ const [showTemplateHelp, setShowTemplateHelp] = (0, import_react24.useState)(false);
32106
32348
  const [cropperOpen, setCropperOpen] = (0, import_react24.useState)(false);
32107
32349
  const [selectedImageFile, setSelectedImageFile] = (0, import_react24.useState)(null);
32108
32350
  const promptTemplates = [
@@ -32356,28 +32598,15 @@ var PersonalitiesTab = ({
32356
32598
  }
32357
32599
  }
32358
32600
  ),
32359
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: {
32360
- height: "100%",
32361
- overflow: "auto",
32362
- p: { xs: 1.5, sm: 2 },
32363
- // Hide scrollbars while keeping scroll functionality
32364
- scrollbarWidth: "none",
32365
- // Firefox
32366
- "&::-webkit-scrollbar": {
32367
- display: "none"
32368
- // Chrome, Safari, Edge
32369
- },
32370
- "-ms-overflow-style": "none"
32371
- // IE and Edge
32372
- }, children: [
32601
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: { p: { xs: 1, sm: 2 } }, children: [
32373
32602
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: {
32374
32603
  display: "flex",
32375
32604
  flexDirection: { xs: "column", md: "row" },
32376
32605
  alignItems: { xs: "flex-start", md: "center" },
32377
32606
  justifyContent: "space-between",
32378
- mb: { xs: 2, md: 3 },
32607
+ mb: { xs: 1.25, md: 3 },
32379
32608
  flexWrap: "wrap",
32380
- gap: { xs: 1.5, md: 2 }
32609
+ gap: { xs: 1, md: 2 }
32381
32610
  }, children: [
32382
32611
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: {
32383
32612
  display: "flex",
@@ -32407,8 +32636,8 @@ var PersonalitiesTab = ({
32407
32636
  backgroundClip: "text",
32408
32637
  WebkitBackgroundClip: "text",
32409
32638
  WebkitTextFillColor: "transparent",
32410
- mb: 0.5,
32411
- fontSize: { xs: "1.55rem", sm: "1.75rem" }
32639
+ mb: { xs: 0.25, sm: 0.5 },
32640
+ fontSize: { xs: "1.35rem", sm: "1.75rem" }
32412
32641
  },
32413
32642
  children: "Quick Start Templates"
32414
32643
  }
@@ -32433,12 +32662,40 @@ var PersonalitiesTab = ({
32433
32662
  color: "white",
32434
32663
  fontWeight: 600,
32435
32664
  animation: "pulse 2s infinite",
32436
- alignSelf: { xs: "flex-start", md: "center" }
32665
+ alignSelf: { xs: "flex-start", md: "center" },
32666
+ display: { xs: "none", md: "inline-flex" }
32437
32667
  }
32438
32668
  }
32439
32669
  )
32440
32670
  ] }),
32441
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
32671
+ isMobile ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
32672
+ import_material18.Box,
32673
+ {
32674
+ sx: {
32675
+ mb: 1.75,
32676
+ borderRadius: 2,
32677
+ border: "1px solid rgba(25, 118, 210, 0.2)",
32678
+ background: "linear-gradient(135deg, rgba(25, 118, 210, 0.05) 0%, rgba(66, 165, 245, 0.05) 100%)",
32679
+ px: 1.25,
32680
+ py: 1
32681
+ },
32682
+ children: [
32683
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 1 }, children: [
32684
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_material18.Typography, { variant: "body2", sx: { fontWeight: 600, color: "primary.main", fontSize: "0.82rem" }, children: "Tap any template to pre-fill your form" }),
32685
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
32686
+ import_material18.Button,
32687
+ {
32688
+ size: "small",
32689
+ onClick: () => setShowTemplateHelp((prev) => !prev),
32690
+ sx: { minWidth: "auto", px: 1, fontSize: "0.72rem", whiteSpace: "nowrap" },
32691
+ children: showTemplateHelp ? "Hide" : "Details"
32692
+ }
32693
+ )
32694
+ ] }),
32695
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_material18.Collapse, { in: showTemplateHelp, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_material18.Typography, { variant: "body2", sx: { color: "text.secondary", fontSize: "0.8rem", lineHeight: 1.4, mt: 0.75 }, children: "Choose a setup you like, then tweak name, tone, and prompt details in the Create/Edit tab." }) })
32696
+ ]
32697
+ }
32698
+ ) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
32442
32699
  import_material18.Alert,
32443
32700
  {
32444
32701
  severity: "info",
@@ -32464,17 +32721,19 @@ var PersonalitiesTab = ({
32464
32721
  import_material18.Card,
32465
32722
  {
32466
32723
  sx: {
32467
- mb: { xs: 3, md: 4 },
32724
+ mb: { xs: 2, md: 4 },
32468
32725
  background: "linear-gradient(135deg, #1976d2 0%, #42a5f5 100%)",
32469
32726
  border: "2px solid transparent",
32470
- borderRadius: 3,
32727
+ borderRadius: { xs: 2.25, sm: 3 },
32471
32728
  cursor: "pointer",
32472
32729
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
32473
32730
  position: "relative",
32474
32731
  overflow: "hidden",
32475
- "&:hover": {
32476
- transform: "translateY(-4px) scale(1.02)",
32477
- boxShadow: "0 12px 40px rgba(25, 118, 210, 0.3)"
32732
+ ...isMobile ? {} : {
32733
+ "&:hover": {
32734
+ transform: "translateY(-4px) scale(1.02)",
32735
+ boxShadow: "0 12px 40px rgba(25, 118, 210, 0.3)"
32736
+ }
32478
32737
  },
32479
32738
  "&::before": {
32480
32739
  content: '""',
@@ -32499,41 +32758,70 @@ var PersonalitiesTab = ({
32499
32758
  setPersonalityTabIndex(1);
32500
32759
  },
32501
32760
  children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.CardContent, { sx: {
32502
- p: { xs: 3, sm: 4 },
32761
+ p: { xs: 1.75, sm: 4 },
32503
32762
  color: "white",
32504
- textAlign: "center",
32763
+ textAlign: { xs: "left", sm: "center" },
32505
32764
  position: "relative",
32506
- zIndex: 1
32765
+ zIndex: 1,
32766
+ display: "flex",
32767
+ flexDirection: { xs: "row", sm: "column" },
32768
+ alignItems: { xs: "center", sm: "center" },
32769
+ gap: { xs: 1.25, sm: 0 }
32507
32770
  }, children: [
32508
32771
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_material18.Box, { sx: {
32509
32772
  display: "flex",
32510
32773
  alignItems: "center",
32511
32774
  justifyContent: "center",
32512
32775
  fontSize: 0,
32513
- mb: { xs: 1.5, sm: 2 }
32514
- }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_AutoAwesome.default, { sx: { fontSize: { xs: 36, sm: 44 }, color: "common.white", filter: "drop-shadow(0 4px 12px rgba(0,0,0,0.25))" } }) }),
32515
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
32516
- import_material18.Typography,
32517
- {
32518
- variant: "h5",
32519
- sx: {
32520
- fontWeight: 700,
32521
- mb: { xs: 0.75, sm: 1 },
32522
- textShadow: "0 2px 4px rgba(0,0,0,0.2)"
32523
- },
32524
- children: "Create from Scratch"
32525
- }
32526
- ),
32527
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
32528
- import_material18.Typography,
32776
+ mb: { xs: 0, sm: 2 },
32777
+ flexShrink: 0
32778
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_AutoAwesome.default, { sx: { fontSize: { xs: 28, sm: 44 }, color: "common.white", filter: "drop-shadow(0 4px 12px rgba(0,0,0,0.25))" } }) }),
32779
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: { flex: 1, minWidth: 0 }, children: [
32780
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
32781
+ import_material18.Typography,
32782
+ {
32783
+ variant: "h5",
32784
+ sx: {
32785
+ fontWeight: 700,
32786
+ mb: { xs: 0.25, sm: 1 },
32787
+ textShadow: "0 2px 4px rgba(0,0,0,0.2)",
32788
+ fontSize: { xs: "1.1rem", sm: "1.75rem" }
32789
+ },
32790
+ children: "Create from Scratch"
32791
+ }
32792
+ ),
32793
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
32794
+ import_material18.Typography,
32795
+ {
32796
+ variant: "body1",
32797
+ sx: {
32798
+ opacity: 0.9,
32799
+ fontWeight: 500,
32800
+ textShadow: "0 1px 2px rgba(0,0,0,0.2)",
32801
+ fontSize: { xs: "0.8rem", sm: "1rem" },
32802
+ lineHeight: { xs: 1.3, sm: 1.5 },
32803
+ display: "-webkit-box",
32804
+ WebkitLineClamp: { xs: 2, sm: "unset" },
32805
+ WebkitBoxOrient: "vertical",
32806
+ overflow: "hidden"
32807
+ },
32808
+ children: "Start with a blank canvas and build your perfect AI personality"
32809
+ }
32810
+ )
32811
+ ] }),
32812
+ isMobile && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
32813
+ import_material18.Chip,
32529
32814
  {
32530
- variant: "body1",
32815
+ label: "Start",
32816
+ size: "small",
32531
32817
  sx: {
32532
- opacity: 0.9,
32533
- fontWeight: 500,
32534
- textShadow: "0 1px 2px rgba(0,0,0,0.2)"
32535
- },
32536
- children: "Start with a blank canvas and build your perfect AI personality"
32818
+ backgroundColor: "rgba(255,255,255,0.2)",
32819
+ color: "common.white",
32820
+ border: "1px solid rgba(255,255,255,0.45)",
32821
+ fontWeight: 600,
32822
+ height: 28,
32823
+ flexShrink: 0
32824
+ }
32537
32825
  }
32538
32826
  )
32539
32827
  ] })
@@ -32548,7 +32836,7 @@ var PersonalitiesTab = ({
32548
32836
  lg: "repeat(4, 1fr)",
32549
32837
  xl: "repeat(4, 1fr)"
32550
32838
  },
32551
- gap: { xs: 2, sm: 2.5, md: 3 },
32839
+ gap: { xs: 1.25, sm: 2.5, md: 3 },
32552
32840
  alignItems: "stretch"
32553
32841
  }, children: promptTemplates.map((template, index) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
32554
32842
  import_material18.Card,
@@ -32561,7 +32849,7 @@ var PersonalitiesTab = ({
32561
32849
  border: "1px solid",
32562
32850
  borderColor: "rgba(255,255,255,0.1)",
32563
32851
  borderRadius: 3,
32564
- minHeight: { xs: "auto", md: "280px" },
32852
+ minHeight: { xs: "200px", md: "280px" },
32565
32853
  display: "flex",
32566
32854
  flexDirection: "column",
32567
32855
  overflow: "hidden",
@@ -32579,19 +32867,21 @@ var PersonalitiesTab = ({
32579
32867
  opacity: 0,
32580
32868
  transition: "opacity 0.3s ease"
32581
32869
  },
32582
- "&:hover": {
32583
- transform: "translateY(-8px) scale(1.02)",
32584
- boxShadow: "0 20px 40px rgba(0,0,0,0.15)",
32585
- borderColor: "primary.main",
32586
- "&::before": {
32587
- opacity: 1
32588
- },
32589
- "& .template-icon": {
32590
- transform: "scale(1.1) rotate(5deg)"
32591
- },
32592
- "& .template-chip": {
32593
- transform: "translateY(-2px)",
32594
- boxShadow: "0 4px 12px rgba(0,0,0,0.2)"
32870
+ ...isMobile ? {} : {
32871
+ "&:hover": {
32872
+ transform: "translateY(-8px) scale(1.02)",
32873
+ boxShadow: "0 20px 40px rgba(0,0,0,0.15)",
32874
+ borderColor: "primary.main",
32875
+ "&::before": {
32876
+ opacity: 1
32877
+ },
32878
+ "& .template-icon": {
32879
+ transform: "scale(1.1) rotate(5deg)"
32880
+ },
32881
+ "& .template-chip": {
32882
+ transform: "translateY(-2px)",
32883
+ boxShadow: "0 4px 12px rgba(0,0,0,0.2)"
32884
+ }
32595
32885
  }
32596
32886
  },
32597
32887
  "&:active": {
@@ -32600,7 +32890,7 @@ var PersonalitiesTab = ({
32600
32890
  },
32601
32891
  onClick: () => handleTemplateSelect(template),
32602
32892
  children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.CardContent, { sx: {
32603
- p: { xs: 2.5, sm: 3 },
32893
+ p: { xs: 2, sm: 3 },
32604
32894
  display: "flex",
32605
32895
  flexDirection: "column",
32606
32896
  height: "100%",
@@ -32610,7 +32900,7 @@ var PersonalitiesTab = ({
32610
32900
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: {
32611
32901
  display: "flex",
32612
32902
  alignItems: "center",
32613
- mb: { xs: 2, md: 2.5 },
32903
+ mb: { xs: 1.25, md: 2.5 },
32614
32904
  minHeight: { xs: "auto", md: "60px" }
32615
32905
  }, children: [
32616
32906
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
@@ -32619,9 +32909,9 @@ var PersonalitiesTab = ({
32619
32909
  src: template.avatar,
32620
32910
  alt: template.name,
32621
32911
  sx: {
32622
- width: { xs: 48, sm: 56, md: 60 },
32623
- height: { xs: 48, sm: 56, md: 60 },
32624
- mr: { xs: 1.5, md: 2 },
32912
+ width: { xs: 40, sm: 56, md: 60 },
32913
+ height: { xs: 40, sm: 56, md: 60 },
32914
+ mr: { xs: 1.2, md: 2 },
32625
32915
  transition: "transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
32626
32916
  boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
32627
32917
  border: "2px solid rgba(255,255,255,0.8)"
@@ -32675,10 +32965,10 @@ var PersonalitiesTab = ({
32675
32965
  lineHeight: 1.5,
32676
32966
  fontSize: { xs: "0.82rem", sm: "0.85rem", md: "0.875rem" },
32677
32967
  display: "-webkit-box",
32678
- WebkitLineClamp: 4,
32968
+ WebkitLineClamp: { xs: 2, sm: 4 },
32679
32969
  WebkitBoxOrient: "vertical",
32680
32970
  overflow: "hidden",
32681
- mb: { xs: 1.5, md: 2 },
32971
+ mb: { xs: 1.25, md: 2 },
32682
32972
  minHeight: { xs: "auto", md: "84px" }
32683
32973
  },
32684
32974
  children: template.description
@@ -32715,7 +33005,7 @@ var PersonalitiesTab = ({
32715
33005
  },
32716
33006
  index
32717
33007
  )) }),
32718
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
33008
+ !isMobile && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
32719
33009
  import_material18.Alert,
32720
33010
  {
32721
33011
  severity: "info",
@@ -32729,20 +33019,7 @@ var PersonalitiesTab = ({
32729
33019
  )
32730
33020
  ] })
32731
33021
  ] });
32732
- const renderCreateEditTab = () => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: {
32733
- height: "100%",
32734
- overflow: "auto",
32735
- p: { xs: 1.5, sm: 2 },
32736
- // Hide scrollbars while keeping scroll functionality
32737
- scrollbarWidth: "none",
32738
- // Firefox
32739
- "&::-webkit-scrollbar": {
32740
- display: "none"
32741
- // Chrome, Safari, Edge
32742
- },
32743
- "-ms-overflow-style": "none"
32744
- // IE and Edge
32745
- }, children: [
33022
+ const renderCreateEditTab = () => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: { p: { xs: 1.5, sm: 2 } }, children: [
32746
33023
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: { mb: { xs: 2.5, md: 4 } }, children: [
32747
33024
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
32748
33025
  import_material18.Typography,
@@ -33212,6 +33489,9 @@ var PersonalitiesTab = ({
33212
33489
  import_material18.Box,
33213
33490
  {
33214
33491
  sx: {
33492
+ position: { xs: "sticky", sm: "static" },
33493
+ bottom: { xs: 10, sm: "auto" },
33494
+ zIndex: { xs: 5, sm: "auto" },
33215
33495
  display: "flex",
33216
33496
  flexDirection: { xs: "column", sm: "row" },
33217
33497
  gap: { xs: 1.5, sm: 2 },
@@ -33219,8 +33499,15 @@ var PersonalitiesTab = ({
33219
33499
  // Changed from flex-end to flex-start
33220
33500
  mr: { xs: 0, sm: 10 },
33221
33501
  // Add right margin to avoid FAB
33222
- mb: { xs: 8, sm: 2 }
33502
+ mb: { xs: 8, sm: 2 },
33223
33503
  // Add bottom margin on mobile for FAB clearance
33504
+ mt: { xs: 1.5, sm: 0 },
33505
+ p: { xs: 1.1, sm: 0 },
33506
+ borderRadius: { xs: 2, sm: 0 },
33507
+ border: { xs: "1px solid", sm: "none" },
33508
+ borderColor: { xs: "divider", sm: "transparent" },
33509
+ bgcolor: { xs: "background.paper", sm: "transparent" },
33510
+ boxShadow: { xs: 3, sm: "none" }
33224
33511
  },
33225
33512
  children: [
33226
33513
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
@@ -33248,20 +33535,7 @@ var PersonalitiesTab = ({
33248
33535
  }
33249
33536
  )
33250
33537
  ] });
33251
- const renderManageTab = () => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: {
33252
- height: "100%",
33253
- overflow: "auto",
33254
- p: { xs: 1.5, sm: 2 },
33255
- // Hide scrollbars while keeping scroll functionality
33256
- scrollbarWidth: "none",
33257
- // Firefox
33258
- "&::-webkit-scrollbar": {
33259
- display: "none"
33260
- // Chrome, Safari, Edge
33261
- },
33262
- "-ms-overflow-style": "none"
33263
- // IE and Edge
33264
- }, children: [
33538
+ const renderManageTab = () => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: { p: { xs: 1.5, sm: 2 } }, children: [
33265
33539
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
33266
33540
  import_material18.Box,
33267
33541
  {
@@ -33510,7 +33784,7 @@ var PersonalitiesTab = ({
33510
33784
  ] })
33511
33785
  ] })
33512
33786
  ] });
33513
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: { height: "100%", display: "flex", flexDirection: "column" }, children: [
33787
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: { display: "flex", flexDirection: "column" }, children: [
33514
33788
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
33515
33789
  import_material18.Box,
33516
33790
  {
@@ -33636,7 +33910,7 @@ var PersonalitiesTab = ({
33636
33910
  ]
33637
33911
  }
33638
33912
  ) }),
33639
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: { flex: 1, overflow: "hidden" }, children: [
33913
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_material18.Box, { sx: { minHeight: 0 }, children: [
33640
33914
  personalityTabIndex === 0 && renderTemplatesTab(),
33641
33915
  personalityTabIndex === 1 && renderCreateEditTab(),
33642
33916
  personalityTabIndex === 2 && renderManageTab()
@@ -37435,6 +37709,7 @@ var import_Add = __toESM(require("@mui/icons-material/Add"));
37435
37709
  var import_Archive = __toESM(require("@mui/icons-material/Archive"));
37436
37710
  var import_Delete6 = __toESM(require("@mui/icons-material/Delete"));
37437
37711
  var import_Description4 = __toESM(require("@mui/icons-material/Description"));
37712
+ var import_FolderOpen = __toESM(require("@mui/icons-material/FolderOpen"));
37438
37713
  var import_Group2 = __toESM(require("@mui/icons-material/Group"));
37439
37714
  var import_Person3 = __toESM(require("@mui/icons-material/Person"));
37440
37715
  var import_Publish = __toESM(require("@mui/icons-material/Publish"));
@@ -37714,6 +37989,22 @@ var archiveSeedPack = async (sid) => {
37714
37989
  throw error;
37715
37990
  }
37716
37991
  };
37992
+ var deleteSeedPack = async (sid) => {
37993
+ const url = buildUrl2(`/seed-packs/${encodeURIComponent(sid)}`);
37994
+ try {
37995
+ const response = await fetch(url, { method: "DELETE", headers: buildHeaders2() });
37996
+ if (response.status === 204) {
37997
+ return;
37998
+ }
37999
+ await handleJsonResponse2(response, "Failed to delete seed pack");
38000
+ } catch (error) {
38001
+ debugLogger.error("seedPackService: failed to delete seed pack", {
38002
+ sid,
38003
+ error: error instanceof Error ? error.message : String(error)
38004
+ });
38005
+ throw error;
38006
+ }
38007
+ };
37717
38008
 
37718
38009
  // src/management/components/SeedPacksTab.tsx
37719
38010
  var import_jsx_runtime24 = require("react/jsx-runtime");
@@ -37749,10 +38040,23 @@ var getPreviewSnippet = (content) => {
37749
38040
  }
37750
38041
  return trimmed.length > 120 ? `${trimmed.slice(0, 120)}...` : trimmed;
37751
38042
  };
38043
+ var getImportedFileKey = (file) => (file.relativePath ?? file.name).toLowerCase();
38044
+ var isMarkdownFileName = (name) => {
38045
+ const lower = name.toLowerCase();
38046
+ return lower.endsWith(".md") || lower.endsWith(".markdown");
38047
+ };
38048
+ var getWebkitRelativePath = (file) => {
38049
+ const relativePath = file.webkitRelativePath;
38050
+ if (!relativePath) {
38051
+ return void 0;
38052
+ }
38053
+ const trimmed = relativePath.trim().replace(/^\/+/, "");
38054
+ return trimmed.length > 0 ? trimmed : void 0;
38055
+ };
37752
38056
  var mergeMarkdownFiles = (existing, incoming) => {
37753
38057
  const next = [...existing];
37754
38058
  incoming.forEach((file) => {
37755
- const index = next.findIndex((item) => item.name === file.name);
38059
+ const index = next.findIndex((item) => getImportedFileKey(item) === getImportedFileKey(file));
37756
38060
  if (index >= 0) {
37757
38061
  next[index] = file;
37758
38062
  } else {
@@ -37764,17 +38068,22 @@ var mergeMarkdownFiles = (existing, incoming) => {
37764
38068
  var buildMarkdownContent = (files) => {
37765
38069
  return files.map((file) => file.content.trim()).filter((content) => content.length > 0).join("\n\n---\n\n");
37766
38070
  };
37767
- var readMarkdownFiles = async (files) => {
38071
+ var readMarkdownFiles = async (files, source = "local") => {
37768
38072
  const list = Array.from(files);
37769
- const markdownFiles = list.filter((file) => file.name.toLowerCase().endsWith(".md"));
38073
+ const markdownFiles = list.filter((file) => isMarkdownFileName(file.name));
37770
38074
  const imported = await Promise.all(
37771
- markdownFiles.map(async (file) => ({
37772
- id: `${file.name}-${file.lastModified}`,
37773
- name: file.name,
37774
- size: file.size,
37775
- content: await file.text(),
37776
- lastModified: file.lastModified
37777
- }))
38075
+ markdownFiles.map(async (file) => {
38076
+ const relativePath = getWebkitRelativePath(file);
38077
+ return {
38078
+ id: `${source}-${relativePath ?? file.name}-${file.lastModified}-${file.size}`,
38079
+ name: file.name,
38080
+ size: file.size,
38081
+ content: await file.text(),
38082
+ lastModified: file.lastModified,
38083
+ relativePath,
38084
+ source
38085
+ };
38086
+ })
37778
38087
  );
37779
38088
  return { imported, skipped: list.length - markdownFiles.length };
37780
38089
  };
@@ -37890,7 +38199,7 @@ var SeedPackFileCard = ({ file, onPreview, onRemove, isReadOnly }) => /* @__PURE
37890
38199
  )
37891
38200
  }
37892
38201
  ),
37893
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Tooltip, { title: file.name, arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
38202
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Tooltip, { title: file.relativePath ?? file.name, arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
37894
38203
  import_material25.Typography,
37895
38204
  {
37896
38205
  variant: "body2",
@@ -37907,6 +38216,21 @@ var SeedPackFileCard = ({ file, onPreview, onRemove, isReadOnly }) => /* @__PURE
37907
38216
  children: file.name
37908
38217
  }
37909
38218
  ) }),
38219
+ file.relativePath && file.relativePath !== file.name && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Tooltip, { title: file.relativePath, arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
38220
+ import_material25.Typography,
38221
+ {
38222
+ variant: "caption",
38223
+ color: "text.secondary",
38224
+ sx: {
38225
+ display: "block",
38226
+ whiteSpace: "nowrap",
38227
+ overflow: "hidden",
38228
+ textOverflow: "ellipsis",
38229
+ mb: 1
38230
+ },
38231
+ children: file.relativePath
38232
+ }
38233
+ ) }),
37910
38234
  /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
37911
38235
  import_material25.Box,
37912
38236
  {
@@ -37923,7 +38247,7 @@ var SeedPackFileCard = ({ file, onPreview, onRemove, isReadOnly }) => /* @__PURE
37923
38247
  import_material25.Chip,
37924
38248
  {
37925
38249
  icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_Person3.default, { sx: { fontSize: "0.9rem !important" } }),
37926
- label: "Local",
38250
+ label: file.source === "azure-wiki" ? "Azure Wiki" : "Local",
37927
38251
  size: "small",
37928
38252
  sx: {
37929
38253
  bgcolor: "#388e3c20",
@@ -38012,16 +38336,20 @@ var SeedPacksTab = () => {
38012
38336
  const [createImportedFiles, setCreateImportedFiles] = (0, import_react33.useState)([]);
38013
38337
  const [previewFile, setPreviewFile] = (0, import_react33.useState)(null);
38014
38338
  const fileInputRef = (0, import_react33.useRef)(null);
38339
+ const wikiFolderInputRef = (0, import_react33.useRef)(null);
38015
38340
  const createFileInputRef = (0, import_react33.useRef)(null);
38341
+ const createWikiFolderInputRef = (0, import_react33.useRef)(null);
38016
38342
  const [isLoadingList, setIsLoadingList] = (0, import_react33.useState)(false);
38017
38343
  const [isLoadingDetail, setIsLoadingDetail] = (0, import_react33.useState)(false);
38018
38344
  const [isSaving, setIsSaving] = (0, import_react33.useState)(false);
38019
38345
  const [isPublishing, setIsPublishing] = (0, import_react33.useState)(false);
38020
38346
  const [isArchiving, setIsArchiving] = (0, import_react33.useState)(false);
38347
+ const [isDeleting, setIsDeleting] = (0, import_react33.useState)(false);
38021
38348
  const [isCreating, setIsCreating] = (0, import_react33.useState)(false);
38022
38349
  const [createDialogOpen, setCreateDialogOpen] = (0, import_react33.useState)(false);
38023
38350
  const [publishDialogOpen, setPublishDialogOpen] = (0, import_react33.useState)(false);
38024
38351
  const [archiveDialogOpen, setArchiveDialogOpen] = (0, import_react33.useState)(false);
38352
+ const [deleteDialogOpen, setDeleteDialogOpen] = (0, import_react33.useState)(false);
38025
38353
  const [newPackName, setNewPackName] = (0, import_react33.useState)("");
38026
38354
  const [newPackDescription, setNewPackDescription] = (0, import_react33.useState)("");
38027
38355
  const [newPackTags, setNewPackTags] = (0, import_react33.useState)("");
@@ -38126,26 +38454,37 @@ var SeedPacksTab = () => {
38126
38454
  void loadSeedPackDetail(selectedSid);
38127
38455
  }
38128
38456
  }, [selectedSid, loadSeedPackDetail]);
38457
+ (0, import_react33.useEffect)(() => {
38458
+ const setDirectoryUploadAttributes = (input) => {
38459
+ if (!input) {
38460
+ return;
38461
+ }
38462
+ input.setAttribute("webkitdirectory", "");
38463
+ input.setAttribute("directory", "");
38464
+ };
38465
+ setDirectoryUploadAttributes(wikiFolderInputRef.current);
38466
+ setDirectoryUploadAttributes(createWikiFolderInputRef.current);
38467
+ }, [selectedSeedPack, createDialogOpen]);
38129
38468
  const handleSelectPack = (pack) => {
38130
38469
  setSelectedSid(pack.sid);
38131
38470
  setSelectedSeedPack(pack);
38132
38471
  hydrateDraft(pack);
38133
38472
  };
38134
38473
  const handleImportFiles = (0, import_react33.useCallback)(
38135
- async (files) => {
38474
+ async (files, source = "local") => {
38136
38475
  if (!files || files.length === 0) {
38137
38476
  return;
38138
38477
  }
38139
- const { imported, skipped } = await readMarkdownFiles(files);
38478
+ const { imported, skipped } = await readMarkdownFiles(files, source);
38140
38479
  if (skipped > 0) {
38141
- showSnackbar("Only .md files are supported for seed packs.", "error");
38480
+ showSnackbar("Only .md and .markdown files are supported for seed packs.", "error");
38142
38481
  }
38143
38482
  if (imported.length === 0) {
38144
38483
  return;
38145
38484
  }
38146
38485
  try {
38147
38486
  const newlyAdded = imported.filter(
38148
- (file) => !importedFiles.some((existing) => existing.name === file.name)
38487
+ (file) => !importedFiles.some((existing) => getImportedFileKey(existing) === getImportedFileKey(file))
38149
38488
  );
38150
38489
  setImportedFiles((prev) => mergeMarkdownFiles(prev, imported));
38151
38490
  const combined = buildMarkdownContent(newlyAdded);
@@ -38160,8 +38499,9 @@ ${combined}` : combined;
38160
38499
  return { ...prev, content: nextContent };
38161
38500
  });
38162
38501
  }
38502
+ const importLabel = source === "azure-wiki" ? "from Azure DevOps wiki folder into the editor" : "into the editor";
38163
38503
  showSnackbar(
38164
- `Imported ${imported.length} markdown file${imported.length === 1 ? "" : "s"} into the editor.`,
38504
+ `Imported ${imported.length} markdown file${imported.length === 1 ? "" : "s"} ${importLabel}.`,
38165
38505
  "success"
38166
38506
  );
38167
38507
  } catch (error) {
@@ -38175,7 +38515,14 @@ ${combined}` : combined;
38175
38515
  );
38176
38516
  const handleFileInputChange = (0, import_react33.useCallback)(
38177
38517
  async (event) => {
38178
- await handleImportFiles(event.target.files);
38518
+ await handleImportFiles(event.target.files, "local");
38519
+ event.target.value = "";
38520
+ },
38521
+ [handleImportFiles]
38522
+ );
38523
+ const handleWikiFolderInputChange = (0, import_react33.useCallback)(
38524
+ async (event) => {
38525
+ await handleImportFiles(event.target.files, "azure-wiki");
38179
38526
  event.target.value = "";
38180
38527
  },
38181
38528
  [handleImportFiles]
@@ -38184,20 +38531,21 @@ ${combined}` : combined;
38184
38531
  setImportedFiles((prev) => prev.filter((file) => file.id !== id));
38185
38532
  }, []);
38186
38533
  const handleCreateImportFiles = (0, import_react33.useCallback)(
38187
- async (files) => {
38534
+ async (files, source = "local") => {
38188
38535
  if (!files || files.length === 0) {
38189
38536
  return;
38190
38537
  }
38191
- const { imported, skipped } = await readMarkdownFiles(files);
38538
+ const { imported, skipped } = await readMarkdownFiles(files, source);
38192
38539
  if (skipped > 0) {
38193
- showSnackbar("Only .md files are supported for seed packs.", "error");
38540
+ showSnackbar("Only .md and .markdown files are supported for seed packs.", "error");
38194
38541
  }
38195
38542
  if (imported.length === 0) {
38196
38543
  return;
38197
38544
  }
38198
38545
  setCreateImportedFiles((prev) => mergeMarkdownFiles(prev, imported));
38546
+ const importLabel = source === "azure-wiki" ? "from Azure DevOps wiki folder for this seed pack" : "for this seed pack";
38199
38547
  showSnackbar(
38200
- `Imported ${imported.length} markdown file${imported.length === 1 ? "" : "s"} for this seed pack.`,
38548
+ `Imported ${imported.length} markdown file${imported.length === 1 ? "" : "s"} ${importLabel}.`,
38201
38549
  "success"
38202
38550
  );
38203
38551
  },
@@ -38205,7 +38553,14 @@ ${combined}` : combined;
38205
38553
  );
38206
38554
  const handleCreateFileInputChange = (0, import_react33.useCallback)(
38207
38555
  async (event) => {
38208
- await handleCreateImportFiles(event.target.files);
38556
+ await handleCreateImportFiles(event.target.files, "local");
38557
+ event.target.value = "";
38558
+ },
38559
+ [handleCreateImportFiles]
38560
+ );
38561
+ const handleCreateWikiFolderInputChange = (0, import_react33.useCallback)(
38562
+ async (event) => {
38563
+ await handleCreateImportFiles(event.target.files, "azure-wiki");
38209
38564
  event.target.value = "";
38210
38565
  },
38211
38566
  [handleCreateImportFiles]
@@ -38350,6 +38705,34 @@ ${combined}` : combined;
38350
38705
  setIsArchiving(false);
38351
38706
  }
38352
38707
  };
38708
+ const handleDelete = async () => {
38709
+ if (!selectedSeedPack) {
38710
+ return;
38711
+ }
38712
+ const deletingSid = selectedSeedPack.sid;
38713
+ const deletingName = selectedSeedPack.name;
38714
+ setDeleteDialogOpen(false);
38715
+ setIsDeleting(true);
38716
+ try {
38717
+ await deleteSeedPack(deletingSid);
38718
+ setSelectedSid(null);
38719
+ setSelectedSeedPack(null);
38720
+ setDraft({ name: "", description: "", content: "" });
38721
+ setTagsInput("");
38722
+ setImportedFiles([]);
38723
+ setPreviewFile(null);
38724
+ await refreshSeedPacks();
38725
+ showSnackbar(`Deleted seed pack "${deletingName}".`, "success");
38726
+ } catch (error) {
38727
+ showSnackbar("Failed to delete seed pack.", "error");
38728
+ debugLogger.error("SeedPacksTab: failed to delete seed pack", {
38729
+ sid: deletingSid,
38730
+ error: error instanceof Error ? error.message : String(error)
38731
+ });
38732
+ } finally {
38733
+ setIsDeleting(false);
38734
+ }
38735
+ };
38353
38736
  const previewContent = draft.content.trim().length > 0 ? draft.content : "Preview will appear here as you type.";
38354
38737
  const selectedStatus = selectedSeedPack?.status ?? "draft";
38355
38738
  const statusChip = getStatusChip(selectedStatus);
@@ -38551,32 +38934,56 @@ ${combined}` : combined;
38551
38934
  sx: { mb: 1 },
38552
38935
  children: [
38553
38936
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Typography, { variant: "subtitle2", children: "Markdown content" }),
38937
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_material25.Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, children: [
38938
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
38939
+ import_material25.Button,
38940
+ {
38941
+ size: "small",
38942
+ variant: "outlined",
38943
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_UploadFile2.default, {}),
38944
+ onClick: () => fileInputRef.current?.click(),
38945
+ disabled: isReadOnly,
38946
+ children: "Import .md"
38947
+ }
38948
+ ),
38949
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
38950
+ import_material25.Button,
38951
+ {
38952
+ size: "small",
38953
+ variant: "outlined",
38954
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_FolderOpen.default, {}),
38955
+ onClick: () => wikiFolderInputRef.current?.click(),
38956
+ disabled: isReadOnly,
38957
+ children: "Import wiki folder"
38958
+ }
38959
+ )
38960
+ ] }),
38554
38961
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
38555
- import_material25.Button,
38962
+ "input",
38556
38963
  {
38557
- size: "small",
38558
- variant: "outlined",
38559
- startIcon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_UploadFile2.default, {}),
38560
- onClick: () => fileInputRef.current?.click(),
38561
- disabled: isReadOnly,
38562
- children: "Import .md"
38964
+ ref: fileInputRef,
38965
+ type: "file",
38966
+ accept: ".md,.markdown,text/markdown",
38967
+ multiple: true,
38968
+ onChange: handleFileInputChange,
38969
+ style: { display: "none" }
38563
38970
  }
38564
38971
  ),
38565
38972
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
38566
38973
  "input",
38567
38974
  {
38568
- ref: fileInputRef,
38975
+ ref: wikiFolderInputRef,
38569
38976
  type: "file",
38570
- accept: ".md",
38977
+ accept: ".md,.markdown,text/markdown",
38571
38978
  multiple: true,
38572
- onChange: handleFileInputChange,
38979
+ onChange: handleWikiFolderInputChange,
38573
38980
  style: { display: "none" }
38574
38981
  }
38575
38982
  )
38576
38983
  ]
38577
38984
  }
38578
38985
  ),
38579
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Typography, { variant: "caption", color: "text.secondary", sx: { mb: 1, display: "block" }, children: "Paste or import markdown files. Imports copy content into the editor." }),
38986
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Typography, { variant: "caption", color: "text.secondary", sx: { mb: 1, display: "block" }, children: "Paste or import markdown files. Use folder import for Azure DevOps wiki clones." }),
38580
38987
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
38581
38988
  import_material25.TextField,
38582
38989
  {
@@ -38675,6 +39082,17 @@ ${combined}` : combined;
38675
39082
  disabled: isReadOnly || isArchiving,
38676
39083
  children: isArchiving ? "Archiving..." : "Archive"
38677
39084
  }
39085
+ ),
39086
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
39087
+ import_material25.Button,
39088
+ {
39089
+ variant: "text",
39090
+ color: "error",
39091
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_Delete6.default, {}),
39092
+ onClick: () => setDeleteDialogOpen(true),
39093
+ disabled: isDeleting,
39094
+ children: isDeleting ? "Deleting..." : "Delete"
39095
+ }
38678
39096
  )
38679
39097
  ] })
38680
39098
  ] })
@@ -38724,26 +39142,50 @@ ${combined}` : combined;
38724
39142
  ),
38725
39143
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Divider, {}),
38726
39144
  /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_material25.Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, alignItems: "center", children: [
39145
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_material25.Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, children: [
39146
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
39147
+ import_material25.Button,
39148
+ {
39149
+ size: "small",
39150
+ variant: "outlined",
39151
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_UploadFile2.default, {}),
39152
+ onClick: () => createFileInputRef.current?.click(),
39153
+ disabled: !canManage,
39154
+ children: "Import .md files"
39155
+ }
39156
+ ),
39157
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
39158
+ import_material25.Button,
39159
+ {
39160
+ size: "small",
39161
+ variant: "outlined",
39162
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_FolderOpen.default, {}),
39163
+ onClick: () => createWikiFolderInputRef.current?.click(),
39164
+ disabled: !canManage,
39165
+ children: "Import wiki folder"
39166
+ }
39167
+ )
39168
+ ] }),
39169
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Typography, { variant: "caption", color: "text.secondary", children: "Optional. Local files or cloned Azure DevOps wiki folders are merged into draft content." }),
38727
39170
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
38728
- import_material25.Button,
39171
+ "input",
38729
39172
  {
38730
- size: "small",
38731
- variant: "outlined",
38732
- startIcon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_UploadFile2.default, {}),
38733
- onClick: () => createFileInputRef.current?.click(),
38734
- disabled: !canManage,
38735
- children: "Import .md files"
39173
+ ref: createFileInputRef,
39174
+ type: "file",
39175
+ accept: ".md,.markdown,text/markdown",
39176
+ multiple: true,
39177
+ onChange: handleCreateFileInputChange,
39178
+ style: { display: "none" }
38736
39179
  }
38737
39180
  ),
38738
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Typography, { variant: "caption", color: "text.secondary", children: "Optional. Files are merged into the draft content." }),
38739
39181
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
38740
39182
  "input",
38741
39183
  {
38742
- ref: createFileInputRef,
39184
+ ref: createWikiFolderInputRef,
38743
39185
  type: "file",
38744
- accept: ".md",
39186
+ accept: ".md,.markdown,text/markdown",
38745
39187
  multiple: true,
38746
- onChange: handleCreateFileInputChange,
39188
+ onChange: handleCreateWikiFolderInputChange,
38747
39189
  style: { display: "none" }
38748
39190
  }
38749
39191
  )
@@ -38808,6 +39250,21 @@ ${combined}` : combined;
38808
39250
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Button, { variant: "contained", color: "error", onClick: handleArchive, disabled: isArchiving, children: isArchiving ? "Archiving..." : "Archive" })
38809
39251
  ] })
38810
39252
  ] }),
39253
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_material25.Dialog, { open: deleteDialogOpen, onClose: () => setDeleteDialogOpen(false), maxWidth: "sm", fullWidth: true, children: [
39254
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.DialogTitle, { children: "Delete seed pack" }),
39255
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_material25.DialogContent, { children: [
39256
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_material25.DialogContentText, { children: [
39257
+ 'Delete "',
39258
+ selectedSeedPack?.name ?? "this seed pack",
39259
+ '" permanently from this scope. Published versions and draft content will no longer be available.'
39260
+ ] }),
39261
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Alert, { severity: "warning", sx: { mt: 2 }, children: "This action cannot be undone." })
39262
+ ] }),
39263
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_material25.DialogActions, { children: [
39264
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Button, { onClick: () => setDeleteDialogOpen(false), children: "Cancel" }),
39265
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material25.Button, { variant: "contained", color: "error", onClick: handleDelete, disabled: isDeleting, children: isDeleting ? "Deleting..." : "Delete" })
39266
+ ] })
39267
+ ] }),
38811
39268
  /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
38812
39269
  import_material25.Dialog,
38813
39270
  {
@@ -39566,15 +40023,7 @@ var StorageTab = ({ currentTheme }) => {
39566
40023
  ] }) })
39567
40024
  ] }),
39568
40025
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_material27.Typography, { variant: "h6", gutterBottom: true, sx: { mb: 2, fontWeight: 600, color: "text.primary" }, children: "Storage Categories" }),
39569
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_material27.Box, { sx: {
39570
- maxHeight: "60vh",
39571
- overflow: "auto",
39572
- "&::-webkit-scrollbar": {
39573
- display: "none"
39574
- },
39575
- msOverflowStyle: "none",
39576
- scrollbarWidth: "none"
39577
- }, children: storageCategories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_material27.Alert, { severity: "info", sx: { mt: 2 }, children: [
40026
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_material27.Box, { children: storageCategories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_material27.Alert, { severity: "info", sx: { mt: 2 }, children: [
39578
40027
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_material27.Typography, { variant: "body2", children: "No storage data found. This could mean:" }),
39579
40028
  /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_material27.Typography, { variant: "body2", component: "ul", sx: { mt: 1, pl: 2 }, children: [
39580
40029
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("li", { children: "All databases are empty" }),
@@ -41093,7 +41542,7 @@ var Management = () => {
41093
41542
  const [modalOpen, setModalOpen] = (0, import_react56.useState)(false);
41094
41543
  const banditHead6 = "https://cdn.burtson.ai/images/bandit-head.png";
41095
41544
  const [fabLogo, setFabLogo] = (0, import_react56.useState)(banditHead6);
41096
- const [tabIndex, setTabIndex] = (0, import_react56.useState)(0);
41545
+ const [tabIndex, setTabIndex] = (0, import_react56.useState)(4);
41097
41546
  const [logoFile, setLogoFile] = (0, import_react56.useState)(null);
41098
41547
  const [logoBase64, setLogoBase64] = (0, import_react56.useState)(null);
41099
41548
  const [brandingText, setBrandingText] = (0, import_react56.useState)("");
@@ -41806,7 +42255,6 @@ var Management = () => {
41806
42255
  }
41807
42256
  });
41808
42257
  }, [theme]);
41809
- if (!brandingLoaded) return null;
41810
42258
  const allNavTabs = [
41811
42259
  {
41812
42260
  label: "Personalities",
@@ -41863,6 +42311,18 @@ var Management = () => {
41863
42311
  }
41864
42312
  return true;
41865
42313
  });
42314
+ const preferredDefaultTabIndex = navTabs.findIndex((tab) => tab.label === "Preferences");
42315
+ const defaultTabIndex = preferredDefaultTabIndex >= 0 ? preferredDefaultTabIndex : 0;
42316
+ (0, import_react56.useEffect)(() => {
42317
+ setTabIndex((current) => {
42318
+ if (current < 0 || current >= navTabs.length) {
42319
+ return defaultTabIndex;
42320
+ }
42321
+ return current;
42322
+ });
42323
+ }, [navTabs.length, defaultTabIndex]);
42324
+ const mobileQuickTabs = navTabs.slice(0, 5);
42325
+ const hasMobileOverflowTabs = navTabs.length > mobileQuickTabs.length;
41866
42326
  const navigationContent = /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
41867
42327
  import_material47.Box,
41868
42328
  {
@@ -42019,6 +42479,7 @@ var Management = () => {
42019
42479
  ]
42020
42480
  }
42021
42481
  );
42482
+ if (!brandingLoaded) return null;
42022
42483
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_material47.ThemeProvider, { theme: currentTheme, children: [
42023
42484
  /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_material47.CssBaseline, {}),
42024
42485
  /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
@@ -42039,7 +42500,7 @@ var Management = () => {
42039
42500
  {
42040
42501
  sx: {
42041
42502
  width: "100%",
42042
- height: 64,
42503
+ minHeight: 64,
42043
42504
  display: "flex",
42044
42505
  alignItems: "center",
42045
42506
  justifyContent: "space-between",
@@ -42122,6 +42583,73 @@ var Management = () => {
42122
42583
  ]
42123
42584
  }
42124
42585
  ),
42586
+ isMobile && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
42587
+ import_material47.Box,
42588
+ {
42589
+ sx: {
42590
+ width: "100%",
42591
+ display: "flex",
42592
+ gap: 1,
42593
+ px: 1.5,
42594
+ py: 1,
42595
+ overflowX: "auto",
42596
+ borderBottom: (theme2) => `1px solid ${theme2.palette.divider}`,
42597
+ bgcolor: (theme2) => theme2.palette.mode === "dark" ? "rgba(24,28,40,0.95)" : "rgba(255,255,255,0.95)",
42598
+ backdropFilter: "blur(12px)"
42599
+ },
42600
+ children: [
42601
+ mobileQuickTabs.map((tab) => {
42602
+ const quickTabIndex = navTabs.findIndex((navTab) => navTab.label === tab.label);
42603
+ const selected = tabIndex === quickTabIndex;
42604
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
42605
+ import_material47.Button,
42606
+ {
42607
+ size: "small",
42608
+ onClick: () => setTabIndex(quickTabIndex),
42609
+ sx: {
42610
+ flexShrink: 0,
42611
+ textTransform: "none",
42612
+ borderRadius: 999,
42613
+ px: 1.5,
42614
+ py: 0.6,
42615
+ minHeight: 32,
42616
+ fontSize: "0.78rem",
42617
+ fontWeight: selected ? 700 : 600,
42618
+ bgcolor: selected ? (theme2) => theme2.palette.mode === "dark" ? "rgba(25,118,210,0.2)" : "rgba(25,118,210,0.12)" : "transparent",
42619
+ color: selected ? "primary.main" : "text.secondary",
42620
+ border: (theme2) => selected ? `1px solid ${theme2.palette.primary.main}66` : `1px solid ${(0, import_styles31.alpha)(theme2.palette.divider, 0.45)}`,
42621
+ "&:hover": {
42622
+ bgcolor: (theme2) => theme2.palette.mode === "dark" ? "rgba(25,118,210,0.16)" : "rgba(25,118,210,0.1)"
42623
+ }
42624
+ },
42625
+ children: tab.label
42626
+ },
42627
+ tab.label
42628
+ );
42629
+ }),
42630
+ hasMobileOverflowTabs && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
42631
+ import_material47.Button,
42632
+ {
42633
+ size: "small",
42634
+ onClick: () => setSidebarOpen(true),
42635
+ sx: {
42636
+ flexShrink: 0,
42637
+ textTransform: "none",
42638
+ borderRadius: 999,
42639
+ px: 1.5,
42640
+ py: 0.6,
42641
+ minHeight: 32,
42642
+ fontSize: "0.78rem",
42643
+ fontWeight: 600,
42644
+ color: "text.secondary",
42645
+ border: (theme2) => `1px dashed ${(0, import_styles31.alpha)(theme2.palette.divider, 0.6)}`
42646
+ },
42647
+ children: "More"
42648
+ }
42649
+ )
42650
+ ]
42651
+ }
42652
+ ),
42125
42653
  isMobile ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
42126
42654
  import_material47.SwipeableDrawer,
42127
42655
  {
@@ -42174,26 +42702,17 @@ var Management = () => {
42174
42702
  flex: 1,
42175
42703
  p: { xs: 1, sm: 3, md: 4 },
42176
42704
  overflowY: "auto",
42177
- height: isMobile ? "auto" : "100vh",
42705
+ overflowX: "hidden",
42178
42706
  maxWidth: "100vw",
42179
42707
  minWidth: 0,
42708
+ minHeight: 0,
42180
42709
  display: "flex",
42181
42710
  flexDirection: "column",
42182
42711
  bgcolor: "background.default",
42183
42712
  ml: isMobile ? 0 : "280px",
42184
42713
  // Fixed left margin only on desktop
42185
42714
  mt: 0,
42186
- transition: "margin-left 0.2s",
42187
- overflow: "auto",
42188
- // Hide scrollbars while keeping scroll functionality
42189
- scrollbarWidth: "none",
42190
- // Firefox
42191
- "&::-webkit-scrollbar": {
42192
- display: "none"
42193
- // Chrome, Safari, Edge
42194
- },
42195
- "-ms-overflow-style": "none"
42196
- // IE and Edge
42715
+ transition: "margin-left 0.2s"
42197
42716
  },
42198
42717
  children: [
42199
42718
  navTabs[tabIndex]?.label === "Personalities" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(