@burtson-labs/bandit-engine 2.0.23 → 2.0.25

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 (145) hide show
  1. package/README.md +8 -6
  2. package/dist/{chat-VOVYLTMX.mjs → chat-2LYIZNWZ.mjs} +2 -2
  3. package/dist/{chunk-ZRTP2N7E.mjs → chunk-IGD4KGB5.mjs} +102 -85
  4. package/dist/chunk-IGD4KGB5.mjs.map +1 -0
  5. package/dist/{chunk-JTZL6WJJ.mjs → chunk-XXMCI2WK.mjs} +2 -2
  6. package/dist/cli/cli.js +1 -1
  7. package/dist/cli/cli.js.map +1 -1
  8. package/dist/index.js +70 -53
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +5 -5
  11. package/dist/management/management.js +70 -53
  12. package/dist/management/management.js.map +1 -1
  13. package/dist/management/management.mjs +1 -1
  14. package/docs/05_cli_quickstart.md +3 -5
  15. package/docs/api_reference/assets/bandit-docs.js +271 -0
  16. package/docs/api_reference/assets/main.js +9 -0
  17. package/docs/api_reference/classes/DebugLogger.html +11 -11
  18. package/docs/api_reference/classes/FeatureFlagService.html +13 -13
  19. package/docs/api_reference/classes/NotificationService.html +10 -10
  20. package/docs/api_reference/classes/StreamingTTSClient.html +9 -9
  21. package/docs/api_reference/classes/VectorDatabaseService.html +24 -24
  22. package/docs/api_reference/classes/VectorMigrationService.html +8 -8
  23. package/docs/api_reference/classes/VoiceService.html +2 -2
  24. package/docs/api_reference/enums/TTSState.html +2 -2
  25. package/docs/api_reference/functions/Chat.html +1 -1
  26. package/docs/api_reference/functions/ChatModal.html +1 -1
  27. package/docs/api_reference/functions/ChatProvider.html +1 -1
  28. package/docs/api_reference/functions/FeatureFlagProvider.html +1 -1
  29. package/docs/api_reference/functions/FeedbackButton.html +1 -1
  30. package/docs/api_reference/functions/FeedbackModal.html +1 -1
  31. package/docs/api_reference/functions/Management.html +1 -1
  32. package/docs/api_reference/functions/NotificationProvider.html +1 -1
  33. package/docs/api_reference/functions/SubscriptionExpiredGuard.html +1 -1
  34. package/docs/api_reference/functions/SubscriptionExpiredModal.html +1 -1
  35. package/docs/api_reference/functions/defineCustomElement.html +1 -1
  36. package/docs/api_reference/functions/getCriticalConfig.html +1 -1
  37. package/docs/api_reference/functions/getFeatureMatrix.html +1 -1
  38. package/docs/api_reference/functions/getStreamingTTSClient.html +1 -1
  39. package/docs/api_reference/functions/getSystemConstants.html +1 -1
  40. package/docs/api_reference/functions/getTTSState.html +1 -1
  41. package/docs/api_reference/functions/handleHttpError.html +1 -1
  42. package/docs/api_reference/functions/handleSubscriptionUpgrade.html +1 -1
  43. package/docs/api_reference/functions/handleValidationError.html +1 -1
  44. package/docs/api_reference/functions/initializeCoreSystem.html +1 -1
  45. package/docs/api_reference/functions/pauseTTS.html +1 -1
  46. package/docs/api_reference/functions/previewTierUpgrade.html +1 -1
  47. package/docs/api_reference/functions/resumeTTS.html +1 -1
  48. package/docs/api_reference/functions/showInfoNotification.html +1 -1
  49. package/docs/api_reference/functions/showSuccessNotification.html +1 -1
  50. package/docs/api_reference/functions/speakWithStreaming.html +1 -1
  51. package/docs/api_reference/functions/stopTTS.html +1 -1
  52. package/docs/api_reference/functions/syncSubscriptionWithAPI.html +1 -1
  53. package/docs/api_reference/functions/updateSubscriptionTier.html +1 -1
  54. package/docs/api_reference/functions/useFeatureFlag.html +1 -1
  55. package/docs/api_reference/functions/useFeatureVisibility.html +1 -1
  56. package/docs/api_reference/functions/useFeatures.html +1 -1
  57. package/docs/api_reference/functions/useGatewayHealth.html +1 -1
  58. package/docs/api_reference/functions/useGatewayMemory.html +1 -1
  59. package/docs/api_reference/functions/useGatewayModels.html +1 -1
  60. package/docs/api_reference/functions/useGlobalTTS.html +1 -1
  61. package/docs/api_reference/functions/useNotification.html +1 -1
  62. package/docs/api_reference/functions/useNotificationService.html +1 -1
  63. package/docs/api_reference/functions/useTTS.html +1 -1
  64. package/docs/api_reference/functions/useVectorStore.html +1 -1
  65. package/docs/api_reference/functions/useVoiceStore.html +2 -2
  66. package/docs/api_reference/functions/useVoices.html +1 -1
  67. package/docs/api_reference/functions/validateEnvironment.html +1 -1
  68. package/docs/api_reference/functions/validateSystemIntegrity.html +1 -1
  69. package/docs/api_reference/index.html +8 -5
  70. package/docs/api_reference/interfaces/AIChatRequest.html +2 -2
  71. package/docs/api_reference/interfaces/AIChatResponse.html +2 -2
  72. package/docs/api_reference/interfaces/AIGenerateRequest.html +2 -2
  73. package/docs/api_reference/interfaces/AIGenerateResponse.html +2 -2
  74. package/docs/api_reference/interfaces/AIMessage.html +2 -2
  75. package/docs/api_reference/interfaces/AIModel.html +2 -2
  76. package/docs/api_reference/interfaces/AIProviderConfig.html +2 -2
  77. package/docs/api_reference/interfaces/ChatConfig.html +3 -3
  78. package/docs/api_reference/interfaces/ChatModalProps.html +3 -3
  79. package/docs/api_reference/interfaces/CreateMemoryOptions.html +2 -2
  80. package/docs/api_reference/interfaces/FeatureEvaluation.html +7 -7
  81. package/docs/api_reference/interfaces/FeatureFlagConfig.html +9 -9
  82. package/docs/api_reference/interfaces/FeatureFlagContextValue.html +8 -8
  83. package/docs/api_reference/interfaces/FeatureFlagProviderProps.html +2 -2
  84. package/docs/api_reference/interfaces/FeedbackButtonProps.html +10 -10
  85. package/docs/api_reference/interfaces/FeedbackCategories.html +2 -2
  86. package/docs/api_reference/interfaces/FeedbackModalProps.html +2 -2
  87. package/docs/api_reference/interfaces/FeedbackPriorities.html +2 -2
  88. package/docs/api_reference/interfaces/FeedbackRequest.html +2 -2
  89. package/docs/api_reference/interfaces/FeedbackResponse.html +2 -2
  90. package/docs/api_reference/interfaces/FileUploadResult.html +2 -2
  91. package/docs/api_reference/interfaces/GatewayChatRequest.html +2 -2
  92. package/docs/api_reference/interfaces/GatewayChatResponse.html +2 -2
  93. package/docs/api_reference/interfaces/GatewayContract.html +2 -2
  94. package/docs/api_reference/interfaces/GatewayGenerateRequest.html +2 -2
  95. package/docs/api_reference/interfaces/GatewayGenerateResponse.html +2 -2
  96. package/docs/api_reference/interfaces/GatewayHealthResponse.html +2 -2
  97. package/docs/api_reference/interfaces/GatewayMemoryRecord.html +2 -2
  98. package/docs/api_reference/interfaces/GatewayMemoryResponse.html +2 -2
  99. package/docs/api_reference/interfaces/GatewayMessage.html +2 -2
  100. package/docs/api_reference/interfaces/GatewayMessageContent.html +2 -2
  101. package/docs/api_reference/interfaces/GatewayModel.html +2 -2
  102. package/docs/api_reference/interfaces/GatewayModelsResponse.html +2 -2
  103. package/docs/api_reference/interfaces/MemorySearchFilters.html +2 -2
  104. package/docs/api_reference/interfaces/MigrationProgress.html +2 -2
  105. package/docs/api_reference/interfaces/MigrationStatus.html +2 -2
  106. package/docs/api_reference/interfaces/NotificationConfig.html +2 -2
  107. package/docs/api_reference/interfaces/NotificationContextType.html +2 -2
  108. package/docs/api_reference/interfaces/NotificationProviderProps.html +2 -2
  109. package/docs/api_reference/interfaces/PackageSettings.html +2 -2
  110. package/docs/api_reference/interfaces/SearchOptions.html +2 -2
  111. package/docs/api_reference/interfaces/SearchResult.html +2 -2
  112. package/docs/api_reference/interfaces/SubscriptionExpiredGuardProps.html +2 -2
  113. package/docs/api_reference/interfaces/SubscriptionExpiredModalProps.html +2 -2
  114. package/docs/api_reference/interfaces/TTSOptions.html +2 -2
  115. package/docs/api_reference/interfaces/TTSProgress.html +2 -2
  116. package/docs/api_reference/interfaces/TrialUsage.html +2 -2
  117. package/docs/api_reference/interfaces/UploadRequest.html +3 -3
  118. package/docs/api_reference/interfaces/UseTTSReturn.html +2 -2
  119. package/docs/api_reference/interfaces/VectorDocument.html +2 -2
  120. package/docs/api_reference/interfaces/VectorMemory.html +2 -2
  121. package/docs/api_reference/interfaces/VectorMemoryMetadata.html +2 -2
  122. package/docs/api_reference/interfaces/VectorStoreStatus.html +2 -2
  123. package/docs/api_reference/interfaces/VoiceModelsResponse.html +2 -2
  124. package/docs/api_reference/interfaces/VoiceState.html +2 -2
  125. package/docs/api_reference/media/05_cli_quickstart.md +3 -5
  126. package/docs/api_reference/types/FeatureKey.html +1 -1
  127. package/docs/api_reference/types/FeatureMatrix.html +1 -1
  128. package/docs/api_reference/types/GatewayQueryOptions.html +1 -1
  129. package/docs/api_reference/types/LogContext.html +1 -1
  130. package/docs/api_reference/types/SubscriptionTier.html +1 -1
  131. package/docs/api_reference/variables/DEFAULT_TIER_FEATURES.html +1 -1
  132. package/docs/api_reference/variables/FeatureFlagContext.html +1 -1
  133. package/docs/api_reference/variables/OSS_DEFAULT_FEATURES.html +1 -1
  134. package/docs/api_reference/variables/SYSTEM_FLAGS.html +1 -1
  135. package/docs/api_reference/variables/authenticationService.html +1 -1
  136. package/docs/api_reference/variables/debugLogger-1.html +1 -1
  137. package/docs/api_reference/variables/featureFlagService-1.html +1 -1
  138. package/docs/api_reference/variables/notificationService-1.html +1 -1
  139. package/docs/api_reference/variables/vectorDatabaseService-1.html +1 -1
  140. package/docs/api_reference/variables/vectorMigrationService-1.html +1 -1
  141. package/docs/api_reference/variables/voiceService-1.html +1 -1
  142. package/package.json +1 -1
  143. package/dist/chunk-ZRTP2N7E.mjs.map +0 -1
  144. /package/dist/{chat-VOVYLTMX.mjs.map → chat-2LYIZNWZ.mjs.map} +0 -0
  145. /package/dist/{chunk-JTZL6WJJ.mjs.map → chunk-XXMCI2WK.mjs.map} +0 -0
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  An AI chat toolkit built for speed, design, and control. Power branded AI assistants with battle-tested React components and a secure gateway contract.
12
12
 
13
- [![npm private](https://img.shields.io/badge/npm-private-lightgrey?logo=npm)](https://www.npmjs.com/package/@burtson-labs/bandit-engine)
13
+ [![npm](https://img.shields.io/npm/v/%40burtson-labs%2Fbandit-engine?logo=npm&color=cb3837)](https://www.npmjs.com/package/@burtson-labs/bandit-engine)
14
14
  [![Docs](https://img.shields.io/badge/docs-banditailabs.com%2Fnpm--package-0C7BD4)](https://banditailabs.com/npm-package)
15
15
  [![Live Demo](https://img.shields.io/badge/live%20demo-banditailabs.com%2Fchat-7F56D9)](https://banditailabs.com/)
16
16
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-3178c6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
@@ -20,7 +20,7 @@ An AI chat toolkit built for speed, design, and control. Power branded AI assist
20
20
  - 🔌 Plug-and-play React chat, modal, and management surfaces
21
21
  - 🧠 Memory, vector knowledge, and provider switching behind a secure gateway
22
22
  - 🎨 Full MUI theming, dark mode, and branding controls out of the box
23
- - 🌐 Multimodal support (voice, images, documents) with Ollama, OpenAI, Azure, Anthropic
23
+ - 🌐 Multimodal support (voice, images, documents) with Ollama, OpenAI, Azure OpenAI, and Anthropic today — tell us which providers you need next so we can prioritize them
24
24
  - 🛠️ CLI scaffolding, sample gateway, and docs to launch in minutes
25
25
 
26
26
  ## Quick Links
@@ -55,7 +55,7 @@ Customize the output with options such as:
55
55
  - `--yes` / `--skip-prompts` to accept defaults non-interactively
56
56
  - `--force` to overwrite a non-empty directory
57
57
 
58
- > 🗝️ The generated project includes an `.npmrc` that targets `https://npm.pkg.github.com/` and expects a `GITHUB_NPM_TOKEN` environment variable. Run `npm login --registry=https://npm.pkg.github.com --scope=@burtson-labs` (or export `GITHUB_NPM_TOKEN`) before installing dependencies.
58
+ > 📦 The generated project installs directly from `https://registry.npmjs.org/` no GitHub npm token is required once the package is public.
59
59
 
60
60
  > ⚠️ The scaffolded gateway focuses on OpenAI/Ollama chat and model discovery. All advanced routes (file storage uploads, vector embedding, voice, MCP, etc.) are generated as `501` placeholders so you can wire them to your own infrastructure. Implement the contracts below before turning on those features in production.
61
61
 
@@ -671,12 +671,14 @@ Bandit Engine features a unified, gateway-based AI provider architecture that su
671
671
 
672
672
  ### Supported Providers
673
673
 
674
- - **🌟 Gateway Provider** (Recommended): Routes all requests through your secure .NET 9 backend
675
- - **Ollama**: Self-hosted models and Ollama-compatible endpoints
674
+ - **🌟 Gateway Provider** (Recommended): Routes all requests through your secure backend
675
+ - **Ollama**: Self-hosted models and Ollama-compatible endpoints
676
676
  - **OpenAI**: GPT models via OpenAI API
677
677
  - **Azure OpenAI**: Azure-hosted OpenAI models
678
678
  - **Anthropic**: Claude models via Anthropic API
679
679
 
680
+ > We do not support every AI provider yet. Let us know which services you rely on—community interest directly shapes the integration roadmap.
681
+
680
682
  ### Gateway Provider (Recommended)
681
683
 
682
684
  The gateway provider offers the most secure and scalable approach by routing all requests through your backend API:
@@ -729,7 +731,7 @@ aiProvider: {
729
731
 
730
732
  ### Migration to Gateway
731
733
 
732
- 1. **Deploy Gateway Backend**: Set up your .NET 9 gateway service
734
+ 1. **Deploy Gateway Backend**: Set up your preferred gateway service
733
735
  2. **Update Configuration**: Switch from direct to gateway provider
734
736
  3. **Test Connection**: Use the Management interface to validate
735
737
  4. **Update API Keys**: Move keys from frontend to backend config
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  chat_default
3
- } from "./chunk-ZRTP2N7E.mjs";
3
+ } from "./chunk-IGD4KGB5.mjs";
4
4
  import "./chunk-ONQMRE2G.mjs";
5
5
  import "./chunk-RTQDQ6TC.mjs";
6
6
  import "./chunk-GBANNFRD.mjs";
@@ -12,4 +12,4 @@ import "./chunk-BJTO5JO5.mjs";
12
12
  export {
13
13
  chat_default as default
14
14
  };
15
- //# sourceMappingURL=chat-VOVYLTMX.mjs.map
15
+ //# sourceMappingURL=chat-2LYIZNWZ.mjs.map
@@ -58,7 +58,7 @@ import {
58
58
  } from "./chunk-KCI46M23.mjs";
59
59
 
60
60
  // src/chat/chat.tsx
61
- import { useCallback as useCallback6, useEffect as useEffect14, useLayoutEffect, useRef as useRef14, useState as useState15 } from "react";
61
+ import { useCallback as useCallback6, useEffect as useEffect15, useLayoutEffect, useRef as useRef14, useState as useState15 } from "react";
62
62
 
63
63
  // src/chat/custom-logo.tsx
64
64
  import React, { useEffect } from "react";
@@ -1138,6 +1138,8 @@ var ChatInput = (props) => {
1138
1138
  const isMemoryEnabled = preferences.memoryEnabled && showMemoryToggle();
1139
1139
  const isDocumentUploadEnabled = showDocumentUpload();
1140
1140
  const isFeedbackEnabled = preferences.feedbackEnabled;
1141
+ const gatewayUrlLower = packageSettings?.gatewayApiUrl?.toLowerCase?.() ?? "";
1142
+ const isPlaygroundMode2 = packageSettings?.playgroundMode === true || gatewayUrlLower.startsWith("playground://") || typeof window !== "undefined" && window.location.pathname.includes("/playground");
1141
1143
  useEffect4(() => {
1142
1144
  const lockViewportHeight = () => {
1143
1145
  if (isMobile) {
@@ -1291,7 +1293,7 @@ ${sanitize(escapePromptInjection(value), file.name)}`;
1291
1293
  const page = await pdf.getPage(i + 1);
1292
1294
  const content = await page.getTextContent();
1293
1295
  return content.items.map((item) => {
1294
- if (typeof item.str === "string") {
1296
+ if (item && typeof item === "object" && "str" in item && typeof item.str === "string") {
1295
1297
  return item.str;
1296
1298
  }
1297
1299
  return "";
@@ -1351,7 +1353,7 @@ ${sanitize(
1351
1353
  inputRef.current?.focus();
1352
1354
  };
1353
1355
  const memory = localStorage.getItem("bandit-memory");
1354
- const hasAttachmentAction = fileInputs.length < 3 && isDocumentUploadEnabled;
1356
+ const hasAttachmentAction = !isPlaygroundMode2 && fileInputs.length < 3 && isDocumentUploadEnabled;
1355
1357
  const hasMemoryAction = isMemoryEnabled;
1356
1358
  const hasFeedbackAction = isFeedbackEnabled && isMobile;
1357
1359
  const hasSttAction = isSTTAvailable && !isVoiceModeEnabled;
@@ -3794,7 +3796,7 @@ var useNetworkStatus = () => {
3794
3796
 
3795
3797
  // src/chat/chat-app-bar.tsx
3796
3798
  import { Avatar as Avatar8 } from "@mui/material";
3797
- import { useRef as useRef11, useState as useState13 } from "react";
3799
+ import { useEffect as useEffect12, useRef as useRef11, useState as useState13 } from "react";
3798
3800
  import {
3799
3801
  Box as Box11,
3800
3802
  IconButton as IconButton10,
@@ -5995,6 +5997,7 @@ var ConversationDrawer = ({ open, onClose }) => {
5995
5997
  display: "flex",
5996
5998
  alignItems: "center",
5997
5999
  gap: 1.5,
6000
+ justifyContent: "center",
5998
6001
  bgcolor: alpha6(theme.palette.background.default, isMobile ? 0.9 : 0.6)
5999
6002
  },
6000
6003
  children: [
@@ -6013,33 +6016,39 @@ var ConversationDrawer = ({ open, onClose }) => {
6013
6016
  children: avatarInitials
6014
6017
  }
6015
6018
  ),
6016
- /* @__PURE__ */ jsxs9(Box9, { sx: { minWidth: 0, flex: 1 }, children: [
6017
- /* @__PURE__ */ jsx12(
6018
- Typography6,
6019
- {
6020
- variant: "subtitle2",
6021
- noWrap: true,
6022
- sx: { fontWeight: 600, color: theme.palette.text.primary },
6023
- children: user ? userDisplayName : "Not signed in"
6024
- }
6025
- ),
6026
- user ? userSecondaryText ? /* @__PURE__ */ jsx12(
6027
- Typography6,
6028
- {
6029
- variant: "caption",
6030
- noWrap: true,
6031
- sx: { color: theme.palette.text.secondary },
6032
- children: userSecondaryText
6033
- }
6034
- ) : null : /* @__PURE__ */ jsx12(
6035
- Typography6,
6036
- {
6037
- variant: "caption",
6038
- sx: { color: theme.palette.text.secondary },
6039
- children: "Connect your account to sync chats"
6040
- }
6041
- )
6042
- ] })
6019
+ /* @__PURE__ */ jsxs9(
6020
+ Box9,
6021
+ {
6022
+ sx: {
6023
+ minWidth: 0,
6024
+ flex: 1,
6025
+ display: "flex",
6026
+ flexDirection: "column",
6027
+ alignItems: isMobile ? "center" : "flex-start",
6028
+ textAlign: isMobile ? "center" : "left",
6029
+ gap: 0.25
6030
+ },
6031
+ children: [
6032
+ /* @__PURE__ */ jsx12(
6033
+ Typography6,
6034
+ {
6035
+ variant: "subtitle2",
6036
+ noWrap: true,
6037
+ sx: { fontWeight: 600, color: theme.palette.text.primary },
6038
+ children: user ? userDisplayName : "Not signed in"
6039
+ }
6040
+ ),
6041
+ !user && /* @__PURE__ */ jsx12(
6042
+ Typography6,
6043
+ {
6044
+ variant: "caption",
6045
+ sx: { color: theme.palette.text.secondary },
6046
+ children: "Connect your account to sync chats"
6047
+ }
6048
+ )
6049
+ ]
6050
+ }
6051
+ )
6043
6052
  ]
6044
6053
  }
6045
6054
  )
@@ -6951,7 +6960,7 @@ var EnhancedMobileConversationsModal = ({
6951
6960
  children: avatarInitials
6952
6961
  }
6953
6962
  ),
6954
- /* @__PURE__ */ jsxs10(Box10, { sx: { display: "flex", alignItems: "center", gap: 1, minWidth: 0, flexWrap: "wrap", justifyContent: "center" }, children: [
6963
+ /* @__PURE__ */ jsxs10(Box10, { sx: { display: "flex", flexDirection: "column", alignItems: "center", gap: 0.5, minWidth: 0 }, children: [
6955
6964
  /* @__PURE__ */ jsx13(
6956
6965
  Typography7,
6957
6966
  {
@@ -6961,24 +6970,13 @@ var EnhancedMobileConversationsModal = ({
6961
6970
  children: user ? userDisplayName : "Not signed in"
6962
6971
  }
6963
6972
  ),
6964
- user ? userSecondaryText ? /* @__PURE__ */ jsxs10(
6965
- Typography7,
6966
- {
6967
- variant: "caption",
6968
- noWrap: true,
6969
- sx: { color: theme.palette.text.secondary },
6970
- children: [
6971
- "\u2022 ",
6972
- userSecondaryText
6973
- ]
6974
- }
6975
- ) : null : /* @__PURE__ */ jsx13(
6973
+ !user && /* @__PURE__ */ jsx13(
6976
6974
  Typography7,
6977
6975
  {
6978
6976
  variant: "caption",
6979
6977
  sx: { color: theme.palette.text.secondary },
6980
6978
  noWrap: true,
6981
- children: "\u2022 Connect your account to sync chats"
6979
+ children: "Connect your account to sync chats"
6982
6980
  }
6983
6981
  )
6984
6982
  ] })
@@ -7133,7 +7131,8 @@ var ChatAppBar = ({
7133
7131
  pendingCount,
7134
7132
  warningConversations,
7135
7133
  oversizedConversations,
7136
- triggerSync
7134
+ triggerSync,
7135
+ setSyncEnabled
7137
7136
  } = useConversationSyncStore((state) => ({
7138
7137
  syncEnabled: state.syncEnabled,
7139
7138
  syncStatus: state.status,
@@ -7141,8 +7140,18 @@ var ChatAppBar = ({
7141
7140
  pendingCount: state.pendingConversationUpserts.size + state.pendingConversationDeletes.size + state.pendingProjectUpserts.size + state.pendingProjectDeletes.size,
7142
7141
  warningConversations: state.warningConversations,
7143
7142
  oversizedConversations: state.oversizedConversations,
7144
- triggerSync: state.runSync
7143
+ triggerSync: state.runSync,
7144
+ setSyncEnabled: state.setSyncEnabled
7145
7145
  }), shallow2);
7146
+ useEffect12(() => {
7147
+ if (isPlaygroundMode2 && syncEnabled) {
7148
+ void setSyncEnabled(false).catch((error) => {
7149
+ debugLogger.warn("ChatAppBar: Failed to disable sync in playground", {
7150
+ error: error instanceof Error ? error.message : String(error)
7151
+ });
7152
+ });
7153
+ }
7154
+ }, [isPlaygroundMode2, syncEnabled, setSyncEnabled]);
7146
7155
  const syncSpinSx = {
7147
7156
  animation: "spin 1s linear infinite",
7148
7157
  "@keyframes spin": {
@@ -7151,7 +7160,7 @@ var ChatAppBar = ({
7151
7160
  }
7152
7161
  };
7153
7162
  const syncIndicatorIcon = (() => {
7154
- if (!syncEnabled) {
7163
+ if (isPlaygroundMode2 || !syncEnabled) {
7155
7164
  return /* @__PURE__ */ jsx14(CloudOffIcon, { fontSize: "small", color: "disabled" });
7156
7165
  }
7157
7166
  switch (syncStatus) {
@@ -7165,6 +7174,9 @@ var ChatAppBar = ({
7165
7174
  }
7166
7175
  })();
7167
7176
  const syncTooltip = (() => {
7177
+ if (isPlaygroundMode2) {
7178
+ return "Cloud sync is unavailable in playground mode.";
7179
+ }
7168
7180
  if (!syncEnabled) {
7169
7181
  return "Cloud sync is disabled. Enable it from Management > Preferences.";
7170
7182
  }
@@ -7184,8 +7196,9 @@ var ChatAppBar = ({
7184
7196
  const last = lastSyncAt ? ` Last sync ${new Date(lastSyncAt).toLocaleTimeString()}.` : "";
7185
7197
  return `${base}${pending}${last}`;
7186
7198
  })();
7199
+ const syncButtonDisabled = isPlaygroundMode2 || !syncEnabled;
7187
7200
  const handleSyncBadgeClick = () => {
7188
- if (!syncEnabled || syncStatus === "syncing") {
7201
+ if (isPlaygroundMode2 || !syncEnabled || syncStatus === "syncing") {
7189
7202
  return;
7190
7203
  }
7191
7204
  void triggerSync({ force: true });
@@ -7315,18 +7328,19 @@ var ChatAppBar = ({
7315
7328
  IconButton10,
7316
7329
  {
7317
7330
  onClick: handleSyncBadgeClick,
7331
+ disabled: syncButtonDisabled,
7318
7332
  sx: {
7319
7333
  ...pillButtonStyles,
7320
- color: syncEnabled ? theme.palette.primary.main : theme.palette.action.disabled,
7321
- bgcolor: syncEnabled ? syncStatus === "error" ? theme.palette.error.main + "20" : theme.palette.primary.main + "12" : "transparent",
7322
- "&:hover": syncEnabled ? {
7334
+ color: syncButtonDisabled ? theme.palette.action.disabled : theme.palette.primary.main,
7335
+ bgcolor: syncButtonDisabled ? "transparent" : syncStatus === "error" ? theme.palette.error.main + "20" : theme.palette.primary.main + "12",
7336
+ "&:hover": syncButtonDisabled ? {} : {
7323
7337
  bgcolor: syncStatus === "error" ? theme.palette.error.main + "30" : theme.palette.primary.main + "20"
7324
- } : {}
7338
+ }
7325
7339
  },
7326
7340
  "aria-label": "Conversation sync status",
7327
7341
  children: [
7328
7342
  syncIndicatorIcon,
7329
- pendingCount > 0 && syncEnabled && syncStatus !== "syncing" && /* @__PURE__ */ jsx14(
7343
+ pendingCount > 0 && !syncButtonDisabled && syncStatus !== "syncing" && /* @__PURE__ */ jsx14(
7330
7344
  Box11,
7331
7345
  {
7332
7346
  sx: {
@@ -7850,7 +7864,7 @@ Respond with just the title and nothing else.
7850
7864
  };
7851
7865
 
7852
7866
  // src/chat/query-suggestion-picker.tsx
7853
- import { useEffect as useEffect12, useRef as useRef12, useState as useState14 } from "react";
7867
+ import { useEffect as useEffect13, useRef as useRef12, useState as useState14 } from "react";
7854
7868
  import { Box as Box12, useMediaQuery as useMediaQuery6 } from "@mui/material";
7855
7869
  import { useTheme as useTheme13, alpha as alpha8 } from "@mui/material/styles";
7856
7870
  import ReactMarkdown2 from "react-markdown";
@@ -7860,7 +7874,10 @@ import { Fragment as Fragment9, jsx as jsx15 } from "react/jsx-runtime";
7860
7874
  var markdownComponents = {
7861
7875
  p: ({ node, ...props }) => /* @__PURE__ */ jsx15("span", { ...props }),
7862
7876
  mark: ({ node, children, ...props }) => /* @__PURE__ */ jsx15("mark", { ...props, children }),
7863
- code: ({ node, inline, children, ...props }) => inline ? /* @__PURE__ */ jsx15("code", { ...props, children }) : /* @__PURE__ */ jsx15("code", { ...props, children })
7877
+ code: ({ node, children, ...props }) => {
7878
+ const { inline, ...rest } = props;
7879
+ return inline ? /* @__PURE__ */ jsx15("code", { ...rest, children }) : /* @__PURE__ */ jsx15("code", { ...rest, children });
7880
+ }
7864
7881
  };
7865
7882
  var QuerySuggestionPicker = ({
7866
7883
  onSend,
@@ -7875,7 +7892,7 @@ var QuerySuggestionPicker = ({
7875
7892
  const isMobile = useMediaQuery6((theme2) => theme2.breakpoints.down("sm"));
7876
7893
  const { background, text, border, hoverBackground, hoverBorder } = theme.palette.chat.suggestion;
7877
7894
  const { getCurrentModel, isLoading } = useModelStore();
7878
- useEffect12(() => {
7895
+ useEffect13(() => {
7879
7896
  if (hasGenerated.current || isLoading) return;
7880
7897
  hasGenerated.current = true;
7881
7898
  const currentModel = getCurrentModel();
@@ -7902,12 +7919,12 @@ var QuerySuggestionPicker = ({
7902
7919
  hasGenerated.current = false;
7903
7920
  });
7904
7921
  }, [getCurrentModel, isLoading]);
7905
- useEffect12(() => {
7922
+ useEffect13(() => {
7906
7923
  if (!isLoading) {
7907
7924
  hasGenerated.current = false;
7908
7925
  }
7909
7926
  }, [isLoading]);
7910
- useEffect12(() => {
7927
+ useEffect13(() => {
7911
7928
  if (hasSentPrompt || examplePrompts.length === 0) return;
7912
7929
  const interval = setInterval(() => {
7913
7930
  setExamplePrompts((prev) => {
@@ -8176,7 +8193,7 @@ var ConnectionStatus = ({
8176
8193
  };
8177
8194
 
8178
8195
  // src/hooks/useVoiceMode.ts
8179
- import { useEffect as useEffect13, useRef as useRef13 } from "react";
8196
+ import { useEffect as useEffect14, useRef as useRef13 } from "react";
8180
8197
  var RMS_BASELINE = 128;
8181
8198
  var RMS_NORMALIZER = 128;
8182
8199
  var computeRms = (data) => {
@@ -8194,10 +8211,10 @@ var useVoiceMode = (config) => {
8194
8211
  const resetTransientState = useVoiceModeStore((state) => state.resetTransientState);
8195
8212
  const setLastTranscript = useVoiceModeStore((state) => state.setLastTranscript);
8196
8213
  const configRef = useRef13(config);
8197
- useEffect13(() => {
8214
+ useEffect14(() => {
8198
8215
  configRef.current = config;
8199
8216
  }, [config]);
8200
- useEffect13(() => {
8217
+ useEffect14(() => {
8201
8218
  if (!enabled) {
8202
8219
  return () => void 0;
8203
8220
  }
@@ -8460,7 +8477,7 @@ var ChatContent = () => {
8460
8477
  const isVoiceModeEnabled = useVoiceModeStore((state) => state.enabled);
8461
8478
  const previousVoiceModeEnabledRef = useRef14(isVoiceModeEnabled);
8462
8479
  const historyRef = useRef14(history);
8463
- useEffect14(() => {
8480
+ useEffect15(() => {
8464
8481
  historyRef.current = history;
8465
8482
  }, [history]);
8466
8483
  const {
@@ -8468,7 +8485,7 @@ var ChatContent = () => {
8468
8485
  stop: ttsStop,
8469
8486
  isAvailable: isTTSAvailable
8470
8487
  } = useTTS();
8471
- useEffect14(() => {
8488
+ useEffect15(() => {
8472
8489
  const timer = setTimeout(() => {
8473
8490
  const isAuthenticated = authenticationService.isAuthenticated();
8474
8491
  if (!initialized || availableVoices.length === 0) {
@@ -8482,7 +8499,7 @@ var ChatContent = () => {
8482
8499
  }, 500);
8483
8500
  return () => clearTimeout(timer);
8484
8501
  }, [initialized, availableVoices.length, loadVoicesFromAPI, token]);
8485
- useEffect14(() => {
8502
+ useEffect15(() => {
8486
8503
  const isAuthenticated = authenticationService.isAuthenticated();
8487
8504
  if (packageSettings?.gatewayApiUrl && availableVoices.length === 0 && !initialized) {
8488
8505
  if (token && isAuthenticated) {
@@ -8533,7 +8550,7 @@ var ChatContent = () => {
8533
8550
  const [brandingLoading, setBrandingLoading] = useState15(true);
8534
8551
  const isBrandingLoadInProgressRef = useRef14(false);
8535
8552
  const logoOnly = history.length === 0 && !brandingLoading;
8536
- useEffect14(() => {
8553
+ useEffect15(() => {
8537
8554
  const isEmptyConversation = (history?.length ?? 0) === 0;
8538
8555
  const isSending = Boolean(pendingMessage);
8539
8556
  const shouldShowLogo = isEmptyConversation && !isSending;
@@ -8563,18 +8580,18 @@ var ChatContent = () => {
8563
8580
  }, 500);
8564
8581
  }
8565
8582
  }, [history, pendingMessage]);
8566
- useEffect14(() => () => {
8583
+ useEffect15(() => () => {
8567
8584
  if (logoFadeTimeoutRef.current) {
8568
8585
  window.clearTimeout(logoFadeTimeoutRef.current);
8569
8586
  logoFadeTimeoutRef.current = null;
8570
8587
  }
8571
8588
  }, []);
8572
- useEffect14(() => {
8589
+ useEffect15(() => {
8573
8590
  if (isStreaming && streamBuffer.trim() === "") {
8574
8591
  streamingGraceUntilRef.current = Date.now() + GRACE_MS;
8575
8592
  }
8576
8593
  }, [isStreaming, streamBuffer]);
8577
- useEffect14(() => {
8594
+ useEffect15(() => {
8578
8595
  if (!isStreaming) return;
8579
8596
  const container = chatContainerRef.current;
8580
8597
  if (!container) return;
@@ -8585,13 +8602,13 @@ var ChatContent = () => {
8585
8602
  container.scrollTo({ top: targetTop, behavior: "smooth" });
8586
8603
  }
8587
8604
  }, [streamBuffer, isStreaming, isMobile, chatContainerRef]);
8588
- useEffect14(() => {
8605
+ useEffect15(() => {
8589
8606
  if (!_hasHydrated) {
8590
8607
  debugLogger.info("Chat component triggering conversation store hydration");
8591
8608
  hydrate();
8592
8609
  }
8593
8610
  }, [_hasHydrated, hydrate]);
8594
- useEffect14(() => {
8611
+ useEffect15(() => {
8595
8612
  const loadBrandingAndTheme = async () => {
8596
8613
  if (isBrandingLoadInProgressRef.current) {
8597
8614
  debugLogger.warn("Branding loading already in progress, skipping");
@@ -8778,19 +8795,19 @@ var ChatContent = () => {
8778
8795
  window.removeEventListener("bandit-theme-changed", handleThemeChange);
8779
8796
  };
8780
8797
  }, []);
8781
- useEffect14(() => {
8798
+ useEffect15(() => {
8782
8799
  if (!chatContainerEl) return;
8783
8800
  const blurInputOnScroll = () => inputRef.current?.blur();
8784
8801
  chatContainerEl.addEventListener("scroll", blurInputOnScroll);
8785
8802
  return () => chatContainerEl.removeEventListener("scroll", blurInputOnScroll);
8786
8803
  }, [chatContainerEl]);
8787
- useEffect14(() => {
8804
+ useEffect15(() => {
8788
8805
  const handleResize = () => setIsMobile(window.innerWidth <= 768);
8789
8806
  handleResize();
8790
8807
  window.addEventListener("resize", handleResize);
8791
8808
  return () => window.removeEventListener("resize", handleResize);
8792
8809
  }, []);
8793
- useEffect14(() => {
8810
+ useEffect15(() => {
8794
8811
  const setViewportHeight = () => {
8795
8812
  document.documentElement.style.setProperty(
8796
8813
  "--vh",
@@ -8801,7 +8818,7 @@ var ChatContent = () => {
8801
8818
  window.addEventListener("resize", setViewportHeight);
8802
8819
  return () => window.removeEventListener("resize", setViewportHeight);
8803
8820
  }, []);
8804
- useEffect14(() => {
8821
+ useEffect15(() => {
8805
8822
  if (!chatContainerEl) return;
8806
8823
  let rafId = null;
8807
8824
  const update = () => {
@@ -8820,7 +8837,7 @@ var ChatContent = () => {
8820
8837
  chatContainerEl.removeEventListener(SCROLL_STATE_CHANGED_EVENT, update);
8821
8838
  };
8822
8839
  }, [chatContainerEl, getScrollState]);
8823
- useEffect14(() => {
8840
+ useEffect15(() => {
8824
8841
  if (!chatContainerEl) return;
8825
8842
  let observer = null;
8826
8843
  let rafId = null;
@@ -8855,7 +8872,7 @@ var ChatContent = () => {
8855
8872
  if (observer) observer.disconnect();
8856
8873
  };
8857
8874
  }, [chatContainerEl, scrollTargetEl, scrollTargetRef, getScrollState, inputHeight, history.length]);
8858
- useEffect14(() => {
8875
+ useEffect15(() => {
8859
8876
  const isTransitioning = isStreaming || streamBuffer.trim() === "";
8860
8877
  const delay = isTransitioning ? 400 : 100;
8861
8878
  const timer = setTimeout(() => {
@@ -8898,7 +8915,7 @@ var ChatContent = () => {
8898
8915
  return () => clearTimeout(scrollTimer);
8899
8916
  }
8900
8917
  }, [history, isStreaming, scrollToBottom, getScrollState, isMobile, chatContainerRef]);
8901
- useEffect14(() => {
8918
+ useEffect15(() => {
8902
8919
  const observer = new ResizeObserver(() => {
8903
8920
  if (inputContainerRef.current)
8904
8921
  setInputHeight(inputContainerRef.current.offsetHeight);
@@ -8909,7 +8926,7 @@ var ChatContent = () => {
8909
8926
  }
8910
8927
  return () => observer.disconnect();
8911
8928
  }, []);
8912
- useEffect14(() => {
8929
+ useEffect15(() => {
8913
8930
  if (!hydrated || !_hasHydrated) return;
8914
8931
  if (currentId === null) {
8915
8932
  useAIQueryStore.setState({ history: [] });
@@ -8958,7 +8975,7 @@ var ChatContent = () => {
8958
8975
  setResponse,
8959
8976
  setComponentStatus
8960
8977
  ]);
8961
- useEffect14(() => {
8978
+ useEffect15(() => {
8962
8979
  debugLogger.info("Chat component conversation state", {
8963
8980
  hasHydrated: _hasHydrated,
8964
8981
  conversationCount: conversations.length,
@@ -8967,7 +8984,7 @@ var ChatContent = () => {
8967
8984
  storeState: "main-chat"
8968
8985
  });
8969
8986
  }, [_hasHydrated, conversations, currentId]);
8970
- useEffect14(() => {
8987
+ useEffect15(() => {
8971
8988
  if (!_hasHydrated || !chatContainerEl) return;
8972
8989
  let rafId = null;
8973
8990
  const sync = () => {
@@ -9139,7 +9156,7 @@ var ChatContent = () => {
9139
9156
  onInterrupt: handleVoiceInterrupt,
9140
9157
  onError: (message) => notificationService?.showError?.(message)
9141
9158
  });
9142
- useEffect14(() => {
9159
+ useEffect15(() => {
9143
9160
  const previouslyEnabled = previousVoiceModeEnabledRef.current;
9144
9161
  previousVoiceModeEnabledRef.current = isVoiceModeEnabled;
9145
9162
  if (!previouslyEnabled && isVoiceModeEnabled) {
@@ -9164,7 +9181,7 @@ var ChatContent = () => {
9164
9181
  }
9165
9182
  }
9166
9183
  }, [isVoiceModeEnabled, ttsStop]);
9167
- useEffect14(() => {
9184
+ useEffect15(() => {
9168
9185
  if (!isVoiceModeEnabled || !isStreaming) {
9169
9186
  return;
9170
9187
  }
@@ -9184,7 +9201,7 @@ var ChatContent = () => {
9184
9201
  }
9185
9202
  lastSpokenResponseRef.current = null;
9186
9203
  }, [isStreaming, isVoiceModeEnabled, ttsStop]);
9187
- useEffect14(() => {
9204
+ useEffect15(() => {
9188
9205
  if (!isVoiceModeEnabled) {
9189
9206
  lastSpokenResponseRef.current = null;
9190
9207
  return;
@@ -9490,4 +9507,4 @@ var chat_default = Chat;
9490
9507
  export {
9491
9508
  chat_default
9492
9509
  };
9493
- //# sourceMappingURL=chunk-ZRTP2N7E.mjs.map
9510
+ //# sourceMappingURL=chunk-IGD4KGB5.mjs.map