@burtson-labs/bandit-engine 2.0.51 → 2.0.53

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 (48) hide show
  1. package/dist/{aiProviderStore-3N3VE6D4.mjs → aiProviderStore-337QNQB3.mjs} +2 -2
  2. package/dist/{chat-W5IFNEUC.mjs → chat-U4SE4JQK.mjs} +6 -6
  3. package/dist/chat-provider.js +242 -17
  4. package/dist/chat-provider.js.map +1 -1
  5. package/dist/chat-provider.mjs +4 -4
  6. package/dist/{chunk-LXD3IV6Z.mjs → chunk-2BGORTWS.mjs} +4 -4
  7. package/dist/{chunk-IDH2YOW3.mjs → chunk-557E5VZ2.mjs} +198 -11
  8. package/dist/chunk-557E5VZ2.mjs.map +1 -0
  9. package/dist/{chunk-QFSEZAG6.mjs → chunk-AVV7HDGR.mjs} +34 -3
  10. package/dist/chunk-AVV7HDGR.mjs.map +1 -0
  11. package/dist/{chunk-N7RMUOFB.mjs → chunk-EULV5CHD.mjs} +2 -2
  12. package/dist/{chunk-STMXPFAQ.mjs → chunk-GNE4TTSI.mjs} +48 -15
  13. package/dist/chunk-GNE4TTSI.mjs.map +1 -0
  14. package/dist/{chunk-BENL3EF2.mjs → chunk-H3BYFEIE.mjs} +18 -10
  15. package/dist/chunk-H3BYFEIE.mjs.map +1 -0
  16. package/dist/{chunk-HETIHZ42.mjs → chunk-NZKLKZJT.mjs} +3 -3
  17. package/dist/{chunk-JBXNXSAH.mjs → chunk-O54PTFJM.mjs} +460 -181
  18. package/dist/chunk-O54PTFJM.mjs.map +1 -0
  19. package/dist/{chunk-EWUUF4GE.mjs → chunk-UFSEYVRS.mjs} +3 -3
  20. package/dist/cli.js +1 -1
  21. package/dist/cli.js.map +1 -1
  22. package/dist/{gateway-oScD5tvE.d.ts → gateway-C5T5FfCy.d.mts} +32 -0
  23. package/dist/{gateway-oScD5tvE.d.mts → gateway-C5T5FfCy.d.ts} +32 -0
  24. package/dist/index.d.mts +2 -2
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.js +738 -202
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.mjs +9 -9
  29. package/dist/management/management.js +708 -202
  30. package/dist/management/management.js.map +1 -1
  31. package/dist/management/management.mjs +7 -7
  32. package/dist/modals/chat-modal/chat-modal.js +214 -17
  33. package/dist/modals/chat-modal/chat-modal.js.map +1 -1
  34. package/dist/modals/chat-modal/chat-modal.mjs +4 -4
  35. package/dist/public-types.d.mts +1 -1
  36. package/dist/public-types.d.ts +1 -1
  37. package/package.json +1 -1
  38. package/dist/chunk-BENL3EF2.mjs.map +0 -1
  39. package/dist/chunk-IDH2YOW3.mjs.map +0 -1
  40. package/dist/chunk-JBXNXSAH.mjs.map +0 -1
  41. package/dist/chunk-QFSEZAG6.mjs.map +0 -1
  42. package/dist/chunk-STMXPFAQ.mjs.map +0 -1
  43. /package/dist/{aiProviderStore-3N3VE6D4.mjs.map → aiProviderStore-337QNQB3.mjs.map} +0 -0
  44. /package/dist/{chat-W5IFNEUC.mjs.map → chat-U4SE4JQK.mjs.map} +0 -0
  45. /package/dist/{chunk-LXD3IV6Z.mjs.map → chunk-2BGORTWS.mjs.map} +0 -0
  46. /package/dist/{chunk-N7RMUOFB.mjs.map → chunk-EULV5CHD.mjs.map} +0 -0
  47. /package/dist/{chunk-HETIHZ42.mjs.map → chunk-NZKLKZJT.mjs.map} +0 -0
  48. /package/dist/{chunk-EWUUF4GE.mjs.map → chunk-UFSEYVRS.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;
@@ -2183,9 +2194,99 @@ function ensureDeviceId() {
2183
2194
  return (0, import_uuid3.v4)();
2184
2195
  }
2185
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
+ }
2186
2222
  function getPackageDefaultAdvancedKnowledgeSync() {
2187
2223
  return usePackageSettingsStore.getState().settings?.advancedKnowledgeSyncDefaultEnabled;
2188
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
+ }
2189
2290
  function mapConversationToDTO(conversation) {
2190
2291
  const updatedAtIso = (conversation.updatedAt ?? /* @__PURE__ */ new Date()).toISOString();
2191
2292
  const createdAtIso = conversation.createdAt ? conversation.createdAt.toISOString() : null;
@@ -2579,7 +2680,7 @@ function buildOversizedMessage(notices) {
2579
2680
  const names = notices.map((n) => `"${n.name || "Untitled"}"`).join(", ");
2580
2681
  return `Some conversations (${names}) are too large for Bandit Cloud. Start a new conversation or archive older turns to continue syncing.`;
2581
2682
  }
2582
- 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;
2583
2684
  var init_conversationSyncStore = __esm({
2584
2685
  "src/store/conversationSyncStore.ts"() {
2585
2686
  "use strict";
@@ -2589,13 +2690,19 @@ var init_conversationSyncStore = __esm({
2589
2690
  init_projectStore();
2590
2691
  init_packageSettingsStore();
2591
2692
  init_authenticationService();
2693
+ init_indexedDBService();
2592
2694
  init_conversationSyncEvents();
2593
2695
  init_conversationSyncService();
2594
2696
  init_debugLogger();
2595
2697
  DEVICE_STORAGE_KEY = "banditConversationDeviceId";
2698
+ SYNC_IDENTITY_STORAGE_KEY = "banditConversationSyncIdentity";
2596
2699
  PAYLOAD_VERSION = 1;
2597
2700
  MAX_CONVERSATION_BYTES = 12 * 1024 * 1024;
2598
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" }];
2599
2706
  suppressTracking = false;
2600
2707
  conversationsMeta = /* @__PURE__ */ new Map();
2601
2708
  projectsMeta = /* @__PURE__ */ new Map();
@@ -2631,6 +2738,9 @@ var init_conversationSyncStore = __esm({
2631
2738
  }
2632
2739
  useConversationSyncStore = (0, import_zustand9.create)((set, get) => ({
2633
2740
  initialized: false,
2741
+ hasLoadedPreference: false,
2742
+ initializedForToken: null,
2743
+ initializedForIdentity: null,
2634
2744
  syncEnabled: false,
2635
2745
  status: "disabled",
2636
2746
  lastSyncAt: null,
@@ -2650,20 +2760,63 @@ var init_conversationSyncStore = __esm({
2650
2760
  warningConversations: [],
2651
2761
  oversizedConversations: [],
2652
2762
  async initialize() {
2653
- if (get().initialized) {
2654
- return;
2655
- }
2656
2763
  ensureTrackersInitialized();
2657
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
+ }
2658
2792
  if (!gatewayUrl) {
2659
2793
  debugLogger.info("conversationSyncStore: gateway API URL not configured; sync disabled");
2660
- 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
+ });
2661
2806
  return;
2662
2807
  }
2663
- const token = authenticationService.getToken();
2664
2808
  if (!token) {
2665
2809
  debugLogger.info("conversationSyncStore: no authentication token; sync disabled until login");
2666
- 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
+ });
2667
2820
  return;
2668
2821
  }
2669
2822
  try {
@@ -2685,14 +2838,27 @@ var init_conversationSyncStore = __esm({
2685
2838
  isAdvancedVectorFeaturesEnabled: get().isAdvancedVectorFeaturesEnabled
2686
2839
  }
2687
2840
  });
2688
- set({ initialized: true });
2841
+ set({
2842
+ initialized: true,
2843
+ hasLoadedPreference: true,
2844
+ initializedForToken: token,
2845
+ initializedForIdentity: tokenIdentity
2846
+ });
2847
+ setStoredSyncIdentity(tokenIdentity);
2689
2848
  if (preference.syncEnabled) {
2690
2849
  await get().runSync({ force: true });
2691
2850
  }
2692
2851
  } catch (error) {
2693
2852
  const message = error instanceof Error ? error.message : "Failed to load conversation sync preference";
2694
2853
  debugLogger.error("conversationSyncStore: initialization failed", { error: message });
2695
- 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
+ });
2696
2862
  }
2697
2863
  },
2698
2864
  async setSyncEnabled(enabled) {
@@ -2720,6 +2886,12 @@ var init_conversationSyncStore = __esm({
2720
2886
  isAdvancedVectorFeaturesEnabled
2721
2887
  }
2722
2888
  });
2889
+ set({
2890
+ hasLoadedPreference: true,
2891
+ initializedForToken: authenticationService.getToken(),
2892
+ initializedForIdentity: resolveAuthIdentity(authenticationService.getToken())
2893
+ });
2894
+ setStoredSyncIdentity(resolveAuthIdentity(authenticationService.getToken()));
2723
2895
  if (enabled) {
2724
2896
  set({ hasCompletedInitialUpload: false });
2725
2897
  }
@@ -2757,6 +2929,12 @@ var init_conversationSyncStore = __esm({
2757
2929
  isAdvancedVectorFeaturesEnabled: enabled
2758
2930
  }
2759
2931
  });
2932
+ set({
2933
+ hasLoadedPreference: true,
2934
+ initializedForToken: authenticationService.getToken(),
2935
+ initializedForIdentity: resolveAuthIdentity(authenticationService.getToken())
2936
+ });
2937
+ setStoredSyncIdentity(resolveAuthIdentity(authenticationService.getToken()));
2760
2938
  if (preference.syncEnabled && preference.isAdvancedVectorFeaturesEnabled) {
2761
2939
  await get().runSync({ force: true });
2762
2940
  }
@@ -2802,6 +2980,15 @@ var init_conversationSyncStore = __esm({
2802
2980
  debugLogger.error("conversationSyncStore: runSync error - missing auth token");
2803
2981
  return;
2804
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
+ }
2805
2992
  const pendingConversationIds = Array.from(state.pendingConversationUpserts);
2806
2993
  const pendingConversationDeleteIds = Array.from(state.pendingConversationDeletes);
2807
2994
  const pendingProjectIds = Array.from(state.pendingProjectUpserts);
@@ -4568,7 +4755,8 @@ var init_gateway_service = __esm({
4568
4755
  index: 0,
4569
4756
  delta: {
4570
4757
  role: parsed.message.role,
4571
- content: parsed.message.content
4758
+ content: parsed.message.content,
4759
+ tool_calls: parsed.message.tool_calls
4572
4760
  },
4573
4761
  finish_reason: parsed.done ? parsed.done_reason || "stop" : null
4574
4762
  }]
@@ -5548,6 +5736,7 @@ var init_gateway_provider = __esm({
5548
5736
  }
5549
5737
  }
5550
5738
  }
5739
+ const toolAwareRequest = request;
5551
5740
  const gatewayRequest = {
5552
5741
  model: request.model,
5553
5742
  messages,
@@ -5556,7 +5745,8 @@ var init_gateway_provider = __esm({
5556
5745
  max_tokens: request.maxTokens,
5557
5746
  provider: this.config.provider,
5558
5747
  // Only include top-level images for Ollama (fallback)
5559
- images: this.config.provider === "ollama" ? request.images : void 0
5748
+ images: this.config.provider === "ollama" ? request.images : void 0,
5749
+ tools: toolAwareRequest.tools?.length ? toolAwareRequest.tools : void 0
5560
5750
  };
5561
5751
  debugLogger.debug("Gateway provider chat request", {
5562
5752
  model: request.model,
@@ -5573,13 +5763,18 @@ var init_gateway_provider = __esm({
5573
5763
  }))
5574
5764
  });
5575
5765
  return this.gatewayService.chat(gatewayRequest).pipe(
5576
- (0, import_rxjs7.map)((response) => ({
5577
- message: {
5578
- content: response.choices?.[0]?.message?.content || response.choices?.[0]?.delta?.content || "",
5579
- role: "assistant"
5580
- },
5581
- done: response.choices?.[0]?.finish_reason === "stop" || response.choices?.[0]?.finish_reason === "length"
5582
- }))
5766
+ (0, import_rxjs7.map)((response) => {
5767
+ const choice = response.choices?.[0];
5768
+ const toolCalls = choice?.message?.tool_calls ?? choice?.delta?.tool_calls;
5769
+ return {
5770
+ message: {
5771
+ content: choice?.message?.content ?? choice?.delta?.content ?? "",
5772
+ role: "assistant",
5773
+ tool_calls: toolCalls
5774
+ },
5775
+ done: choice?.finish_reason === "stop" || choice?.finish_reason === "length" || choice?.finish_reason === "tool_calls"
5776
+ };
5777
+ })
5583
5778
  );
5584
5779
  }
5585
5780
  generate(request) {
@@ -14897,6 +15092,7 @@ var init_chat_messages = __esm({
14897
15092
  scrollTargetRef,
14898
15093
  responseStarted,
14899
15094
  isStreaming,
15095
+ isThinking = false,
14900
15096
  isNetworkSlow = false,
14901
15097
  showInstantFeedback = true,
14902
15098
  selectedModel,
@@ -14913,6 +15109,7 @@ var init_chat_messages = __esm({
14913
15109
  const isLast = index === lastIndex;
14914
15110
  const isPlaceholder = entry.answer === "...";
14915
15111
  const showLoader = isLast && isStreaming && streamBuffer.trim() === "";
15112
+ const showThinking = showLoader && isThinking;
14916
15113
  const content = isLast ? isStreaming ? streamBuffer || "" : isPlaceholder ? "" : entry.answer : entry.answer;
14917
15114
  const rawSources = entry.sourceFiles;
14918
15115
  const sourceSummaries = rawSources ? rawSources.filter((doc) => doc && typeof doc.name === "string" && doc.name.trim()).map((doc) => ({ id: doc.id || doc.name, name: doc.name.trim() })) : void 0;
@@ -14940,11 +15137,27 @@ var init_chat_messages = __esm({
14940
15137
  pointerEvents: showLoader ? "auto" : "none",
14941
15138
  zIndex: showLoader ? 1 : 0
14942
15139
  },
14943
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material9.Box, { sx: { display: "flex", alignItems: "center", minHeight: "40px", pl: 2 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "typing-only", children: [
14944
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dot" }),
14945
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dot" }),
14946
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dot" })
14947
- ] }) })
15140
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.Box, { sx: { display: "flex", alignItems: "center", gap: 1, minHeight: "40px", pl: 2 }, children: [
15141
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "typing-only", children: [
15142
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dot" }),
15143
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dot" }),
15144
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "dot" })
15145
+ ] }),
15146
+ showThinking && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
15147
+ import_material9.Box,
15148
+ {
15149
+ component: "span",
15150
+ sx: {
15151
+ fontSize: "0.75rem",
15152
+ color: "text.secondary",
15153
+ opacity: 0.6,
15154
+ fontStyle: "italic",
15155
+ userSelect: "none"
15156
+ },
15157
+ children: "Thinking\u2026"
15158
+ }
15159
+ )
15160
+ ] })
14948
15161
  }
14949
15162
  ),
14950
15163
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
@@ -19825,6 +20038,7 @@ var init_useAIProvider = __esm({
19825
20038
  setIsSubmitting,
19826
20039
  setResponseStarted,
19827
20040
  setIsStreaming,
20041
+ setIsThinking,
19828
20042
  setResponse,
19829
20043
  setPastedImages,
19830
20044
  setPendingMessage,
@@ -20282,6 +20496,12 @@ ${protocol}`;
20282
20496
  let fullMessage = "";
20283
20497
  let latestDisplayMessage = "";
20284
20498
  let sawToolBlock = false;
20499
+ const stripThinking = (text) => {
20500
+ let result = text.replace(/<think>[\s\S]*?<\/think>/g, "");
20501
+ const openIdx = result.indexOf("<think>");
20502
+ if (openIdx !== -1) result = result.slice(0, openIdx);
20503
+ return result.trimStart();
20504
+ };
20285
20505
  const flushNow = () => {
20286
20506
  clearFlushTimer();
20287
20507
  if (!sawToolBlock) {
@@ -20309,13 +20529,16 @@ ${protocol}`;
20309
20529
  }
20310
20530
  const sub = stream.subscribe({
20311
20531
  next: (data) => {
20312
- if (!data?.message?.content) return;
20313
- fullMessage += data.message.content;
20314
- if (/```(?:tool_code|TOOL_CODE)/.test(fullMessage)) {
20532
+ if (!data?.message?.content && !data?.message?.tool_calls) return;
20533
+ if (data.message.content) fullMessage += data.message.content;
20534
+ const inThinkBlock = /<think>/.test(fullMessage) && !/<think>[\s\S]*<\/think>/.test(fullMessage);
20535
+ setIsThinking?.(inThinkBlock);
20536
+ const visibleMessage = stripThinking(fullMessage);
20537
+ if (/```(?:tool_code|TOOL_CODE)/.test(visibleMessage)) {
20315
20538
  sawToolBlock = true;
20316
20539
  clearFlushTimer();
20317
20540
  }
20318
- latestDisplayMessage = fullMessage;
20541
+ latestDisplayMessage = visibleMessage;
20319
20542
  if (!sawToolBlock) {
20320
20543
  scheduleFlush();
20321
20544
  }
@@ -20336,6 +20559,7 @@ ${protocol}`;
20336
20559
  setResponse(partial);
20337
20560
  }
20338
20561
  setStreamBuffer("");
20562
+ setIsThinking?.(false);
20339
20563
  setPendingMessage(null);
20340
20564
  setLogoVisible(false);
20341
20565
  if (onError) {
@@ -20344,7 +20568,8 @@ ${protocol}`;
20344
20568
  },
20345
20569
  complete: async () => {
20346
20570
  try {
20347
- latestDisplayMessage = fullMessage;
20571
+ setIsThinking?.(false);
20572
+ latestDisplayMessage = stripThinking(fullMessage);
20348
20573
  if (!sawToolBlock) {
20349
20574
  flushNow();
20350
20575
  }
@@ -28335,6 +28560,7 @@ var init_chat2 = __esm({
28335
28560
  const [streamBuffer, setStreamBuffer] = (0, import_react35.useState)("");
28336
28561
  const [responseStarted, setResponseStarted] = (0, import_react35.useState)(false);
28337
28562
  const [isStreaming, setIsStreaming] = (0, import_react35.useState)(false);
28563
+ const [isThinking, setIsThinking] = (0, import_react35.useState)(false);
28338
28564
  const initialLogoState = history.length === 0;
28339
28565
  const [logoVisible, setLogoVisible] = (0, import_react35.useState)(initialLogoState);
28340
28566
  const [logoShouldRender, setLogoShouldRender] = (0, import_react35.useState)(initialLogoState);
@@ -28818,6 +29044,7 @@ var init_chat2 = __esm({
28818
29044
  overrideComponentStatus: setComponentStatus,
28819
29045
  setIsSubmitting,
28820
29046
  setIsStreaming,
29047
+ setIsThinking,
28821
29048
  setResponseStarted,
28822
29049
  setResponse,
28823
29050
  setStreamBuffer,
@@ -29224,6 +29451,7 @@ var init_chat2 = __esm({
29224
29451
  chat_messages_default,
29225
29452
  {
29226
29453
  isStreaming,
29454
+ isThinking,
29227
29455
  history,
29228
29456
  pendingMessage,
29229
29457
  streamBuffer,
@@ -29845,6 +30073,36 @@ var ChatProvider = (props) => {
29845
30073
  };
29846
30074
  initializeAsync();
29847
30075
  }, [props.packageSettings, loadDocuments]);
30076
+ (0, import_react6.useEffect)(() => {
30077
+ const isPlaygroundRoute = typeof window !== "undefined" && window.location.pathname.includes("/playground");
30078
+ const isPlaygroundMode3 = isPlaygroundRoute || props.packageSettings.playgroundMode === true;
30079
+ if (isPlaygroundMode3 || !props.packageSettings.gatewayApiUrl) {
30080
+ return;
30081
+ }
30082
+ const initializeSyncState = async () => {
30083
+ try {
30084
+ await useConversationSyncStore.getState().initialize();
30085
+ } catch (error) {
30086
+ debugLogger.error("ChatProvider: deferred sync initialization failed", {
30087
+ error: error instanceof Error ? error.message : String(error)
30088
+ });
30089
+ }
30090
+ };
30091
+ if (typeof window === "undefined") {
30092
+ return;
30093
+ }
30094
+ const handleAuthTokenChange = () => {
30095
+ void initializeSyncState();
30096
+ };
30097
+ window.addEventListener(AUTH_TOKEN_CHANGED_EVENT, handleAuthTokenChange);
30098
+ window.addEventListener("pageshow", handleAuthTokenChange);
30099
+ window.addEventListener("focus", handleAuthTokenChange);
30100
+ return () => {
30101
+ window.removeEventListener(AUTH_TOKEN_CHANGED_EVENT, handleAuthTokenChange);
30102
+ window.removeEventListener("pageshow", handleAuthTokenChange);
30103
+ window.removeEventListener("focus", handleAuthTokenChange);
30104
+ };
30105
+ }, [props.packageSettings.gatewayApiUrl, props.packageSettings.playgroundMode]);
29848
30106
  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 }) }) });
29849
30107
  };
29850
30108
  var chat_provider_default = ChatProvider;
@@ -33032,6 +33290,7 @@ var PersonalitiesTab = ({
33032
33290
  const [deleteDialogOpen, setDeleteDialogOpen] = (0, import_react44.useState)(false);
33033
33291
  const [personalityToDelete, setPersonalityToDelete] = (0, import_react44.useState)(null);
33034
33292
  const [clickedChips, setClickedChips] = (0, import_react44.useState)(/* @__PURE__ */ new Set());
33293
+ const [showTemplateHelp, setShowTemplateHelp] = (0, import_react44.useState)(false);
33035
33294
  const [cropperOpen, setCropperOpen] = (0, import_react44.useState)(false);
33036
33295
  const [selectedImageFile, setSelectedImageFile] = (0, import_react44.useState)(null);
33037
33296
  const promptTemplates = [
@@ -33285,28 +33544,15 @@ var PersonalitiesTab = ({
33285
33544
  }
33286
33545
  }
33287
33546
  ),
33288
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: {
33289
- height: "100%",
33290
- overflow: "auto",
33291
- p: { xs: 1.5, sm: 2 },
33292
- // Hide scrollbars while keeping scroll functionality
33293
- scrollbarWidth: "none",
33294
- // Firefox
33295
- "&::-webkit-scrollbar": {
33296
- display: "none"
33297
- // Chrome, Safari, Edge
33298
- },
33299
- "-ms-overflow-style": "none"
33300
- // IE and Edge
33301
- }, children: [
33547
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { p: { xs: 1, sm: 2 } }, children: [
33302
33548
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: {
33303
33549
  display: "flex",
33304
33550
  flexDirection: { xs: "column", md: "row" },
33305
33551
  alignItems: { xs: "flex-start", md: "center" },
33306
33552
  justifyContent: "space-between",
33307
- mb: { xs: 2, md: 3 },
33553
+ mb: { xs: 1.25, md: 3 },
33308
33554
  flexWrap: "wrap",
33309
- gap: { xs: 1.5, md: 2 }
33555
+ gap: { xs: 1, md: 2 }
33310
33556
  }, children: [
33311
33557
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: {
33312
33558
  display: "flex",
@@ -33336,8 +33582,8 @@ var PersonalitiesTab = ({
33336
33582
  backgroundClip: "text",
33337
33583
  WebkitBackgroundClip: "text",
33338
33584
  WebkitTextFillColor: "transparent",
33339
- mb: 0.5,
33340
- fontSize: { xs: "1.55rem", sm: "1.75rem" }
33585
+ mb: { xs: 0.25, sm: 0.5 },
33586
+ fontSize: { xs: "1.35rem", sm: "1.75rem" }
33341
33587
  },
33342
33588
  children: "Quick Start Templates"
33343
33589
  }
@@ -33362,12 +33608,40 @@ var PersonalitiesTab = ({
33362
33608
  color: "white",
33363
33609
  fontWeight: 600,
33364
33610
  animation: "pulse 2s infinite",
33365
- alignSelf: { xs: "flex-start", md: "center" }
33611
+ alignSelf: { xs: "flex-start", md: "center" },
33612
+ display: { xs: "none", md: "inline-flex" }
33366
33613
  }
33367
33614
  }
33368
33615
  )
33369
33616
  ] }),
33370
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33617
+ isMobile ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
33618
+ import_material36.Box,
33619
+ {
33620
+ sx: {
33621
+ mb: 1.75,
33622
+ borderRadius: 2,
33623
+ border: "1px solid rgba(25, 118, 210, 0.2)",
33624
+ background: "linear-gradient(135deg, rgba(25, 118, 210, 0.05) 0%, rgba(66, 165, 245, 0.05) 100%)",
33625
+ px: 1.25,
33626
+ py: 1
33627
+ },
33628
+ children: [
33629
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 1 }, children: [
33630
+ /* @__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" }),
33631
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33632
+ import_material36.Button,
33633
+ {
33634
+ size: "small",
33635
+ onClick: () => setShowTemplateHelp((prev) => !prev),
33636
+ sx: { minWidth: "auto", px: 1, fontSize: "0.72rem", whiteSpace: "nowrap" },
33637
+ children: showTemplateHelp ? "Hide" : "Details"
33638
+ }
33639
+ )
33640
+ ] }),
33641
+ /* @__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." }) })
33642
+ ]
33643
+ }
33644
+ ) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33371
33645
  import_material36.Alert,
33372
33646
  {
33373
33647
  severity: "info",
@@ -33393,17 +33667,19 @@ var PersonalitiesTab = ({
33393
33667
  import_material36.Card,
33394
33668
  {
33395
33669
  sx: {
33396
- mb: { xs: 3, md: 4 },
33670
+ mb: { xs: 2, md: 4 },
33397
33671
  background: "linear-gradient(135deg, #1976d2 0%, #42a5f5 100%)",
33398
33672
  border: "2px solid transparent",
33399
- borderRadius: 3,
33673
+ borderRadius: { xs: 2.25, sm: 3 },
33400
33674
  cursor: "pointer",
33401
33675
  transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
33402
33676
  position: "relative",
33403
33677
  overflow: "hidden",
33404
- "&:hover": {
33405
- transform: "translateY(-4px) scale(1.02)",
33406
- boxShadow: "0 12px 40px rgba(25, 118, 210, 0.3)"
33678
+ ...isMobile ? {} : {
33679
+ "&:hover": {
33680
+ transform: "translateY(-4px) scale(1.02)",
33681
+ boxShadow: "0 12px 40px rgba(25, 118, 210, 0.3)"
33682
+ }
33407
33683
  },
33408
33684
  "&::before": {
33409
33685
  content: '""',
@@ -33428,41 +33704,70 @@ var PersonalitiesTab = ({
33428
33704
  setPersonalityTabIndex(1);
33429
33705
  },
33430
33706
  children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.CardContent, { sx: {
33431
- p: { xs: 3, sm: 4 },
33707
+ p: { xs: 1.75, sm: 4 },
33432
33708
  color: "white",
33433
- textAlign: "center",
33709
+ textAlign: { xs: "left", sm: "center" },
33434
33710
  position: "relative",
33435
- zIndex: 1
33711
+ zIndex: 1,
33712
+ display: "flex",
33713
+ flexDirection: { xs: "row", sm: "column" },
33714
+ alignItems: { xs: "center", sm: "center" },
33715
+ gap: { xs: 1.25, sm: 0 }
33436
33716
  }, children: [
33437
33717
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_material36.Box, { sx: {
33438
33718
  display: "flex",
33439
33719
  alignItems: "center",
33440
33720
  justifyContent: "center",
33441
33721
  fontSize: 0,
33442
- mb: { xs: 1.5, sm: 2 }
33443
- }, 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))" } }) }),
33444
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33445
- import_material36.Typography,
33446
- {
33447
- variant: "h5",
33448
- sx: {
33449
- fontWeight: 700,
33450
- mb: { xs: 0.75, sm: 1 },
33451
- textShadow: "0 2px 4px rgba(0,0,0,0.2)"
33452
- },
33453
- children: "Create from Scratch"
33454
- }
33455
- ),
33456
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33457
- import_material36.Typography,
33722
+ mb: { xs: 0, sm: 2 },
33723
+ flexShrink: 0
33724
+ }, 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))" } }) }),
33725
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { flex: 1, minWidth: 0 }, children: [
33726
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33727
+ import_material36.Typography,
33728
+ {
33729
+ variant: "h5",
33730
+ sx: {
33731
+ fontWeight: 700,
33732
+ mb: { xs: 0.25, sm: 1 },
33733
+ textShadow: "0 2px 4px rgba(0,0,0,0.2)",
33734
+ fontSize: { xs: "1.1rem", sm: "1.75rem" }
33735
+ },
33736
+ children: "Create from Scratch"
33737
+ }
33738
+ ),
33739
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33740
+ import_material36.Typography,
33741
+ {
33742
+ variant: "body1",
33743
+ sx: {
33744
+ opacity: 0.9,
33745
+ fontWeight: 500,
33746
+ textShadow: "0 1px 2px rgba(0,0,0,0.2)",
33747
+ fontSize: { xs: "0.8rem", sm: "1rem" },
33748
+ lineHeight: { xs: 1.3, sm: 1.5 },
33749
+ display: "-webkit-box",
33750
+ WebkitLineClamp: { xs: 2, sm: "unset" },
33751
+ WebkitBoxOrient: "vertical",
33752
+ overflow: "hidden"
33753
+ },
33754
+ children: "Start with a blank canvas and build your perfect AI personality"
33755
+ }
33756
+ )
33757
+ ] }),
33758
+ isMobile && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33759
+ import_material36.Chip,
33458
33760
  {
33459
- variant: "body1",
33761
+ label: "Start",
33762
+ size: "small",
33460
33763
  sx: {
33461
- opacity: 0.9,
33462
- fontWeight: 500,
33463
- textShadow: "0 1px 2px rgba(0,0,0,0.2)"
33464
- },
33465
- children: "Start with a blank canvas and build your perfect AI personality"
33764
+ backgroundColor: "rgba(255,255,255,0.2)",
33765
+ color: "common.white",
33766
+ border: "1px solid rgba(255,255,255,0.45)",
33767
+ fontWeight: 600,
33768
+ height: 28,
33769
+ flexShrink: 0
33770
+ }
33466
33771
  }
33467
33772
  )
33468
33773
  ] })
@@ -33477,7 +33782,7 @@ var PersonalitiesTab = ({
33477
33782
  lg: "repeat(4, 1fr)",
33478
33783
  xl: "repeat(4, 1fr)"
33479
33784
  },
33480
- gap: { xs: 2, sm: 2.5, md: 3 },
33785
+ gap: { xs: 1.25, sm: 2.5, md: 3 },
33481
33786
  alignItems: "stretch"
33482
33787
  }, children: promptTemplates.map((template, index) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33483
33788
  import_material36.Card,
@@ -33490,7 +33795,7 @@ var PersonalitiesTab = ({
33490
33795
  border: "1px solid",
33491
33796
  borderColor: "rgba(255,255,255,0.1)",
33492
33797
  borderRadius: 3,
33493
- minHeight: { xs: "auto", md: "280px" },
33798
+ minHeight: { xs: "200px", md: "280px" },
33494
33799
  display: "flex",
33495
33800
  flexDirection: "column",
33496
33801
  overflow: "hidden",
@@ -33508,19 +33813,21 @@ var PersonalitiesTab = ({
33508
33813
  opacity: 0,
33509
33814
  transition: "opacity 0.3s ease"
33510
33815
  },
33511
- "&:hover": {
33512
- transform: "translateY(-8px) scale(1.02)",
33513
- boxShadow: "0 20px 40px rgba(0,0,0,0.15)",
33514
- borderColor: "primary.main",
33515
- "&::before": {
33516
- opacity: 1
33517
- },
33518
- "& .template-icon": {
33519
- transform: "scale(1.1) rotate(5deg)"
33520
- },
33521
- "& .template-chip": {
33522
- transform: "translateY(-2px)",
33523
- boxShadow: "0 4px 12px rgba(0,0,0,0.2)"
33816
+ ...isMobile ? {} : {
33817
+ "&:hover": {
33818
+ transform: "translateY(-8px) scale(1.02)",
33819
+ boxShadow: "0 20px 40px rgba(0,0,0,0.15)",
33820
+ borderColor: "primary.main",
33821
+ "&::before": {
33822
+ opacity: 1
33823
+ },
33824
+ "& .template-icon": {
33825
+ transform: "scale(1.1) rotate(5deg)"
33826
+ },
33827
+ "& .template-chip": {
33828
+ transform: "translateY(-2px)",
33829
+ boxShadow: "0 4px 12px rgba(0,0,0,0.2)"
33830
+ }
33524
33831
  }
33525
33832
  },
33526
33833
  "&:active": {
@@ -33529,7 +33836,7 @@ var PersonalitiesTab = ({
33529
33836
  },
33530
33837
  onClick: () => handleTemplateSelect(template),
33531
33838
  children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.CardContent, { sx: {
33532
- p: { xs: 2.5, sm: 3 },
33839
+ p: { xs: 2, sm: 3 },
33533
33840
  display: "flex",
33534
33841
  flexDirection: "column",
33535
33842
  height: "100%",
@@ -33539,7 +33846,7 @@ var PersonalitiesTab = ({
33539
33846
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: {
33540
33847
  display: "flex",
33541
33848
  alignItems: "center",
33542
- mb: { xs: 2, md: 2.5 },
33849
+ mb: { xs: 1.25, md: 2.5 },
33543
33850
  minHeight: { xs: "auto", md: "60px" }
33544
33851
  }, children: [
33545
33852
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
@@ -33548,9 +33855,9 @@ var PersonalitiesTab = ({
33548
33855
  src: template.avatar,
33549
33856
  alt: template.name,
33550
33857
  sx: {
33551
- width: { xs: 48, sm: 56, md: 60 },
33552
- height: { xs: 48, sm: 56, md: 60 },
33553
- mr: { xs: 1.5, md: 2 },
33858
+ width: { xs: 40, sm: 56, md: 60 },
33859
+ height: { xs: 40, sm: 56, md: 60 },
33860
+ mr: { xs: 1.2, md: 2 },
33554
33861
  transition: "transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
33555
33862
  boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
33556
33863
  border: "2px solid rgba(255,255,255,0.8)"
@@ -33604,10 +33911,10 @@ var PersonalitiesTab = ({
33604
33911
  lineHeight: 1.5,
33605
33912
  fontSize: { xs: "0.82rem", sm: "0.85rem", md: "0.875rem" },
33606
33913
  display: "-webkit-box",
33607
- WebkitLineClamp: 4,
33914
+ WebkitLineClamp: { xs: 2, sm: 4 },
33608
33915
  WebkitBoxOrient: "vertical",
33609
33916
  overflow: "hidden",
33610
- mb: { xs: 1.5, md: 2 },
33917
+ mb: { xs: 1.25, md: 2 },
33611
33918
  minHeight: { xs: "auto", md: "84px" }
33612
33919
  },
33613
33920
  children: template.description
@@ -33644,7 +33951,7 @@ var PersonalitiesTab = ({
33644
33951
  },
33645
33952
  index
33646
33953
  )) }),
33647
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
33954
+ !isMobile && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
33648
33955
  import_material36.Alert,
33649
33956
  {
33650
33957
  severity: "info",
@@ -33658,20 +33965,7 @@ var PersonalitiesTab = ({
33658
33965
  )
33659
33966
  ] })
33660
33967
  ] });
33661
- const renderCreateEditTab = () => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: {
33662
- height: "100%",
33663
- overflow: "auto",
33664
- p: { xs: 1.5, sm: 2 },
33665
- // Hide scrollbars while keeping scroll functionality
33666
- scrollbarWidth: "none",
33667
- // Firefox
33668
- "&::-webkit-scrollbar": {
33669
- display: "none"
33670
- // Chrome, Safari, Edge
33671
- },
33672
- "-ms-overflow-style": "none"
33673
- // IE and Edge
33674
- }, children: [
33968
+ const renderCreateEditTab = () => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { p: { xs: 1.5, sm: 2 } }, children: [
33675
33969
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { mb: { xs: 2.5, md: 4 } }, children: [
33676
33970
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
33677
33971
  import_material36.Typography,
@@ -34141,6 +34435,9 @@ var PersonalitiesTab = ({
34141
34435
  import_material36.Box,
34142
34436
  {
34143
34437
  sx: {
34438
+ position: { xs: "sticky", sm: "static" },
34439
+ bottom: { xs: 10, sm: "auto" },
34440
+ zIndex: { xs: 5, sm: "auto" },
34144
34441
  display: "flex",
34145
34442
  flexDirection: { xs: "column", sm: "row" },
34146
34443
  gap: { xs: 1.5, sm: 2 },
@@ -34148,8 +34445,15 @@ var PersonalitiesTab = ({
34148
34445
  // Changed from flex-end to flex-start
34149
34446
  mr: { xs: 0, sm: 10 },
34150
34447
  // Add right margin to avoid FAB
34151
- mb: { xs: 8, sm: 2 }
34448
+ mb: { xs: 8, sm: 2 },
34152
34449
  // Add bottom margin on mobile for FAB clearance
34450
+ mt: { xs: 1.5, sm: 0 },
34451
+ p: { xs: 1.1, sm: 0 },
34452
+ borderRadius: { xs: 2, sm: 0 },
34453
+ border: { xs: "1px solid", sm: "none" },
34454
+ borderColor: { xs: "divider", sm: "transparent" },
34455
+ bgcolor: { xs: "background.paper", sm: "transparent" },
34456
+ boxShadow: { xs: 3, sm: "none" }
34153
34457
  },
34154
34458
  children: [
34155
34459
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
@@ -34177,20 +34481,7 @@ var PersonalitiesTab = ({
34177
34481
  }
34178
34482
  )
34179
34483
  ] });
34180
- const renderManageTab = () => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: {
34181
- height: "100%",
34182
- overflow: "auto",
34183
- p: { xs: 1.5, sm: 2 },
34184
- // Hide scrollbars while keeping scroll functionality
34185
- scrollbarWidth: "none",
34186
- // Firefox
34187
- "&::-webkit-scrollbar": {
34188
- display: "none"
34189
- // Chrome, Safari, Edge
34190
- },
34191
- "-ms-overflow-style": "none"
34192
- // IE and Edge
34193
- }, children: [
34484
+ const renderManageTab = () => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { p: { xs: 1.5, sm: 2 } }, children: [
34194
34485
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
34195
34486
  import_material36.Box,
34196
34487
  {
@@ -34439,7 +34730,7 @@ var PersonalitiesTab = ({
34439
34730
  ] })
34440
34731
  ] })
34441
34732
  ] });
34442
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { height: "100%", display: "flex", flexDirection: "column" }, children: [
34733
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { display: "flex", flexDirection: "column" }, children: [
34443
34734
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
34444
34735
  import_material36.Box,
34445
34736
  {
@@ -34565,7 +34856,7 @@ var PersonalitiesTab = ({
34565
34856
  ]
34566
34857
  }
34567
34858
  ) }),
34568
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { flex: 1, overflow: "hidden" }, children: [
34859
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_material36.Box, { sx: { minHeight: 0 }, children: [
34569
34860
  personalityTabIndex === 0 && renderTemplatesTab(),
34570
34861
  personalityTabIndex === 1 && renderCreateEditTab(),
34571
34862
  personalityTabIndex === 2 && renderManageTab()
@@ -38394,6 +38685,7 @@ var import_Add2 = __toESM(require("@mui/icons-material/Add"));
38394
38685
  var import_Archive = __toESM(require("@mui/icons-material/Archive"));
38395
38686
  var import_Delete6 = __toESM(require("@mui/icons-material/Delete"));
38396
38687
  var import_Description4 = __toESM(require("@mui/icons-material/Description"));
38688
+ var import_FolderOpen = __toESM(require("@mui/icons-material/FolderOpen"));
38397
38689
  var import_Group2 = __toESM(require("@mui/icons-material/Group"));
38398
38690
  var import_Person3 = __toESM(require("@mui/icons-material/Person"));
38399
38691
  var import_Publish = __toESM(require("@mui/icons-material/Publish"));
@@ -38673,6 +38965,22 @@ var archiveSeedPack = async (sid) => {
38673
38965
  throw error;
38674
38966
  }
38675
38967
  };
38968
+ var deleteSeedPack = async (sid) => {
38969
+ const url = buildUrl2(`/seed-packs/${encodeURIComponent(sid)}`);
38970
+ try {
38971
+ const response = await fetch(url, { method: "DELETE", headers: buildHeaders2() });
38972
+ if (response.status === 204) {
38973
+ return;
38974
+ }
38975
+ await handleJsonResponse2(response, "Failed to delete seed pack");
38976
+ } catch (error) {
38977
+ debugLogger.error("seedPackService: failed to delete seed pack", {
38978
+ sid,
38979
+ error: error instanceof Error ? error.message : String(error)
38980
+ });
38981
+ throw error;
38982
+ }
38983
+ };
38676
38984
 
38677
38985
  // src/management/components/SeedPacksTab.tsx
38678
38986
  var import_jsx_runtime42 = require("react/jsx-runtime");
@@ -38708,10 +39016,23 @@ var getPreviewSnippet = (content) => {
38708
39016
  }
38709
39017
  return trimmed.length > 120 ? `${trimmed.slice(0, 120)}...` : trimmed;
38710
39018
  };
39019
+ var getImportedFileKey = (file) => (file.relativePath ?? file.name).toLowerCase();
39020
+ var isMarkdownFileName = (name) => {
39021
+ const lower = name.toLowerCase();
39022
+ return lower.endsWith(".md") || lower.endsWith(".markdown");
39023
+ };
39024
+ var getWebkitRelativePath = (file) => {
39025
+ const relativePath = file.webkitRelativePath;
39026
+ if (!relativePath) {
39027
+ return void 0;
39028
+ }
39029
+ const trimmed = relativePath.trim().replace(/^\/+/, "");
39030
+ return trimmed.length > 0 ? trimmed : void 0;
39031
+ };
38711
39032
  var mergeMarkdownFiles = (existing, incoming) => {
38712
39033
  const next = [...existing];
38713
39034
  incoming.forEach((file) => {
38714
- const index = next.findIndex((item) => item.name === file.name);
39035
+ const index = next.findIndex((item) => getImportedFileKey(item) === getImportedFileKey(file));
38715
39036
  if (index >= 0) {
38716
39037
  next[index] = file;
38717
39038
  } else {
@@ -38723,17 +39044,22 @@ var mergeMarkdownFiles = (existing, incoming) => {
38723
39044
  var buildMarkdownContent = (files) => {
38724
39045
  return files.map((file) => file.content.trim()).filter((content) => content.length > 0).join("\n\n---\n\n");
38725
39046
  };
38726
- var readMarkdownFiles = async (files) => {
39047
+ var readMarkdownFiles = async (files, source = "local") => {
38727
39048
  const list = Array.from(files);
38728
- const markdownFiles = list.filter((file) => file.name.toLowerCase().endsWith(".md"));
39049
+ const markdownFiles = list.filter((file) => isMarkdownFileName(file.name));
38729
39050
  const imported = await Promise.all(
38730
- markdownFiles.map(async (file) => ({
38731
- id: `${file.name}-${file.lastModified}`,
38732
- name: file.name,
38733
- size: file.size,
38734
- content: await file.text(),
38735
- lastModified: file.lastModified
38736
- }))
39051
+ markdownFiles.map(async (file) => {
39052
+ const relativePath = getWebkitRelativePath(file);
39053
+ return {
39054
+ id: `${source}-${relativePath ?? file.name}-${file.lastModified}-${file.size}`,
39055
+ name: file.name,
39056
+ size: file.size,
39057
+ content: await file.text(),
39058
+ lastModified: file.lastModified,
39059
+ relativePath,
39060
+ source
39061
+ };
39062
+ })
38737
39063
  );
38738
39064
  return { imported, skipped: list.length - markdownFiles.length };
38739
39065
  };
@@ -38849,7 +39175,7 @@ var SeedPackFileCard = ({ file, onPreview, onRemove, isReadOnly }) => /* @__PURE
38849
39175
  )
38850
39176
  }
38851
39177
  ),
38852
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Tooltip, { title: file.name, arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39178
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Tooltip, { title: file.relativePath ?? file.name, arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
38853
39179
  import_material42.Typography,
38854
39180
  {
38855
39181
  variant: "body2",
@@ -38866,6 +39192,21 @@ var SeedPackFileCard = ({ file, onPreview, onRemove, isReadOnly }) => /* @__PURE
38866
39192
  children: file.name
38867
39193
  }
38868
39194
  ) }),
39195
+ 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)(
39196
+ import_material42.Typography,
39197
+ {
39198
+ variant: "caption",
39199
+ color: "text.secondary",
39200
+ sx: {
39201
+ display: "block",
39202
+ whiteSpace: "nowrap",
39203
+ overflow: "hidden",
39204
+ textOverflow: "ellipsis",
39205
+ mb: 1
39206
+ },
39207
+ children: file.relativePath
39208
+ }
39209
+ ) }),
38869
39210
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
38870
39211
  import_material42.Box,
38871
39212
  {
@@ -38882,7 +39223,7 @@ var SeedPackFileCard = ({ file, onPreview, onRemove, isReadOnly }) => /* @__PURE
38882
39223
  import_material42.Chip,
38883
39224
  {
38884
39225
  icon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_Person3.default, { sx: { fontSize: "0.9rem !important" } }),
38885
- label: "Local",
39226
+ label: file.source === "azure-wiki" ? "Azure Wiki" : "Local",
38886
39227
  size: "small",
38887
39228
  sx: {
38888
39229
  bgcolor: "#388e3c20",
@@ -38971,16 +39312,20 @@ var SeedPacksTab = () => {
38971
39312
  const [createImportedFiles, setCreateImportedFiles] = (0, import_react52.useState)([]);
38972
39313
  const [previewFile, setPreviewFile] = (0, import_react52.useState)(null);
38973
39314
  const fileInputRef = (0, import_react52.useRef)(null);
39315
+ const wikiFolderInputRef = (0, import_react52.useRef)(null);
38974
39316
  const createFileInputRef = (0, import_react52.useRef)(null);
39317
+ const createWikiFolderInputRef = (0, import_react52.useRef)(null);
38975
39318
  const [isLoadingList, setIsLoadingList] = (0, import_react52.useState)(false);
38976
39319
  const [isLoadingDetail, setIsLoadingDetail] = (0, import_react52.useState)(false);
38977
39320
  const [isSaving, setIsSaving] = (0, import_react52.useState)(false);
38978
39321
  const [isPublishing, setIsPublishing] = (0, import_react52.useState)(false);
38979
39322
  const [isArchiving, setIsArchiving] = (0, import_react52.useState)(false);
39323
+ const [isDeleting, setIsDeleting] = (0, import_react52.useState)(false);
38980
39324
  const [isCreating, setIsCreating] = (0, import_react52.useState)(false);
38981
39325
  const [createDialogOpen, setCreateDialogOpen] = (0, import_react52.useState)(false);
38982
39326
  const [publishDialogOpen, setPublishDialogOpen] = (0, import_react52.useState)(false);
38983
39327
  const [archiveDialogOpen, setArchiveDialogOpen] = (0, import_react52.useState)(false);
39328
+ const [deleteDialogOpen, setDeleteDialogOpen] = (0, import_react52.useState)(false);
38984
39329
  const [newPackName, setNewPackName] = (0, import_react52.useState)("");
38985
39330
  const [newPackDescription, setNewPackDescription] = (0, import_react52.useState)("");
38986
39331
  const [newPackTags, setNewPackTags] = (0, import_react52.useState)("");
@@ -39085,26 +39430,37 @@ var SeedPacksTab = () => {
39085
39430
  void loadSeedPackDetail(selectedSid);
39086
39431
  }
39087
39432
  }, [selectedSid, loadSeedPackDetail]);
39433
+ (0, import_react52.useEffect)(() => {
39434
+ const setDirectoryUploadAttributes = (input) => {
39435
+ if (!input) {
39436
+ return;
39437
+ }
39438
+ input.setAttribute("webkitdirectory", "");
39439
+ input.setAttribute("directory", "");
39440
+ };
39441
+ setDirectoryUploadAttributes(wikiFolderInputRef.current);
39442
+ setDirectoryUploadAttributes(createWikiFolderInputRef.current);
39443
+ }, [selectedSeedPack, createDialogOpen]);
39088
39444
  const handleSelectPack = (pack) => {
39089
39445
  setSelectedSid(pack.sid);
39090
39446
  setSelectedSeedPack(pack);
39091
39447
  hydrateDraft(pack);
39092
39448
  };
39093
39449
  const handleImportFiles = (0, import_react52.useCallback)(
39094
- async (files) => {
39450
+ async (files, source = "local") => {
39095
39451
  if (!files || files.length === 0) {
39096
39452
  return;
39097
39453
  }
39098
- const { imported, skipped } = await readMarkdownFiles(files);
39454
+ const { imported, skipped } = await readMarkdownFiles(files, source);
39099
39455
  if (skipped > 0) {
39100
- showSnackbar("Only .md files are supported for seed packs.", "error");
39456
+ showSnackbar("Only .md and .markdown files are supported for seed packs.", "error");
39101
39457
  }
39102
39458
  if (imported.length === 0) {
39103
39459
  return;
39104
39460
  }
39105
39461
  try {
39106
39462
  const newlyAdded = imported.filter(
39107
- (file) => !importedFiles.some((existing) => existing.name === file.name)
39463
+ (file) => !importedFiles.some((existing) => getImportedFileKey(existing) === getImportedFileKey(file))
39108
39464
  );
39109
39465
  setImportedFiles((prev) => mergeMarkdownFiles(prev, imported));
39110
39466
  const combined = buildMarkdownContent(newlyAdded);
@@ -39119,8 +39475,9 @@ ${combined}` : combined;
39119
39475
  return { ...prev, content: nextContent };
39120
39476
  });
39121
39477
  }
39478
+ const importLabel = source === "azure-wiki" ? "from Azure DevOps wiki folder into the editor" : "into the editor";
39122
39479
  showSnackbar(
39123
- `Imported ${imported.length} markdown file${imported.length === 1 ? "" : "s"} into the editor.`,
39480
+ `Imported ${imported.length} markdown file${imported.length === 1 ? "" : "s"} ${importLabel}.`,
39124
39481
  "success"
39125
39482
  );
39126
39483
  } catch (error) {
@@ -39134,7 +39491,14 @@ ${combined}` : combined;
39134
39491
  );
39135
39492
  const handleFileInputChange = (0, import_react52.useCallback)(
39136
39493
  async (event) => {
39137
- await handleImportFiles(event.target.files);
39494
+ await handleImportFiles(event.target.files, "local");
39495
+ event.target.value = "";
39496
+ },
39497
+ [handleImportFiles]
39498
+ );
39499
+ const handleWikiFolderInputChange = (0, import_react52.useCallback)(
39500
+ async (event) => {
39501
+ await handleImportFiles(event.target.files, "azure-wiki");
39138
39502
  event.target.value = "";
39139
39503
  },
39140
39504
  [handleImportFiles]
@@ -39143,20 +39507,21 @@ ${combined}` : combined;
39143
39507
  setImportedFiles((prev) => prev.filter((file) => file.id !== id));
39144
39508
  }, []);
39145
39509
  const handleCreateImportFiles = (0, import_react52.useCallback)(
39146
- async (files) => {
39510
+ async (files, source = "local") => {
39147
39511
  if (!files || files.length === 0) {
39148
39512
  return;
39149
39513
  }
39150
- const { imported, skipped } = await readMarkdownFiles(files);
39514
+ const { imported, skipped } = await readMarkdownFiles(files, source);
39151
39515
  if (skipped > 0) {
39152
- showSnackbar("Only .md files are supported for seed packs.", "error");
39516
+ showSnackbar("Only .md and .markdown files are supported for seed packs.", "error");
39153
39517
  }
39154
39518
  if (imported.length === 0) {
39155
39519
  return;
39156
39520
  }
39157
39521
  setCreateImportedFiles((prev) => mergeMarkdownFiles(prev, imported));
39522
+ const importLabel = source === "azure-wiki" ? "from Azure DevOps wiki folder for this seed pack" : "for this seed pack";
39158
39523
  showSnackbar(
39159
- `Imported ${imported.length} markdown file${imported.length === 1 ? "" : "s"} for this seed pack.`,
39524
+ `Imported ${imported.length} markdown file${imported.length === 1 ? "" : "s"} ${importLabel}.`,
39160
39525
  "success"
39161
39526
  );
39162
39527
  },
@@ -39164,7 +39529,14 @@ ${combined}` : combined;
39164
39529
  );
39165
39530
  const handleCreateFileInputChange = (0, import_react52.useCallback)(
39166
39531
  async (event) => {
39167
- await handleCreateImportFiles(event.target.files);
39532
+ await handleCreateImportFiles(event.target.files, "local");
39533
+ event.target.value = "";
39534
+ },
39535
+ [handleCreateImportFiles]
39536
+ );
39537
+ const handleCreateWikiFolderInputChange = (0, import_react52.useCallback)(
39538
+ async (event) => {
39539
+ await handleCreateImportFiles(event.target.files, "azure-wiki");
39168
39540
  event.target.value = "";
39169
39541
  },
39170
39542
  [handleCreateImportFiles]
@@ -39309,6 +39681,34 @@ ${combined}` : combined;
39309
39681
  setIsArchiving(false);
39310
39682
  }
39311
39683
  };
39684
+ const handleDelete = async () => {
39685
+ if (!selectedSeedPack) {
39686
+ return;
39687
+ }
39688
+ const deletingSid = selectedSeedPack.sid;
39689
+ const deletingName = selectedSeedPack.name;
39690
+ setDeleteDialogOpen(false);
39691
+ setIsDeleting(true);
39692
+ try {
39693
+ await deleteSeedPack(deletingSid);
39694
+ setSelectedSid(null);
39695
+ setSelectedSeedPack(null);
39696
+ setDraft({ name: "", description: "", content: "" });
39697
+ setTagsInput("");
39698
+ setImportedFiles([]);
39699
+ setPreviewFile(null);
39700
+ await refreshSeedPacks();
39701
+ showSnackbar(`Deleted seed pack "${deletingName}".`, "success");
39702
+ } catch (error) {
39703
+ showSnackbar("Failed to delete seed pack.", "error");
39704
+ debugLogger.error("SeedPacksTab: failed to delete seed pack", {
39705
+ sid: deletingSid,
39706
+ error: error instanceof Error ? error.message : String(error)
39707
+ });
39708
+ } finally {
39709
+ setIsDeleting(false);
39710
+ }
39711
+ };
39312
39712
  const previewContent = draft.content.trim().length > 0 ? draft.content : "Preview will appear here as you type.";
39313
39713
  const selectedStatus = selectedSeedPack?.status ?? "draft";
39314
39714
  const statusChip = getStatusChip(selectedStatus);
@@ -39510,32 +39910,56 @@ ${combined}` : combined;
39510
39910
  sx: { mb: 1 },
39511
39911
  children: [
39512
39912
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Typography, { variant: "subtitle2", children: "Markdown content" }),
39913
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, children: [
39914
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39915
+ import_material42.Button,
39916
+ {
39917
+ size: "small",
39918
+ variant: "outlined",
39919
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_UploadFile2.default, {}),
39920
+ onClick: () => fileInputRef.current?.click(),
39921
+ disabled: isReadOnly,
39922
+ children: "Import .md"
39923
+ }
39924
+ ),
39925
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39926
+ import_material42.Button,
39927
+ {
39928
+ size: "small",
39929
+ variant: "outlined",
39930
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_FolderOpen.default, {}),
39931
+ onClick: () => wikiFolderInputRef.current?.click(),
39932
+ disabled: isReadOnly,
39933
+ children: "Import wiki folder"
39934
+ }
39935
+ )
39936
+ ] }),
39513
39937
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39514
- import_material42.Button,
39938
+ "input",
39515
39939
  {
39516
- size: "small",
39517
- variant: "outlined",
39518
- startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_UploadFile2.default, {}),
39519
- onClick: () => fileInputRef.current?.click(),
39520
- disabled: isReadOnly,
39521
- children: "Import .md"
39940
+ ref: fileInputRef,
39941
+ type: "file",
39942
+ accept: ".md,.markdown,text/markdown",
39943
+ multiple: true,
39944
+ onChange: handleFileInputChange,
39945
+ style: { display: "none" }
39522
39946
  }
39523
39947
  ),
39524
39948
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39525
39949
  "input",
39526
39950
  {
39527
- ref: fileInputRef,
39951
+ ref: wikiFolderInputRef,
39528
39952
  type: "file",
39529
- accept: ".md",
39953
+ accept: ".md,.markdown,text/markdown",
39530
39954
  multiple: true,
39531
- onChange: handleFileInputChange,
39955
+ onChange: handleWikiFolderInputChange,
39532
39956
  style: { display: "none" }
39533
39957
  }
39534
39958
  )
39535
39959
  ]
39536
39960
  }
39537
39961
  ),
39538
- /* @__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." }),
39962
+ /* @__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." }),
39539
39963
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39540
39964
  import_material42.TextField,
39541
39965
  {
@@ -39634,6 +40058,17 @@ ${combined}` : combined;
39634
40058
  disabled: isReadOnly || isArchiving,
39635
40059
  children: isArchiving ? "Archiving..." : "Archive"
39636
40060
  }
40061
+ ),
40062
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
40063
+ import_material42.Button,
40064
+ {
40065
+ variant: "text",
40066
+ color: "error",
40067
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_Delete6.default, {}),
40068
+ onClick: () => setDeleteDialogOpen(true),
40069
+ disabled: isDeleting,
40070
+ children: isDeleting ? "Deleting..." : "Delete"
40071
+ }
39637
40072
  )
39638
40073
  ] })
39639
40074
  ] })
@@ -39683,26 +40118,50 @@ ${combined}` : combined;
39683
40118
  ),
39684
40119
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Divider, {}),
39685
40120
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, alignItems: "center", children: [
40121
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, children: [
40122
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
40123
+ import_material42.Button,
40124
+ {
40125
+ size: "small",
40126
+ variant: "outlined",
40127
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_UploadFile2.default, {}),
40128
+ onClick: () => createFileInputRef.current?.click(),
40129
+ disabled: !canManage,
40130
+ children: "Import .md files"
40131
+ }
40132
+ ),
40133
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
40134
+ import_material42.Button,
40135
+ {
40136
+ size: "small",
40137
+ variant: "outlined",
40138
+ startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_FolderOpen.default, {}),
40139
+ onClick: () => createWikiFolderInputRef.current?.click(),
40140
+ disabled: !canManage,
40141
+ children: "Import wiki folder"
40142
+ }
40143
+ )
40144
+ ] }),
40145
+ /* @__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." }),
39686
40146
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39687
- import_material42.Button,
40147
+ "input",
39688
40148
  {
39689
- size: "small",
39690
- variant: "outlined",
39691
- startIcon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_UploadFile2.default, {}),
39692
- onClick: () => createFileInputRef.current?.click(),
39693
- disabled: !canManage,
39694
- children: "Import .md files"
40149
+ ref: createFileInputRef,
40150
+ type: "file",
40151
+ accept: ".md,.markdown,text/markdown",
40152
+ multiple: true,
40153
+ onChange: handleCreateFileInputChange,
40154
+ style: { display: "none" }
39695
40155
  }
39696
40156
  ),
39697
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Typography, { variant: "caption", color: "text.secondary", children: "Optional. Files are merged into the draft content." }),
39698
40157
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
39699
40158
  "input",
39700
40159
  {
39701
- ref: createFileInputRef,
40160
+ ref: createWikiFolderInputRef,
39702
40161
  type: "file",
39703
- accept: ".md",
40162
+ accept: ".md,.markdown,text/markdown",
39704
40163
  multiple: true,
39705
- onChange: handleCreateFileInputChange,
40164
+ onChange: handleCreateWikiFolderInputChange,
39706
40165
  style: { display: "none" }
39707
40166
  }
39708
40167
  )
@@ -39767,6 +40226,21 @@ ${combined}` : combined;
39767
40226
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Button, { variant: "contained", color: "error", onClick: handleArchive, disabled: isArchiving, children: isArchiving ? "Archiving..." : "Archive" })
39768
40227
  ] })
39769
40228
  ] }),
40229
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.Dialog, { open: deleteDialogOpen, onClose: () => setDeleteDialogOpen(false), maxWidth: "sm", fullWidth: true, children: [
40230
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.DialogTitle, { children: "Delete seed pack" }),
40231
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.DialogContent, { children: [
40232
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.DialogContentText, { children: [
40233
+ 'Delete "',
40234
+ selectedSeedPack?.name ?? "this seed pack",
40235
+ '" permanently from this scope. Published versions and draft content will no longer be available.'
40236
+ ] }),
40237
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Alert, { severity: "warning", sx: { mt: 2 }, children: "This action cannot be undone." })
40238
+ ] }),
40239
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_material42.DialogActions, { children: [
40240
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Button, { onClick: () => setDeleteDialogOpen(false), children: "Cancel" }),
40241
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_material42.Button, { variant: "contained", color: "error", onClick: handleDelete, disabled: isDeleting, children: isDeleting ? "Deleting..." : "Delete" })
40242
+ ] })
40243
+ ] }),
39770
40244
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
39771
40245
  import_material42.Dialog,
39772
40246
  {
@@ -40525,15 +40999,7 @@ var StorageTab = ({ currentTheme }) => {
40525
40999
  ] }) })
40526
41000
  ] }),
40527
41001
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_material44.Typography, { variant: "h6", gutterBottom: true, sx: { mb: 2, fontWeight: 600, color: "text.primary" }, children: "Storage Categories" }),
40528
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_material44.Box, { sx: {
40529
- maxHeight: "60vh",
40530
- overflow: "auto",
40531
- "&::-webkit-scrollbar": {
40532
- display: "none"
40533
- },
40534
- msOverflowStyle: "none",
40535
- scrollbarWidth: "none"
40536
- }, children: storageCategories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_material44.Alert, { severity: "info", sx: { mt: 2 }, children: [
41002
+ /* @__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: [
40537
41003
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_material44.Typography, { variant: "body2", children: "No storage data found. This could mean:" }),
40538
41004
  /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_material44.Typography, { variant: "body2", component: "ul", sx: { mt: 1, pl: 2 }, children: [
40539
41005
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("li", { children: "All databases are empty" }),
@@ -41775,7 +42241,7 @@ var Management = () => {
41775
42241
  const [modalOpen, setModalOpen] = (0, import_react57.useState)(false);
41776
42242
  const banditHead6 = "https://cdn.burtson.ai/images/bandit-head.png";
41777
42243
  const [fabLogo, setFabLogo] = (0, import_react57.useState)(banditHead6);
41778
- const [tabIndex, setTabIndex] = (0, import_react57.useState)(0);
42244
+ const [tabIndex, setTabIndex] = (0, import_react57.useState)(4);
41779
42245
  const [logoFile, setLogoFile] = (0, import_react57.useState)(null);
41780
42246
  const [logoBase64, setLogoBase64] = (0, import_react57.useState)(null);
41781
42247
  const [brandingText, setBrandingText] = (0, import_react57.useState)("");
@@ -42488,7 +42954,6 @@ var Management = () => {
42488
42954
  }
42489
42955
  });
42490
42956
  }, [theme]);
42491
- if (!brandingLoaded) return null;
42492
42957
  const allNavTabs = [
42493
42958
  {
42494
42959
  label: "Personalities",
@@ -42545,6 +43010,18 @@ var Management = () => {
42545
43010
  }
42546
43011
  return true;
42547
43012
  });
43013
+ const preferredDefaultTabIndex = navTabs.findIndex((tab) => tab.label === "Preferences");
43014
+ const defaultTabIndex = preferredDefaultTabIndex >= 0 ? preferredDefaultTabIndex : 0;
43015
+ (0, import_react57.useEffect)(() => {
43016
+ setTabIndex((current) => {
43017
+ if (current < 0 || current >= navTabs.length) {
43018
+ return defaultTabIndex;
43019
+ }
43020
+ return current;
43021
+ });
43022
+ }, [navTabs.length, defaultTabIndex]);
43023
+ const mobileQuickTabs = navTabs.slice(0, 5);
43024
+ const hasMobileOverflowTabs = navTabs.length > mobileQuickTabs.length;
42548
43025
  const navigationContent = /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
42549
43026
  import_material47.Box,
42550
43027
  {
@@ -42701,6 +43178,7 @@ var Management = () => {
42701
43178
  ]
42702
43179
  }
42703
43180
  );
43181
+ if (!brandingLoaded) return null;
42704
43182
  return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_material47.ThemeProvider, { theme: currentTheme, children: [
42705
43183
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_material47.CssBaseline, {}),
42706
43184
  /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
@@ -42721,7 +43199,7 @@ var Management = () => {
42721
43199
  {
42722
43200
  sx: {
42723
43201
  width: "100%",
42724
- height: 64,
43202
+ minHeight: 64,
42725
43203
  display: "flex",
42726
43204
  alignItems: "center",
42727
43205
  justifyContent: "space-between",
@@ -42804,6 +43282,73 @@ var Management = () => {
42804
43282
  ]
42805
43283
  }
42806
43284
  ),
43285
+ isMobile && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
43286
+ import_material47.Box,
43287
+ {
43288
+ sx: {
43289
+ width: "100%",
43290
+ display: "flex",
43291
+ gap: 1,
43292
+ px: 1.5,
43293
+ py: 1,
43294
+ overflowX: "auto",
43295
+ borderBottom: (theme2) => `1px solid ${theme2.palette.divider}`,
43296
+ bgcolor: (theme2) => theme2.palette.mode === "dark" ? "rgba(24,28,40,0.95)" : "rgba(255,255,255,0.95)",
43297
+ backdropFilter: "blur(12px)"
43298
+ },
43299
+ children: [
43300
+ mobileQuickTabs.map((tab) => {
43301
+ const quickTabIndex = navTabs.findIndex((navTab) => navTab.label === tab.label);
43302
+ const selected = tabIndex === quickTabIndex;
43303
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
43304
+ import_material47.Button,
43305
+ {
43306
+ size: "small",
43307
+ onClick: () => setTabIndex(quickTabIndex),
43308
+ sx: {
43309
+ flexShrink: 0,
43310
+ textTransform: "none",
43311
+ borderRadius: 999,
43312
+ px: 1.5,
43313
+ py: 0.6,
43314
+ minHeight: 32,
43315
+ fontSize: "0.78rem",
43316
+ fontWeight: selected ? 700 : 600,
43317
+ bgcolor: selected ? (theme2) => theme2.palette.mode === "dark" ? "rgba(25,118,210,0.2)" : "rgba(25,118,210,0.12)" : "transparent",
43318
+ color: selected ? "primary.main" : "text.secondary",
43319
+ border: (theme2) => selected ? `1px solid ${theme2.palette.primary.main}66` : `1px solid ${(0, import_styles31.alpha)(theme2.palette.divider, 0.45)}`,
43320
+ "&:hover": {
43321
+ bgcolor: (theme2) => theme2.palette.mode === "dark" ? "rgba(25,118,210,0.16)" : "rgba(25,118,210,0.1)"
43322
+ }
43323
+ },
43324
+ children: tab.label
43325
+ },
43326
+ tab.label
43327
+ );
43328
+ }),
43329
+ hasMobileOverflowTabs && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
43330
+ import_material47.Button,
43331
+ {
43332
+ size: "small",
43333
+ onClick: () => setSidebarOpen(true),
43334
+ sx: {
43335
+ flexShrink: 0,
43336
+ textTransform: "none",
43337
+ borderRadius: 999,
43338
+ px: 1.5,
43339
+ py: 0.6,
43340
+ minHeight: 32,
43341
+ fontSize: "0.78rem",
43342
+ fontWeight: 600,
43343
+ color: "text.secondary",
43344
+ border: (theme2) => `1px dashed ${(0, import_styles31.alpha)(theme2.palette.divider, 0.6)}`
43345
+ },
43346
+ children: "More"
43347
+ }
43348
+ )
43349
+ ]
43350
+ }
43351
+ ),
42807
43352
  isMobile ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
42808
43353
  import_material47.SwipeableDrawer,
42809
43354
  {
@@ -42856,26 +43401,17 @@ var Management = () => {
42856
43401
  flex: 1,
42857
43402
  p: { xs: 1, sm: 3, md: 4 },
42858
43403
  overflowY: "auto",
42859
- height: isMobile ? "auto" : "100vh",
43404
+ overflowX: "hidden",
42860
43405
  maxWidth: "100vw",
42861
43406
  minWidth: 0,
43407
+ minHeight: 0,
42862
43408
  display: "flex",
42863
43409
  flexDirection: "column",
42864
43410
  bgcolor: "background.default",
42865
43411
  ml: isMobile ? 0 : "280px",
42866
43412
  // Fixed left margin only on desktop
42867
43413
  mt: 0,
42868
- transition: "margin-left 0.2s",
42869
- overflow: "auto",
42870
- // Hide scrollbars while keeping scroll functionality
42871
- scrollbarWidth: "none",
42872
- // Firefox
42873
- "&::-webkit-scrollbar": {
42874
- display: "none"
42875
- // Chrome, Safari, Edge
42876
- },
42877
- "-ms-overflow-style": "none"
42878
- // IE and Edge
43414
+ transition: "margin-left 0.2s"
42879
43415
  },
42880
43416
  children: [
42881
43417
  navTabs[tabIndex]?.label === "Personalities" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(