@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
package/dist/index.js CHANGED
@@ -210,13 +210,22 @@ var init_debugLogger = __esm({
210
210
  });
211
211
 
212
212
  // src/services/auth/authenticationService.ts
213
- var TOKEN_KEY2, AuthenticationService, authenticationService;
213
+ function emitAuthTokenChanged(token) {
214
+ if (typeof window === "undefined") {
215
+ return;
216
+ }
217
+ window.dispatchEvent(new CustomEvent(AUTH_TOKEN_CHANGED_EVENT, {
218
+ detail: { token }
219
+ }));
220
+ }
221
+ var TOKEN_KEY2, AUTH_TOKEN_CHANGED_EVENT, AuthenticationService, authenticationService;
214
222
  var init_authenticationService = __esm({
215
223
  "src/services/auth/authenticationService.ts"() {
216
224
  "use strict";
217
225
  init_authenticationStore();
218
226
  init_debugLogger();
219
227
  TOKEN_KEY2 = "authToken";
228
+ AUTH_TOKEN_CHANGED_EVENT = "bandit:auth-token-changed";
220
229
  AuthenticationService = class {
221
230
  getToken() {
222
231
  const token = localStorage.getItem(TOKEN_KEY2);
@@ -225,10 +234,12 @@ var init_authenticationService = __esm({
225
234
  setToken(token) {
226
235
  localStorage.setItem(TOKEN_KEY2, token);
227
236
  useAuthenticationStore.getState().setToken(token);
237
+ emitAuthTokenChanged(token);
228
238
  }
229
239
  clearToken() {
230
240
  localStorage.removeItem(TOKEN_KEY2);
231
241
  useAuthenticationStore.getState().clearToken();
242
+ emitAuthTokenChanged(null);
232
243
  }
233
244
  isAuthenticated() {
234
245
  const token = useAuthenticationStore.getState().token;
@@ -467,7 +478,18 @@ async function saveStateToDB(state) {
467
478
  await indexedDBService_default.put(DB_NAME, DB_VERSION, STORE_NAME, state, storeConfigs, STORAGE_KEY);
468
479
  }
469
480
  async function loadStateFromDB() {
470
- return indexedDBService_default.get(DB_NAME, DB_VERSION, STORE_NAME, STORAGE_KEY, storeConfigs);
481
+ let timeoutId;
482
+ const timeoutPromise = new Promise((resolve) => {
483
+ timeoutId = window.setTimeout(() => resolve(void 0), 1200);
484
+ });
485
+ try {
486
+ const getPromise = indexedDBService_default.get(DB_NAME, DB_VERSION, STORE_NAME, STORAGE_KEY, storeConfigs).catch(() => void 0);
487
+ return await Promise.race([getPromise, timeoutPromise]);
488
+ } finally {
489
+ if (timeoutId !== void 0) {
490
+ window.clearTimeout(timeoutId);
491
+ }
492
+ }
471
493
  }
472
494
  var import_zustand3, DB_NAME, STORE_NAME, DB_VERSION, STORAGE_KEY, storeConfigs, useAIQueryStore;
473
495
  var init_aiQueryStore = __esm({
@@ -534,19 +556,23 @@ var init_aiQueryStore = __esm({
534
556
  saveStateToDB(resetState);
535
557
  },
536
558
  hydrate: async () => {
537
- const storedState = await loadStateFromDB();
538
- if (storedState) {
539
- set({
540
- inputValue: storedState.inputValue ?? "",
541
- response: storedState.response ?? "",
542
- previousQuestion: storedState.previousQuestion ?? "",
543
- position: storedState.position ?? { x: window.innerWidth / 2 - 300, y: window.innerHeight - 350 },
544
- componentStatus: "Idle",
545
- history: storedState.history ?? [],
546
- apiKey: storedState.apiKey ?? "",
547
- hydrated: true
548
- });
549
- } else {
559
+ try {
560
+ const storedState = await loadStateFromDB();
561
+ if (storedState) {
562
+ set({
563
+ inputValue: storedState.inputValue ?? "",
564
+ response: storedState.response ?? "",
565
+ previousQuestion: storedState.previousQuestion ?? "",
566
+ position: storedState.position ?? { x: window.innerWidth / 2 - 300, y: window.innerHeight - 350 },
567
+ componentStatus: "Idle",
568
+ history: storedState.history ?? [],
569
+ apiKey: storedState.apiKey ?? "",
570
+ hydrated: true
571
+ });
572
+ } else {
573
+ set({ hydrated: true });
574
+ }
575
+ } catch {
550
576
  set({ hydrated: true });
551
577
  }
552
578
  }
@@ -2168,9 +2194,99 @@ function ensureDeviceId() {
2168
2194
  return (0, import_uuid3.v4)();
2169
2195
  }
2170
2196
  }
2197
+ function getStoredSyncIdentity() {
2198
+ if (typeof window === "undefined") {
2199
+ return null;
2200
+ }
2201
+ try {
2202
+ return window.localStorage.getItem(SYNC_IDENTITY_STORAGE_KEY);
2203
+ } catch (error) {
2204
+ debugLogger.warn("conversationSyncStore: unable to read stored sync identity", { error });
2205
+ return null;
2206
+ }
2207
+ }
2208
+ function setStoredSyncIdentity(identity) {
2209
+ if (typeof window === "undefined") {
2210
+ return;
2211
+ }
2212
+ try {
2213
+ if (identity) {
2214
+ window.localStorage.setItem(SYNC_IDENTITY_STORAGE_KEY, identity);
2215
+ } else {
2216
+ window.localStorage.removeItem(SYNC_IDENTITY_STORAGE_KEY);
2217
+ }
2218
+ } catch (error) {
2219
+ debugLogger.warn("conversationSyncStore: unable to persist sync identity", { error });
2220
+ }
2221
+ }
2171
2222
  function getPackageDefaultAdvancedKnowledgeSync() {
2172
2223
  return usePackageSettingsStore.getState().settings?.advancedKnowledgeSyncDefaultEnabled;
2173
2224
  }
2225
+ function clearAutoSyncTimer() {
2226
+ if (autoSyncTimeout) {
2227
+ clearTimeout(autoSyncTimeout);
2228
+ autoSyncTimeout = null;
2229
+ }
2230
+ }
2231
+ function resolveAuthIdentity(token) {
2232
+ if (!token) {
2233
+ return null;
2234
+ }
2235
+ const claims = authenticationService.parseJwtClaims(token);
2236
+ if (claims?.sub) {
2237
+ return claims.sub;
2238
+ }
2239
+ if (claims?.email) {
2240
+ return `email:${claims.email.toLowerCase()}`;
2241
+ }
2242
+ return `token:${token.slice(0, 32)}`;
2243
+ }
2244
+ function buildQueueResetState() {
2245
+ return {
2246
+ pendingConversationUpserts: /* @__PURE__ */ new Set(),
2247
+ pendingConversationDeletes: /* @__PURE__ */ new Set(),
2248
+ pendingProjectUpserts: /* @__PURE__ */ new Set(),
2249
+ pendingProjectDeletes: /* @__PURE__ */ new Set(),
2250
+ conflicts: null,
2251
+ lastSyncAt: null,
2252
+ cursor: null,
2253
+ lastError: null,
2254
+ totalConversationsOnServer: void 0,
2255
+ totalProjectsOnServer: void 0,
2256
+ hasCompletedInitialUpload: false,
2257
+ warningConversations: [],
2258
+ oversizedConversations: []
2259
+ };
2260
+ }
2261
+ async function clearLocalStoresForIdentitySwitch(fromIdentity, toIdentity) {
2262
+ const conversationCount = useConversationStore.getState().conversations.length;
2263
+ const projectCount = useProjectStore.getState().projects.length;
2264
+ debugLogger.warn("conversationSyncStore: auth identity changed, clearing local conversation/project cache", {
2265
+ fromIdentity,
2266
+ toIdentity,
2267
+ conversationCount,
2268
+ projectCount
2269
+ });
2270
+ suppressTracking = true;
2271
+ try {
2272
+ await useConversationStore.getState().clearAllConversations();
2273
+ await indexedDBService_default.clear(
2274
+ PROJECT_DB_NAME,
2275
+ PROJECT_DB_VERSION,
2276
+ PROJECT_STORE_NAME,
2277
+ PROJECT_STORE_CONFIGS
2278
+ );
2279
+ useProjectStore.setState({ projects: [] });
2280
+ conversationsMeta = snapshotConversationMetaMap(useConversationStore.getState().conversations);
2281
+ projectsMeta = snapshotProjectMetaMap(useProjectStore.getState().projects);
2282
+ } catch (error) {
2283
+ debugLogger.error("conversationSyncStore: failed to clear local stores on auth switch", {
2284
+ error: error instanceof Error ? error.message : String(error)
2285
+ });
2286
+ } finally {
2287
+ suppressTracking = false;
2288
+ }
2289
+ }
2174
2290
  function mapConversationToDTO(conversation) {
2175
2291
  const updatedAtIso = (conversation.updatedAt ?? /* @__PURE__ */ new Date()).toISOString();
2176
2292
  const createdAtIso = conversation.createdAt ? conversation.createdAt.toISOString() : null;
@@ -2564,7 +2680,7 @@ function buildOversizedMessage(notices) {
2564
2680
  const names = notices.map((n) => `"${n.name || "Untitled"}"`).join(", ");
2565
2681
  return `Some conversations (${names}) are too large for Bandit Cloud. Start a new conversation or archive older turns to continue syncing.`;
2566
2682
  }
2567
- var import_zustand9, import_uuid3, DEVICE_STORAGE_KEY, PAYLOAD_VERSION, MAX_CONVERSATION_BYTES, WARN_CONVERSATION_BYTES, suppressTracking, conversationsMeta, projectsMeta, conversationUnsubscribe, projectUnsubscribe, autoSyncTimeout, AUTO_SYNC_DELAY_MS, useConversationSyncStore;
2683
+ var import_zustand9, import_uuid3, 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;
2568
2684
  var init_conversationSyncStore = __esm({
2569
2685
  "src/store/conversationSyncStore.ts"() {
2570
2686
  "use strict";
@@ -2574,13 +2690,19 @@ var init_conversationSyncStore = __esm({
2574
2690
  init_projectStore();
2575
2691
  init_packageSettingsStore();
2576
2692
  init_authenticationService();
2693
+ init_indexedDBService();
2577
2694
  init_conversationSyncEvents();
2578
2695
  init_conversationSyncService();
2579
2696
  init_debugLogger();
2580
2697
  DEVICE_STORAGE_KEY = "banditConversationDeviceId";
2698
+ SYNC_IDENTITY_STORAGE_KEY = "banditConversationSyncIdentity";
2581
2699
  PAYLOAD_VERSION = 1;
2582
2700
  MAX_CONVERSATION_BYTES = 12 * 1024 * 1024;
2583
2701
  WARN_CONVERSATION_BYTES = 10 * 1024 * 1024;
2702
+ PROJECT_DB_NAME = "bandit-projects";
2703
+ PROJECT_DB_VERSION = 1;
2704
+ PROJECT_STORE_NAME = "projects";
2705
+ PROJECT_STORE_CONFIGS = [{ name: PROJECT_STORE_NAME, keyPath: "id" }];
2584
2706
  suppressTracking = false;
2585
2707
  conversationsMeta = /* @__PURE__ */ new Map();
2586
2708
  projectsMeta = /* @__PURE__ */ new Map();
@@ -2616,6 +2738,9 @@ var init_conversationSyncStore = __esm({
2616
2738
  }
2617
2739
  useConversationSyncStore = (0, import_zustand9.create)((set, get) => ({
2618
2740
  initialized: false,
2741
+ hasLoadedPreference: false,
2742
+ initializedForToken: null,
2743
+ initializedForIdentity: null,
2619
2744
  syncEnabled: false,
2620
2745
  status: "disabled",
2621
2746
  lastSyncAt: null,
@@ -2635,20 +2760,63 @@ var init_conversationSyncStore = __esm({
2635
2760
  warningConversations: [],
2636
2761
  oversizedConversations: [],
2637
2762
  async initialize() {
2638
- if (get().initialized) {
2639
- return;
2640
- }
2641
2763
  ensureTrackersInitialized();
2642
2764
  const gatewayUrl = usePackageSettingsStore.getState().settings?.gatewayApiUrl;
2765
+ const token = authenticationService.getToken();
2766
+ const tokenIdentity = resolveAuthIdentity(token);
2767
+ const current = get();
2768
+ const storedIdentity = getStoredSyncIdentity();
2769
+ const knownIdentity = current.initializedForIdentity ?? storedIdentity;
2770
+ if (current.initialized && current.hasLoadedPreference && knownIdentity && tokenIdentity && knownIdentity === tokenIdentity) {
2771
+ return;
2772
+ }
2773
+ const hasIdentitySwitch = Boolean(
2774
+ knownIdentity && tokenIdentity && knownIdentity !== tokenIdentity
2775
+ );
2776
+ if (hasIdentitySwitch) {
2777
+ clearAutoSyncTimer();
2778
+ set({
2779
+ ...buildQueueResetState(),
2780
+ syncEnabled: false,
2781
+ status: "disabled",
2782
+ hasLoadedPreference: false,
2783
+ initializedForToken: null,
2784
+ initializedForIdentity: tokenIdentity
2785
+ });
2786
+ await clearLocalStoresForIdentitySwitch(
2787
+ knownIdentity,
2788
+ tokenIdentity
2789
+ );
2790
+ setStoredSyncIdentity(tokenIdentity);
2791
+ }
2643
2792
  if (!gatewayUrl) {
2644
2793
  debugLogger.info("conversationSyncStore: gateway API URL not configured; sync disabled");
2645
- set({ initialized: true, status: "disabled", syncEnabled: false });
2794
+ if (tokenIdentity) {
2795
+ setStoredSyncIdentity(tokenIdentity);
2796
+ }
2797
+ set({
2798
+ ...buildQueueResetState(),
2799
+ initialized: true,
2800
+ hasLoadedPreference: false,
2801
+ initializedForToken: null,
2802
+ initializedForIdentity: tokenIdentity,
2803
+ status: "disabled",
2804
+ syncEnabled: false
2805
+ });
2646
2806
  return;
2647
2807
  }
2648
- const token = authenticationService.getToken();
2649
2808
  if (!token) {
2650
2809
  debugLogger.info("conversationSyncStore: no authentication token; sync disabled until login");
2651
- set({ initialized: true, status: "disabled", syncEnabled: false });
2810
+ clearAutoSyncTimer();
2811
+ set({
2812
+ ...buildQueueResetState(),
2813
+ initialized: true,
2814
+ hasLoadedPreference: false,
2815
+ initializedForToken: null,
2816
+ initializedForIdentity: null,
2817
+ status: "disabled",
2818
+ syncEnabled: false
2819
+ });
2652
2820
  return;
2653
2821
  }
2654
2822
  try {
@@ -2670,14 +2838,27 @@ var init_conversationSyncStore = __esm({
2670
2838
  isAdvancedVectorFeaturesEnabled: get().isAdvancedVectorFeaturesEnabled
2671
2839
  }
2672
2840
  });
2673
- set({ initialized: true });
2841
+ set({
2842
+ initialized: true,
2843
+ hasLoadedPreference: true,
2844
+ initializedForToken: token,
2845
+ initializedForIdentity: tokenIdentity
2846
+ });
2847
+ setStoredSyncIdentity(tokenIdentity);
2674
2848
  if (preference.syncEnabled) {
2675
2849
  await get().runSync({ force: true });
2676
2850
  }
2677
2851
  } catch (error) {
2678
2852
  const message = error instanceof Error ? error.message : "Failed to load conversation sync preference";
2679
2853
  debugLogger.error("conversationSyncStore: initialization failed", { error: message });
2680
- set({ initialized: true, status: "error", lastError: message });
2854
+ set({
2855
+ initialized: true,
2856
+ hasLoadedPreference: false,
2857
+ initializedForToken: null,
2858
+ initializedForIdentity: tokenIdentity,
2859
+ status: "error",
2860
+ lastError: message
2861
+ });
2681
2862
  }
2682
2863
  },
2683
2864
  async setSyncEnabled(enabled) {
@@ -2705,6 +2886,12 @@ var init_conversationSyncStore = __esm({
2705
2886
  isAdvancedVectorFeaturesEnabled
2706
2887
  }
2707
2888
  });
2889
+ set({
2890
+ hasLoadedPreference: true,
2891
+ initializedForToken: authenticationService.getToken(),
2892
+ initializedForIdentity: resolveAuthIdentity(authenticationService.getToken())
2893
+ });
2894
+ setStoredSyncIdentity(resolveAuthIdentity(authenticationService.getToken()));
2708
2895
  if (enabled) {
2709
2896
  set({ hasCompletedInitialUpload: false });
2710
2897
  }
@@ -2742,6 +2929,12 @@ var init_conversationSyncStore = __esm({
2742
2929
  isAdvancedVectorFeaturesEnabled: enabled
2743
2930
  }
2744
2931
  });
2932
+ set({
2933
+ hasLoadedPreference: true,
2934
+ initializedForToken: authenticationService.getToken(),
2935
+ initializedForIdentity: resolveAuthIdentity(authenticationService.getToken())
2936
+ });
2937
+ setStoredSyncIdentity(resolveAuthIdentity(authenticationService.getToken()));
2745
2938
  if (preference.syncEnabled && preference.isAdvancedVectorFeaturesEnabled) {
2746
2939
  await get().runSync({ force: true });
2747
2940
  }
@@ -2787,6 +2980,15 @@ var init_conversationSyncStore = __esm({
2787
2980
  debugLogger.error("conversationSyncStore: runSync error - missing auth token");
2788
2981
  return;
2789
2982
  }
2983
+ const tokenIdentity = resolveAuthIdentity(token);
2984
+ if (state.initializedForIdentity && tokenIdentity && state.initializedForIdentity !== tokenIdentity) {
2985
+ debugLogger.warn("conversationSyncStore: runSync aborted due auth identity mismatch; reinitializing", {
2986
+ initializedForIdentity: state.initializedForIdentity,
2987
+ tokenIdentity
2988
+ });
2989
+ await get().initialize();
2990
+ return;
2991
+ }
2790
2992
  const pendingConversationIds = Array.from(state.pendingConversationUpserts);
2791
2993
  const pendingConversationDeleteIds = Array.from(state.pendingConversationDeletes);
2792
2994
  const pendingProjectIds = Array.from(state.pendingProjectUpserts);
@@ -28365,6 +28567,22 @@ var init_chat2 = __esm({
28365
28567
  }, 500);
28366
28568
  }
28367
28569
  }, [history, pendingMessage]);
28570
+ (0, import_react35.useEffect)(() => {
28571
+ if (!brandingLoading && !themeLoading) {
28572
+ return;
28573
+ }
28574
+ const timeoutId = window.setTimeout(() => {
28575
+ if (brandingLoading || themeLoading) {
28576
+ debugLogger.warn("Chat: branding/theme load timed out, falling back to defaults");
28577
+ setBrandingLoading(false);
28578
+ setThemeLoading(false);
28579
+ if (!selectedTheme) {
28580
+ setSelectedTheme("bandit-dark");
28581
+ }
28582
+ }
28583
+ }, 2500);
28584
+ return () => window.clearTimeout(timeoutId);
28585
+ }, [brandingLoading, themeLoading, selectedTheme]);
28368
28586
  (0, import_react35.useEffect)(() => () => {
28369
28587
  if (logoFadeTimeoutRef.current) {
28370
28588
  window.clearTimeout(logoFadeTimeoutRef.current);
@@ -29082,7 +29300,30 @@ var init_chat2 = __esm({
29082
29300
  requestAnimationFrame(pump);
29083
29301
  }
29084
29302
  };
29085
- if (!hydrated || brandingLoading || themeLoading) return null;
29303
+ if (!hydrated || brandingLoading || themeLoading) {
29304
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_material27.ThemeProvider, { theme: banditTheme, children: [
29305
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_material27.CssBaseline, {}),
29306
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
29307
+ import_material27.Box,
29308
+ {
29309
+ sx: (theme) => ({
29310
+ minHeight: "100dvh",
29311
+ display: "flex",
29312
+ alignItems: "center",
29313
+ justifyContent: "center",
29314
+ flexDirection: "column",
29315
+ gap: 1.5,
29316
+ bgcolor: theme.palette.chat.shell,
29317
+ color: theme.palette.text.primary
29318
+ }),
29319
+ children: [
29320
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_material27.CircularProgress, { size: 32, thickness: 4 }),
29321
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_material27.Typography, { variant: "body2", color: "text.secondary", children: "Preparing your workspace..." })
29322
+ ]
29323
+ }
29324
+ )
29325
+ ] });
29326
+ }
29086
29327
  const userHasAccess = playgroundBypassAccess || ossMode || claims?.roles?.includes("super-user") || claims?.roles?.includes("admin");
29087
29328
  if (!userHasAccess) {
29088
29329
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_material27.ThemeProvider, { theme: banditTheme, children: [
@@ -29791,6 +30032,36 @@ var ChatProvider = (props) => {
29791
30032
  };
29792
30033
  initializeAsync();
29793
30034
  }, [props.packageSettings, loadDocuments]);
30035
+ (0, import_react6.useEffect)(() => {
30036
+ const isPlaygroundRoute = typeof window !== "undefined" && window.location.pathname.includes("/playground");
30037
+ const isPlaygroundMode3 = isPlaygroundRoute || props.packageSettings.playgroundMode === true;
30038
+ if (isPlaygroundMode3 || !props.packageSettings.gatewayApiUrl) {
30039
+ return;
30040
+ }
30041
+ const initializeSyncState = async () => {
30042
+ try {
30043
+ await useConversationSyncStore.getState().initialize();
30044
+ } catch (error) {
30045
+ debugLogger.error("ChatProvider: deferred sync initialization failed", {
30046
+ error: error instanceof Error ? error.message : String(error)
30047
+ });
30048
+ }
30049
+ };
30050
+ if (typeof window === "undefined") {
30051
+ return;
30052
+ }
30053
+ const handleAuthTokenChange = () => {
30054
+ void initializeSyncState();
30055
+ };
30056
+ window.addEventListener(AUTH_TOKEN_CHANGED_EVENT, handleAuthTokenChange);
30057
+ window.addEventListener("pageshow", handleAuthTokenChange);
30058
+ window.addEventListener("focus", handleAuthTokenChange);
30059
+ return () => {
30060
+ window.removeEventListener(AUTH_TOKEN_CHANGED_EVENT, handleAuthTokenChange);
30061
+ window.removeEventListener("pageshow", handleAuthTokenChange);
30062
+ window.removeEventListener("focus", handleAuthTokenChange);
30063
+ };
30064
+ }, [props.packageSettings.gatewayApiUrl, props.packageSettings.playgroundMode]);
29794
30065
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_query.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(FeatureFlagProvider, { config: featureFlagConfig, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(NotificationProvider, { children: props.children }) }) });
29795
30066
  };
29796
30067
  var chat_provider_default = ChatProvider;
@@ -32978,6 +33249,7 @@ var PersonalitiesTab = ({
32978
33249
  const [deleteDialogOpen, setDeleteDialogOpen] = (0, import_react44.useState)(false);
32979
33250
  const [personalityToDelete, setPersonalityToDelete] = (0, import_react44.useState)(null);
32980
33251
  const [clickedChips, setClickedChips] = (0, import_react44.useState)(/* @__PURE__ */ new Set());
33252
+ const [showTemplateHelp, setShowTemplateHelp] = (0, import_react44.useState)(false);
32981
33253
  const [cropperOpen, setCropperOpen] = (0, import_react44.useState)(false);
32982
33254
  const [selectedImageFile, setSelectedImageFile] = (0, import_react44.useState)(null);
32983
33255
  const promptTemplates = [
@@ -33231,28 +33503,15 @@ var PersonalitiesTab = ({
33231
33503
  }
33232
33504
  }
33233
33505
  ),
33234
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: {
33235
- height: "100%",
33236
- overflow: "auto",
33237
- p: { xs: 1.5, sm: 2 },
33238
- // Hide scrollbars while keeping scroll functionality
33239
- scrollbarWidth: "none",
33240
- // Firefox
33241
- "&::-webkit-scrollbar": {
33242
- display: "none"
33243
- // Chrome, Safari, Edge
33244
- },
33245
- "-ms-overflow-style": "none"
33246
- // IE and Edge
33247
- }, children: [
33506
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { p: { xs: 1, sm: 2 } }, children: [
33248
33507
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: {
33249
33508
  display: "flex",
33250
33509
  flexDirection: { xs: "column", md: "row" },
33251
33510
  alignItems: { xs: "flex-start", md: "center" },
33252
33511
  justifyContent: "space-between",
33253
- mb: { xs: 2, md: 3 },
33512
+ mb: { xs: 1.25, md: 3 },
33254
33513
  flexWrap: "wrap",
33255
- gap: { xs: 1.5, md: 2 }
33514
+ gap: { xs: 1, md: 2 }
33256
33515
  }, children: [
33257
33516
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: {
33258
33517
  display: "flex",
@@ -33282,8 +33541,8 @@ var PersonalitiesTab = ({
33282
33541
  backgroundClip: "text",
33283
33542
  WebkitBackgroundClip: "text",
33284
33543
  WebkitTextFillColor: "transparent",
33285
- mb: 0.5,
33286
- fontSize: { xs: "1.55rem", sm: "1.75rem" }
33544
+ mb: { xs: 0.25, sm: 0.5 },
33545
+ fontSize: { xs: "1.35rem", sm: "1.75rem" }
33287
33546
  },
33288
33547
  children: "Quick Start Templates"
33289
33548
  }
@@ -33308,12 +33567,40 @@ var PersonalitiesTab = ({
33308
33567
  color: "white",
33309
33568
  fontWeight: 600,
33310
33569
  animation: "pulse 2s infinite",
33311
- alignSelf: { xs: "flex-start", md: "center" }
33570
+ alignSelf: { xs: "flex-start", md: "center" },
33571
+ display: { xs: "none", md: "inline-flex" }
33312
33572
  }
33313
33573
  }
33314
33574
  )
33315
33575
  ] }),
33316
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33576
+ isMobile ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
33577
+ import_material36.Box,
33578
+ {
33579
+ sx: {
33580
+ mb: 1.75,
33581
+ borderRadius: 2,
33582
+ border: "1px solid rgba(25, 118, 210, 0.2)",
33583
+ background: "linear-gradient(135deg, rgba(25, 118, 210, 0.05) 0%, rgba(66, 165, 245, 0.05) 100%)",
33584
+ px: 1.25,
33585
+ py: 1
33586
+ },
33587
+ children: [
33588
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 1 }, children: [
33589
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_material36.Typography, { variant: "body2", sx: { fontWeight: 600, color: "primary.main", fontSize: "0.82rem" }, children: "Tap any template to pre-fill your form" }),
33590
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33591
+ import_material36.Button,
33592
+ {
33593
+ size: "small",
33594
+ onClick: () => setShowTemplateHelp((prev) => !prev),
33595
+ sx: { minWidth: "auto", px: 1, fontSize: "0.72rem", whiteSpace: "nowrap" },
33596
+ children: showTemplateHelp ? "Hide" : "Details"
33597
+ }
33598
+ )
33599
+ ] }),
33600
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_material36.Collapse, { in: showTemplateHelp, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_material36.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." }) })
33601
+ ]
33602
+ }
33603
+ ) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33317
33604
  import_material36.Alert,
33318
33605
  {
33319
33606
  severity: "info",
@@ -33339,17 +33626,19 @@ var PersonalitiesTab = ({
33339
33626
  import_material36.Card,
33340
33627
  {
33341
33628
  sx: {
33342
- mb: { xs: 3, md: 4 },
33629
+ mb: { xs: 2, md: 4 },
33343
33630
  background: "linear-gradient(135deg, #1976d2 0%, #42a5f5 100%)",
33344
33631
  border: "2px solid transparent",
33345
- borderRadius: 3,
33632
+ borderRadius: { xs: 2.25, sm: 3 },
33346
33633
  cursor: "pointer",
33347
33634
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
33348
33635
  position: "relative",
33349
33636
  overflow: "hidden",
33350
- "&:hover": {
33351
- transform: "translateY(-4px) scale(1.02)",
33352
- boxShadow: "0 12px 40px rgba(25, 118, 210, 0.3)"
33637
+ ...isMobile ? {} : {
33638
+ "&:hover": {
33639
+ transform: "translateY(-4px) scale(1.02)",
33640
+ boxShadow: "0 12px 40px rgba(25, 118, 210, 0.3)"
33641
+ }
33353
33642
  },
33354
33643
  "&::before": {
33355
33644
  content: '""',
@@ -33374,41 +33663,70 @@ var PersonalitiesTab = ({
33374
33663
  setPersonalityTabIndex(1);
33375
33664
  },
33376
33665
  children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.CardContent, { sx: {
33377
- p: { xs: 3, sm: 4 },
33666
+ p: { xs: 1.75, sm: 4 },
33378
33667
  color: "white",
33379
- textAlign: "center",
33668
+ textAlign: { xs: "left", sm: "center" },
33380
33669
  position: "relative",
33381
- zIndex: 1
33670
+ zIndex: 1,
33671
+ display: "flex",
33672
+ flexDirection: { xs: "row", sm: "column" },
33673
+ alignItems: { xs: "center", sm: "center" },
33674
+ gap: { xs: 1.25, sm: 0 }
33382
33675
  }, children: [
33383
33676
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_material36.Box, { sx: {
33384
33677
  display: "flex",
33385
33678
  alignItems: "center",
33386
33679
  justifyContent: "center",
33387
33680
  fontSize: 0,
33388
- mb: { xs: 1.5, sm: 2 }
33389
- }, children: /* @__PURE__ */ (0, import_jsx_runtime36.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))" } }) }),
33390
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33391
- import_material36.Typography,
33392
- {
33393
- variant: "h5",
33394
- sx: {
33395
- fontWeight: 700,
33396
- mb: { xs: 0.75, sm: 1 },
33397
- textShadow: "0 2px 4px rgba(0,0,0,0.2)"
33398
- },
33399
- children: "Create from Scratch"
33400
- }
33401
- ),
33402
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33403
- import_material36.Typography,
33681
+ mb: { xs: 0, sm: 2 },
33682
+ flexShrink: 0
33683
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime36.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))" } }) }),
33684
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { flex: 1, minWidth: 0 }, children: [
33685
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33686
+ import_material36.Typography,
33687
+ {
33688
+ variant: "h5",
33689
+ sx: {
33690
+ fontWeight: 700,
33691
+ mb: { xs: 0.25, sm: 1 },
33692
+ textShadow: "0 2px 4px rgba(0,0,0,0.2)",
33693
+ fontSize: { xs: "1.1rem", sm: "1.75rem" }
33694
+ },
33695
+ children: "Create from Scratch"
33696
+ }
33697
+ ),
33698
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33699
+ import_material36.Typography,
33700
+ {
33701
+ variant: "body1",
33702
+ sx: {
33703
+ opacity: 0.9,
33704
+ fontWeight: 500,
33705
+ textShadow: "0 1px 2px rgba(0,0,0,0.2)",
33706
+ fontSize: { xs: "0.8rem", sm: "1rem" },
33707
+ lineHeight: { xs: 1.3, sm: 1.5 },
33708
+ display: "-webkit-box",
33709
+ WebkitLineClamp: { xs: 2, sm: "unset" },
33710
+ WebkitBoxOrient: "vertical",
33711
+ overflow: "hidden"
33712
+ },
33713
+ children: "Start with a blank canvas and build your perfect AI personality"
33714
+ }
33715
+ )
33716
+ ] }),
33717
+ isMobile && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33718
+ import_material36.Chip,
33404
33719
  {
33405
- variant: "body1",
33720
+ label: "Start",
33721
+ size: "small",
33406
33722
  sx: {
33407
- opacity: 0.9,
33408
- fontWeight: 500,
33409
- textShadow: "0 1px 2px rgba(0,0,0,0.2)"
33410
- },
33411
- children: "Start with a blank canvas and build your perfect AI personality"
33723
+ backgroundColor: "rgba(255,255,255,0.2)",
33724
+ color: "common.white",
33725
+ border: "1px solid rgba(255,255,255,0.45)",
33726
+ fontWeight: 600,
33727
+ height: 28,
33728
+ flexShrink: 0
33729
+ }
33412
33730
  }
33413
33731
  )
33414
33732
  ] })
@@ -33423,7 +33741,7 @@ var PersonalitiesTab = ({
33423
33741
  lg: "repeat(4, 1fr)",
33424
33742
  xl: "repeat(4, 1fr)"
33425
33743
  },
33426
- gap: { xs: 2, sm: 2.5, md: 3 },
33744
+ gap: { xs: 1.25, sm: 2.5, md: 3 },
33427
33745
  alignItems: "stretch"
33428
33746
  }, children: promptTemplates.map((template, index) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33429
33747
  import_material36.Card,
@@ -33436,7 +33754,7 @@ var PersonalitiesTab = ({
33436
33754
  border: "1px solid",
33437
33755
  borderColor: "rgba(255,255,255,0.1)",
33438
33756
  borderRadius: 3,
33439
- minHeight: { xs: "auto", md: "280px" },
33757
+ minHeight: { xs: "200px", md: "280px" },
33440
33758
  display: "flex",
33441
33759
  flexDirection: "column",
33442
33760
  overflow: "hidden",
@@ -33454,19 +33772,21 @@ var PersonalitiesTab = ({
33454
33772
  opacity: 0,
33455
33773
  transition: "opacity 0.3s ease"
33456
33774
  },
33457
- "&:hover": {
33458
- transform: "translateY(-8px) scale(1.02)",
33459
- boxShadow: "0 20px 40px rgba(0,0,0,0.15)",
33460
- borderColor: "primary.main",
33461
- "&::before": {
33462
- opacity: 1
33463
- },
33464
- "& .template-icon": {
33465
- transform: "scale(1.1) rotate(5deg)"
33466
- },
33467
- "& .template-chip": {
33468
- transform: "translateY(-2px)",
33469
- boxShadow: "0 4px 12px rgba(0,0,0,0.2)"
33775
+ ...isMobile ? {} : {
33776
+ "&:hover": {
33777
+ transform: "translateY(-8px) scale(1.02)",
33778
+ boxShadow: "0 20px 40px rgba(0,0,0,0.15)",
33779
+ borderColor: "primary.main",
33780
+ "&::before": {
33781
+ opacity: 1
33782
+ },
33783
+ "& .template-icon": {
33784
+ transform: "scale(1.1) rotate(5deg)"
33785
+ },
33786
+ "& .template-chip": {
33787
+ transform: "translateY(-2px)",
33788
+ boxShadow: "0 4px 12px rgba(0,0,0,0.2)"
33789
+ }
33470
33790
  }
33471
33791
  },
33472
33792
  "&:active": {
@@ -33475,7 +33795,7 @@ var PersonalitiesTab = ({
33475
33795
  },
33476
33796
  onClick: () => handleTemplateSelect(template),
33477
33797
  children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.CardContent, { sx: {
33478
- p: { xs: 2.5, sm: 3 },
33798
+ p: { xs: 2, sm: 3 },
33479
33799
  display: "flex",
33480
33800
  flexDirection: "column",
33481
33801
  height: "100%",
@@ -33485,7 +33805,7 @@ var PersonalitiesTab = ({
33485
33805
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: {
33486
33806
  display: "flex",
33487
33807
  alignItems: "center",
33488
- mb: { xs: 2, md: 2.5 },
33808
+ mb: { xs: 1.25, md: 2.5 },
33489
33809
  minHeight: { xs: "auto", md: "60px" }
33490
33810
  }, children: [
33491
33811
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
@@ -33494,9 +33814,9 @@ var PersonalitiesTab = ({
33494
33814
  src: template.avatar,
33495
33815
  alt: template.name,
33496
33816
  sx: {
33497
- width: { xs: 48, sm: 56, md: 60 },
33498
- height: { xs: 48, sm: 56, md: 60 },
33499
- mr: { xs: 1.5, md: 2 },
33817
+ width: { xs: 40, sm: 56, md: 60 },
33818
+ height: { xs: 40, sm: 56, md: 60 },
33819
+ mr: { xs: 1.2, md: 2 },
33500
33820
  transition: "transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
33501
33821
  boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
33502
33822
  border: "2px solid rgba(255,255,255,0.8)"
@@ -33550,10 +33870,10 @@ var PersonalitiesTab = ({
33550
33870
  lineHeight: 1.5,
33551
33871
  fontSize: { xs: "0.82rem", sm: "0.85rem", md: "0.875rem" },
33552
33872
  display: "-webkit-box",
33553
- WebkitLineClamp: 4,
33873
+ WebkitLineClamp: { xs: 2, sm: 4 },
33554
33874
  WebkitBoxOrient: "vertical",
33555
33875
  overflow: "hidden",
33556
- mb: { xs: 1.5, md: 2 },
33876
+ mb: { xs: 1.25, md: 2 },
33557
33877
  minHeight: { xs: "auto", md: "84px" }
33558
33878
  },
33559
33879
  children: template.description
@@ -33590,7 +33910,7 @@ var PersonalitiesTab = ({
33590
33910
  },
33591
33911
  index
33592
33912
  )) }),
33593
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
33913
+ !isMobile && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
33594
33914
  import_material36.Alert,
33595
33915
  {
33596
33916
  severity: "info",
@@ -33604,20 +33924,7 @@ var PersonalitiesTab = ({
33604
33924
  )
33605
33925
  ] })
33606
33926
  ] });
33607
- const renderCreateEditTab = () => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: {
33608
- height: "100%",
33609
- overflow: "auto",
33610
- p: { xs: 1.5, sm: 2 },
33611
- // Hide scrollbars while keeping scroll functionality
33612
- scrollbarWidth: "none",
33613
- // Firefox
33614
- "&::-webkit-scrollbar": {
33615
- display: "none"
33616
- // Chrome, Safari, Edge
33617
- },
33618
- "-ms-overflow-style": "none"
33619
- // IE and Edge
33620
- }, children: [
33927
+ const renderCreateEditTab = () => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { p: { xs: 1.5, sm: 2 } }, children: [
33621
33928
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { mb: { xs: 2.5, md: 4 } }, children: [
33622
33929
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33623
33930
  import_material36.Typography,
@@ -34087,6 +34394,9 @@ var PersonalitiesTab = ({
34087
34394
  import_material36.Box,
34088
34395
  {
34089
34396
  sx: {
34397
+ position: { xs: "sticky", sm: "static" },
34398
+ bottom: { xs: 10, sm: "auto" },
34399
+ zIndex: { xs: 5, sm: "auto" },
34090
34400
  display: "flex",
34091
34401
  flexDirection: { xs: "column", sm: "row" },
34092
34402
  gap: { xs: 1.5, sm: 2 },
@@ -34094,8 +34404,15 @@ var PersonalitiesTab = ({
34094
34404
  // Changed from flex-end to flex-start
34095
34405
  mr: { xs: 0, sm: 10 },
34096
34406
  // Add right margin to avoid FAB
34097
- mb: { xs: 8, sm: 2 }
34407
+ mb: { xs: 8, sm: 2 },
34098
34408
  // Add bottom margin on mobile for FAB clearance
34409
+ mt: { xs: 1.5, sm: 0 },
34410
+ p: { xs: 1.1, sm: 0 },
34411
+ borderRadius: { xs: 2, sm: 0 },
34412
+ border: { xs: "1px solid", sm: "none" },
34413
+ borderColor: { xs: "divider", sm: "transparent" },
34414
+ bgcolor: { xs: "background.paper", sm: "transparent" },
34415
+ boxShadow: { xs: 3, sm: "none" }
34099
34416
  },
34100
34417
  children: [
34101
34418
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
@@ -34123,20 +34440,7 @@ var PersonalitiesTab = ({
34123
34440
  }
34124
34441
  )
34125
34442
  ] });
34126
- const renderManageTab = () => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: {
34127
- height: "100%",
34128
- overflow: "auto",
34129
- p: { xs: 1.5, sm: 2 },
34130
- // Hide scrollbars while keeping scroll functionality
34131
- scrollbarWidth: "none",
34132
- // Firefox
34133
- "&::-webkit-scrollbar": {
34134
- display: "none"
34135
- // Chrome, Safari, Edge
34136
- },
34137
- "-ms-overflow-style": "none"
34138
- // IE and Edge
34139
- }, children: [
34443
+ const renderManageTab = () => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { p: { xs: 1.5, sm: 2 } }, children: [
34140
34444
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
34141
34445
  import_material36.Box,
34142
34446
  {
@@ -34385,7 +34689,7 @@ var PersonalitiesTab = ({
34385
34689
  ] })
34386
34690
  ] })
34387
34691
  ] });
34388
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { height: "100%", display: "flex", flexDirection: "column" }, children: [
34692
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { display: "flex", flexDirection: "column" }, children: [
34389
34693
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
34390
34694
  import_material36.Box,
34391
34695
  {
@@ -34511,7 +34815,7 @@ var PersonalitiesTab = ({
34511
34815
  ]
34512
34816
  }
34513
34817
  ) }),
34514
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { flex: 1, overflow: "hidden" }, children: [
34818
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { minHeight: 0 }, children: [
34515
34819
  personalityTabIndex === 0 && renderTemplatesTab(),
34516
34820
  personalityTabIndex === 1 && renderCreateEditTab(),
34517
34821
  personalityTabIndex === 2 && renderManageTab()
@@ -38340,6 +38644,7 @@ var import_Add2 = __toESM(require("@mui/icons-material/Add"));
38340
38644
  var import_Archive = __toESM(require("@mui/icons-material/Archive"));
38341
38645
  var import_Delete6 = __toESM(require("@mui/icons-material/Delete"));
38342
38646
  var import_Description4 = __toESM(require("@mui/icons-material/Description"));
38647
+ var import_FolderOpen = __toESM(require("@mui/icons-material/FolderOpen"));
38343
38648
  var import_Group2 = __toESM(require("@mui/icons-material/Group"));
38344
38649
  var import_Person3 = __toESM(require("@mui/icons-material/Person"));
38345
38650
  var import_Publish = __toESM(require("@mui/icons-material/Publish"));
@@ -38619,6 +38924,22 @@ var archiveSeedPack = async (sid) => {
38619
38924
  throw error;
38620
38925
  }
38621
38926
  };
38927
+ var deleteSeedPack = async (sid) => {
38928
+ const url = buildUrl2(`/seed-packs/${encodeURIComponent(sid)}`);
38929
+ try {
38930
+ const response = await fetch(url, { method: "DELETE", headers: buildHeaders2() });
38931
+ if (response.status === 204) {
38932
+ return;
38933
+ }
38934
+ await handleJsonResponse2(response, "Failed to delete seed pack");
38935
+ } catch (error) {
38936
+ debugLogger.error("seedPackService: failed to delete seed pack", {
38937
+ sid,
38938
+ error: error instanceof Error ? error.message : String(error)
38939
+ });
38940
+ throw error;
38941
+ }
38942
+ };
38622
38943
 
38623
38944
  // src/management/components/SeedPacksTab.tsx
38624
38945
  var import_jsx_runtime42 = require("react/jsx-runtime");
@@ -38654,10 +38975,23 @@ var getPreviewSnippet = (content) => {
38654
38975
  }
38655
38976
  return trimmed.length > 120 ? `${trimmed.slice(0, 120)}...` : trimmed;
38656
38977
  };
38978
+ var getImportedFileKey = (file) => (file.relativePath ?? file.name).toLowerCase();
38979
+ var isMarkdownFileName = (name) => {
38980
+ const lower = name.toLowerCase();
38981
+ return lower.endsWith(".md") || lower.endsWith(".markdown");
38982
+ };
38983
+ var getWebkitRelativePath = (file) => {
38984
+ const relativePath = file.webkitRelativePath;
38985
+ if (!relativePath) {
38986
+ return void 0;
38987
+ }
38988
+ const trimmed = relativePath.trim().replace(/^\/+/, "");
38989
+ return trimmed.length > 0 ? trimmed : void 0;
38990
+ };
38657
38991
  var mergeMarkdownFiles = (existing, incoming) => {
38658
38992
  const next = [...existing];
38659
38993
  incoming.forEach((file) => {
38660
- const index = next.findIndex((item) => item.name === file.name);
38994
+ const index = next.findIndex((item) => getImportedFileKey(item) === getImportedFileKey(file));
38661
38995
  if (index >= 0) {
38662
38996
  next[index] = file;
38663
38997
  } else {
@@ -38669,17 +39003,22 @@ var mergeMarkdownFiles = (existing, incoming) => {
38669
39003
  var buildMarkdownContent = (files) => {
38670
39004
  return files.map((file) => file.content.trim()).filter((content) => content.length > 0).join("\n\n---\n\n");
38671
39005
  };
38672
- var readMarkdownFiles = async (files) => {
39006
+ var readMarkdownFiles = async (files, source = "local") => {
38673
39007
  const list = Array.from(files);
38674
- const markdownFiles = list.filter((file) => file.name.toLowerCase().endsWith(".md"));
39008
+ const markdownFiles = list.filter((file) => isMarkdownFileName(file.name));
38675
39009
  const imported = await Promise.all(
38676
- markdownFiles.map(async (file) => ({
38677
- id: `${file.name}-${file.lastModified}`,
38678
- name: file.name,
38679
- size: file.size,
38680
- content: await file.text(),
38681
- lastModified: file.lastModified
38682
- }))
39010
+ markdownFiles.map(async (file) => {
39011
+ const relativePath = getWebkitRelativePath(file);
39012
+ return {
39013
+ id: `${source}-${relativePath ?? file.name}-${file.lastModified}-${file.size}`,
39014
+ name: file.name,
39015
+ size: file.size,
39016
+ content: await file.text(),
39017
+ lastModified: file.lastModified,
39018
+ relativePath,
39019
+ source
39020
+ };
39021
+ })
38683
39022
  );
38684
39023
  return { imported, skipped: list.length - markdownFiles.length };
38685
39024
  };
@@ -38795,7 +39134,7 @@ var SeedPackFileCard = ({ file, onPreview, onRemove, isReadOnly }) => /* @__PURE
38795
39134
  )
38796
39135
  }
38797
39136
  ),
38798
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Tooltip, { title: file.name, arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39137
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Tooltip, { title: file.relativePath ?? file.name, arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
38799
39138
  import_material42.Typography,
38800
39139
  {
38801
39140
  variant: "body2",
@@ -38812,6 +39151,21 @@ var SeedPackFileCard = ({ file, onPreview, onRemove, isReadOnly }) => /* @__PURE
38812
39151
  children: file.name
38813
39152
  }
38814
39153
  ) }),
39154
+ file.relativePath && file.relativePath !== file.name && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Tooltip, { title: file.relativePath, arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39155
+ import_material42.Typography,
39156
+ {
39157
+ variant: "caption",
39158
+ color: "text.secondary",
39159
+ sx: {
39160
+ display: "block",
39161
+ whiteSpace: "nowrap",
39162
+ overflow: "hidden",
39163
+ textOverflow: "ellipsis",
39164
+ mb: 1
39165
+ },
39166
+ children: file.relativePath
39167
+ }
39168
+ ) }),
38815
39169
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
38816
39170
  import_material42.Box,
38817
39171
  {
@@ -38828,7 +39182,7 @@ var SeedPackFileCard = ({ file, onPreview, onRemove, isReadOnly }) => /* @__PURE
38828
39182
  import_material42.Chip,
38829
39183
  {
38830
39184
  icon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_Person3.default, { sx: { fontSize: "0.9rem !important" } }),
38831
- label: "Local",
39185
+ label: file.source === "azure-wiki" ? "Azure Wiki" : "Local",
38832
39186
  size: "small",
38833
39187
  sx: {
38834
39188
  bgcolor: "#388e3c20",
@@ -38917,16 +39271,20 @@ var SeedPacksTab = () => {
38917
39271
  const [createImportedFiles, setCreateImportedFiles] = (0, import_react52.useState)([]);
38918
39272
  const [previewFile, setPreviewFile] = (0, import_react52.useState)(null);
38919
39273
  const fileInputRef = (0, import_react52.useRef)(null);
39274
+ const wikiFolderInputRef = (0, import_react52.useRef)(null);
38920
39275
  const createFileInputRef = (0, import_react52.useRef)(null);
39276
+ const createWikiFolderInputRef = (0, import_react52.useRef)(null);
38921
39277
  const [isLoadingList, setIsLoadingList] = (0, import_react52.useState)(false);
38922
39278
  const [isLoadingDetail, setIsLoadingDetail] = (0, import_react52.useState)(false);
38923
39279
  const [isSaving, setIsSaving] = (0, import_react52.useState)(false);
38924
39280
  const [isPublishing, setIsPublishing] = (0, import_react52.useState)(false);
38925
39281
  const [isArchiving, setIsArchiving] = (0, import_react52.useState)(false);
39282
+ const [isDeleting, setIsDeleting] = (0, import_react52.useState)(false);
38926
39283
  const [isCreating, setIsCreating] = (0, import_react52.useState)(false);
38927
39284
  const [createDialogOpen, setCreateDialogOpen] = (0, import_react52.useState)(false);
38928
39285
  const [publishDialogOpen, setPublishDialogOpen] = (0, import_react52.useState)(false);
38929
39286
  const [archiveDialogOpen, setArchiveDialogOpen] = (0, import_react52.useState)(false);
39287
+ const [deleteDialogOpen, setDeleteDialogOpen] = (0, import_react52.useState)(false);
38930
39288
  const [newPackName, setNewPackName] = (0, import_react52.useState)("");
38931
39289
  const [newPackDescription, setNewPackDescription] = (0, import_react52.useState)("");
38932
39290
  const [newPackTags, setNewPackTags] = (0, import_react52.useState)("");
@@ -39031,26 +39389,37 @@ var SeedPacksTab = () => {
39031
39389
  void loadSeedPackDetail(selectedSid);
39032
39390
  }
39033
39391
  }, [selectedSid, loadSeedPackDetail]);
39392
+ (0, import_react52.useEffect)(() => {
39393
+ const setDirectoryUploadAttributes = (input) => {
39394
+ if (!input) {
39395
+ return;
39396
+ }
39397
+ input.setAttribute("webkitdirectory", "");
39398
+ input.setAttribute("directory", "");
39399
+ };
39400
+ setDirectoryUploadAttributes(wikiFolderInputRef.current);
39401
+ setDirectoryUploadAttributes(createWikiFolderInputRef.current);
39402
+ }, [selectedSeedPack, createDialogOpen]);
39034
39403
  const handleSelectPack = (pack) => {
39035
39404
  setSelectedSid(pack.sid);
39036
39405
  setSelectedSeedPack(pack);
39037
39406
  hydrateDraft(pack);
39038
39407
  };
39039
39408
  const handleImportFiles = (0, import_react52.useCallback)(
39040
- async (files) => {
39409
+ async (files, source = "local") => {
39041
39410
  if (!files || files.length === 0) {
39042
39411
  return;
39043
39412
  }
39044
- const { imported, skipped } = await readMarkdownFiles(files);
39413
+ const { imported, skipped } = await readMarkdownFiles(files, source);
39045
39414
  if (skipped > 0) {
39046
- showSnackbar("Only .md files are supported for seed packs.", "error");
39415
+ showSnackbar("Only .md and .markdown files are supported for seed packs.", "error");
39047
39416
  }
39048
39417
  if (imported.length === 0) {
39049
39418
  return;
39050
39419
  }
39051
39420
  try {
39052
39421
  const newlyAdded = imported.filter(
39053
- (file) => !importedFiles.some((existing) => existing.name === file.name)
39422
+ (file) => !importedFiles.some((existing) => getImportedFileKey(existing) === getImportedFileKey(file))
39054
39423
  );
39055
39424
  setImportedFiles((prev) => mergeMarkdownFiles(prev, imported));
39056
39425
  const combined = buildMarkdownContent(newlyAdded);
@@ -39065,8 +39434,9 @@ ${combined}` : combined;
39065
39434
  return { ...prev, content: nextContent };
39066
39435
  });
39067
39436
  }
39437
+ const importLabel = source === "azure-wiki" ? "from Azure DevOps wiki folder into the editor" : "into the editor";
39068
39438
  showSnackbar(
39069
- `Imported ${imported.length} markdown file${imported.length === 1 ? "" : "s"} into the editor.`,
39439
+ `Imported ${imported.length} markdown file${imported.length === 1 ? "" : "s"} ${importLabel}.`,
39070
39440
  "success"
39071
39441
  );
39072
39442
  } catch (error) {
@@ -39080,7 +39450,14 @@ ${combined}` : combined;
39080
39450
  );
39081
39451
  const handleFileInputChange = (0, import_react52.useCallback)(
39082
39452
  async (event) => {
39083
- await handleImportFiles(event.target.files);
39453
+ await handleImportFiles(event.target.files, "local");
39454
+ event.target.value = "";
39455
+ },
39456
+ [handleImportFiles]
39457
+ );
39458
+ const handleWikiFolderInputChange = (0, import_react52.useCallback)(
39459
+ async (event) => {
39460
+ await handleImportFiles(event.target.files, "azure-wiki");
39084
39461
  event.target.value = "";
39085
39462
  },
39086
39463
  [handleImportFiles]
@@ -39089,20 +39466,21 @@ ${combined}` : combined;
39089
39466
  setImportedFiles((prev) => prev.filter((file) => file.id !== id));
39090
39467
  }, []);
39091
39468
  const handleCreateImportFiles = (0, import_react52.useCallback)(
39092
- async (files) => {
39469
+ async (files, source = "local") => {
39093
39470
  if (!files || files.length === 0) {
39094
39471
  return;
39095
39472
  }
39096
- const { imported, skipped } = await readMarkdownFiles(files);
39473
+ const { imported, skipped } = await readMarkdownFiles(files, source);
39097
39474
  if (skipped > 0) {
39098
- showSnackbar("Only .md files are supported for seed packs.", "error");
39475
+ showSnackbar("Only .md and .markdown files are supported for seed packs.", "error");
39099
39476
  }
39100
39477
  if (imported.length === 0) {
39101
39478
  return;
39102
39479
  }
39103
39480
  setCreateImportedFiles((prev) => mergeMarkdownFiles(prev, imported));
39481
+ const importLabel = source === "azure-wiki" ? "from Azure DevOps wiki folder for this seed pack" : "for this seed pack";
39104
39482
  showSnackbar(
39105
- `Imported ${imported.length} markdown file${imported.length === 1 ? "" : "s"} for this seed pack.`,
39483
+ `Imported ${imported.length} markdown file${imported.length === 1 ? "" : "s"} ${importLabel}.`,
39106
39484
  "success"
39107
39485
  );
39108
39486
  },
@@ -39110,7 +39488,14 @@ ${combined}` : combined;
39110
39488
  );
39111
39489
  const handleCreateFileInputChange = (0, import_react52.useCallback)(
39112
39490
  async (event) => {
39113
- await handleCreateImportFiles(event.target.files);
39491
+ await handleCreateImportFiles(event.target.files, "local");
39492
+ event.target.value = "";
39493
+ },
39494
+ [handleCreateImportFiles]
39495
+ );
39496
+ const handleCreateWikiFolderInputChange = (0, import_react52.useCallback)(
39497
+ async (event) => {
39498
+ await handleCreateImportFiles(event.target.files, "azure-wiki");
39114
39499
  event.target.value = "";
39115
39500
  },
39116
39501
  [handleCreateImportFiles]
@@ -39255,6 +39640,34 @@ ${combined}` : combined;
39255
39640
  setIsArchiving(false);
39256
39641
  }
39257
39642
  };
39643
+ const handleDelete = async () => {
39644
+ if (!selectedSeedPack) {
39645
+ return;
39646
+ }
39647
+ const deletingSid = selectedSeedPack.sid;
39648
+ const deletingName = selectedSeedPack.name;
39649
+ setDeleteDialogOpen(false);
39650
+ setIsDeleting(true);
39651
+ try {
39652
+ await deleteSeedPack(deletingSid);
39653
+ setSelectedSid(null);
39654
+ setSelectedSeedPack(null);
39655
+ setDraft({ name: "", description: "", content: "" });
39656
+ setTagsInput("");
39657
+ setImportedFiles([]);
39658
+ setPreviewFile(null);
39659
+ await refreshSeedPacks();
39660
+ showSnackbar(`Deleted seed pack "${deletingName}".`, "success");
39661
+ } catch (error) {
39662
+ showSnackbar("Failed to delete seed pack.", "error");
39663
+ debugLogger.error("SeedPacksTab: failed to delete seed pack", {
39664
+ sid: deletingSid,
39665
+ error: error instanceof Error ? error.message : String(error)
39666
+ });
39667
+ } finally {
39668
+ setIsDeleting(false);
39669
+ }
39670
+ };
39258
39671
  const previewContent = draft.content.trim().length > 0 ? draft.content : "Preview will appear here as you type.";
39259
39672
  const selectedStatus = selectedSeedPack?.status ?? "draft";
39260
39673
  const statusChip = getStatusChip(selectedStatus);
@@ -39456,32 +39869,56 @@ ${combined}` : combined;
39456
39869
  sx: { mb: 1 },
39457
39870
  children: [
39458
39871
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Typography, { variant: "subtitle2", children: "Markdown content" }),
39872
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, children: [
39873
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39874
+ import_material42.Button,
39875
+ {
39876
+ size: "small",
39877
+ variant: "outlined",
39878
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_UploadFile2.default, {}),
39879
+ onClick: () => fileInputRef.current?.click(),
39880
+ disabled: isReadOnly,
39881
+ children: "Import .md"
39882
+ }
39883
+ ),
39884
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39885
+ import_material42.Button,
39886
+ {
39887
+ size: "small",
39888
+ variant: "outlined",
39889
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_FolderOpen.default, {}),
39890
+ onClick: () => wikiFolderInputRef.current?.click(),
39891
+ disabled: isReadOnly,
39892
+ children: "Import wiki folder"
39893
+ }
39894
+ )
39895
+ ] }),
39459
39896
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39460
- import_material42.Button,
39897
+ "input",
39461
39898
  {
39462
- size: "small",
39463
- variant: "outlined",
39464
- startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_UploadFile2.default, {}),
39465
- onClick: () => fileInputRef.current?.click(),
39466
- disabled: isReadOnly,
39467
- children: "Import .md"
39899
+ ref: fileInputRef,
39900
+ type: "file",
39901
+ accept: ".md,.markdown,text/markdown",
39902
+ multiple: true,
39903
+ onChange: handleFileInputChange,
39904
+ style: { display: "none" }
39468
39905
  }
39469
39906
  ),
39470
39907
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39471
39908
  "input",
39472
39909
  {
39473
- ref: fileInputRef,
39910
+ ref: wikiFolderInputRef,
39474
39911
  type: "file",
39475
- accept: ".md",
39912
+ accept: ".md,.markdown,text/markdown",
39476
39913
  multiple: true,
39477
- onChange: handleFileInputChange,
39914
+ onChange: handleWikiFolderInputChange,
39478
39915
  style: { display: "none" }
39479
39916
  }
39480
39917
  )
39481
39918
  ]
39482
39919
  }
39483
39920
  ),
39484
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Typography, { variant: "caption", color: "text.secondary", sx: { mb: 1, display: "block" }, children: "Paste or import markdown files. Imports copy content into the editor." }),
39921
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.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." }),
39485
39922
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39486
39923
  import_material42.TextField,
39487
39924
  {
@@ -39580,6 +40017,17 @@ ${combined}` : combined;
39580
40017
  disabled: isReadOnly || isArchiving,
39581
40018
  children: isArchiving ? "Archiving..." : "Archive"
39582
40019
  }
40020
+ ),
40021
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
40022
+ import_material42.Button,
40023
+ {
40024
+ variant: "text",
40025
+ color: "error",
40026
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_Delete6.default, {}),
40027
+ onClick: () => setDeleteDialogOpen(true),
40028
+ disabled: isDeleting,
40029
+ children: isDeleting ? "Deleting..." : "Delete"
40030
+ }
39583
40031
  )
39584
40032
  ] })
39585
40033
  ] })
@@ -39629,26 +40077,50 @@ ${combined}` : combined;
39629
40077
  ),
39630
40078
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Divider, {}),
39631
40079
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, alignItems: "center", children: [
40080
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, children: [
40081
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
40082
+ import_material42.Button,
40083
+ {
40084
+ size: "small",
40085
+ variant: "outlined",
40086
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_UploadFile2.default, {}),
40087
+ onClick: () => createFileInputRef.current?.click(),
40088
+ disabled: !canManage,
40089
+ children: "Import .md files"
40090
+ }
40091
+ ),
40092
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
40093
+ import_material42.Button,
40094
+ {
40095
+ size: "small",
40096
+ variant: "outlined",
40097
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_FolderOpen.default, {}),
40098
+ onClick: () => createWikiFolderInputRef.current?.click(),
40099
+ disabled: !canManage,
40100
+ children: "Import wiki folder"
40101
+ }
40102
+ )
40103
+ ] }),
40104
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Typography, { variant: "caption", color: "text.secondary", children: "Optional. Local files or cloned Azure DevOps wiki folders are merged into draft content." }),
39632
40105
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39633
- import_material42.Button,
40106
+ "input",
39634
40107
  {
39635
- size: "small",
39636
- variant: "outlined",
39637
- startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_UploadFile2.default, {}),
39638
- onClick: () => createFileInputRef.current?.click(),
39639
- disabled: !canManage,
39640
- children: "Import .md files"
40108
+ ref: createFileInputRef,
40109
+ type: "file",
40110
+ accept: ".md,.markdown,text/markdown",
40111
+ multiple: true,
40112
+ onChange: handleCreateFileInputChange,
40113
+ style: { display: "none" }
39641
40114
  }
39642
40115
  ),
39643
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Typography, { variant: "caption", color: "text.secondary", children: "Optional. Files are merged into the draft content." }),
39644
40116
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39645
40117
  "input",
39646
40118
  {
39647
- ref: createFileInputRef,
40119
+ ref: createWikiFolderInputRef,
39648
40120
  type: "file",
39649
- accept: ".md",
40121
+ accept: ".md,.markdown,text/markdown",
39650
40122
  multiple: true,
39651
- onChange: handleCreateFileInputChange,
40123
+ onChange: handleCreateWikiFolderInputChange,
39652
40124
  style: { display: "none" }
39653
40125
  }
39654
40126
  )
@@ -39713,6 +40185,21 @@ ${combined}` : combined;
39713
40185
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Button, { variant: "contained", color: "error", onClick: handleArchive, disabled: isArchiving, children: isArchiving ? "Archiving..." : "Archive" })
39714
40186
  ] })
39715
40187
  ] }),
40188
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.Dialog, { open: deleteDialogOpen, onClose: () => setDeleteDialogOpen(false), maxWidth: "sm", fullWidth: true, children: [
40189
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.DialogTitle, { children: "Delete seed pack" }),
40190
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.DialogContent, { children: [
40191
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.DialogContentText, { children: [
40192
+ 'Delete "',
40193
+ selectedSeedPack?.name ?? "this seed pack",
40194
+ '" permanently from this scope. Published versions and draft content will no longer be available.'
40195
+ ] }),
40196
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Alert, { severity: "warning", sx: { mt: 2 }, children: "This action cannot be undone." })
40197
+ ] }),
40198
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.DialogActions, { children: [
40199
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Button, { onClick: () => setDeleteDialogOpen(false), children: "Cancel" }),
40200
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Button, { variant: "contained", color: "error", onClick: handleDelete, disabled: isDeleting, children: isDeleting ? "Deleting..." : "Delete" })
40201
+ ] })
40202
+ ] }),
39716
40203
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
39717
40204
  import_material42.Dialog,
39718
40205
  {
@@ -40471,15 +40958,7 @@ var StorageTab = ({ currentTheme }) => {
40471
40958
  ] }) })
40472
40959
  ] }),
40473
40960
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_material44.Typography, { variant: "h6", gutterBottom: true, sx: { mb: 2, fontWeight: 600, color: "text.primary" }, children: "Storage Categories" }),
40474
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_material44.Box, { sx: {
40475
- maxHeight: "60vh",
40476
- overflow: "auto",
40477
- "&::-webkit-scrollbar": {
40478
- display: "none"
40479
- },
40480
- msOverflowStyle: "none",
40481
- scrollbarWidth: "none"
40482
- }, children: storageCategories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_material44.Alert, { severity: "info", sx: { mt: 2 }, children: [
40961
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_material44.Box, { children: storageCategories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_material44.Alert, { severity: "info", sx: { mt: 2 }, children: [
40483
40962
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_material44.Typography, { variant: "body2", children: "No storage data found. This could mean:" }),
40484
40963
  /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_material44.Typography, { variant: "body2", component: "ul", sx: { mt: 1, pl: 2 }, children: [
40485
40964
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("li", { children: "All databases are empty" }),
@@ -41721,7 +42200,7 @@ var Management = () => {
41721
42200
  const [modalOpen, setModalOpen] = (0, import_react57.useState)(false);
41722
42201
  const banditHead6 = "https://cdn.burtson.ai/images/bandit-head.png";
41723
42202
  const [fabLogo, setFabLogo] = (0, import_react57.useState)(banditHead6);
41724
- const [tabIndex, setTabIndex] = (0, import_react57.useState)(0);
42203
+ const [tabIndex, setTabIndex] = (0, import_react57.useState)(4);
41725
42204
  const [logoFile, setLogoFile] = (0, import_react57.useState)(null);
41726
42205
  const [logoBase64, setLogoBase64] = (0, import_react57.useState)(null);
41727
42206
  const [brandingText, setBrandingText] = (0, import_react57.useState)("");
@@ -42434,7 +42913,6 @@ var Management = () => {
42434
42913
  }
42435
42914
  });
42436
42915
  }, [theme]);
42437
- if (!brandingLoaded) return null;
42438
42916
  const allNavTabs = [
42439
42917
  {
42440
42918
  label: "Personalities",
@@ -42491,6 +42969,18 @@ var Management = () => {
42491
42969
  }
42492
42970
  return true;
42493
42971
  });
42972
+ const preferredDefaultTabIndex = navTabs.findIndex((tab) => tab.label === "Preferences");
42973
+ const defaultTabIndex = preferredDefaultTabIndex >= 0 ? preferredDefaultTabIndex : 0;
42974
+ (0, import_react57.useEffect)(() => {
42975
+ setTabIndex((current) => {
42976
+ if (current < 0 || current >= navTabs.length) {
42977
+ return defaultTabIndex;
42978
+ }
42979
+ return current;
42980
+ });
42981
+ }, [navTabs.length, defaultTabIndex]);
42982
+ const mobileQuickTabs = navTabs.slice(0, 5);
42983
+ const hasMobileOverflowTabs = navTabs.length > mobileQuickTabs.length;
42494
42984
  const navigationContent = /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
42495
42985
  import_material47.Box,
42496
42986
  {
@@ -42647,6 +43137,7 @@ var Management = () => {
42647
43137
  ]
42648
43138
  }
42649
43139
  );
43140
+ if (!brandingLoaded) return null;
42650
43141
  return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_material47.ThemeProvider, { theme: currentTheme, children: [
42651
43142
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_material47.CssBaseline, {}),
42652
43143
  /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
@@ -42667,7 +43158,7 @@ var Management = () => {
42667
43158
  {
42668
43159
  sx: {
42669
43160
  width: "100%",
42670
- height: 64,
43161
+ minHeight: 64,
42671
43162
  display: "flex",
42672
43163
  alignItems: "center",
42673
43164
  justifyContent: "space-between",
@@ -42750,6 +43241,73 @@ var Management = () => {
42750
43241
  ]
42751
43242
  }
42752
43243
  ),
43244
+ isMobile && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
43245
+ import_material47.Box,
43246
+ {
43247
+ sx: {
43248
+ width: "100%",
43249
+ display: "flex",
43250
+ gap: 1,
43251
+ px: 1.5,
43252
+ py: 1,
43253
+ overflowX: "auto",
43254
+ borderBottom: (theme2) => `1px solid ${theme2.palette.divider}`,
43255
+ bgcolor: (theme2) => theme2.palette.mode === "dark" ? "rgba(24,28,40,0.95)" : "rgba(255,255,255,0.95)",
43256
+ backdropFilter: "blur(12px)"
43257
+ },
43258
+ children: [
43259
+ mobileQuickTabs.map((tab) => {
43260
+ const quickTabIndex = navTabs.findIndex((navTab) => navTab.label === tab.label);
43261
+ const selected = tabIndex === quickTabIndex;
43262
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
43263
+ import_material47.Button,
43264
+ {
43265
+ size: "small",
43266
+ onClick: () => setTabIndex(quickTabIndex),
43267
+ sx: {
43268
+ flexShrink: 0,
43269
+ textTransform: "none",
43270
+ borderRadius: 999,
43271
+ px: 1.5,
43272
+ py: 0.6,
43273
+ minHeight: 32,
43274
+ fontSize: "0.78rem",
43275
+ fontWeight: selected ? 700 : 600,
43276
+ bgcolor: selected ? (theme2) => theme2.palette.mode === "dark" ? "rgba(25,118,210,0.2)" : "rgba(25,118,210,0.12)" : "transparent",
43277
+ color: selected ? "primary.main" : "text.secondary",
43278
+ border: (theme2) => selected ? `1px solid ${theme2.palette.primary.main}66` : `1px solid ${(0, import_styles31.alpha)(theme2.palette.divider, 0.45)}`,
43279
+ "&:hover": {
43280
+ bgcolor: (theme2) => theme2.palette.mode === "dark" ? "rgba(25,118,210,0.16)" : "rgba(25,118,210,0.1)"
43281
+ }
43282
+ },
43283
+ children: tab.label
43284
+ },
43285
+ tab.label
43286
+ );
43287
+ }),
43288
+ hasMobileOverflowTabs && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
43289
+ import_material47.Button,
43290
+ {
43291
+ size: "small",
43292
+ onClick: () => setSidebarOpen(true),
43293
+ sx: {
43294
+ flexShrink: 0,
43295
+ textTransform: "none",
43296
+ borderRadius: 999,
43297
+ px: 1.5,
43298
+ py: 0.6,
43299
+ minHeight: 32,
43300
+ fontSize: "0.78rem",
43301
+ fontWeight: 600,
43302
+ color: "text.secondary",
43303
+ border: (theme2) => `1px dashed ${(0, import_styles31.alpha)(theme2.palette.divider, 0.6)}`
43304
+ },
43305
+ children: "More"
43306
+ }
43307
+ )
43308
+ ]
43309
+ }
43310
+ ),
42753
43311
  isMobile ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
42754
43312
  import_material47.SwipeableDrawer,
42755
43313
  {
@@ -42802,26 +43360,17 @@ var Management = () => {
42802
43360
  flex: 1,
42803
43361
  p: { xs: 1, sm: 3, md: 4 },
42804
43362
  overflowY: "auto",
42805
- height: isMobile ? "auto" : "100vh",
43363
+ overflowX: "hidden",
42806
43364
  maxWidth: "100vw",
42807
43365
  minWidth: 0,
43366
+ minHeight: 0,
42808
43367
  display: "flex",
42809
43368
  flexDirection: "column",
42810
43369
  bgcolor: "background.default",
42811
43370
  ml: isMobile ? 0 : "280px",
42812
43371
  // Fixed left margin only on desktop
42813
43372
  mt: 0,
42814
- transition: "margin-left 0.2s",
42815
- overflow: "auto",
42816
- // Hide scrollbars while keeping scroll functionality
42817
- scrollbarWidth: "none",
42818
- // Firefox
42819
- "&::-webkit-scrollbar": {
42820
- display: "none"
42821
- // Chrome, Safari, Edge
42822
- },
42823
- "-ms-overflow-style": "none"
42824
- // IE and Edge
43373
+ transition: "margin-left 0.2s"
42825
43374
  },
42826
43375
  children: [
42827
43376
  navTabs[tabIndex]?.label === "Personalities" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(