@burtson-labs/bandit-engine 2.0.168 → 2.1.0

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