@burtson-labs/bandit-engine 2.0.8 → 2.0.10

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 (193) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +161 -56
  3. package/dist/{aiProviderStore-YWJHSWFA.mjs → aiProviderStore-3YS2BZU3.mjs} +2 -2
  4. package/dist/chat-ZPJNWIXI.mjs +15 -0
  5. package/dist/chat-provider.js +9608 -0
  6. package/dist/chat-provider.js.map +1 -0
  7. package/dist/chat-provider.mjs +17 -0
  8. package/dist/chunk-2ZNIQD26.mjs +259 -0
  9. package/dist/chunk-2ZNIQD26.mjs.map +1 -0
  10. package/dist/chunk-5UVULH77.mjs +9427 -0
  11. package/dist/chunk-5UVULH77.mjs.map +1 -0
  12. package/dist/chunk-CY227I4F.mjs +160 -0
  13. package/dist/chunk-CY227I4F.mjs.map +1 -0
  14. package/dist/chunk-IFN52MQL.mjs +8763 -0
  15. package/dist/chunk-IFN52MQL.mjs.map +1 -0
  16. package/dist/{chunk-AVC6IZJQ.mjs → chunk-IHJPVIGB.mjs} +179 -2
  17. package/dist/chunk-IHJPVIGB.mjs.map +1 -0
  18. package/dist/chunk-L7UOQ2Y2.mjs +2810 -0
  19. package/dist/chunk-L7UOQ2Y2.mjs.map +1 -0
  20. package/dist/chunk-ONQMRE2G.mjs +26 -0
  21. package/dist/chunk-ONQMRE2G.mjs.map +1 -0
  22. package/dist/chunk-RTQDQ6TC.mjs +231 -0
  23. package/dist/chunk-RTQDQ6TC.mjs.map +1 -0
  24. package/dist/chunk-UMPVXYVC.mjs +5658 -0
  25. package/dist/chunk-UMPVXYVC.mjs.map +1 -0
  26. package/dist/chunk-XEG45Q6V.mjs +8925 -0
  27. package/dist/chunk-XEG45Q6V.mjs.map +1 -0
  28. package/dist/{chunk-WYS5CZVG.mjs → chunk-XUBYA5I7.mjs} +2 -2
  29. package/dist/{chunk-WYS5CZVG.mjs.map → chunk-XUBYA5I7.mjs.map} +1 -1
  30. package/dist/cli/cli.js +24 -13
  31. package/dist/cli/cli.js.map +1 -1
  32. package/dist/gateway-BiHRHJMM.d.mts +314 -0
  33. package/dist/gateway-BiHRHJMM.d.ts +314 -0
  34. package/dist/index.d.mts +11 -309
  35. package/dist/index.d.ts +11 -309
  36. package/dist/index.js +400 -155
  37. package/dist/index.js.map +1 -1
  38. package/dist/index.mjs +86 -11874
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/management/management.js +39535 -0
  41. package/dist/management/management.js.map +1 -0
  42. package/dist/management/management.mjs +16 -0
  43. package/dist/management/management.mjs.map +1 -0
  44. package/dist/{chunk-BIPELT57.mjs → modals/chat-modal/chat-modal.js} +16818 -20860
  45. package/dist/modals/chat-modal/chat-modal.js.map +1 -0
  46. package/dist/modals/chat-modal/chat-modal.mjs +19 -0
  47. package/dist/modals/chat-modal/chat-modal.mjs.map +1 -0
  48. package/dist/{modelStore-Y3LZWRQC.mjs → modelStore-UMJBDSEF.mjs} +2 -2
  49. package/dist/modelStore-UMJBDSEF.mjs.map +1 -0
  50. package/dist/public-types.d.mts +32 -0
  51. package/dist/public-types.d.ts +32 -0
  52. package/docs/01_quickstart.md +9 -6
  53. package/docs/02_gateway_api.md +55 -12
  54. package/docs/04_local_dev.md +1 -1
  55. package/docs/api_reference/assets/navigation.js +1 -1
  56. package/docs/api_reference/assets/search.js +1 -1
  57. package/docs/api_reference/classes/DebugLogger.html +11 -11
  58. package/docs/api_reference/classes/FeatureFlagService.html +13 -13
  59. package/docs/api_reference/classes/NotificationService.html +10 -10
  60. package/docs/api_reference/classes/StreamingTTSClient.html +9 -9
  61. package/docs/api_reference/classes/VectorDatabaseService.html +24 -24
  62. package/docs/api_reference/classes/VectorMigrationService.html +8 -8
  63. package/docs/api_reference/classes/VoiceService.html +2 -2
  64. package/docs/api_reference/enums/TTSState.html +2 -2
  65. package/docs/api_reference/functions/Chat.html +1 -1
  66. package/docs/api_reference/functions/ChatModal.html +4 -4
  67. package/docs/api_reference/functions/ChatProvider.html +1 -1
  68. package/docs/api_reference/functions/FeatureFlagProvider.html +1 -1
  69. package/docs/api_reference/functions/FeedbackButton.html +1 -1
  70. package/docs/api_reference/functions/FeedbackModal.html +1 -1
  71. package/docs/api_reference/functions/Management.html +1 -1
  72. package/docs/api_reference/functions/NotificationProvider.html +1 -1
  73. package/docs/api_reference/functions/SubscriptionExpiredGuard.html +1 -1
  74. package/docs/api_reference/functions/SubscriptionExpiredModal.html +1 -1
  75. package/docs/api_reference/functions/defineCustomElement.html +1 -1
  76. package/docs/api_reference/functions/getCriticalConfig.html +1 -1
  77. package/docs/api_reference/functions/getFeatureMatrix.html +1 -1
  78. package/docs/api_reference/functions/getStreamingTTSClient.html +1 -1
  79. package/docs/api_reference/functions/getSystemConstants.html +1 -1
  80. package/docs/api_reference/functions/getTTSState.html +1 -1
  81. package/docs/api_reference/functions/handleHttpError.html +1 -1
  82. package/docs/api_reference/functions/handleSubscriptionUpgrade.html +1 -1
  83. package/docs/api_reference/functions/handleValidationError.html +1 -1
  84. package/docs/api_reference/functions/initializeCoreSystem.html +1 -1
  85. package/docs/api_reference/functions/pauseTTS.html +1 -1
  86. package/docs/api_reference/functions/previewTierUpgrade.html +1 -1
  87. package/docs/api_reference/functions/resumeTTS.html +1 -1
  88. package/docs/api_reference/functions/showInfoNotification.html +1 -1
  89. package/docs/api_reference/functions/showSuccessNotification.html +1 -1
  90. package/docs/api_reference/functions/speakWithStreaming.html +1 -1
  91. package/docs/api_reference/functions/stopTTS.html +1 -1
  92. package/docs/api_reference/functions/syncSubscriptionWithAPI.html +1 -1
  93. package/docs/api_reference/functions/updateSubscriptionTier.html +1 -1
  94. package/docs/api_reference/functions/useFeatureFlag.html +1 -1
  95. package/docs/api_reference/functions/useFeatureVisibility.html +1 -1
  96. package/docs/api_reference/functions/useFeatures.html +1 -1
  97. package/docs/api_reference/functions/useGatewayHealth.html +1 -1
  98. package/docs/api_reference/functions/useGatewayMemory.html +1 -1
  99. package/docs/api_reference/functions/useGatewayModels.html +1 -1
  100. package/docs/api_reference/functions/useGlobalTTS.html +1 -1
  101. package/docs/api_reference/functions/useNotification.html +1 -1
  102. package/docs/api_reference/functions/useNotificationService.html +1 -1
  103. package/docs/api_reference/functions/useTTS.html +1 -1
  104. package/docs/api_reference/functions/useVectorStore.html +1 -1
  105. package/docs/api_reference/functions/useVoiceStore.html +2 -2
  106. package/docs/api_reference/functions/useVoices.html +1 -1
  107. package/docs/api_reference/functions/validateEnvironment.html +1 -1
  108. package/docs/api_reference/functions/validateSystemIntegrity.html +1 -1
  109. package/docs/api_reference/index.html +130 -40
  110. package/docs/api_reference/interfaces/AIChatRequest.html +2 -2
  111. package/docs/api_reference/interfaces/AIChatResponse.html +2 -2
  112. package/docs/api_reference/interfaces/AIGenerateRequest.html +2 -2
  113. package/docs/api_reference/interfaces/AIGenerateResponse.html +2 -2
  114. package/docs/api_reference/interfaces/AIMessage.html +2 -2
  115. package/docs/api_reference/interfaces/AIModel.html +2 -2
  116. package/docs/api_reference/interfaces/AIProviderConfig.html +2 -2
  117. package/docs/api_reference/interfaces/ChatConfig.html +3 -3
  118. package/docs/api_reference/interfaces/ChatModalProps.html +7 -0
  119. package/docs/api_reference/interfaces/CreateMemoryOptions.html +2 -2
  120. package/docs/api_reference/interfaces/FeatureEvaluation.html +7 -7
  121. package/docs/api_reference/interfaces/FeatureFlagConfig.html +9 -9
  122. package/docs/api_reference/interfaces/FeatureFlagContextValue.html +8 -8
  123. package/docs/api_reference/interfaces/FeatureFlagProviderProps.html +2 -2
  124. package/docs/api_reference/interfaces/FeedbackButtonProps.html +10 -10
  125. package/docs/api_reference/interfaces/FeedbackCategories.html +2 -2
  126. package/docs/api_reference/interfaces/FeedbackModalProps.html +2 -2
  127. package/docs/api_reference/interfaces/FeedbackPriorities.html +2 -2
  128. package/docs/api_reference/interfaces/FeedbackRequest.html +2 -2
  129. package/docs/api_reference/interfaces/FeedbackResponse.html +2 -2
  130. package/docs/api_reference/interfaces/FileUploadResult.html +2 -2
  131. package/docs/api_reference/interfaces/GatewayChatRequest.html +2 -2
  132. package/docs/api_reference/interfaces/GatewayChatResponse.html +2 -2
  133. package/docs/api_reference/interfaces/GatewayContract.html +2 -2
  134. package/docs/api_reference/interfaces/GatewayGenerateRequest.html +2 -2
  135. package/docs/api_reference/interfaces/GatewayGenerateResponse.html +2 -2
  136. package/docs/api_reference/interfaces/GatewayHealthResponse.html +2 -2
  137. package/docs/api_reference/interfaces/GatewayMemoryRecord.html +2 -2
  138. package/docs/api_reference/interfaces/GatewayMemoryResponse.html +2 -2
  139. package/docs/api_reference/interfaces/GatewayMessage.html +2 -2
  140. package/docs/api_reference/interfaces/GatewayMessageContent.html +2 -2
  141. package/docs/api_reference/interfaces/GatewayModel.html +2 -2
  142. package/docs/api_reference/interfaces/GatewayModelsResponse.html +2 -2
  143. package/docs/api_reference/interfaces/MemorySearchFilters.html +2 -2
  144. package/docs/api_reference/interfaces/MigrationProgress.html +2 -2
  145. package/docs/api_reference/interfaces/MigrationStatus.html +2 -2
  146. package/docs/api_reference/interfaces/NotificationConfig.html +2 -2
  147. package/docs/api_reference/interfaces/NotificationContextType.html +2 -2
  148. package/docs/api_reference/interfaces/NotificationProviderProps.html +2 -2
  149. package/docs/api_reference/interfaces/PackageSettings.html +5 -3
  150. package/docs/api_reference/interfaces/SearchOptions.html +2 -2
  151. package/docs/api_reference/interfaces/SearchResult.html +2 -2
  152. package/docs/api_reference/interfaces/SubscriptionExpiredGuardProps.html +2 -2
  153. package/docs/api_reference/interfaces/SubscriptionExpiredModalProps.html +2 -2
  154. package/docs/api_reference/interfaces/TTSOptions.html +2 -2
  155. package/docs/api_reference/interfaces/TTSProgress.html +2 -2
  156. package/docs/api_reference/interfaces/TrialUsage.html +2 -2
  157. package/docs/api_reference/interfaces/UploadRequest.html +3 -3
  158. package/docs/api_reference/interfaces/UseTTSReturn.html +2 -2
  159. package/docs/api_reference/interfaces/VectorDocument.html +2 -2
  160. package/docs/api_reference/interfaces/VectorMemory.html +2 -2
  161. package/docs/api_reference/interfaces/VectorMemoryMetadata.html +2 -2
  162. package/docs/api_reference/interfaces/VectorStoreStatus.html +2 -2
  163. package/docs/api_reference/interfaces/VoiceModelsResponse.html +2 -2
  164. package/docs/api_reference/interfaces/VoiceState.html +2 -2
  165. package/docs/api_reference/media/02_gateway_api.md +55 -12
  166. package/docs/api_reference/media/LICENSE +2 -2
  167. package/docs/api_reference/media/PROTECTION-README.md +6 -8
  168. package/docs/api_reference/media/README.md +37 -9
  169. package/docs/api_reference/modules.html +1 -0
  170. package/docs/api_reference/types/FeatureKey.html +1 -1
  171. package/docs/api_reference/types/FeatureMatrix.html +1 -1
  172. package/docs/api_reference/types/GatewayQueryOptions.html +1 -1
  173. package/docs/api_reference/types/LogContext.html +1 -1
  174. package/docs/api_reference/types/SubscriptionTier.html +1 -1
  175. package/docs/api_reference/variables/DEFAULT_TIER_FEATURES.html +1 -1
  176. package/docs/api_reference/variables/FeatureFlagContext.html +1 -1
  177. package/docs/api_reference/variables/OSS_DEFAULT_FEATURES.html +1 -1
  178. package/docs/api_reference/variables/SYSTEM_FLAGS.html +1 -1
  179. package/docs/api_reference/variables/authenticationService.html +1 -1
  180. package/docs/api_reference/variables/debugLogger-1.html +1 -1
  181. package/docs/api_reference/variables/featureFlagService-1.html +1 -1
  182. package/docs/api_reference/variables/notificationService-1.html +1 -1
  183. package/docs/api_reference/variables/vectorDatabaseService-1.html +1 -1
  184. package/docs/api_reference/variables/vectorMigrationService-1.html +1 -1
  185. package/docs/api_reference/variables/voiceService-1.html +1 -1
  186. package/package.json +24 -13
  187. package/dist/chat-QXB526NZ.mjs +0 -11
  188. package/dist/chunk-AVC6IZJQ.mjs.map +0 -1
  189. package/dist/chunk-BIPELT57.mjs.map +0 -1
  190. package/docs/api_reference/media/README-1.md +0 -23
  191. /package/dist/{aiProviderStore-YWJHSWFA.mjs.map → aiProviderStore-3YS2BZU3.mjs.map} +0 -0
  192. /package/dist/{chat-QXB526NZ.mjs.map → chat-ZPJNWIXI.mjs.map} +0 -0
  193. /package/dist/{modelStore-Y3LZWRQC.mjs.map → chat-provider.mjs.map} +0 -0
@@ -0,0 +1,2810 @@
1
+ import {
2
+ FeedbackButton,
3
+ ai_response_text_field_default,
4
+ banditDarkTheme,
5
+ memory_modal_default,
6
+ speakStream,
7
+ themeMap_default,
8
+ useNotificationService,
9
+ useTTS,
10
+ useVoiceStore
11
+ } from "./chunk-XEG45Q6V.mjs";
12
+ import {
13
+ brandingService_default,
14
+ toTitleCase,
15
+ useAIQueryStore,
16
+ useConversationStore,
17
+ useMemoryStore
18
+ } from "./chunk-UMPVXYVC.mjs";
19
+ import {
20
+ indexedDBService_default,
21
+ useModelStore,
22
+ usePackageSettingsStore,
23
+ usePreferencesStore
24
+ } from "./chunk-XUBYA5I7.mjs";
25
+ import {
26
+ useAIProviderStore
27
+ } from "./chunk-IHJPVIGB.mjs";
28
+ import {
29
+ debugLogger
30
+ } from "./chunk-KCI46M23.mjs";
31
+
32
+ // src/modals/chat-modal/chat-modal.tsx
33
+ import { useEffect as useEffect5, useLayoutEffect, useRef as useRef3, useState as useState6 } from "react";
34
+ import {
35
+ Modal,
36
+ InputAdornment as InputAdornment3,
37
+ Tooltip as Tooltip4,
38
+ IconButton as IconButton4,
39
+ Box as Box6,
40
+ Avatar as Avatar2,
41
+ Menu,
42
+ MenuItem as MenuItem2,
43
+ ThemeProvider,
44
+ Typography as Typography3
45
+ } from "@mui/material";
46
+ import { useNavigate } from "react-router-dom";
47
+ import CloseIcon3 from "@mui/icons-material/Close";
48
+ import SendIcon from "@mui/icons-material/Send";
49
+ import RecordVoiceOverIcon2 from "@mui/icons-material/RecordVoiceOver";
50
+
51
+ // src/modals/chat-modal/draggable-box.tsx
52
+ import React, { useEffect, useState } from "react";
53
+ import { Box, useTheme, Fade } from "@mui/material";
54
+ import { jsx } from "react/jsx-runtime";
55
+ var SCROLLABLE_THRESHOLD = 200;
56
+ var DraggableBox = React.forwardRef(
57
+ ({ children, fullScreen, position, setPosition, onDrag, onScrollThresholdExceeded }, ref) => {
58
+ const theme = useTheme();
59
+ const [transitionProps, setTransitionProps] = useState("all");
60
+ const [isDragging, setIsDragging] = useState(false);
61
+ const [isHovering, setIsHovering] = useState(false);
62
+ useEffect(() => {
63
+ if (ref && typeof ref !== "function" && ref.current && !fullScreen) {
64
+ const modal = ref.current;
65
+ const contentHeight = modal.scrollHeight;
66
+ const modalHeight = modal.clientHeight;
67
+ const hasOverflow = contentHeight > modalHeight + SCROLLABLE_THRESHOLD;
68
+ if (hasOverflow) {
69
+ onScrollThresholdExceeded?.();
70
+ }
71
+ }
72
+ }, [children, fullScreen, onScrollThresholdExceeded, ref]);
73
+ return /* @__PURE__ */ jsx(Fade, { in: true, timeout: 300, children: /* @__PURE__ */ jsx(
74
+ Box,
75
+ {
76
+ ref,
77
+ tabIndex: -1,
78
+ onMouseDown: (e) => {
79
+ setTransitionProps("none");
80
+ setIsDragging(true);
81
+ },
82
+ onMouseUp: (e) => {
83
+ setTransitionProps("all");
84
+ setIsDragging(false);
85
+ },
86
+ onMouseEnter: () => setIsHovering(true),
87
+ onMouseLeave: () => setIsHovering(false),
88
+ sx: {
89
+ transitionProperty: transitionProps,
90
+ transitionDuration: fullScreen ? "0.4s" : "0.3s",
91
+ transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)",
92
+ position: "absolute",
93
+ top: fullScreen ? 0 : position.y,
94
+ left: fullScreen ? 0 : position.x,
95
+ width: fullScreen ? "calc(100vw)" : "90vw",
96
+ maxWidth: fullScreen ? "100vw" : 600,
97
+ height: fullScreen ? "100vh" : "auto",
98
+ minHeight: fullScreen ? "100vh" : "fit-content",
99
+ maxHeight: fullScreen ? "100vh" : "85vh",
100
+ // Add max height for scrolling
101
+ overflow: "hidden",
102
+ // Prevent modal itself from scrolling
103
+ bgcolor: theme.palette.background.paper,
104
+ borderRadius: fullScreen ? 0 : "20px",
105
+ boxShadow: fullScreen ? "none" : isDragging ? `0 25px 50px ${theme.palette.mode === "dark" ? "rgba(0,0,0,0.7)" : "rgba(0,0,0,0.4)"}` : isHovering ? `0 16px 32px ${theme.palette.mode === "dark" ? "rgba(0,0,0,0.5)" : "rgba(0,0,0,0.25)"}` : `0 12px 24px ${theme.palette.mode === "dark" ? "rgba(0,0,0,0.4)" : "rgba(0,0,0,0.2)"}`,
106
+ p: fullScreen ? 2 : 3,
107
+ display: "flex",
108
+ flexDirection: "column",
109
+ outline: "none",
110
+ backdropFilter: fullScreen ? "none" : "blur(20px)",
111
+ border: fullScreen ? "none" : `1px solid ${theme.palette.mode === "dark" ? "rgba(255,255,255,0.15)" : "rgba(0,0,0,0.15)"}`,
112
+ // Removed transform to prevent jitter and layout shifts
113
+ "&:focus": {
114
+ outline: `2px solid ${theme.palette.primary.main}40`,
115
+ outlineOffset: "2px"
116
+ }
117
+ },
118
+ children: /* @__PURE__ */ jsx(
119
+ Box,
120
+ {
121
+ sx: {
122
+ position: "relative",
123
+ width: "100%",
124
+ height: "100%",
125
+ display: "flex",
126
+ flexDirection: "column"
127
+ },
128
+ children
129
+ }
130
+ )
131
+ }
132
+ ) });
133
+ }
134
+ );
135
+ var draggable_box_default = DraggableBox;
136
+
137
+ // src/modals/chat-modal/modal-header.tsx
138
+ import { useState as useState2 } from "react";
139
+ import {
140
+ Avatar,
141
+ Box as Box2,
142
+ IconButton,
143
+ Tooltip,
144
+ useMediaQuery,
145
+ useTheme as useTheme2,
146
+ Typography,
147
+ Chip,
148
+ Fade as Fade2
149
+ } from "@mui/material";
150
+ import MinimizeIcon from "@mui/icons-material/Minimize";
151
+ import FullscreenIcon from "@mui/icons-material/Fullscreen";
152
+ import FullscreenExitIcon from "@mui/icons-material/FullscreenExit";
153
+ import CloseIcon from "@mui/icons-material/Close";
154
+ import HistoryIcon from "@mui/icons-material/History";
155
+ import DragIndicatorIcon from "@mui/icons-material/DragIndicator";
156
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
157
+ var banditaiLogo = "https://cdn.burtson.ai/logos/bandit-ai-logo.png";
158
+ var banditHead = "https://cdn.burtson.ai/images/bandit-head.png";
159
+ var ModalHeader = ({
160
+ fullScreen,
161
+ setFullScreen,
162
+ onClose,
163
+ onDrawerOpen,
164
+ onMouseDown,
165
+ logo,
166
+ historyCount = 0,
167
+ onManualFullscreenToggle,
168
+ onExitFullscreen
169
+ }) => {
170
+ const theme = useTheme2();
171
+ const isMobile = useMediaQuery((theme2) => theme2.breakpoints.down("sm"));
172
+ const displayLogo = logo && logo !== banditaiLogo ? logo : banditHead;
173
+ const [isHovering, setIsHovering] = useState2(false);
174
+ const buttonStyles = {
175
+ transition: "all 0.15s ease-out",
176
+ borderRadius: "8px",
177
+ minWidth: "36px",
178
+ minHeight: "36px",
179
+ "&:hover": {
180
+ bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.06)"
181
+ // Removed transform to prevent jitter
182
+ },
183
+ "&:active": {
184
+ bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.12)" : "rgba(0,0,0,0.08)"
185
+ }
186
+ };
187
+ const handleMinimize = (e) => {
188
+ e.stopPropagation();
189
+ onClose();
190
+ };
191
+ const handleToggleFullScreen = (e) => {
192
+ e.stopPropagation();
193
+ const wasFullScreen = fullScreen;
194
+ setFullScreen((prev) => !prev);
195
+ if (wasFullScreen && onExitFullscreen) {
196
+ setTimeout(() => {
197
+ onExitFullscreen();
198
+ }, 100);
199
+ }
200
+ if (onManualFullscreenToggle) {
201
+ onManualFullscreenToggle();
202
+ }
203
+ };
204
+ return /* @__PURE__ */ jsxs(
205
+ Box2,
206
+ {
207
+ onMouseDown,
208
+ onMouseEnter: () => setIsHovering(true),
209
+ onMouseLeave: () => setIsHovering(false),
210
+ sx: {
211
+ display: "flex",
212
+ justifyContent: "space-between",
213
+ alignItems: "center",
214
+ cursor: "grab",
215
+ userSelect: "none",
216
+ mb: 2,
217
+ p: 1.5,
218
+ borderRadius: "16px",
219
+ bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.03)" : "rgba(0,0,0,0.03)",
220
+ border: `1px solid ${theme.palette.mode === "dark" ? "rgba(255,255,255,0.12)" : "rgba(0,0,0,0.12)"}`,
221
+ backdropFilter: "blur(12px)",
222
+ transition: "all 0.2s ease-out",
223
+ "&:hover": {
224
+ bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.06)",
225
+ borderColor: theme.palette.primary.main + "50",
226
+ boxShadow: `0 8px 32px ${theme.palette.mode === "dark" ? "rgba(0,0,0,0.4)" : "rgba(0,0,0,0.15)"}`
227
+ // Removed transform to prevent layout shifts
228
+ },
229
+ "&:active": {
230
+ cursor: "grabbing"
231
+ }
232
+ },
233
+ children: [
234
+ /* @__PURE__ */ jsxs(Box2, { sx: { display: "flex", alignItems: "center", gap: 2, flex: 1 }, children: [
235
+ /* @__PURE__ */ jsx2(
236
+ Avatar,
237
+ {
238
+ src: displayLogo,
239
+ alt: "AI Assistant",
240
+ sx: {
241
+ width: fullScreen ? 72 : 60,
242
+ height: fullScreen ? 72 : 60,
243
+ bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)",
244
+ border: "2px solid #a78bfa",
245
+ boxShadow: "0 0 8px rgba(167, 139, 250, 0.3)",
246
+ filter: "brightness(1.05)",
247
+ color: "#fff",
248
+ transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
249
+ "&:hover": {
250
+ backgroundColor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.05)",
251
+ transform: "scale(1.02)"
252
+ }
253
+ }
254
+ }
255
+ ),
256
+ /* @__PURE__ */ jsx2(Fade2, { in: isHovering && !fullScreen, children: /* @__PURE__ */ jsxs(Box2, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
257
+ /* @__PURE__ */ jsx2(
258
+ DragIndicatorIcon,
259
+ {
260
+ sx: {
261
+ color: theme.palette.text.secondary,
262
+ fontSize: "1.2rem",
263
+ opacity: 0.6
264
+ }
265
+ }
266
+ ),
267
+ /* @__PURE__ */ jsx2(
268
+ Typography,
269
+ {
270
+ variant: "caption",
271
+ sx: {
272
+ color: theme.palette.text.secondary,
273
+ fontWeight: 500
274
+ },
275
+ children: "Drag to move"
276
+ }
277
+ )
278
+ ] }) })
279
+ ] }),
280
+ /* @__PURE__ */ jsxs(Box2, { sx: { display: "flex", alignItems: "center", gap: 0.5 }, children: [
281
+ /* @__PURE__ */ jsx2(Tooltip, { title: "Chat History", arrow: true, children: /* @__PURE__ */ jsxs(
282
+ IconButton,
283
+ {
284
+ "aria-label": "Open chat history",
285
+ onClick: (e) => {
286
+ e.stopPropagation();
287
+ onDrawerOpen();
288
+ },
289
+ sx: {
290
+ ...buttonStyles,
291
+ position: "relative",
292
+ color: theme.palette.text.primary
293
+ },
294
+ children: [
295
+ /* @__PURE__ */ jsx2(HistoryIcon, {}),
296
+ historyCount > 0 && /* @__PURE__ */ jsx2(
297
+ Chip,
298
+ {
299
+ label: historyCount > 99 ? "99+" : historyCount,
300
+ size: "small",
301
+ sx: {
302
+ position: "absolute",
303
+ top: -8,
304
+ right: -8,
305
+ height: 18,
306
+ fontSize: "0.65rem",
307
+ bgcolor: theme.palette.primary.main,
308
+ color: "white",
309
+ "& .MuiChip-label": {
310
+ px: 0.5
311
+ }
312
+ }
313
+ }
314
+ )
315
+ ]
316
+ }
317
+ ) }),
318
+ !isMobile && /* @__PURE__ */ jsx2(Tooltip, { title: fullScreen ? "Exit Fullscreen" : "Enter Fullscreen", arrow: true, children: /* @__PURE__ */ jsx2(
319
+ IconButton,
320
+ {
321
+ "aria-label": fullScreen ? "exit fullscreen" : "enter fullscreen",
322
+ onClick: handleToggleFullScreen,
323
+ sx: {
324
+ ...buttonStyles,
325
+ color: theme.palette.text.primary,
326
+ bgcolor: fullScreen ? theme.palette.primary.main + "20" : "transparent"
327
+ },
328
+ children: fullScreen ? /* @__PURE__ */ jsx2(FullscreenExitIcon, {}) : /* @__PURE__ */ jsx2(FullscreenIcon, {})
329
+ }
330
+ ) }),
331
+ /* @__PURE__ */ jsx2(Tooltip, { title: "Minimize", arrow: true, children: /* @__PURE__ */ jsx2(
332
+ IconButton,
333
+ {
334
+ "aria-label": "minimize window",
335
+ onClick: handleMinimize,
336
+ sx: {
337
+ ...buttonStyles,
338
+ color: theme.palette.warning.main
339
+ },
340
+ children: /* @__PURE__ */ jsx2(MinimizeIcon, {})
341
+ }
342
+ ) }),
343
+ /* @__PURE__ */ jsx2(Tooltip, { title: "Close", arrow: true, children: /* @__PURE__ */ jsx2(
344
+ IconButton,
345
+ {
346
+ "aria-label": "close window",
347
+ onClick: (e) => {
348
+ e.stopPropagation();
349
+ onClose();
350
+ },
351
+ sx: {
352
+ ...buttonStyles,
353
+ color: theme.palette.error.main,
354
+ "&:hover": {
355
+ bgcolor: theme.palette.error.main + "15",
356
+ color: theme.palette.error.main
357
+ // Removed transform to prevent jitter
358
+ }
359
+ },
360
+ children: /* @__PURE__ */ jsx2(CloseIcon, {})
361
+ }
362
+ ) })
363
+ ] })
364
+ ]
365
+ }
366
+ );
367
+ };
368
+ var modal_header_default = ModalHeader;
369
+
370
+ // src/modals/chat-modal/query-input.tsx
371
+ import { useRef } from "react";
372
+ import { Box as Box3, TextField, IconButton as IconButton2, Tooltip as Tooltip2, InputAdornment, useTheme as useTheme3 } from "@mui/material";
373
+ import CheckIcon from "@mui/icons-material/Check";
374
+ import { jsx as jsx3 } from "react/jsx-runtime";
375
+ var QueryInput = ({
376
+ inputValue,
377
+ onChange,
378
+ onSend,
379
+ apiKey,
380
+ setApiKey,
381
+ showSettings,
382
+ setShowSettings,
383
+ startAdornment,
384
+ // Destructure startAdornment
385
+ endAdornment
386
+ // Destructure endAdornment
387
+ }) => {
388
+ const theme = useTheme3();
389
+ const inputRef = useRef(null);
390
+ const handleSend = (e, payload) => {
391
+ onSend(e, payload);
392
+ };
393
+ const handleKeyPress = (e) => {
394
+ if (e.key === "Enter" && !e.shiftKey) {
395
+ e.preventDefault();
396
+ if (inputValue.trim() !== "") {
397
+ handleSend(e, inputValue);
398
+ }
399
+ }
400
+ };
401
+ return /* @__PURE__ */ jsx3(Box3, { onMouseDown: (e) => e.stopPropagation(), sx: { padding: 2 }, children: showSettings ? /* @__PURE__ */ jsx3(
402
+ TextField,
403
+ {
404
+ fullWidth: true,
405
+ variant: "outlined",
406
+ label: "API Key",
407
+ value: apiKey,
408
+ onChange: (e) => setApiKey(e.target.value),
409
+ InputProps: {
410
+ sx: { color: theme.palette.text.primary, borderColor: theme.palette.divider },
411
+ startAdornment: /* @__PURE__ */ jsx3(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx3(Tooltip2, { title: "Toggle Settings", children: /* @__PURE__ */ jsx3(
412
+ IconButton2,
413
+ {
414
+ "aria-label": "settings",
415
+ onClick: () => setShowSettings(!showSettings),
416
+ children: /* @__PURE__ */ jsx3(CheckIcon, { sx: { color: showSettings ? theme.palette.primary.main : theme.palette.text.primary } })
417
+ }
418
+ ) }) })
419
+ },
420
+ sx: { bgcolor: theme.palette.background.paper, borderRadius: 1 }
421
+ }
422
+ ) : /* @__PURE__ */ jsx3(
423
+ TextField,
424
+ {
425
+ fullWidth: true,
426
+ variant: "outlined",
427
+ placeholder: "Ask me anything...",
428
+ value: inputValue,
429
+ inputRef,
430
+ onChange: (e) => onChange(e.target.value),
431
+ onKeyDown: handleKeyPress,
432
+ multiline: true,
433
+ maxRows: 4,
434
+ InputProps: {
435
+ sx: { color: theme.palette.text.primary, borderColor: theme.palette.divider },
436
+ startAdornment,
437
+ // Use startAdornment prop
438
+ endAdornment
439
+ // Use endAdornment prop
440
+ },
441
+ sx: {
442
+ bgcolor: theme.palette.background.paper,
443
+ borderRadius: 1,
444
+ "& .MuiOutlinedInput-root": { padding: "10px" }
445
+ }
446
+ }
447
+ ) });
448
+ };
449
+ var query_input_default = QueryInput;
450
+
451
+ // src/modals/chat-modal/chat-drawer.tsx
452
+ import React4, { useState as useState3, useEffect as useEffect2, useMemo } from "react";
453
+ import {
454
+ Drawer,
455
+ Box as Box4,
456
+ Typography as Typography2,
457
+ List,
458
+ ListItem,
459
+ useMediaQuery as useMediaQuery2,
460
+ useTheme as useTheme4,
461
+ Chip as Chip2,
462
+ IconButton as IconButton3,
463
+ Tooltip as Tooltip3,
464
+ Collapse,
465
+ TextField as TextField2,
466
+ InputAdornment as InputAdornment2,
467
+ Divider,
468
+ Dialog,
469
+ DialogTitle,
470
+ DialogContent,
471
+ DialogActions,
472
+ DialogContentText,
473
+ Button,
474
+ MenuItem
475
+ } from "@mui/material";
476
+ import CloseIcon2 from "@mui/icons-material/Close";
477
+ import SearchIcon from "@mui/icons-material/Search";
478
+ import DeleteIcon from "@mui/icons-material/Delete";
479
+ import HistoryIcon2 from "@mui/icons-material/History";
480
+ import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
481
+ import RecordVoiceOverIcon from "@mui/icons-material/RecordVoiceOver";
482
+ import MemoryIcon from "@mui/icons-material/Memory";
483
+ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
484
+ import ExpandLessIcon from "@mui/icons-material/ExpandLess";
485
+ import RefreshIcon from "@mui/icons-material/Refresh";
486
+ import { Subscription } from "rxjs";
487
+ import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
488
+ var AIQueriesDrawer = ({ drawerOpen, onClose, onClearComplete, onNavigateToMain }) => {
489
+ const theme = useTheme4();
490
+ const isMobile = useMediaQuery2(
491
+ (theme2) => theme2.breakpoints.down("sm")
492
+ );
493
+ const history = useAIQueryStore((state) => state.history);
494
+ const clearHistory = useAIQueryStore((state) => state.clearHistory);
495
+ const setResponse = useAIQueryStore((state) => state.setResponse);
496
+ const setPreviousQuestion = useAIQueryStore((state) => state.setPreviousQuestion);
497
+ const setInputValue = useAIQueryStore((state) => state.setInputValue);
498
+ const { conversations, currentId, switchConversation, _hasHydrated, hydrate } = useConversationStore();
499
+ const { availableVoices, selectedVoice, setSelectedVoice, isServiceAvailable, refreshVoices } = useVoiceStore();
500
+ const { entries: memoryEntries } = useMemoryStore();
501
+ const { preferences } = usePreferencesStore();
502
+ const { settings: packageSettings } = usePackageSettingsStore();
503
+ const provider = useAIProviderStore((state) => state.provider);
504
+ const { selectedModel, availableModels } = useModelStore();
505
+ const [searchTerm, setSearchTerm] = useState3("");
506
+ const [expandedItems, setExpandedItems] = useState3(/* @__PURE__ */ new Set());
507
+ const [expandedConversations, setExpandedConversations] = useState3(/* @__PURE__ */ new Set());
508
+ const [confirmClearOpen, setConfirmClearOpen] = useState3(false);
509
+ const [infoDialogOpen, setInfoDialogOpen] = useState3(false);
510
+ const [memoryModalOpen, setMemoryModalOpen] = useState3(false);
511
+ const [contextMode, setContextMode] = useState3("local");
512
+ const [expandedSections, setExpandedSections] = useState3(/* @__PURE__ */ new Set(["history", "voice"]));
513
+ const [audioSub, setAudioSub] = useState3(new Subscription());
514
+ const [isContextSwitching, setIsContextSwitching] = useState3(false);
515
+ const [isDrawerLoading, setIsDrawerLoading] = useState3(false);
516
+ useEffect2(() => {
517
+ if (drawerOpen && !_hasHydrated) {
518
+ hydrate();
519
+ }
520
+ }, [drawerOpen, _hasHydrated, hydrate]);
521
+ useEffect2(() => {
522
+ if (!drawerOpen) {
523
+ setIsDrawerLoading(false);
524
+ const cleanupTimer = setTimeout(() => {
525
+ setSearchTerm("");
526
+ setExpandedItems(/* @__PURE__ */ new Set());
527
+ setExpandedConversations(/* @__PURE__ */ new Set());
528
+ }, 225);
529
+ return () => clearTimeout(cleanupTimer);
530
+ }
531
+ }, [drawerOpen]);
532
+ useEffect2(() => {
533
+ return () => {
534
+ audioSub.unsubscribe();
535
+ };
536
+ }, [audioSub]);
537
+ const toggleSection = (section) => {
538
+ setExpandedSections((prev) => {
539
+ const newSet = new Set(prev);
540
+ if (newSet.has(section)) {
541
+ newSet.delete(section);
542
+ } else {
543
+ newSet.add(section);
544
+ }
545
+ return newSet;
546
+ });
547
+ };
548
+ const handleContextSwitch = async (newMode) => {
549
+ if (newMode === contextMode) return;
550
+ setIsContextSwitching(true);
551
+ try {
552
+ await new Promise((resolve) => requestAnimationFrame(resolve));
553
+ if (newMode === "main" && !_hasHydrated) {
554
+ debugLogger.debug("Context switch triggering hydration", { newMode, hasHydrated: _hasHydrated });
555
+ await new Promise((resolve) => {
556
+ setTimeout(async () => {
557
+ await hydrate();
558
+ resolve(void 0);
559
+ }, 50);
560
+ });
561
+ await new Promise((resolve) => setTimeout(resolve, 100));
562
+ }
563
+ await new Promise((resolve) => requestAnimationFrame(resolve));
564
+ setContextMode(newMode);
565
+ setExpandedItems(/* @__PURE__ */ new Set());
566
+ setExpandedConversations(/* @__PURE__ */ new Set());
567
+ debugLogger.debug("Context switch completed", { newMode, conversationCount: conversations.length });
568
+ } catch (error) {
569
+ debugLogger.error("Error during context switch", { error: String(error) });
570
+ } finally {
571
+ setTimeout(() => setIsContextSwitching(false), 300);
572
+ }
573
+ };
574
+ const isVoiceAvailable = isServiceAvailable && preferences.ttsEnabled && !!packageSettings?.gatewayApiUrl;
575
+ const isMemoryAvailable = preferences.memoryEnabled;
576
+ const currentConversation = conversations.find((c) => c.id === currentId);
577
+ const isInitialLoading = !_hasHydrated && contextMode === "main";
578
+ const isContentLoading = isContextSwitching || isInitialLoading;
579
+ useEffect2(() => {
580
+ if (drawerOpen) {
581
+ const debugTimer = setTimeout(() => {
582
+ debugLogger.debug("Chat drawer loading states", {
583
+ drawerOpen,
584
+ _hasHydrated,
585
+ isDrawerLoading,
586
+ isContentLoading,
587
+ contextMode,
588
+ storeState: "modal-chat-drawer-loading"
589
+ });
590
+ }, 400);
591
+ return () => clearTimeout(debugTimer);
592
+ }
593
+ }, [drawerOpen, _hasHydrated, isDrawerLoading, isContentLoading, contextMode]);
594
+ useEffect2(() => {
595
+ debugLogger.debug("Chat drawer voice availability check", {
596
+ isServiceAvailable,
597
+ ttsEnabled: preferences.ttsEnabled,
598
+ gatewayApiUrl: !!packageSettings?.gatewayApiUrl,
599
+ isVoiceAvailable,
600
+ availableVoicesCount: availableVoices.length,
601
+ selectedVoice,
602
+ storeState: "modal-chat-drawer-voice"
603
+ });
604
+ }, [isServiceAvailable, preferences.ttsEnabled, packageSettings?.gatewayApiUrl, isVoiceAvailable, availableVoices.length, selectedVoice]);
605
+ const activeHistory = useMemo(() => {
606
+ if (contextMode === "local") {
607
+ return history;
608
+ }
609
+ return currentConversation?.history ?? [];
610
+ }, [contextMode, history, currentConversation]);
611
+ const effectiveContextMode = contextMode === "main" && (!currentConversation || currentConversation.history.length === 0) ? "local" : contextMode;
612
+ useEffect2(() => {
613
+ debugLogger.debug("Chat drawer context state", {
614
+ contextMode,
615
+ effectiveContextMode,
616
+ conversationCount: conversations.length,
617
+ currentConversationId: currentId,
618
+ currentConversationName: currentConversation?.name,
619
+ currentConversationHistoryLength: currentConversation?.history.length || 0,
620
+ localHistoryLength: history.length,
621
+ hasHydrated: _hasHydrated,
622
+ storeState: "modal-chat-drawer"
623
+ });
624
+ }, [contextMode, effectiveContextMode, conversations.length, currentId, currentConversation, history.length, _hasHydrated]);
625
+ const filteredHistory = useMemo(() => {
626
+ const filtered = activeHistory.filter(
627
+ (entry) => entry.question.toLowerCase().includes(searchTerm.toLowerCase()) || entry.answer.toLowerCase().includes(searchTerm.toLowerCase())
628
+ );
629
+ return filtered.slice(-20);
630
+ }, [activeHistory, searchTerm]);
631
+ const filteredConversations = useMemo(() => {
632
+ const filtered = conversations.filter(
633
+ (conversation) => conversation.name.toLowerCase().includes(searchTerm.toLowerCase()) || conversation.history.some(
634
+ (entry) => entry.question.toLowerCase().includes(searchTerm.toLowerCase()) || entry.answer.toLowerCase().includes(searchTerm.toLowerCase())
635
+ )
636
+ );
637
+ return filtered.slice(0, 20);
638
+ }, [conversations, searchTerm]);
639
+ const toggleExpanded = (index) => {
640
+ const newExpanded = new Set(expandedItems);
641
+ if (newExpanded.has(index)) {
642
+ newExpanded.delete(index);
643
+ } else {
644
+ newExpanded.add(index);
645
+ }
646
+ setExpandedItems(newExpanded);
647
+ };
648
+ const toggleConversationExpanded = (conversationId) => {
649
+ const newExpanded = new Set(expandedConversations);
650
+ if (newExpanded.has(conversationId)) {
651
+ newExpanded.delete(conversationId);
652
+ } else {
653
+ newExpanded.add(conversationId);
654
+ }
655
+ setExpandedConversations(newExpanded);
656
+ };
657
+ const handleVoiceChange = (newVoice) => {
658
+ debugLogger.debug("Chat drawer voice change initiated", {
659
+ oldVoice: selectedVoice,
660
+ newVoice,
661
+ storeState: "modal-chat-drawer-voice-change"
662
+ });
663
+ setSelectedVoice(newVoice);
664
+ const voiceName = newVoice.split("-")[1];
665
+ const defaultModel = packageSettings?.defaultModel;
666
+ const currentModelConfig = availableModels.find((m) => m.name === selectedModel);
667
+ const personalityName = currentModelConfig ? currentModelConfig.name.replace("Bandit-", "Bandit ") : selectedModel || defaultModel || "Bandit";
668
+ const isTTSAvailable = !!packageSettings?.gatewayApiUrl && preferences.ttsEnabled;
669
+ if (isTTSAvailable) {
670
+ debugLogger.debug("Playing voice greeting", { voiceName, personalityName });
671
+ const greetingText = `Hi, I'm ${personalityName} speaking with ${voiceName}'s voice.`;
672
+ const spoken = speakStream(greetingText, newVoice);
673
+ audioSub.unsubscribe();
674
+ setAudioSub(
675
+ spoken.subscribe({
676
+ next: () => debugLogger.debug("Voice greeting played successfully"),
677
+ error: (err) => {
678
+ debugLogger.error(`Error changing voices: ${err}`);
679
+ }
680
+ })
681
+ );
682
+ } else {
683
+ debugLogger.debug("Voice greeting skipped", {
684
+ hasProvider: !!provider,
685
+ isTTSAvailable,
686
+ hasDefaultModel: !!defaultModel
687
+ });
688
+ }
689
+ };
690
+ const handleClearHistory = () => {
691
+ setConfirmClearOpen(true);
692
+ };
693
+ const handleConfirmClear = () => {
694
+ clearHistory();
695
+ setResponse("");
696
+ setPreviousQuestion("");
697
+ setInputValue("");
698
+ setExpandedItems(/* @__PURE__ */ new Set());
699
+ setSearchTerm("");
700
+ setConfirmClearOpen(false);
701
+ onClose();
702
+ if (onClearComplete) {
703
+ onClearComplete();
704
+ }
705
+ };
706
+ const handleCancelClear = () => {
707
+ setConfirmClearOpen(false);
708
+ };
709
+ return /* @__PURE__ */ jsxs2(
710
+ Drawer,
711
+ {
712
+ anchor: "right",
713
+ open: drawerOpen,
714
+ onClose,
715
+ keepMounted: false,
716
+ disablePortal: false,
717
+ sx: {
718
+ zIndex: 1400,
719
+ "& .MuiDrawer-paper": {
720
+ width: isMobile ? "100vw" : "50vw",
721
+ maxWidth: isMobile ? "100vw" : "600px",
722
+ bgcolor: theme.palette.background.paper,
723
+ borderLeft: `1px solid ${theme.palette.divider}`,
724
+ backdropFilter: "blur(20px)",
725
+ boxShadow: theme.palette.mode === "dark" ? "0 8px 32px rgba(0,0,0,0.5)" : "0 8px 32px rgba(0,0,0,0.2)",
726
+ // Optimize animations
727
+ transition: "transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms"
728
+ }
729
+ },
730
+ transitionDuration: 225,
731
+ SlideProps: {
732
+ timeout: 225
733
+ // Consistent timing
734
+ },
735
+ children: [
736
+ /* @__PURE__ */ jsxs2(
737
+ Box4,
738
+ {
739
+ sx: {
740
+ height: "100%",
741
+ bgcolor: theme.palette.background.paper,
742
+ color: theme.palette.text.primary,
743
+ display: "flex",
744
+ flexDirection: "column",
745
+ position: "relative"
746
+ },
747
+ role: "presentation",
748
+ children: [
749
+ /* @__PURE__ */ jsxs2(
750
+ Box4,
751
+ {
752
+ sx: {
753
+ p: 3,
754
+ borderBottom: `1px solid ${theme.palette.divider}`,
755
+ bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.02)" : "rgba(0,0,0,0.02)",
756
+ backdropFilter: "blur(10px)"
757
+ },
758
+ children: [
759
+ /* @__PURE__ */ jsxs2(Box4, { sx: { display: "flex", alignItems: "center", justifyContent: "space-between", mb: 2 }, children: [
760
+ /* @__PURE__ */ jsxs2(Box4, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
761
+ /* @__PURE__ */ jsx4(HistoryIcon2, { sx: { color: theme.palette.primary.main } }),
762
+ /* @__PURE__ */ jsx4(Typography2, { variant: "h6", sx: { fontWeight: 600, color: "text.primary" }, children: "Chat Control Center" }),
763
+ /* @__PURE__ */ jsx4(Tooltip3, { title: "About Chat History", arrow: true, children: /* @__PURE__ */ jsx4(
764
+ IconButton3,
765
+ {
766
+ onClick: () => setInfoDialogOpen(true),
767
+ size: "small",
768
+ sx: {
769
+ color: theme.palette.info.main,
770
+ "&:hover": {
771
+ bgcolor: theme.palette.info.main + "20"
772
+ }
773
+ },
774
+ children: /* @__PURE__ */ jsx4(InfoOutlinedIcon, { fontSize: "small" })
775
+ }
776
+ ) }),
777
+ /* @__PURE__ */ jsx4(Tooltip3, { title: "Refresh Conversations", arrow: true, children: /* @__PURE__ */ jsx4(
778
+ IconButton3,
779
+ {
780
+ onClick: () => {
781
+ debugLogger.info("Manual conversation refresh triggered", {
782
+ currentConversationCount: conversations.length,
783
+ hasHydrated: _hasHydrated,
784
+ currentId
785
+ });
786
+ hydrate();
787
+ if (availableVoices.length === 0) {
788
+ refreshVoices();
789
+ }
790
+ },
791
+ size: "small",
792
+ sx: {
793
+ color: theme.palette.primary.main,
794
+ "&:hover": {
795
+ bgcolor: theme.palette.primary.main + "20"
796
+ }
797
+ },
798
+ children: /* @__PURE__ */ jsx4(RefreshIcon, { fontSize: "small" })
799
+ }
800
+ ) })
801
+ ] }),
802
+ /* @__PURE__ */ jsx4(Tooltip3, { title: "Close", arrow: true, children: /* @__PURE__ */ jsx4(
803
+ IconButton3,
804
+ {
805
+ onClick: onClose,
806
+ size: "small",
807
+ sx: {
808
+ color: theme.palette.text.secondary,
809
+ "&:hover": {
810
+ bgcolor: theme.palette.action.hover,
811
+ color: theme.palette.text.primary
812
+ }
813
+ },
814
+ children: /* @__PURE__ */ jsx4(CloseIcon2, {})
815
+ }
816
+ ) })
817
+ ] }),
818
+ /* @__PURE__ */ jsx4(Box4, { sx: { mb: 2 }, children: /* @__PURE__ */ jsxs2(
819
+ Box4,
820
+ {
821
+ sx: {
822
+ display: "flex",
823
+ bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.05)",
824
+ borderRadius: "12px",
825
+ p: 0.5,
826
+ border: `1px solid ${theme.palette.divider}`
827
+ },
828
+ children: [
829
+ /* @__PURE__ */ jsx4(
830
+ Button,
831
+ {
832
+ onClick: () => handleContextSwitch("local"),
833
+ variant: contextMode === "local" ? "contained" : "text",
834
+ disabled: isContextSwitching,
835
+ sx: {
836
+ flex: 1,
837
+ textTransform: "none",
838
+ borderRadius: "8px",
839
+ fontWeight: 600,
840
+ fontSize: "0.8rem",
841
+ position: "relative",
842
+ ...contextMode === "local" && {
843
+ bgcolor: theme.palette.primary.main,
844
+ color: theme.palette.primary.contrastText,
845
+ "&:hover": {
846
+ bgcolor: theme.palette.primary.dark
847
+ }
848
+ }
849
+ },
850
+ children: isContextSwitching && contextMode !== "local" ? /* @__PURE__ */ jsxs2(Box4, { sx: {
851
+ display: "flex",
852
+ alignItems: "center",
853
+ gap: 1,
854
+ opacity: 0.7
855
+ }, children: [
856
+ /* @__PURE__ */ jsx4(Box4, { sx: {
857
+ width: 12,
858
+ height: 12,
859
+ border: "2px solid currentColor",
860
+ borderTop: "2px solid transparent",
861
+ borderRadius: "50%",
862
+ animation: "spin 1s linear infinite",
863
+ "@keyframes spin": {
864
+ "0%": { transform: "rotate(0deg)" },
865
+ "100%": { transform: "rotate(360deg)" }
866
+ }
867
+ } }),
868
+ "Loading..."
869
+ ] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
870
+ "Session Context",
871
+ /* @__PURE__ */ jsx4(
872
+ Chip2,
873
+ {
874
+ label: history.length,
875
+ size: "small",
876
+ sx: {
877
+ ml: 1,
878
+ height: "18px",
879
+ fontSize: "0.6rem",
880
+ bgcolor: contextMode === "local" ? theme.palette.primary.contrastText + "20" : theme.palette.primary.main + "20",
881
+ color: contextMode === "local" ? theme.palette.primary.contrastText : theme.palette.primary.main
882
+ }
883
+ }
884
+ )
885
+ ] })
886
+ }
887
+ ),
888
+ /* @__PURE__ */ jsx4(Tooltip3, { title: "Switch to conversation history", arrow: true, children: /* @__PURE__ */ jsx4(
889
+ Button,
890
+ {
891
+ onClick: () => handleContextSwitch("main"),
892
+ variant: contextMode === "main" ? "contained" : "text",
893
+ disabled: conversations.length === 0 || isContextSwitching,
894
+ sx: {
895
+ flex: 1,
896
+ textTransform: "none",
897
+ borderRadius: "8px",
898
+ fontWeight: 600,
899
+ fontSize: "0.8rem",
900
+ position: "relative",
901
+ ...contextMode === "main" && {
902
+ bgcolor: theme.palette.secondary.main,
903
+ color: theme.palette.secondary.contrastText,
904
+ "&:hover": {
905
+ bgcolor: theme.palette.secondary.dark
906
+ }
907
+ }
908
+ },
909
+ children: isContextSwitching && contextMode !== "main" ? /* @__PURE__ */ jsxs2(Box4, { sx: {
910
+ display: "flex",
911
+ alignItems: "center",
912
+ gap: 1,
913
+ opacity: 0.7
914
+ }, children: [
915
+ /* @__PURE__ */ jsx4(Box4, { sx: {
916
+ width: 12,
917
+ height: 12,
918
+ border: "2px solid currentColor",
919
+ borderTop: "2px solid transparent",
920
+ borderRadius: "50%",
921
+ animation: "spin 1s linear infinite",
922
+ "@keyframes spin": {
923
+ "0%": { transform: "rotate(0deg)" },
924
+ "100%": { transform: "rotate(360deg)" }
925
+ }
926
+ } }),
927
+ "Loading..."
928
+ ] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
929
+ "Main Conversation",
930
+ /* @__PURE__ */ jsx4(
931
+ Chip2,
932
+ {
933
+ label: conversations.length,
934
+ size: "small",
935
+ sx: {
936
+ ml: 1,
937
+ height: "18px",
938
+ fontSize: "0.6rem",
939
+ bgcolor: contextMode === "main" ? theme.palette.secondary.contrastText + "20" : theme.palette.secondary.main + "20",
940
+ color: contextMode === "main" ? theme.palette.secondary.contrastText : theme.palette.secondary.main
941
+ }
942
+ }
943
+ )
944
+ ] })
945
+ }
946
+ ) })
947
+ ]
948
+ }
949
+ ) }),
950
+ isVoiceAvailable ? /* @__PURE__ */ jsxs2(Box4, { sx: { mb: 2 }, children: [
951
+ /* @__PURE__ */ jsxs2(
952
+ Box4,
953
+ {
954
+ onClick: () => toggleSection("voice"),
955
+ sx: {
956
+ display: "flex",
957
+ alignItems: "center",
958
+ justifyContent: "space-between",
959
+ cursor: "pointer",
960
+ p: 1,
961
+ borderRadius: "8px",
962
+ "&:hover": {
963
+ bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.05)"
964
+ }
965
+ },
966
+ children: [
967
+ /* @__PURE__ */ jsxs2(Box4, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
968
+ /* @__PURE__ */ jsx4(RecordVoiceOverIcon, { sx: { color: theme.palette.success.main, fontSize: "1.2rem" } }),
969
+ /* @__PURE__ */ jsx4(Typography2, { variant: "subtitle2", sx: { fontWeight: 600, color: "text.primary" }, children: "Voice Model" }),
970
+ /* @__PURE__ */ jsx4(
971
+ Chip2,
972
+ {
973
+ label: selectedVoice ? toTitleCase(selectedVoice.split("-")[1]) : "Default",
974
+ size: "small",
975
+ sx: {
976
+ height: "18px",
977
+ fontSize: "0.6rem",
978
+ bgcolor: theme.palette.success.main + "20",
979
+ color: theme.palette.success.main
980
+ }
981
+ }
982
+ ),
983
+ /* @__PURE__ */ jsx4(Tooltip3, { title: "Refresh Voices", arrow: true, children: /* @__PURE__ */ jsx4(
984
+ IconButton3,
985
+ {
986
+ onClick: (e) => {
987
+ e.stopPropagation();
988
+ debugLogger.debug("Manual voice refresh triggered from chat drawer");
989
+ refreshVoices();
990
+ },
991
+ size: "small",
992
+ sx: {
993
+ color: theme.palette.text.secondary,
994
+ "&:hover": {
995
+ bgcolor: theme.palette.success.main + "20",
996
+ color: theme.palette.success.main
997
+ }
998
+ },
999
+ children: /* @__PURE__ */ jsx4(RefreshIcon, { fontSize: "small" })
1000
+ }
1001
+ ) })
1002
+ ] }),
1003
+ expandedSections.has("voice") ? /* @__PURE__ */ jsx4(ExpandLessIcon, {}) : /* @__PURE__ */ jsx4(ExpandMoreIcon, {})
1004
+ ]
1005
+ }
1006
+ ),
1007
+ /* @__PURE__ */ jsx4(Collapse, { in: expandedSections.has("voice"), children: /* @__PURE__ */ jsx4(Box4, { sx: { pl: 2, pt: 1 }, children: availableVoices.length > 0 ? /* @__PURE__ */ jsx4(
1008
+ TextField2,
1009
+ {
1010
+ select: true,
1011
+ fullWidth: true,
1012
+ size: "small",
1013
+ label: "Voice Model",
1014
+ value: selectedVoice,
1015
+ onChange: (e) => {
1016
+ const newVoice = e.target.value;
1017
+ handleVoiceChange(newVoice);
1018
+ },
1019
+ sx: {
1020
+ "& .MuiOutlinedInput-root": {
1021
+ borderRadius: "8px"
1022
+ }
1023
+ },
1024
+ children: availableVoices.map((voice) => /* @__PURE__ */ jsx4(MenuItem, { value: voice, children: /* @__PURE__ */ jsxs2(Box4, { sx: { display: "flex", alignItems: "center", gap: 1, width: "100%" }, children: [
1025
+ /* @__PURE__ */ jsx4(RecordVoiceOverIcon, { fontSize: "small", sx: { color: theme.palette.text.secondary } }),
1026
+ /* @__PURE__ */ jsxs2(Box4, { sx: { flex: 1 }, children: [
1027
+ /* @__PURE__ */ jsx4(Typography2, { variant: "body2", children: toTitleCase(voice.split("-")[1]) }),
1028
+ /* @__PURE__ */ jsx4(Typography2, { variant: "caption", sx: { color: theme.palette.text.secondary }, children: voice === selectedVoice ? "Currently active" : "Switch to this voice" })
1029
+ ] }),
1030
+ voice === selectedVoice && /* @__PURE__ */ jsx4(
1031
+ Box4,
1032
+ {
1033
+ sx: {
1034
+ width: 8,
1035
+ height: 8,
1036
+ borderRadius: "50%",
1037
+ bgcolor: theme.palette.success.main
1038
+ }
1039
+ }
1040
+ )
1041
+ ] }) }, voice))
1042
+ }
1043
+ ) : /* @__PURE__ */ jsxs2(Box4, { sx: { textAlign: "center", py: 2 }, children: [
1044
+ /* @__PURE__ */ jsx4(Typography2, { variant: "body2", color: "text.secondary", children: "No voices available" }),
1045
+ /* @__PURE__ */ jsxs2(Typography2, { variant: "caption", color: "text.secondary", sx: { display: "block", mt: 1 }, children: [
1046
+ "Service: ",
1047
+ isServiceAvailable ? "\u2713" : "\u2717",
1048
+ " | TTS: ",
1049
+ preferences.ttsEnabled ? "\u2713" : "\u2717",
1050
+ " | Gateway: ",
1051
+ !!packageSettings?.gatewayApiUrl ? "\u2713" : "\u2717"
1052
+ ] })
1053
+ ] }) }) })
1054
+ ] }) : /* @__PURE__ */ jsx4(Box4, { sx: { mb: 2 }, children: /* @__PURE__ */ jsxs2(Box4, { sx: { p: 1, borderRadius: "8px", bgcolor: theme.palette.warning.main + "10" }, children: [
1055
+ /* @__PURE__ */ jsxs2(Box4, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
1056
+ /* @__PURE__ */ jsx4(RecordVoiceOverIcon, { sx: { color: theme.palette.warning.main, fontSize: "1.2rem" } }),
1057
+ /* @__PURE__ */ jsx4(Typography2, { variant: "subtitle2", sx: { fontWeight: 600, color: theme.palette.warning.main }, children: "Voice Not Available" })
1058
+ ] }),
1059
+ /* @__PURE__ */ jsxs2(Typography2, { variant: "caption", color: "text.secondary", sx: { display: "block", mt: 1, pl: 4 }, children: [
1060
+ "Service: ",
1061
+ isServiceAvailable ? "\u2713" : "\u2717",
1062
+ " | TTS: ",
1063
+ preferences.ttsEnabled ? "\u2713" : "\u2717",
1064
+ " | Gateway: ",
1065
+ !!packageSettings?.gatewayApiUrl ? "\u2713" : "\u2717"
1066
+ ] })
1067
+ ] }) }),
1068
+ isMemoryAvailable && /* @__PURE__ */ jsxs2(Box4, { sx: { mb: 2 }, children: [
1069
+ /* @__PURE__ */ jsxs2(
1070
+ Box4,
1071
+ {
1072
+ onClick: () => toggleSection("memory"),
1073
+ sx: {
1074
+ display: "flex",
1075
+ alignItems: "center",
1076
+ justifyContent: "space-between",
1077
+ cursor: "pointer",
1078
+ p: 1,
1079
+ borderRadius: "8px",
1080
+ "&:hover": {
1081
+ bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.05)"
1082
+ }
1083
+ },
1084
+ children: [
1085
+ /* @__PURE__ */ jsxs2(Box4, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
1086
+ /* @__PURE__ */ jsx4(MemoryIcon, { sx: { color: theme.palette.warning.main, fontSize: "1.2rem" } }),
1087
+ /* @__PURE__ */ jsx4(Typography2, { variant: "subtitle2", sx: { fontWeight: 600, color: "text.primary" }, children: "Personal Memory" }),
1088
+ /* @__PURE__ */ jsx4(
1089
+ Chip2,
1090
+ {
1091
+ label: memoryEntries.length,
1092
+ size: "small",
1093
+ sx: {
1094
+ height: "18px",
1095
+ fontSize: "0.6rem",
1096
+ bgcolor: theme.palette.warning.main + "20",
1097
+ color: theme.palette.warning.main
1098
+ }
1099
+ }
1100
+ )
1101
+ ] }),
1102
+ expandedSections.has("memory") ? /* @__PURE__ */ jsx4(ExpandLessIcon, {}) : /* @__PURE__ */ jsx4(ExpandMoreIcon, {})
1103
+ ]
1104
+ }
1105
+ ),
1106
+ /* @__PURE__ */ jsx4(Collapse, { in: expandedSections.has("memory"), children: /* @__PURE__ */ jsx4(Box4, { sx: { pl: 2, pt: 1 }, children: /* @__PURE__ */ jsx4(
1107
+ Button,
1108
+ {
1109
+ fullWidth: true,
1110
+ variant: "outlined",
1111
+ onClick: () => setMemoryModalOpen(true),
1112
+ startIcon: /* @__PURE__ */ jsx4(MemoryIcon, {}),
1113
+ sx: {
1114
+ textTransform: "none",
1115
+ borderRadius: "8px",
1116
+ fontWeight: 600,
1117
+ fontSize: "0.8rem"
1118
+ },
1119
+ children: "Manage Memories"
1120
+ }
1121
+ ) }) })
1122
+ ] }),
1123
+ /* @__PURE__ */ jsxs2(
1124
+ Box4,
1125
+ {
1126
+ onClick: () => toggleSection("history"),
1127
+ sx: {
1128
+ display: "flex",
1129
+ alignItems: "center",
1130
+ justifyContent: "space-between",
1131
+ cursor: "pointer",
1132
+ p: 1,
1133
+ borderRadius: "8px",
1134
+ mb: 1,
1135
+ "&:hover": {
1136
+ bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.05)"
1137
+ }
1138
+ },
1139
+ children: [
1140
+ /* @__PURE__ */ jsxs2(Box4, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
1141
+ /* @__PURE__ */ jsx4(HistoryIcon2, { sx: { color: theme.palette.primary.main, fontSize: "1.2rem" } }),
1142
+ /* @__PURE__ */ jsx4(Typography2, { variant: "subtitle2", sx: { fontWeight: 600, color: "text.primary" }, children: contextMode === "local" ? "Session History" : "Conversation History" }),
1143
+ /* @__PURE__ */ jsx4(
1144
+ Chip2,
1145
+ {
1146
+ label: activeHistory.length,
1147
+ size: "small",
1148
+ sx: {
1149
+ height: "18px",
1150
+ fontSize: "0.6rem",
1151
+ bgcolor: theme.palette.primary.main + "20",
1152
+ color: theme.palette.primary.main
1153
+ }
1154
+ }
1155
+ ),
1156
+ activeHistory.length > 0 && contextMode === "local" && /* @__PURE__ */ jsx4(Tooltip3, { title: "Clear Session History", arrow: true, children: /* @__PURE__ */ jsx4(
1157
+ IconButton3,
1158
+ {
1159
+ onClick: (e) => {
1160
+ e.stopPropagation();
1161
+ handleClearHistory();
1162
+ },
1163
+ size: "small",
1164
+ sx: {
1165
+ color: theme.palette.error.main,
1166
+ "&:hover": {
1167
+ bgcolor: theme.palette.error.main + "20"
1168
+ }
1169
+ },
1170
+ children: /* @__PURE__ */ jsx4(DeleteIcon, { fontSize: "small" })
1171
+ }
1172
+ ) })
1173
+ ] }),
1174
+ expandedSections.has("history") ? /* @__PURE__ */ jsx4(ExpandLessIcon, {}) : /* @__PURE__ */ jsx4(ExpandMoreIcon, {})
1175
+ ]
1176
+ }
1177
+ ),
1178
+ /* @__PURE__ */ jsx4(Collapse, { in: expandedSections.has("history"), children: /* @__PURE__ */ jsx4(Box4, { sx: { mb: 1 }, children: activeHistory.length > 0 && /* @__PURE__ */ jsx4(
1179
+ TextField2,
1180
+ {
1181
+ fullWidth: true,
1182
+ size: "small",
1183
+ placeholder: `Search ${contextMode === "local" ? "session" : "conversation"} history...`,
1184
+ value: searchTerm,
1185
+ onChange: (e) => setSearchTerm(e.target.value),
1186
+ InputProps: {
1187
+ startAdornment: /* @__PURE__ */ jsx4(InputAdornment2, { position: "start", children: /* @__PURE__ */ jsx4(SearchIcon, { sx: { color: theme.palette.text.secondary } }) }),
1188
+ sx: {
1189
+ borderRadius: "12px",
1190
+ bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.05)",
1191
+ "& .MuiOutlinedInput-notchedOutline": {
1192
+ border: `1px solid ${theme.palette.divider}`
1193
+ },
1194
+ "&:hover .MuiOutlinedInput-notchedOutline": {
1195
+ borderColor: theme.palette.primary.main + "60"
1196
+ },
1197
+ "&.Mui-focused .MuiOutlinedInput-notchedOutline": {
1198
+ borderColor: theme.palette.primary.main
1199
+ }
1200
+ }
1201
+ }
1202
+ }
1203
+ ) }) })
1204
+ ]
1205
+ }
1206
+ ),
1207
+ /* @__PURE__ */ jsx4(Collapse, { in: expandedSections.has("history"), children: /* @__PURE__ */ jsxs2(
1208
+ Box4,
1209
+ {
1210
+ sx: {
1211
+ flex: 1,
1212
+ overflowY: "auto",
1213
+ p: 2,
1214
+ minHeight: "200px",
1215
+ // Reduced minimum height
1216
+ maxHeight: "400px",
1217
+ // Reduced max height for better performance
1218
+ position: "relative",
1219
+ // For loading overlay positioning
1220
+ // Custom scrollbar
1221
+ "&::-webkit-scrollbar": {
1222
+ width: "8px"
1223
+ },
1224
+ "&::-webkit-scrollbar-track": {
1225
+ background: theme.palette.mode === "dark" ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.1)",
1226
+ borderRadius: "4px"
1227
+ },
1228
+ "&::-webkit-scrollbar-thumb": {
1229
+ background: theme.palette.mode === "dark" ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)",
1230
+ borderRadius: "4px",
1231
+ "&:hover": {
1232
+ background: theme.palette.mode === "dark" ? "rgba(255,255,255,0.3)" : "rgba(0,0,0,0.3)"
1233
+ }
1234
+ },
1235
+ // Firefox scrollbar
1236
+ scrollbarWidth: "thin",
1237
+ scrollbarColor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.2) rgba(255,255,255,0.1)" : "rgba(0,0,0,0.2) rgba(0,0,0,0.1)"
1238
+ },
1239
+ children: [
1240
+ isContentLoading && /* @__PURE__ */ jsxs2(
1241
+ Box4,
1242
+ {
1243
+ sx: {
1244
+ position: "absolute",
1245
+ top: 0,
1246
+ left: 0,
1247
+ right: 0,
1248
+ bottom: 0,
1249
+ bgcolor: theme.palette.mode === "dark" ? "rgba(0, 0, 0, 0.7)" : "rgba(255, 255, 255, 0.8)",
1250
+ backdropFilter: "blur(4px)",
1251
+ zIndex: 10,
1252
+ display: "flex",
1253
+ flexDirection: "column",
1254
+ alignItems: "center",
1255
+ justifyContent: "center",
1256
+ gap: 2
1257
+ },
1258
+ children: [
1259
+ /* @__PURE__ */ jsx4(Box4, { sx: {
1260
+ width: 40,
1261
+ height: 40,
1262
+ border: "3px solid currentColor",
1263
+ borderTop: "3px solid transparent",
1264
+ borderRadius: "50%",
1265
+ animation: "spin 1s linear infinite",
1266
+ color: theme.palette.primary.main,
1267
+ "@keyframes spin": {
1268
+ "0%": { transform: "rotate(0deg)" },
1269
+ "100%": { transform: "rotate(360deg)" }
1270
+ }
1271
+ } }),
1272
+ /* @__PURE__ */ jsx4(
1273
+ Typography2,
1274
+ {
1275
+ variant: "body2",
1276
+ sx: {
1277
+ color: theme.palette.text.primary,
1278
+ fontWeight: 500
1279
+ },
1280
+ children: isInitialLoading ? "Loading conversations..." : "Switching context..."
1281
+ }
1282
+ )
1283
+ ]
1284
+ }
1285
+ ),
1286
+ !isContentLoading && (contextMode === "main" ? (
1287
+ // Show conversation list when in main context
1288
+ filteredConversations.length === 0 ? /* @__PURE__ */ jsxs2(
1289
+ Box4,
1290
+ {
1291
+ sx: {
1292
+ display: "flex",
1293
+ flexDirection: "column",
1294
+ alignItems: "center",
1295
+ justifyContent: "center",
1296
+ height: "200px",
1297
+ textAlign: "center",
1298
+ color: theme.palette.text.secondary
1299
+ },
1300
+ children: [
1301
+ /* @__PURE__ */ jsx4(HistoryIcon2, { sx: { fontSize: "3rem", mb: 2, opacity: 0.5 } }),
1302
+ /* @__PURE__ */ jsx4(Typography2, { variant: "h6", sx: { mb: 1, fontWeight: 500, color: "text.primary" }, children: searchTerm ? "No Matching Conversations" : "No Conversations Yet" }),
1303
+ /* @__PURE__ */ jsx4(Typography2, { variant: "body2", children: searchTerm ? "Try adjusting your search terms" : "Create your first conversation to get started" })
1304
+ ]
1305
+ }
1306
+ ) : /* @__PURE__ */ jsx4(List, { sx: { p: 0 }, children: filteredConversations.map((conversation, index) => {
1307
+ const isCurrent = conversation.id === currentId;
1308
+ const isExpanded = expandedConversations.has(conversation.id);
1309
+ const conversationHistory = conversation.history || [];
1310
+ return /* @__PURE__ */ jsx4(
1311
+ ListItem,
1312
+ {
1313
+ sx: {
1314
+ display: "block",
1315
+ p: 0,
1316
+ mb: 1
1317
+ },
1318
+ children: /* @__PURE__ */ jsxs2(
1319
+ Box4,
1320
+ {
1321
+ sx: {
1322
+ bgcolor: isCurrent ? theme.palette.primary.main + "20" : theme.palette.background.default,
1323
+ borderRadius: "8px",
1324
+ border: `1px solid ${isCurrent ? theme.palette.primary.main + "40" : theme.palette.divider}`,
1325
+ overflow: "hidden",
1326
+ transition: "all 0.2s ease-in-out"
1327
+ },
1328
+ children: [
1329
+ /* @__PURE__ */ jsxs2(
1330
+ Box4,
1331
+ {
1332
+ onClick: () => {
1333
+ toggleConversationExpanded(conversation.id);
1334
+ switchConversation(conversation.id);
1335
+ },
1336
+ sx: {
1337
+ p: 2,
1338
+ cursor: "pointer",
1339
+ "&:hover": {
1340
+ bgcolor: isCurrent ? theme.palette.primary.main + "30" : theme.palette.primary.main + "10"
1341
+ }
1342
+ },
1343
+ children: [
1344
+ /* @__PURE__ */ jsxs2(Box4, { sx: { display: "flex", alignItems: "center", justifyContent: "space-between", mb: 1 }, children: [
1345
+ /* @__PURE__ */ jsx4(
1346
+ Typography2,
1347
+ {
1348
+ variant: "subtitle2",
1349
+ sx: {
1350
+ fontWeight: 600,
1351
+ color: isCurrent ? theme.palette.primary.main : theme.palette.text.primary,
1352
+ flex: 1,
1353
+ overflow: "hidden",
1354
+ textOverflow: "ellipsis",
1355
+ whiteSpace: "nowrap"
1356
+ },
1357
+ children: conversation.name
1358
+ }
1359
+ ),
1360
+ /* @__PURE__ */ jsxs2(Box4, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
1361
+ isCurrent && /* @__PURE__ */ jsx4(
1362
+ Chip2,
1363
+ {
1364
+ label: "Current",
1365
+ size: "small",
1366
+ sx: {
1367
+ height: "18px",
1368
+ fontSize: "0.6rem",
1369
+ bgcolor: theme.palette.primary.main,
1370
+ color: theme.palette.primary.contrastText
1371
+ }
1372
+ }
1373
+ ),
1374
+ isExpanded ? /* @__PURE__ */ jsx4(ExpandLessIcon, {}) : /* @__PURE__ */ jsx4(ExpandMoreIcon, {})
1375
+ ] })
1376
+ ] }),
1377
+ /* @__PURE__ */ jsxs2(Box4, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
1378
+ /* @__PURE__ */ jsxs2(
1379
+ Typography2,
1380
+ {
1381
+ variant: "caption",
1382
+ sx: {
1383
+ color: theme.palette.text.secondary
1384
+ },
1385
+ children: [
1386
+ conversationHistory.length,
1387
+ " messages"
1388
+ ]
1389
+ }
1390
+ ),
1391
+ /* @__PURE__ */ jsxs2(
1392
+ Typography2,
1393
+ {
1394
+ variant: "caption",
1395
+ sx: {
1396
+ color: theme.palette.text.secondary
1397
+ },
1398
+ children: [
1399
+ "\u2022 Model: ",
1400
+ conversation.model
1401
+ ]
1402
+ }
1403
+ )
1404
+ ] })
1405
+ ]
1406
+ }
1407
+ ),
1408
+ /* @__PURE__ */ jsx4(Collapse, { in: isExpanded, children: conversationHistory.length > 0 ? /* @__PURE__ */ jsx4(Box4, { sx: { borderTop: `1px solid ${theme.palette.divider}`, bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.02)" : "rgba(0,0,0,0.02)" }, children: conversationHistory.filter(
1409
+ (entry) => !searchTerm || entry.question.toLowerCase().includes(searchTerm.toLowerCase()) || entry.answer.toLowerCase().includes(searchTerm.toLowerCase())
1410
+ ).slice().reverse().map((entry, messageIndex) => {
1411
+ const isMessageExpanded = expandedItems.has(messageIndex);
1412
+ return /* @__PURE__ */ jsxs2(Box4, { sx: { borderBottom: `1px solid ${theme.palette.divider}` }, children: [
1413
+ /* @__PURE__ */ jsxs2(
1414
+ Box4,
1415
+ {
1416
+ onClick: (e) => {
1417
+ e.stopPropagation();
1418
+ toggleExpanded(messageIndex);
1419
+ },
1420
+ sx: {
1421
+ p: 2,
1422
+ cursor: "pointer",
1423
+ "&:hover": {
1424
+ bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.05)"
1425
+ }
1426
+ },
1427
+ children: [
1428
+ /* @__PURE__ */ jsx4(
1429
+ Typography2,
1430
+ {
1431
+ variant: "body2",
1432
+ sx: {
1433
+ fontWeight: 500,
1434
+ color: theme.palette.text.primary,
1435
+ mb: 1,
1436
+ display: "-webkit-box",
1437
+ WebkitLineClamp: 2,
1438
+ WebkitBoxOrient: "vertical",
1439
+ overflow: "hidden"
1440
+ },
1441
+ children: entry.question
1442
+ }
1443
+ ),
1444
+ /* @__PURE__ */ jsx4(
1445
+ Typography2,
1446
+ {
1447
+ variant: "caption",
1448
+ sx: {
1449
+ color: theme.palette.text.secondary,
1450
+ display: "-webkit-box",
1451
+ WebkitLineClamp: 1,
1452
+ WebkitBoxOrient: "vertical",
1453
+ overflow: "hidden"
1454
+ },
1455
+ children: entry.answer
1456
+ }
1457
+ )
1458
+ ]
1459
+ }
1460
+ ),
1461
+ /* @__PURE__ */ jsx4(Collapse, { in: isMessageExpanded, children: /* @__PURE__ */ jsx4(Box4, { sx: { p: 2, pt: 0, bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.02)" : "rgba(0,0,0,0.02)" }, children: /* @__PURE__ */ jsx4(
1462
+ ai_response_text_field_default,
1463
+ {
1464
+ question: entry.question,
1465
+ response: entry.answer
1466
+ }
1467
+ ) }) })
1468
+ ] }, messageIndex);
1469
+ }) }) : /* @__PURE__ */ jsx4(Box4, { sx: { p: 2, textAlign: "center", color: theme.palette.text.secondary, borderTop: `1px solid ${theme.palette.divider}` }, children: /* @__PURE__ */ jsx4(Typography2, { variant: "body2", children: "No messages in this conversation yet" }) }) })
1470
+ ]
1471
+ }
1472
+ )
1473
+ },
1474
+ conversation.id
1475
+ );
1476
+ }) })
1477
+ ) : (
1478
+ // Show message history when in local context
1479
+ activeHistory.length === 0 ? /* @__PURE__ */ jsxs2(
1480
+ Box4,
1481
+ {
1482
+ sx: {
1483
+ display: "flex",
1484
+ flexDirection: "column",
1485
+ alignItems: "center",
1486
+ justifyContent: "center",
1487
+ height: "200px",
1488
+ textAlign: "center",
1489
+ color: theme.palette.text.secondary
1490
+ },
1491
+ children: [
1492
+ /* @__PURE__ */ jsx4(HistoryIcon2, { sx: { fontSize: "3rem", mb: 2, opacity: 0.5 } }),
1493
+ /* @__PURE__ */ jsx4(Typography2, { variant: "h6", sx: { mb: 1, fontWeight: 500, color: "text.primary" }, children: "No Session History Yet" }),
1494
+ /* @__PURE__ */ jsx4(Typography2, { variant: "body2", children: "Start a conversation to see your session history here" })
1495
+ ]
1496
+ }
1497
+ ) : filteredHistory.length === 0 ? /* @__PURE__ */ jsxs2(
1498
+ Box4,
1499
+ {
1500
+ sx: {
1501
+ display: "flex",
1502
+ flexDirection: "column",
1503
+ alignItems: "center",
1504
+ justifyContent: "center",
1505
+ height: "200px",
1506
+ textAlign: "center",
1507
+ color: theme.palette.text.secondary
1508
+ },
1509
+ children: [
1510
+ /* @__PURE__ */ jsx4(SearchIcon, { sx: { fontSize: "3rem", mb: 2, opacity: 0.5 } }),
1511
+ /* @__PURE__ */ jsx4(Typography2, { variant: "h6", sx: { mb: 1, fontWeight: 500, color: "text.primary" }, children: "No Results Found" }),
1512
+ /* @__PURE__ */ jsx4(Typography2, { variant: "body2", children: "Try adjusting your search terms" })
1513
+ ]
1514
+ }
1515
+ ) : /* @__PURE__ */ jsx4(List, { sx: { p: 0 }, children: [...filteredHistory].reverse().map((entry, index) => {
1516
+ const isExpanded = expandedItems.has(index);
1517
+ return /* @__PURE__ */ jsx4(React4.Fragment, { children: /* @__PURE__ */ jsx4(
1518
+ ListItem,
1519
+ {
1520
+ sx: {
1521
+ display: "block",
1522
+ p: 0,
1523
+ mb: 2
1524
+ },
1525
+ children: /* @__PURE__ */ jsxs2(
1526
+ Box4,
1527
+ {
1528
+ onClick: () => toggleExpanded(index),
1529
+ sx: {
1530
+ bgcolor: theme.palette.background.default,
1531
+ borderRadius: "12px",
1532
+ border: `1px solid ${theme.palette.divider}`,
1533
+ overflow: "hidden",
1534
+ cursor: "pointer",
1535
+ transition: "all 0.2s ease-in-out",
1536
+ "&:hover": {
1537
+ borderColor: theme.palette.primary.main + "60",
1538
+ boxShadow: `0 4px 12px ${theme.palette.mode === "dark" ? "rgba(0,0,0,0.3)" : "rgba(0,0,0,0.1)"}`,
1539
+ transform: "translateY(-1px)"
1540
+ }
1541
+ },
1542
+ children: [
1543
+ /* @__PURE__ */ jsxs2(Box4, { sx: { p: 2 }, children: [
1544
+ /* @__PURE__ */ jsx4(
1545
+ Typography2,
1546
+ {
1547
+ variant: "body2",
1548
+ sx: {
1549
+ fontWeight: 500,
1550
+ color: theme.palette.text.primary,
1551
+ mb: 1,
1552
+ display: "-webkit-box",
1553
+ WebkitLineClamp: 2,
1554
+ WebkitBoxOrient: "vertical",
1555
+ overflow: "hidden"
1556
+ },
1557
+ children: entry.question
1558
+ }
1559
+ ),
1560
+ /* @__PURE__ */ jsx4(
1561
+ Typography2,
1562
+ {
1563
+ variant: "caption",
1564
+ sx: {
1565
+ color: theme.palette.text.secondary,
1566
+ display: "-webkit-box",
1567
+ WebkitLineClamp: 1,
1568
+ WebkitBoxOrient: "vertical",
1569
+ overflow: "hidden"
1570
+ },
1571
+ children: entry.answer
1572
+ }
1573
+ )
1574
+ ] }),
1575
+ /* @__PURE__ */ jsxs2(Collapse, { in: isExpanded, children: [
1576
+ /* @__PURE__ */ jsx4(Divider, {}),
1577
+ /* @__PURE__ */ jsx4(Box4, { sx: { p: 2 }, children: /* @__PURE__ */ jsx4(
1578
+ ai_response_text_field_default,
1579
+ {
1580
+ question: entry.question,
1581
+ response: entry.answer
1582
+ }
1583
+ ) })
1584
+ ] })
1585
+ ]
1586
+ }
1587
+ )
1588
+ }
1589
+ ) }, index);
1590
+ }) })
1591
+ ))
1592
+ ]
1593
+ }
1594
+ ) })
1595
+ ]
1596
+ }
1597
+ ),
1598
+ /* @__PURE__ */ jsxs2(
1599
+ Dialog,
1600
+ {
1601
+ open: confirmClearOpen,
1602
+ onClose: handleCancelClear,
1603
+ maxWidth: "sm",
1604
+ fullWidth: true,
1605
+ sx: {
1606
+ zIndex: 1500
1607
+ // Higher than drawer (1400)
1608
+ },
1609
+ PaperProps: {
1610
+ sx: {
1611
+ borderRadius: "16px",
1612
+ bgcolor: theme.palette.mode === "dark" ? "rgba(30, 30, 30, 0.95)" : "rgba(255, 255, 255, 0.95)",
1613
+ backdropFilter: "blur(20px)",
1614
+ border: `1px solid ${theme.palette.mode === "dark" ? "rgba(255,255,255,0.12)" : "rgba(0,0,0,0.12)"}`,
1615
+ boxShadow: `0 24px 48px ${theme.palette.mode === "dark" ? "rgba(0,0,0,0.5)" : "rgba(0,0,0,0.15)"}`
1616
+ }
1617
+ },
1618
+ BackdropProps: {
1619
+ sx: {
1620
+ bgcolor: "rgba(0, 0, 0, 0.4)",
1621
+ backdropFilter: "blur(8px)"
1622
+ }
1623
+ },
1624
+ children: [
1625
+ /* @__PURE__ */ jsxs2(
1626
+ DialogTitle,
1627
+ {
1628
+ sx: {
1629
+ pb: 1,
1630
+ fontSize: "1.5rem",
1631
+ fontWeight: 600,
1632
+ color: theme.palette.error.main,
1633
+ display: "flex",
1634
+ alignItems: "center",
1635
+ gap: 1
1636
+ },
1637
+ children: [
1638
+ /* @__PURE__ */ jsx4(DeleteIcon, { sx: { fontSize: "1.75rem" } }),
1639
+ "Clear Chat History"
1640
+ ]
1641
+ }
1642
+ ),
1643
+ /* @__PURE__ */ jsxs2(DialogContent, { sx: { pb: 2 }, children: [
1644
+ /* @__PURE__ */ jsx4(
1645
+ DialogContentText,
1646
+ {
1647
+ sx: {
1648
+ fontSize: "1rem",
1649
+ color: theme.palette.text.primary,
1650
+ mb: 2
1651
+ },
1652
+ children: "Are you sure you want to clear all chat history?"
1653
+ }
1654
+ ),
1655
+ /* @__PURE__ */ jsx4(
1656
+ DialogContentText,
1657
+ {
1658
+ sx: {
1659
+ fontSize: "0.9rem",
1660
+ color: theme.palette.text.secondary,
1661
+ fontStyle: "italic"
1662
+ },
1663
+ children: "This action cannot be undone. All your conversation history will be permanently deleted."
1664
+ }
1665
+ )
1666
+ ] }),
1667
+ /* @__PURE__ */ jsxs2(
1668
+ DialogActions,
1669
+ {
1670
+ sx: {
1671
+ p: 3,
1672
+ pt: 1,
1673
+ gap: 1
1674
+ },
1675
+ children: [
1676
+ /* @__PURE__ */ jsx4(
1677
+ Button,
1678
+ {
1679
+ onClick: handleCancelClear,
1680
+ variant: "outlined",
1681
+ sx: {
1682
+ borderRadius: "12px",
1683
+ textTransform: "none",
1684
+ fontWeight: 600,
1685
+ minWidth: "100px",
1686
+ border: `2px solid ${theme.palette.text.secondary}`,
1687
+ color: theme.palette.text.primary,
1688
+ "&:hover": {
1689
+ border: `2px solid ${theme.palette.text.primary}`,
1690
+ bgcolor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.05)"
1691
+ }
1692
+ },
1693
+ children: "Cancel"
1694
+ }
1695
+ ),
1696
+ /* @__PURE__ */ jsx4(
1697
+ Button,
1698
+ {
1699
+ onClick: handleConfirmClear,
1700
+ variant: "contained",
1701
+ color: "error",
1702
+ sx: {
1703
+ borderRadius: "12px",
1704
+ textTransform: "none",
1705
+ fontWeight: 600,
1706
+ minWidth: "100px",
1707
+ bgcolor: theme.palette.error.main,
1708
+ "&:hover": {
1709
+ bgcolor: theme.palette.error.dark,
1710
+ transform: "translateY(-1px)",
1711
+ boxShadow: `0 6px 20px ${theme.palette.error.main}40`
1712
+ },
1713
+ transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)"
1714
+ },
1715
+ children: "Clear All"
1716
+ }
1717
+ )
1718
+ ]
1719
+ }
1720
+ )
1721
+ ]
1722
+ }
1723
+ ),
1724
+ /* @__PURE__ */ jsxs2(
1725
+ Dialog,
1726
+ {
1727
+ open: infoDialogOpen,
1728
+ onClose: () => setInfoDialogOpen(false),
1729
+ maxWidth: "sm",
1730
+ fullWidth: true,
1731
+ sx: {
1732
+ zIndex: 1500
1733
+ // Higher than drawer (1400)
1734
+ },
1735
+ PaperProps: {
1736
+ sx: {
1737
+ borderRadius: "16px",
1738
+ bgcolor: theme.palette.mode === "dark" ? "rgba(30, 30, 30, 0.95)" : "rgba(255, 255, 255, 0.95)",
1739
+ backdropFilter: "blur(20px)",
1740
+ border: `1px solid ${theme.palette.mode === "dark" ? "rgba(255,255,255,0.12)" : "rgba(0,0,0,0.12)"}`,
1741
+ boxShadow: `0 24px 48px ${theme.palette.mode === "dark" ? "rgba(0,0,0,0.5)" : "rgba(0,0,0,0.15)"}`
1742
+ }
1743
+ },
1744
+ BackdropProps: {
1745
+ sx: {
1746
+ bgcolor: "rgba(0, 0, 0, 0.4)",
1747
+ backdropFilter: "blur(8px)"
1748
+ }
1749
+ },
1750
+ children: [
1751
+ /* @__PURE__ */ jsxs2(
1752
+ DialogTitle,
1753
+ {
1754
+ sx: {
1755
+ pb: 2,
1756
+ fontSize: "1.5rem",
1757
+ fontWeight: 600,
1758
+ color: theme.palette.info.main,
1759
+ display: "flex",
1760
+ alignItems: "center",
1761
+ gap: 1
1762
+ },
1763
+ children: [
1764
+ /* @__PURE__ */ jsx4(InfoOutlinedIcon, { sx: { fontSize: "1.75rem" } }),
1765
+ "About Chat Control Center"
1766
+ ]
1767
+ }
1768
+ ),
1769
+ /* @__PURE__ */ jsxs2(DialogContent, { sx: { pb: 2 }, children: [
1770
+ /* @__PURE__ */ jsx4(
1771
+ DialogContentText,
1772
+ {
1773
+ sx: {
1774
+ fontSize: "1rem",
1775
+ color: theme.palette.text.primary,
1776
+ mb: 2,
1777
+ lineHeight: 1.6
1778
+ },
1779
+ children: "This control center gives you full access to your chat experience and AI capabilities."
1780
+ }
1781
+ ),
1782
+ /* @__PURE__ */ jsxs2(
1783
+ DialogContentText,
1784
+ {
1785
+ sx: {
1786
+ fontSize: "0.95rem",
1787
+ color: theme.palette.text.secondary,
1788
+ mb: 2,
1789
+ lineHeight: 1.6
1790
+ },
1791
+ children: [
1792
+ /* @__PURE__ */ jsx4("strong", { children: "Context Modes:" }),
1793
+ /* @__PURE__ */ jsx4("br", {}),
1794
+ "\u2022 ",
1795
+ /* @__PURE__ */ jsx4("strong", { children: "Session Context" }),
1796
+ ": Local conversation for this modal session only",
1797
+ /* @__PURE__ */ jsx4("br", {}),
1798
+ "\u2022 ",
1799
+ /* @__PURE__ */ jsx4("strong", { children: "Main Conversation" }),
1800
+ ": Your persistent account conversations",
1801
+ /* @__PURE__ */ jsx4("br", {}),
1802
+ "\u2022 Switch between them to access different conversation histories",
1803
+ /* @__PURE__ */ jsx4("br", {}),
1804
+ /* @__PURE__ */ jsx4("br", {}),
1805
+ /* @__PURE__ */ jsx4("strong", { children: "Additional Features:" }),
1806
+ /* @__PURE__ */ jsx4("br", {}),
1807
+ "\u2022 ",
1808
+ /* @__PURE__ */ jsx4("strong", { children: "Voice Models" }),
1809
+ ": Change AI voice when TTS is enabled",
1810
+ /* @__PURE__ */ jsx4("br", {}),
1811
+ "\u2022 ",
1812
+ /* @__PURE__ */ jsx4("strong", { children: "Personal Memory" }),
1813
+ ": Manage what the AI remembers about you",
1814
+ /* @__PURE__ */ jsx4("br", {}),
1815
+ "\u2022 ",
1816
+ /* @__PURE__ */ jsx4("strong", { children: "Search & Organization" }),
1817
+ ": Find specific conversations quickly"
1818
+ ]
1819
+ }
1820
+ ),
1821
+ /* @__PURE__ */ jsxs2(
1822
+ DialogContentText,
1823
+ {
1824
+ sx: {
1825
+ fontSize: "0.9rem",
1826
+ color: theme.palette.info.main,
1827
+ fontStyle: "italic",
1828
+ bgcolor: theme.palette.mode === "dark" ? "rgba(33, 150, 243, 0.1)" : "rgba(33, 150, 243, 0.05)",
1829
+ p: 2,
1830
+ borderRadius: "8px",
1831
+ border: `1px solid ${theme.palette.info.main}30`
1832
+ },
1833
+ children: [
1834
+ "\u{1F4A1} ",
1835
+ /* @__PURE__ */ jsx4("strong", { children: "Pro Tip:" }),
1836
+ " Use Session Context for quick experiments and Main Conversation for important discussions you want to keep. All features respect your privacy settings!"
1837
+ ]
1838
+ }
1839
+ )
1840
+ ] }),
1841
+ /* @__PURE__ */ jsx4(
1842
+ DialogActions,
1843
+ {
1844
+ sx: {
1845
+ p: 3,
1846
+ pt: 1
1847
+ },
1848
+ children: /* @__PURE__ */ jsx4(
1849
+ Button,
1850
+ {
1851
+ onClick: () => setInfoDialogOpen(false),
1852
+ variant: "contained",
1853
+ sx: {
1854
+ borderRadius: "12px",
1855
+ textTransform: "none",
1856
+ fontWeight: 600,
1857
+ minWidth: "100px",
1858
+ bgcolor: theme.palette.info.main,
1859
+ "&:hover": {
1860
+ bgcolor: theme.palette.info.dark,
1861
+ transform: "translateY(-1px)",
1862
+ boxShadow: `0 6px 20px ${theme.palette.info.main}40`
1863
+ },
1864
+ transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)"
1865
+ },
1866
+ children: "Got it!"
1867
+ }
1868
+ )
1869
+ }
1870
+ )
1871
+ ]
1872
+ }
1873
+ ),
1874
+ /* @__PURE__ */ jsx4(
1875
+ memory_modal_default,
1876
+ {
1877
+ open: memoryModalOpen,
1878
+ onClose: () => setMemoryModalOpen(false)
1879
+ }
1880
+ )
1881
+ ]
1882
+ }
1883
+ );
1884
+ };
1885
+ var chat_drawer_default = AIQueriesDrawer;
1886
+
1887
+ // src/shared/generic-loader.tsx
1888
+ import { Box as Box5, CircularProgress, useTheme as useTheme5 } from "@mui/material";
1889
+ import { jsx as jsx5 } from "react/jsx-runtime";
1890
+ var GenericLoader = ({
1891
+ size = 40,
1892
+ color,
1893
+ variant = "spinner"
1894
+ }) => {
1895
+ const theme = useTheme5();
1896
+ const loaderColor = color || theme.palette.primary.main;
1897
+ if (variant === "dots") {
1898
+ return /* @__PURE__ */ jsx5(
1899
+ Box5,
1900
+ {
1901
+ sx: {
1902
+ display: "flex",
1903
+ justifyContent: "center",
1904
+ alignItems: "center",
1905
+ gap: 1,
1906
+ py: 2,
1907
+ "@keyframes bounce": {
1908
+ "0%, 80%, 100%": {
1909
+ transform: "scale(0)"
1910
+ },
1911
+ "40%": {
1912
+ transform: "scale(1.0)"
1913
+ }
1914
+ }
1915
+ },
1916
+ children: [0, 0.15, 0.3].map((delay, index) => /* @__PURE__ */ jsx5(
1917
+ Box5,
1918
+ {
1919
+ sx: {
1920
+ width: 8,
1921
+ height: 8,
1922
+ backgroundColor: loaderColor,
1923
+ borderRadius: "50%",
1924
+ animation: "bounce 1.4s infinite ease-in-out both",
1925
+ animationDelay: `${delay}s`
1926
+ }
1927
+ },
1928
+ index
1929
+ ))
1930
+ }
1931
+ );
1932
+ }
1933
+ if (variant === "pulse") {
1934
+ return /* @__PURE__ */ jsx5(
1935
+ Box5,
1936
+ {
1937
+ sx: {
1938
+ display: "flex",
1939
+ justifyContent: "center",
1940
+ alignItems: "center",
1941
+ py: 2,
1942
+ "@keyframes pulse": {
1943
+ "0%": {
1944
+ transform: "scale(0.9)",
1945
+ opacity: 1
1946
+ },
1947
+ "50%": {
1948
+ transform: "scale(1.1)",
1949
+ opacity: 0.7
1950
+ },
1951
+ "100%": {
1952
+ transform: "scale(0.9)",
1953
+ opacity: 1
1954
+ }
1955
+ }
1956
+ },
1957
+ children: /* @__PURE__ */ jsx5(
1958
+ Box5,
1959
+ {
1960
+ sx: {
1961
+ width: size,
1962
+ height: size,
1963
+ borderRadius: "50%",
1964
+ backgroundColor: loaderColor,
1965
+ animation: "pulse 1.5s infinite ease-in-out"
1966
+ }
1967
+ }
1968
+ )
1969
+ }
1970
+ );
1971
+ }
1972
+ return /* @__PURE__ */ jsx5(
1973
+ Box5,
1974
+ {
1975
+ sx: {
1976
+ display: "flex",
1977
+ justifyContent: "center",
1978
+ alignItems: "center",
1979
+ py: 2
1980
+ },
1981
+ children: /* @__PURE__ */ jsx5(
1982
+ CircularProgress,
1983
+ {
1984
+ size,
1985
+ sx: { color: loaderColor }
1986
+ }
1987
+ )
1988
+ }
1989
+ );
1990
+ };
1991
+ var generic_loader_default = GenericLoader;
1992
+
1993
+ // src/hooks/useAiChat.ts
1994
+ import { useState as useState4, useEffect as useEffect3 } from "react";
1995
+ import { useMediaQuery as useMediaQuery3 } from "@mui/material";
1996
+ var useAIChat = () => {
1997
+ const isMobile = useMediaQuery3((theme) => theme.breakpoints.down("sm"));
1998
+ const provider = useAIProviderStore((state) => state.provider);
1999
+ const SYSTEM_PROMPT = useModelStore((state) => state.systemPrompt);
2000
+ const OLLAMA_MODEL = usePackageSettingsStore((state) => state.settings?.defaultModel || "");
2001
+ const [fullScreen, setFullScreen] = useState4(isMobile);
2002
+ const [drawerOpen, setDrawerOpen] = useState4(false);
2003
+ const [showSettings, setShowSettings] = useState4(false);
2004
+ const [, setAutoFullscreenTriggered] = useState4(false);
2005
+ const {
2006
+ apiKey,
2007
+ inputValue,
2008
+ setApiKey,
2009
+ setInputValue,
2010
+ setResponse,
2011
+ setPreviousQuestion,
2012
+ setComponentStatus,
2013
+ addHistory
2014
+ } = useAIQueryStore();
2015
+ const sendWithAIProvider = () => {
2016
+ if (!provider) {
2017
+ debugLogger.error("No AI provider available for chat");
2018
+ setComponentStatus("Error");
2019
+ return;
2020
+ }
2021
+ let message = "";
2022
+ setComponentStatus("Loading");
2023
+ const stream = provider.chat({
2024
+ model: OLLAMA_MODEL,
2025
+ stream: true,
2026
+ messages: [
2027
+ { role: "system", content: SYSTEM_PROMPT },
2028
+ { role: "user", content: inputValue }
2029
+ ]
2030
+ });
2031
+ stream.subscribe({
2032
+ next: (data) => {
2033
+ message += data.message.content;
2034
+ setResponse(message);
2035
+ },
2036
+ error: (err) => {
2037
+ debugLogger.error("Stream error in AI chat", { error: err });
2038
+ setComponentStatus("Idle");
2039
+ },
2040
+ complete: () => {
2041
+ setComponentStatus("Idle");
2042
+ setPreviousQuestion(inputValue);
2043
+ setResponse(message);
2044
+ addHistory({ question: inputValue, answer: message });
2045
+ setInputValue("");
2046
+ }
2047
+ });
2048
+ };
2049
+ const sendWithOpenAI = async () => {
2050
+ setComponentStatus("Loading");
2051
+ setResponse("");
2052
+ setAutoFullscreenTriggered(false);
2053
+ const history = useAIQueryStore.getState().history;
2054
+ const contextMessages = history.slice(-5).flatMap((entry) => [
2055
+ { role: "user", content: entry.question },
2056
+ { role: "assistant", content: entry.answer }
2057
+ ]);
2058
+ const payload = {
2059
+ model: "gpt-3.5-turbo",
2060
+ messages: [...contextMessages, { role: "user", content: inputValue }],
2061
+ temperature: 0.7
2062
+ };
2063
+ try {
2064
+ const res = await fetch("https://api.openai.com/v1/chat/completions", {
2065
+ method: "POST",
2066
+ headers: {
2067
+ "Content-Type": "application/json",
2068
+ Authorization: `Bearer ${apiKey}`
2069
+ },
2070
+ body: JSON.stringify(payload)
2071
+ });
2072
+ const data = await res.json();
2073
+ const stubbedAnswer = data.choices[0].message.content;
2074
+ setComponentStatus("Idle");
2075
+ setPreviousQuestion(inputValue);
2076
+ setResponse(stubbedAnswer);
2077
+ addHistory({ question: inputValue, answer: stubbedAnswer });
2078
+ setInputValue("");
2079
+ } catch (err) {
2080
+ debugLogger.error("Failed to handle AI chat query", { error: err });
2081
+ setComponentStatus("Idle");
2082
+ }
2083
+ };
2084
+ const handleSend = () => {
2085
+ if (inputValue.trim() === "") return;
2086
+ if (apiKey) {
2087
+ void sendWithOpenAI();
2088
+ return;
2089
+ }
2090
+ sendWithAIProvider();
2091
+ };
2092
+ useEffect3(() => {
2093
+ setFullScreen(isMobile);
2094
+ }, [isMobile]);
2095
+ return {
2096
+ fullScreen,
2097
+ setFullScreen,
2098
+ drawerOpen,
2099
+ setDrawerOpen,
2100
+ showSettings,
2101
+ setShowSettings,
2102
+ handleSend
2103
+ };
2104
+ };
2105
+ var useAiChat_default = useAIChat;
2106
+
2107
+ // src/hooks/useDraggable.ts
2108
+ import { useCallback, useEffect as useEffect4, useRef as useRef2, useState as useState5 } from "react";
2109
+ var useDraggable = () => {
2110
+ const modalRef = useRef2(null);
2111
+ const [dragging, setDragging] = useState5(false);
2112
+ const [offset, setOffset] = useState5({ x: 0, y: 0 });
2113
+ const [position, setPosition] = useState5({ x: 0, y: 0 });
2114
+ const handleHeaderMouseDown = (e) => {
2115
+ const rect = modalRef.current?.getBoundingClientRect();
2116
+ if (rect) {
2117
+ setOffset({ x: e.clientX - rect.left, y: e.clientY - rect.top });
2118
+ setDragging(true);
2119
+ }
2120
+ };
2121
+ const handleHeaderMouseMove = useCallback(
2122
+ (e) => {
2123
+ if (dragging) {
2124
+ setPosition({ x: e.clientX - offset.x, y: e.clientY - offset.y });
2125
+ }
2126
+ },
2127
+ [dragging, offset]
2128
+ );
2129
+ const handleHeaderMouseUp = () => {
2130
+ setDragging(false);
2131
+ };
2132
+ useEffect4(() => {
2133
+ if (dragging) {
2134
+ document.addEventListener("mousemove", handleHeaderMouseMove);
2135
+ document.addEventListener("mouseup", handleHeaderMouseUp);
2136
+ } else {
2137
+ document.removeEventListener("mousemove", handleHeaderMouseMove);
2138
+ document.removeEventListener("mouseup", handleHeaderMouseUp);
2139
+ }
2140
+ return () => {
2141
+ document.removeEventListener("mousemove", handleHeaderMouseMove);
2142
+ document.removeEventListener("mouseup", handleHeaderMouseUp);
2143
+ };
2144
+ }, [dragging, handleHeaderMouseMove]);
2145
+ return {
2146
+ modalRef,
2147
+ position,
2148
+ setPosition,
2149
+ handleDrag: handleHeaderMouseMove,
2150
+ handleHeaderMouseDown
2151
+ };
2152
+ };
2153
+ var useDraggable_default = useDraggable;
2154
+
2155
+ // src/modals/chat-modal/chat-modal.tsx
2156
+ import { Subscription as Subscription2 } from "rxjs";
2157
+ import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
2158
+ var FULL_SCREEN_THRESHOLD = 100;
2159
+ var MIN_WINDOWED_HEIGHT = 400;
2160
+ var MAX_WINDOWED_HEIGHT = 600;
2161
+ var CDN_BASE = "https://cdn.burtson.ai/";
2162
+ var banditHead2 = `${CDN_BASE}/images/bandit-head.png`;
2163
+ var modelAvatars = {
2164
+ "Bandit-Core": `${CDN_BASE}/avatars/core-avatar.png`,
2165
+ "Bandit-Muse": `${CDN_BASE}/avatars/muse-avatar.png`,
2166
+ "Bandit-Logic": `${CDN_BASE}/avatars/logic-avatar.png`,
2167
+ "Bandit-D1VA": `${CDN_BASE}/avatars/d1va-avatar.png`,
2168
+ "Bandit-Exec": `${CDN_BASE}/avatars/exec-avatar.png`
2169
+ };
2170
+ var useOptionalNavigate = () => {
2171
+ const hasLoggedRef = useRef3(false);
2172
+ try {
2173
+ return useNavigate();
2174
+ } catch (error) {
2175
+ if (!hasLoggedRef.current) {
2176
+ debugLogger.debug("Navigation not available in ChatModal context", { error });
2177
+ hasLoggedRef.current = true;
2178
+ }
2179
+ return null;
2180
+ }
2181
+ };
2182
+ var ChatModal = ({
2183
+ open,
2184
+ onClose
2185
+ }) => {
2186
+ const navigate = useOptionalNavigate();
2187
+ const getOptimalLogo = async () => {
2188
+ const banditAiLogo = "https://cdn.burtson.ai/logos/bandit-ai-logo.png";
2189
+ try {
2190
+ const branding = await brandingService_default.getBranding();
2191
+ if (branding?.logoBase64) {
2192
+ return branding.logoBase64;
2193
+ }
2194
+ return banditAiLogo;
2195
+ } catch (error) {
2196
+ debugLogger.error("Failed to get optimal logo", { error });
2197
+ return banditAiLogo;
2198
+ }
2199
+ };
2200
+ const {
2201
+ inputValue,
2202
+ response,
2203
+ previousQuestion,
2204
+ componentStatus,
2205
+ apiKey,
2206
+ history,
2207
+ setInputValue,
2208
+ setApiKey
2209
+ } = useAIQueryStore();
2210
+ const {
2211
+ fullScreen,
2212
+ setFullScreen,
2213
+ drawerOpen,
2214
+ setDrawerOpen,
2215
+ showSettings,
2216
+ setShowSettings,
2217
+ handleSend
2218
+ } = useAiChat_default();
2219
+ const { modalRef, position, setPosition, handleDrag, handleHeaderMouseDown } = useDraggable_default();
2220
+ const [pastedImages, setPastedImages] = useState6([]);
2221
+ const [responseStarted, setResponseStarted] = useState6(false);
2222
+ const [modalLogo, setModalLogo] = useState6("https://cdn.burtson.ai/logos/bandit-ai-logo.png");
2223
+ const [modelAnchorEl, setModelAnchorEl] = useState6(null);
2224
+ const [voiceAnchorEl, setVoiceAnchorEl] = useState6(null);
2225
+ const [audioSub, setAudioSub] = useState6(new Subscription2());
2226
+ const [selectedTheme, setSelectedTheme] = useState6(null);
2227
+ const [themeLoading, setThemeLoading] = useState6(true);
2228
+ const [autoFullscreenTriggered, setAutoFullscreenTriggered] = useState6(false);
2229
+ const [userHasDragged, setUserHasDragged] = useState6(false);
2230
+ const [manualFullscreenToggleTime, setManualFullscreenToggleTime] = useState6(0);
2231
+ const handleExitFullscreen = () => {
2232
+ setPosition({
2233
+ x: Math.max(0, window.innerWidth / 2 - 300),
2234
+ y: Math.max(0, window.innerHeight / 2 - 300)
2235
+ });
2236
+ setUserHasDragged(false);
2237
+ };
2238
+ const handleCustomDrag = (e) => {
2239
+ handleDrag(e);
2240
+ setUserHasDragged(true);
2241
+ };
2242
+ const activeTheme = themeMap_default[selectedTheme ?? "bandit-dark"] || banditDarkTheme;
2243
+ const { availableModels, selectedModel, setSelectedModel } = useModelStore();
2244
+ const SYSTEM_PROMPT = useModelStore((state) => state.systemPrompt);
2245
+ const { availableVoices, selectedVoice, setSelectedVoice } = useVoiceStore();
2246
+ const { speak: ttsSpeak, stop: ttsStop, isAvailable: isTTSAvailable } = useTTS();
2247
+ const { preferences } = usePreferencesStore();
2248
+ const { settings: packageSettings } = usePackageSettingsStore();
2249
+ const provider = useAIProviderStore((state) => state.provider);
2250
+ const notificationService = useNotificationService();
2251
+ const currentModel = availableModels.find((m) => m.name === selectedModel);
2252
+ const currentAvatar = currentModel?.avatarBase64 || modelAvatars[selectedModel] || banditHead2;
2253
+ const removeImage = (index) => {
2254
+ setPastedImages((prev) => prev.filter((_, i) => i !== index));
2255
+ };
2256
+ const handleVoiceChange = async (newVoice) => {
2257
+ ttsStop();
2258
+ setSelectedVoice(newVoice);
2259
+ await new Promise((resolve) => setTimeout(resolve, 50));
2260
+ const voiceName = newVoice.split("-")[1];
2261
+ const defaultModel = packageSettings?.defaultModel;
2262
+ const currentModelConfig = availableModels.find((m) => m.name === selectedModel);
2263
+ const personalityName = currentModelConfig ? currentModelConfig.name.replace("Bandit-", "Bandit ") : selectedModel || defaultModel || "Bandit";
2264
+ if (isTTSAvailable) {
2265
+ try {
2266
+ const greetingText = `Hi, I'm ${personalityName} speaking with ${voiceName}'s voice.`;
2267
+ await ttsSpeak(greetingText, { useStreaming: true });
2268
+ } catch (ttsError) {
2269
+ debugLogger.error("TTS failed for voice greeting:", { error: ttsError instanceof Error ? ttsError.message : String(ttsError) });
2270
+ }
2271
+ }
2272
+ };
2273
+ const toTitleCase2 = (str) => {
2274
+ return str.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase());
2275
+ };
2276
+ useEffect5(() => {
2277
+ if (!SYSTEM_PROMPT) {
2278
+ const defaultModel = availableModels.length > 0 ? availableModels[0] : null;
2279
+ if (defaultModel) {
2280
+ setSelectedModel(defaultModel.name);
2281
+ }
2282
+ }
2283
+ }, [SYSTEM_PROMPT, availableModels, setSelectedModel]);
2284
+ useEffect5(() => {
2285
+ return () => {
2286
+ audioSub.unsubscribe();
2287
+ };
2288
+ }, [audioSub]);
2289
+ useEffect5(() => {
2290
+ if (open) {
2291
+ setPosition({
2292
+ x: Math.max(0, window.innerWidth / 2 - 300),
2293
+ y: Math.max(0, window.innerHeight / 2 - 300)
2294
+ });
2295
+ setAutoFullscreenTriggered(false);
2296
+ setUserHasDragged(false);
2297
+ setManualFullscreenToggleTime(0);
2298
+ getOptimalLogo().then(setModalLogo);
2299
+ }
2300
+ }, [open, setPosition]);
2301
+ useEffect5(() => {
2302
+ if (!open) return;
2303
+ const fetchTheme = async () => {
2304
+ try {
2305
+ const config = await indexedDBService_default.get(
2306
+ "banditConfig",
2307
+ 1,
2308
+ "config",
2309
+ "main",
2310
+ [{ name: "config", keyPath: "id" }]
2311
+ );
2312
+ if (config?.branding?.theme) {
2313
+ setSelectedTheme(config.branding.theme);
2314
+ } else {
2315
+ setSelectedTheme("bandit-dark");
2316
+ }
2317
+ } catch (err) {
2318
+ debugLogger.error("Failed to load theme from IndexedDB:", { error: err });
2319
+ setSelectedTheme("bandit-dark");
2320
+ } finally {
2321
+ setThemeLoading(false);
2322
+ }
2323
+ };
2324
+ fetchTheme();
2325
+ const handleThemeChange = () => {
2326
+ if (open) {
2327
+ fetchTheme();
2328
+ }
2329
+ };
2330
+ window.addEventListener("bandit-theme-changed", handleThemeChange);
2331
+ return () => {
2332
+ window.removeEventListener("bandit-theme-changed", handleThemeChange);
2333
+ };
2334
+ }, [open]);
2335
+ useLayoutEffect(() => {
2336
+ const timeSinceManualToggle = Date.now() - manualFullscreenToggleTime;
2337
+ const manualToggleRecentlyUsed = timeSinceManualToggle < 5e3;
2338
+ if (modalRef.current && response && !fullScreen && !autoFullscreenTriggered && !manualToggleRecentlyUsed) {
2339
+ const modal = modalRef.current;
2340
+ requestAnimationFrame(() => {
2341
+ if (!modal) return;
2342
+ const modalHeight = modal.scrollHeight;
2343
+ const viewportHeight = window.innerHeight;
2344
+ const maxAllowedHeight = viewportHeight * 0.75;
2345
+ if (modalHeight > maxAllowedHeight + FULL_SCREEN_THRESHOLD) {
2346
+ setFullScreen(true);
2347
+ setAutoFullscreenTriggered(true);
2348
+ }
2349
+ });
2350
+ }
2351
+ }, [
2352
+ response,
2353
+ fullScreen,
2354
+ autoFullscreenTriggered,
2355
+ manualFullscreenToggleTime,
2356
+ modalRef,
2357
+ setFullScreen,
2358
+ setAutoFullscreenTriggered
2359
+ ]);
2360
+ useEffect5(() => {
2361
+ const handlePaste = (e) => {
2362
+ const items = e.clipboardData?.items;
2363
+ if (items) {
2364
+ for (const item of items) {
2365
+ if (item.type.startsWith("image/")) {
2366
+ const file = item.getAsFile();
2367
+ if (file) {
2368
+ const reader = new FileReader();
2369
+ reader.onload = (event) => {
2370
+ if (event.target?.result) {
2371
+ setPastedImages((prev) => [...prev, event.target.result]);
2372
+ }
2373
+ };
2374
+ reader.readAsDataURL(file);
2375
+ }
2376
+ }
2377
+ }
2378
+ }
2379
+ };
2380
+ document.addEventListener("paste", handlePaste);
2381
+ return () => {
2382
+ document.removeEventListener("paste", handlePaste);
2383
+ };
2384
+ }, []);
2385
+ useEffect5(() => {
2386
+ if (response && !responseStarted) {
2387
+ setResponseStarted(true);
2388
+ }
2389
+ }, [response, responseStarted]);
2390
+ const handleDrawerClose = () => setDrawerOpen(false);
2391
+ const handleClose = () => {
2392
+ const isMobile = window.innerWidth < 600;
2393
+ if (!isMobile) {
2394
+ setFullScreen(false);
2395
+ }
2396
+ setAutoFullscreenTriggered(false);
2397
+ setThemeLoading(true);
2398
+ onClose();
2399
+ };
2400
+ const onSend = (e, value) => {
2401
+ setResponseStarted(false);
2402
+ handleSend();
2403
+ };
2404
+ if (themeLoading) {
2405
+ return null;
2406
+ }
2407
+ return /* @__PURE__ */ jsx6(ThemeProvider, { theme: activeTheme, children: /* @__PURE__ */ jsx6(Modal, { open, onClose: handleClose, children: /* @__PURE__ */ jsxs3(
2408
+ draggable_box_default,
2409
+ {
2410
+ ref: modalRef,
2411
+ position,
2412
+ setPosition,
2413
+ fullScreen,
2414
+ onDrag: handleCustomDrag,
2415
+ children: [
2416
+ /* @__PURE__ */ jsx6(
2417
+ modal_header_default,
2418
+ {
2419
+ fullScreen,
2420
+ setFullScreen,
2421
+ onClose: handleClose,
2422
+ onDrawerOpen: () => setDrawerOpen(true),
2423
+ onMouseDown: handleHeaderMouseDown,
2424
+ logo: modalLogo,
2425
+ historyCount: history.length,
2426
+ onManualFullscreenToggle: () => {
2427
+ setAutoFullscreenTriggered(false);
2428
+ setManualFullscreenToggleTime(Date.now());
2429
+ },
2430
+ onExitFullscreen: handleExitFullscreen
2431
+ }
2432
+ ),
2433
+ /* @__PURE__ */ jsx6(
2434
+ Box6,
2435
+ {
2436
+ sx: {
2437
+ flex: 1,
2438
+ display: "flex",
2439
+ flexDirection: "column",
2440
+ overflow: "hidden",
2441
+ // Let child handle scrolling
2442
+ minHeight: 0
2443
+ // Important for flex scrolling
2444
+ },
2445
+ children: /* @__PURE__ */ jsxs3(
2446
+ Box6,
2447
+ {
2448
+ sx: {
2449
+ flex: 1,
2450
+ overflow: "auto",
2451
+ // Enable scrolling here
2452
+ display: "flex",
2453
+ flexDirection: "column",
2454
+ gap: 2,
2455
+ // Ensure proper height calculation for both fullscreen and windowed
2456
+ height: fullScreen ? "auto" : "100%",
2457
+ maxHeight: fullScreen ? "none" : "100%",
2458
+ // Custom scrollbar styling
2459
+ "&::-webkit-scrollbar": {
2460
+ width: "8px"
2461
+ },
2462
+ "&::-webkit-scrollbar-track": {
2463
+ background: activeTheme.palette.mode === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.05)",
2464
+ borderRadius: "4px"
2465
+ },
2466
+ "&::-webkit-scrollbar-thumb": {
2467
+ background: activeTheme.palette.mode === "dark" ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.2)",
2468
+ borderRadius: "4px",
2469
+ "&:hover": {
2470
+ background: activeTheme.palette.mode === "dark" ? "rgba(255,255,255,0.3)" : "rgba(0,0,0,0.3)"
2471
+ }
2472
+ }
2473
+ },
2474
+ children: [
2475
+ /* @__PURE__ */ jsx6(
2476
+ query_input_default,
2477
+ {
2478
+ inputValue,
2479
+ onChange: setInputValue,
2480
+ onSend,
2481
+ apiKey,
2482
+ showSettings,
2483
+ setShowSettings,
2484
+ setApiKey,
2485
+ startAdornment: /* @__PURE__ */ jsxs3(InputAdornment3, { position: "start", sx: { gap: 1 }, children: [
2486
+ /* @__PURE__ */ jsx6(Tooltip4, { title: `Current AI: ${selectedModel.replace("Bandit-", "")}`, arrow: true, children: /* @__PURE__ */ jsx6(
2487
+ IconButton4,
2488
+ {
2489
+ onClick: (e) => setModelAnchorEl(e.currentTarget),
2490
+ sx: {
2491
+ p: 0.5,
2492
+ borderRadius: "8px",
2493
+ transition: "all 0.2s ease-in-out",
2494
+ "&:hover": {
2495
+ backgroundColor: activeTheme.palette.action.hover,
2496
+ transform: "scale(1.05)"
2497
+ }
2498
+ },
2499
+ children: /* @__PURE__ */ jsx6(
2500
+ Avatar2,
2501
+ {
2502
+ src: currentAvatar,
2503
+ alt: selectedModel,
2504
+ sx: {
2505
+ width: 32,
2506
+ height: 32,
2507
+ filter: "brightness(1.7)",
2508
+ border: `2px solid ${activeTheme.palette.primary.main}30`,
2509
+ transition: "all 0.2s ease-in-out"
2510
+ }
2511
+ }
2512
+ )
2513
+ }
2514
+ ) }),
2515
+ /* @__PURE__ */ jsx6(
2516
+ Menu,
2517
+ {
2518
+ anchorEl: modelAnchorEl,
2519
+ open: Boolean(modelAnchorEl),
2520
+ onClose: () => setModelAnchorEl(null),
2521
+ transformOrigin: { horizontal: "left", vertical: "top" },
2522
+ anchorOrigin: { horizontal: "left", vertical: "bottom" },
2523
+ PaperProps: {
2524
+ sx: {
2525
+ bgcolor: activeTheme.palette.background.paper,
2526
+ color: activeTheme.palette.text.primary,
2527
+ fontSize: "0.875rem",
2528
+ zIndex: 2e4,
2529
+ maxHeight: 300,
2530
+ minWidth: 200,
2531
+ border: `1px solid ${activeTheme.palette.divider}`,
2532
+ borderRadius: "12px",
2533
+ boxShadow: activeTheme.palette.mode === "dark" ? "0 8px 32px rgba(0,0,0,0.5)" : "0 8px 32px rgba(0,0,0,0.2)",
2534
+ "& .MuiMenuItem-root": {
2535
+ borderRadius: "8px",
2536
+ margin: "4px 8px",
2537
+ transition: "all 0.15s ease-in-out",
2538
+ "&:hover": {
2539
+ bgcolor: activeTheme.palette.mode === "dark" ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.04)",
2540
+ transform: "translateX(2px)"
2541
+ },
2542
+ "&.Mui-selected": {
2543
+ bgcolor: activeTheme.palette.primary.main + "20",
2544
+ color: activeTheme.palette.primary.main,
2545
+ "&:hover": {
2546
+ bgcolor: activeTheme.palette.primary.main + "30"
2547
+ }
2548
+ }
2549
+ }
2550
+ }
2551
+ },
2552
+ children: availableModels.map((model) => /* @__PURE__ */ jsxs3(
2553
+ MenuItem2,
2554
+ {
2555
+ selected: model.name === selectedModel,
2556
+ onClick: () => {
2557
+ setSelectedModel(model.name);
2558
+ useModelStore.getState().setSelectedModel(model.name);
2559
+ setModelAnchorEl(null);
2560
+ },
2561
+ sx: {
2562
+ display: "flex",
2563
+ alignItems: "center",
2564
+ gap: 1.5,
2565
+ minHeight: 48,
2566
+ px: 2
2567
+ },
2568
+ children: [
2569
+ /* @__PURE__ */ jsx6(
2570
+ Avatar2,
2571
+ {
2572
+ src: model.avatarBase64 || modelAvatars[model.name] || banditHead2,
2573
+ alt: model.name,
2574
+ sx: {
2575
+ width: 28,
2576
+ height: 28,
2577
+ filter: "brightness(1.7)",
2578
+ transition: "all 0.2s ease-in-out"
2579
+ }
2580
+ }
2581
+ ),
2582
+ /* @__PURE__ */ jsxs3(Box6, { sx: { flex: 1 }, children: [
2583
+ /* @__PURE__ */ jsx6(Typography3, { variant: "body2", sx: { fontWeight: 500 }, children: model.name.replace("Bandit-", "") }),
2584
+ /* @__PURE__ */ jsx6(Typography3, { variant: "caption", sx: { color: activeTheme.palette.text.secondary }, children: model.name === selectedModel ? "Currently active" : "Switch to this AI" })
2585
+ ] }),
2586
+ model.name === selectedModel && /* @__PURE__ */ jsx6(
2587
+ Box6,
2588
+ {
2589
+ sx: {
2590
+ width: 8,
2591
+ height: 8,
2592
+ borderRadius: "50%",
2593
+ bgcolor: activeTheme.palette.primary.main
2594
+ }
2595
+ }
2596
+ )
2597
+ ]
2598
+ },
2599
+ model.name
2600
+ ))
2601
+ }
2602
+ ),
2603
+ isTTSAvailable && /* @__PURE__ */ jsxs3(Fragment2, { children: [
2604
+ /* @__PURE__ */ jsx6(Tooltip4, { title: `Voice: ${selectedVoice ? toTitleCase2(selectedVoice.split("-")[1]) : "Default"}`, arrow: true, children: /* @__PURE__ */ jsx6(
2605
+ IconButton4,
2606
+ {
2607
+ onClick: (e) => setVoiceAnchorEl(e.currentTarget),
2608
+ sx: {
2609
+ p: 0.5,
2610
+ borderRadius: "8px",
2611
+ bgcolor: activeTheme.palette.info.main + "20",
2612
+ color: activeTheme.palette.info.main,
2613
+ transition: "all 0.2s ease-in-out",
2614
+ "&:hover": {
2615
+ backgroundColor: activeTheme.palette.info.main + "30",
2616
+ transform: "scale(1.05)"
2617
+ }
2618
+ },
2619
+ "aria-label": `Change voice. Currently using ${selectedVoice ? toTitleCase2(selectedVoice.split("-")[1]) : "default"}`,
2620
+ children: /* @__PURE__ */ jsx6(RecordVoiceOverIcon2, { fontSize: "small" })
2621
+ }
2622
+ ) }),
2623
+ /* @__PURE__ */ jsx6(
2624
+ Menu,
2625
+ {
2626
+ anchorEl: voiceAnchorEl,
2627
+ open: Boolean(voiceAnchorEl),
2628
+ onClose: () => setVoiceAnchorEl(null),
2629
+ transformOrigin: { horizontal: "left", vertical: "top" },
2630
+ anchorOrigin: { horizontal: "left", vertical: "bottom" },
2631
+ PaperProps: {
2632
+ sx: {
2633
+ bgcolor: activeTheme.palette.background.paper,
2634
+ color: activeTheme.palette.text.primary,
2635
+ fontSize: "0.875rem",
2636
+ zIndex: 2e4,
2637
+ borderRadius: 2,
2638
+ border: `1px solid ${activeTheme.palette.divider}`,
2639
+ boxShadow: activeTheme.palette.mode === "dark" ? "0 8px 32px rgba(0,0,0,0.5)" : "0 8px 32px rgba(0,0,0,0.2)",
2640
+ "& .MuiMenuItem-root": {
2641
+ borderRadius: "8px",
2642
+ margin: "4px 8px",
2643
+ transition: "all 0.15s ease-in-out",
2644
+ "&:hover": {
2645
+ bgcolor: activeTheme.palette.mode === "dark" ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.04)"
2646
+ },
2647
+ "&.Mui-selected": {
2648
+ bgcolor: activeTheme.palette.info.main + "20",
2649
+ color: activeTheme.palette.info.main,
2650
+ "&:hover": {
2651
+ bgcolor: activeTheme.palette.info.main + "30"
2652
+ }
2653
+ }
2654
+ }
2655
+ }
2656
+ },
2657
+ children: availableVoices.length > 0 ? availableVoices.map((voice) => /* @__PURE__ */ jsx6(
2658
+ MenuItem2,
2659
+ {
2660
+ selected: voice === selectedVoice,
2661
+ onClick: () => {
2662
+ handleVoiceChange(voice);
2663
+ setVoiceAnchorEl(null);
2664
+ },
2665
+ children: /* @__PURE__ */ jsxs3(Box6, { sx: { display: "flex", alignItems: "center", gap: 1, width: "100%" }, children: [
2666
+ /* @__PURE__ */ jsx6(RecordVoiceOverIcon2, { fontSize: "small", sx: { color: activeTheme.palette.text.secondary } }),
2667
+ /* @__PURE__ */ jsxs3(Box6, { sx: { flex: 1 }, children: [
2668
+ /* @__PURE__ */ jsx6(Typography3, { variant: "body2", children: toTitleCase2(voice.split("-")[1]) }),
2669
+ /* @__PURE__ */ jsx6(Typography3, { variant: "caption", sx: { color: activeTheme.palette.text.secondary }, children: voice === selectedVoice ? "Currently active" : "Switch to this voice" })
2670
+ ] }),
2671
+ voice === selectedVoice && /* @__PURE__ */ jsx6(
2672
+ Box6,
2673
+ {
2674
+ sx: {
2675
+ width: 8,
2676
+ height: 8,
2677
+ borderRadius: "50%",
2678
+ bgcolor: activeTheme.palette.info.main
2679
+ }
2680
+ }
2681
+ )
2682
+ ] })
2683
+ },
2684
+ voice
2685
+ )) : /* @__PURE__ */ jsx6(MenuItem2, { disabled: true, children: /* @__PURE__ */ jsx6(Typography3, { variant: "body2", color: "text.secondary", children: "No voices available" }) })
2686
+ }
2687
+ )
2688
+ ] }),
2689
+ pastedImages.map((img, idx) => /* @__PURE__ */ jsxs3(
2690
+ Box6,
2691
+ {
2692
+ sx: {
2693
+ position: "relative",
2694
+ transition: "all 0.15s ease-out",
2695
+ "&:hover": {
2696
+ // Removed transform to prevent jitter
2697
+ }
2698
+ },
2699
+ children: [
2700
+ /* @__PURE__ */ jsx6(
2701
+ Avatar2,
2702
+ {
2703
+ src: img,
2704
+ variant: "rounded",
2705
+ sx: {
2706
+ width: 32,
2707
+ height: 32,
2708
+ borderRadius: "8px",
2709
+ border: `2px solid ${activeTheme.palette.primary.main}30`,
2710
+ cursor: "pointer"
2711
+ }
2712
+ }
2713
+ ),
2714
+ /* @__PURE__ */ jsx6(Tooltip4, { title: "Remove image", arrow: true, children: /* @__PURE__ */ jsx6(
2715
+ IconButton4,
2716
+ {
2717
+ size: "small",
2718
+ onClick: () => removeImage(idx),
2719
+ sx: {
2720
+ position: "absolute",
2721
+ top: -8,
2722
+ right: -8,
2723
+ width: 20,
2724
+ height: 20,
2725
+ bgcolor: activeTheme.palette.error.main,
2726
+ color: "white",
2727
+ border: `2px solid ${activeTheme.palette.background.paper}`,
2728
+ transition: "all 0.15s ease-out",
2729
+ "&:hover": {
2730
+ bgcolor: activeTheme.palette.error.dark
2731
+ // Removed transform to prevent jitter
2732
+ }
2733
+ },
2734
+ children: /* @__PURE__ */ jsx6(CloseIcon3, { sx: { fontSize: 12 } })
2735
+ }
2736
+ ) })
2737
+ ]
2738
+ },
2739
+ idx
2740
+ ))
2741
+ ] }),
2742
+ endAdornment: /* @__PURE__ */ jsxs3(InputAdornment3, { position: "end", sx: { gap: 1 }, children: [
2743
+ preferences.feedbackEnabled && /* @__PURE__ */ jsx6(
2744
+ FeedbackButton,
2745
+ {
2746
+ inline: true,
2747
+ size: "small",
2748
+ buttonText: ""
2749
+ }
2750
+ ),
2751
+ /* @__PURE__ */ jsx6(Tooltip4, { title: inputValue.trim() === "" ? "Type a message first" : "Send Message", arrow: true, children: /* @__PURE__ */ jsx6("span", { children: /* @__PURE__ */ jsx6(
2752
+ IconButton4,
2753
+ {
2754
+ onClick: handleSend,
2755
+ disabled: inputValue.trim() === "",
2756
+ sx: {
2757
+ color: inputValue.trim() !== "" ? activeTheme.palette.primary.main : activeTheme.palette.action.disabled,
2758
+ transition: "all 0.15s ease-out",
2759
+ borderRadius: "8px",
2760
+ minWidth: "40px",
2761
+ minHeight: "40px",
2762
+ "&:hover": {
2763
+ bgcolor: inputValue.trim() !== "" ? activeTheme.palette.primary.main + "15" : "transparent"
2764
+ // Removed transform to prevent jitter
2765
+ },
2766
+ "&:active": {
2767
+ bgcolor: inputValue.trim() !== "" ? activeTheme.palette.primary.main + "25" : "transparent"
2768
+ },
2769
+ "&:disabled": {
2770
+ color: activeTheme.palette.action.disabled
2771
+ }
2772
+ },
2773
+ children: /* @__PURE__ */ jsx6(SendIcon, {})
2774
+ }
2775
+ ) }) })
2776
+ ] })
2777
+ }
2778
+ ),
2779
+ !responseStarted && componentStatus === "Loading" && /* @__PURE__ */ jsx6(generic_loader_default, { variant: "dots" }),
2780
+ responseStarted && response && !showSettings && /* @__PURE__ */ jsx6(ai_response_text_field_default, { question: previousQuestion, response })
2781
+ ]
2782
+ }
2783
+ )
2784
+ }
2785
+ ),
2786
+ /* @__PURE__ */ jsx6(
2787
+ chat_drawer_default,
2788
+ {
2789
+ drawerOpen,
2790
+ onClose: handleDrawerClose,
2791
+ onClearComplete: handleClose,
2792
+ onNavigateToMain: navigate ? () => {
2793
+ onClose();
2794
+ navigate("/chat");
2795
+ } : void 0
2796
+ }
2797
+ )
2798
+ ]
2799
+ }
2800
+ ) }) });
2801
+ };
2802
+ var chat_modal_default = ChatModal;
2803
+
2804
+ export {
2805
+ FULL_SCREEN_THRESHOLD,
2806
+ MIN_WINDOWED_HEIGHT,
2807
+ MAX_WINDOWED_HEIGHT,
2808
+ chat_modal_default
2809
+ };
2810
+ //# sourceMappingURL=chunk-L7UOQ2Y2.mjs.map