@adminide-stack/yantra-mobile 12.0.28-alpha.7 → 12.0.28-alpha.72

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 (75) hide show
  1. package/lib/api/stt.js +54 -0
  2. package/lib/api/stt.js.map +1 -0
  3. package/lib/assets/icon.png +0 -0
  4. package/lib/components/CustomDrawer.js +479 -0
  5. package/lib/components/CustomDrawer.js.map +1 -0
  6. package/lib/components/GatewayConnector/GatewayConnector.js +18 -0
  7. package/lib/components/GatewayConnector/GatewayConnector.js.map +1 -0
  8. package/lib/components/GatewayToolbarButtonMobile.js +84 -0
  9. package/lib/components/GatewayToolbarButtonMobile.js.map +1 -0
  10. package/lib/components/NavigationHeader/NavigationHeader.js +214 -0
  11. package/lib/components/NavigationHeader/NavigationHeader.js.map +1 -0
  12. package/lib/components/ThinkingIndicator.js +55 -0
  13. package/lib/components/ThinkingIndicator.js.map +1 -0
  14. package/lib/components/YantraBrandLoader.js +94 -0
  15. package/lib/components/YantraBrandLoader.js.map +1 -0
  16. package/lib/compute.js +114 -5
  17. package/lib/compute.js.map +1 -1
  18. package/lib/config/constants.js +16 -0
  19. package/lib/config/constants.js.map +1 -0
  20. package/lib/config/env-config.js +74 -19
  21. package/lib/config/env-config.js.map +1 -1
  22. package/lib/contexts/CdecliConnectionContext.js +47 -0
  23. package/lib/contexts/CdecliConnectionContext.js.map +1 -0
  24. package/lib/contexts/GatewayContext.js +77 -0
  25. package/lib/contexts/GatewayContext.js.map +1 -0
  26. package/lib/features/audio-input/AudioRecorderPanel.js +224 -0
  27. package/lib/features/audio-input/AudioRecorderPanel.js.map +1 -0
  28. package/lib/features/audio-input/MicErrorBoundary.js +34 -0
  29. package/lib/features/audio-input/MicErrorBoundary.js.map +1 -0
  30. package/lib/graphql/agentGatewayDocuments.js +53 -0
  31. package/lib/graphql/agentGatewayDocuments.js.map +1 -0
  32. package/lib/hooks/useCdecliAutoConnect.js +242 -0
  33. package/lib/hooks/useCdecliAutoConnect.js.map +1 -0
  34. package/lib/hooks/useCdecliChannel.js +226 -0
  35. package/lib/hooks/useCdecliChannel.js.map +1 -0
  36. package/lib/hooks/useChatApi.js +338 -171
  37. package/lib/hooks/useChatApi.js.map +1 -1
  38. package/lib/hooks/useChatStream.js +281 -64
  39. package/lib/hooks/useChatStream.js.map +1 -1
  40. package/lib/hooks/useGatewayConnection.js +123 -0
  41. package/lib/hooks/useGatewayConnection.js.map +1 -0
  42. package/lib/hooks/useGatewayRegistry.js +28 -0
  43. package/lib/hooks/useGatewayRegistry.js.map +1 -0
  44. package/lib/hooks/usePrerequisiteIds.js +181 -0
  45. package/lib/hooks/usePrerequisiteIds.js.map +1 -0
  46. package/lib/hooks/useWorkspaceProvisioner.js +236 -0
  47. package/lib/hooks/useWorkspaceProvisioner.js.map +1 -0
  48. package/lib/index.js +1 -1
  49. package/lib/index.js.map +1 -1
  50. package/lib/routes.json +120 -5
  51. package/lib/screens/Chat/index.js +404 -0
  52. package/lib/screens/Chat/index.js.map +1 -0
  53. package/lib/screens/ChatHistory/index.js +56 -0
  54. package/lib/screens/ChatHistory/index.js.map +1 -0
  55. package/lib/screens/Home/HomeScreen.js +397 -143
  56. package/lib/screens/Home/HomeScreen.js.map +1 -1
  57. package/lib/screens/Home/components/ChatHistoryLanding.js +487 -0
  58. package/lib/screens/Home/components/ChatHistoryLanding.js.map +1 -0
  59. package/lib/screens/Home/components/DeepSearchModal.js +349 -0
  60. package/lib/screens/Home/components/DeepSearchModal.js.map +1 -0
  61. package/lib/screens/Home/deepSearchUtils.js +41 -0
  62. package/lib/screens/Home/deepSearchUtils.js.map +1 -0
  63. package/lib/screens/NewChat/index.js +79 -0
  64. package/lib/screens/NewChat/index.js.map +1 -0
  65. package/lib/services/agentSessionManager.js +451 -0
  66. package/lib/services/agentSessionManager.js.map +1 -0
  67. package/lib/services/gatewayApiKeyBridge.js +4 -0
  68. package/lib/services/gatewayApiKeyBridge.js.map +1 -0
  69. package/lib/services/gatewayClient.js +470 -0
  70. package/lib/services/gatewayClient.js.map +1 -0
  71. package/lib/theme/mobileTokens.js +18 -0
  72. package/lib/theme/mobileTokens.js.map +1 -0
  73. package/lib/utils/gatewaySelectionStorage.js +21 -0
  74. package/lib/utils/gatewaySelectionStorage.js.map +1 -0
  75. package/package.json +7 -3
@@ -1,4 +1,4 @@
1
- import {jsx,jsxs}from'react/jsx-runtime';import {useState,useCallback,useEffect}from'react';import {Pressable,StyleSheet}from'react-native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {getDefaultLeftItems,getDefaultRightItems,Box,Text,InputToolBar}from'@admin-layout/gluestack-ui-mobile';import {SafeAreaView}from'react-native-safe-area-context';import {useGetAccountChatSessionsQuery}from'common/graphql';import {v4}from'uuid';import {useNavigation}from'@react-navigation/native';import {MessagesContainerUI}from'@messenger-box/platform-mobile';import {useChatMutations}from'../../hooks/useChatApi.js';import {useChatStream}from'../../hooks/useChatStream.js';var __defProp = Object.defineProperty;
1
+ import {jsx,jsxs}from'react/jsx-runtime';import React,{useRef,useState,useMemo,useEffect,useCallback}from'react';import {useWindowDimensions,useColorScheme,Platform,Keyboard,TouchableWithoutFeedback,View,StyleSheet,Pressable}from'react-native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {getDefaultLeftItems,getDefaultRightItems,Box,Text,InputToolBar}from'@admin-layout/gluestack-ui-mobile';import {useSafeAreaInsets,SafeAreaView}from'react-native-safe-area-context';import {useNavigation,useRoute,CommonActions}from'@react-navigation/native';import {v4}from'uuid';import {ContributionSchemaId}from'common';import {useGetContextDataQuery,useGetPageSettingsQuery}from'common/graphql';import {usePrerequisiteIds}from'../../hooks/usePrerequisiteIds.js';import {useChatMutations}from'../../hooks/useChatApi.js';import {AudioRecorderPanel}from'../../features/audio-input/AudioRecorderPanel.js';import {MicErrorBoundary}from'../../features/audio-input/MicErrorBoundary.js';import {mobileTokens}from'../../theme/mobileTokens.js';var __defProp = Object.defineProperty;
2
2
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
3
  var __hasOwnProp = Object.prototype.hasOwnProperty;
4
4
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -14,47 +14,200 @@ var __spreadValues = (a, b) => {
14
14
  }
15
15
  return a;
16
16
  };
17
+ function buildChannelTitle(mode, channelId) {
18
+ return mode === "deep-search" ? `deep-search-${channelId}` : `chat-channel-${channelId}`;
19
+ }
20
+ function organizationFromSettingsValue(settings) {
21
+ if (settings == null) return null;
22
+ if (typeof settings === "string") {
23
+ try {
24
+ const parsed = JSON.parse(settings);
25
+ const o = parsed == null ? void 0 : parsed.organization;
26
+ return typeof o === "string" && o.trim() ? o.trim() : null;
27
+ } catch (e) {
28
+ return null;
29
+ }
30
+ }
31
+ if (typeof settings === "object" && settings !== null && "organization" in settings) {
32
+ const o = settings.organization;
33
+ return typeof o === "string" && o.trim() ? o.trim() : null;
34
+ }
35
+ return null;
36
+ }
37
+ function projectFromSettingsValue(settings) {
38
+ if (settings == null) return null;
39
+ if (typeof settings === "string") {
40
+ try {
41
+ const parsed = JSON.parse(settings);
42
+ const p = parsed == null ? void 0 : parsed.project;
43
+ return typeof p === "string" && p.trim() ? p.trim() : null;
44
+ } catch (e) {
45
+ return null;
46
+ }
47
+ }
48
+ if (typeof settings === "object" && settings !== null && "project" in settings) {
49
+ const p = settings.project;
50
+ return typeof p === "string" && p.trim() ? p.trim() : null;
51
+ }
52
+ return null;
53
+ }
54
+ const EmptyStateSection = React.memo(function EmptyStateSection2({
55
+ isDark,
56
+ secondaryTextColor,
57
+ primaryTextColor,
58
+ activeMode,
59
+ onModeSwitch
60
+ }) {
61
+ return /* @__PURE__ */ jsx(Box, { flex: 1, width: "100%", children: /* @__PURE__ */ jsxs(View, { style: styles.emptyCenterTitleWrap, children: [
62
+ /* @__PURE__ */ jsx(Text, { style: [styles.emptyEyebrow, {
63
+ color: secondaryTextColor
64
+ }], children: "Choose your mode" }),
65
+ /* @__PURE__ */ jsxs(View, { style: [styles.emptyModePillRow, {
66
+ backgroundColor: isDark ? "rgba(30, 41, 59, 0.9)" : "#eef2ff",
67
+ borderColor: isDark ? "rgba(148, 163, 184, 0.26)" : "rgba(67, 56, 202, 0.15)"
68
+ }], children: [
69
+ /* @__PURE__ */ jsxs(Pressable, { onPress: () => onModeSwitch("chat"), style: [styles.emptyModePill, activeMode === "chat" && styles.emptyModePillActive, activeMode === "chat" && {
70
+ backgroundColor: isDark ? "#312e81" : "#4338ca"
71
+ }], accessibilityRole: "button", accessibilityLabel: "Switch to chat mode", children: [
72
+ /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "magnify", size: 14, color: activeMode === "chat" ? "#ffffff" : secondaryTextColor }),
73
+ /* @__PURE__ */ jsx(Text, { style: [styles.emptyModePillLabel, {
74
+ color: activeMode === "chat" ? "#ffffff" : secondaryTextColor
75
+ }], children: "Chat" })
76
+ ] }),
77
+ /* @__PURE__ */ jsxs(Pressable, { onPress: () => onModeSwitch("deep-search"), style: [styles.emptyModePill, activeMode === "deep-search" && styles.emptyModePillActive, activeMode === "deep-search" && {
78
+ backgroundColor: isDark ? "#312e81" : "#4338ca"
79
+ }], accessibilityRole: "button", accessibilityLabel: "Switch to deep-search mode", children: [
80
+ /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "lightning-bolt-outline", size: 14, color: activeMode === "deep-search" ? "#ffffff" : secondaryTextColor }),
81
+ /* @__PURE__ */ jsx(Text, { style: [styles.emptyModePillLabel, {
82
+ color: activeMode === "deep-search" ? "#ffffff" : secondaryTextColor
83
+ }], children: "Deep Search" })
84
+ ] }),
85
+ /* @__PURE__ */ jsxs(Pressable, { onPress: () => {
86
+ console.log("build mode");
87
+ }, style: styles.emptyModePill, accessibilityRole: "button", accessibilityLabel: "Build mode (preview)", children: [
88
+ /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "lightbulb-outline", size: 14, color: secondaryTextColor }),
89
+ /* @__PURE__ */ jsx(Text, { style: [styles.emptyModePillLabel, {
90
+ color: secondaryTextColor
91
+ }], children: "Build" })
92
+ ] })
93
+ ] }),
94
+ /* @__PURE__ */ jsx(Text, { style: [styles.emptyCenterTitle, {
95
+ color: primaryTextColor
96
+ }], children: "How do you want to start?" }),
97
+ /* @__PURE__ */ jsx(Text, { style: [styles.emptySubtitle, {
98
+ color: secondaryTextColor
99
+ }], children: "Use Chat for quick help, Deep Search for source-backed answers, or Build to assemble workflows." })
100
+ ] }) });
101
+ });
17
102
  function HomeScreenContent({
18
103
  initialMode = "chat",
19
104
  onSubmit: onSubmitProp,
20
- onStop,
21
105
  isLoading: isLoadingProp = false,
22
106
  disabled = false
23
107
  }) {
108
+ var _a, _b, _c, _d, _e;
109
+ const {
110
+ width: screenWidth
111
+ } = useWindowDimensions();
112
+ const colorScheme = useColorScheme();
113
+ const isDark = colorScheme === "dark";
24
114
  const navigation = useNavigation();
115
+ const route = useRoute();
116
+ const hasRehydratedOrgRef = useRef(false);
25
117
  const [value, setValue] = useState("");
26
118
  const [activeMode, setActiveMode] = useState(initialMode);
27
- const [activeSessionId, setActiveSessionId] = useState(null);
119
+ const [showAudioRecorder, setShowAudioRecorder] = useState(false);
120
+ const [voiceError, setVoiceError] = useState(null);
28
121
  const {
29
- createSession
122
+ createChannel
30
123
  } = useChatMutations();
31
- const chat = useChatStream(activeSessionId);
32
- useGetAccountChatSessionsQuery({
124
+ const {
125
+ orgName: resolvedOrgName,
126
+ projectId
127
+ } = usePrerequisiteIds();
128
+ const {
129
+ data: contextData
130
+ } = useGetContextDataQuery();
131
+ const cdecodeUri = (_a = contextData == null ? void 0 : contextData.getContextData) == null ? void 0 : _a.cdecodeUri;
132
+ const {
133
+ data: pageSettingsData
134
+ } = useGetPageSettingsQuery({
33
135
  variables: {
34
- first: 25,
35
- includeArchived: false
136
+ resourceUri: cdecodeUri,
137
+ options: {
138
+ schemaId: ContributionSchemaId.Configuration,
139
+ configKey: "account.default",
140
+ includeMarketplace: true
141
+ }
36
142
  },
143
+ skip: !cdecodeUri,
37
144
  fetchPolicy: "cache-first"
38
145
  });
39
- const {
40
- messages,
41
- response,
42
- error: chatError,
43
- isLoading: chatLoading,
44
- isStreaming,
45
- hasMessages,
46
- sendMessage,
47
- cancel
48
- } = chat;
146
+ const fallbackOrgNameFromSettings = useMemo(() => {
147
+ var _a2;
148
+ return organizationFromSettingsValue((_a2 = pageSettingsData == null ? void 0 : pageSettingsData.pageSettings) == null ? void 0 : _a2.settings);
149
+ }, [pageSettingsData]);
150
+ const fallbackProjectIdFromSettings = useMemo(() => {
151
+ var _a2;
152
+ return projectFromSettingsValue((_a2 = pageSettingsData == null ? void 0 : pageSettingsData.pageSettings) == null ? void 0 : _a2.settings);
153
+ }, [pageSettingsData]);
154
+ const routeOrgName = ((_c = (_b = route == null ? void 0 : route.params) == null ? void 0 : _b.orgName) != null ? _c : "").trim() || null;
155
+ const effectiveOrgName = resolvedOrgName || fallbackOrgNameFromSettings || routeOrgName || null;
156
+ const effectiveProjectId = projectId || fallbackProjectIdFromSettings || null;
49
157
  const trimmedQuery = value.trim();
50
158
  const hasQuery = trimmedQuery.length > 0;
51
- const canSubmit = hasQuery;
52
- const isLoading = isLoadingProp || chatLoading;
159
+ const canSubmit = hasQuery && Boolean(routeOrgName || effectiveOrgName);
160
+ const isLoading = isLoadingProp;
53
161
  const isResearchMode = activeMode === "deep-search";
54
- const inputPlaceholder = isResearchMode ? "Research anything..." : "Ask anything...";
162
+ const inputPlaceholder = !effectiveOrgName ? "Initializing workspace..." : isResearchMode ? "Research anything..." : "Ask anything...";
163
+ const insets = useSafeAreaInsets();
164
+ const [keyboardHeight, setKeyboardHeight] = useState(0);
165
+ useEffect(() => {
166
+ if (Platform.OS === "ios") {
167
+ const frameSub = Keyboard.addListener("keyboardWillChangeFrame", (event) => {
168
+ var _a2, _b2;
169
+ return setKeyboardHeight((_b2 = (_a2 = event.endCoordinates) == null ? void 0 : _a2.height) != null ? _b2 : 0);
170
+ });
171
+ const showSub2 = Keyboard.addListener("keyboardWillShow", (event) => {
172
+ var _a2, _b2;
173
+ return setKeyboardHeight((_b2 = (_a2 = event.endCoordinates) == null ? void 0 : _a2.height) != null ? _b2 : 0);
174
+ });
175
+ const hideSub2 = Keyboard.addListener("keyboardWillHide", () => setKeyboardHeight(0));
176
+ return () => {
177
+ frameSub.remove();
178
+ showSub2.remove();
179
+ hideSub2.remove();
180
+ };
181
+ }
182
+ const showSub = Keyboard.addListener("keyboardDidShow", (event) => {
183
+ var _a2, _b2;
184
+ return setKeyboardHeight((_b2 = (_a2 = event.endCoordinates) == null ? void 0 : _a2.height) != null ? _b2 : 0);
185
+ });
186
+ const hideSub = Keyboard.addListener("keyboardDidHide", () => setKeyboardHeight(0));
187
+ return () => {
188
+ showSub.remove();
189
+ hideSub.remove();
190
+ };
191
+ }, []);
55
192
  const handleModeSwitch = useCallback((mode) => {
56
193
  setActiveMode(mode);
57
194
  }, []);
195
+ const navigateToChat = useCallback((channelId, query, mode, attachments) => {
196
+ var _a2;
197
+ const params = {
198
+ channelId,
199
+ orgName: (_a2 = effectiveOrgName != null ? effectiveOrgName : routeOrgName) != null ? _a2 : void 0,
200
+ initialQuery: query,
201
+ initialMode: mode
202
+ };
203
+ if (attachments && attachments.length > 0) {
204
+ params.initialAttachments = attachments;
205
+ }
206
+ navigation.dispatch(CommonActions.navigate({
207
+ name: "MainStack.Chat",
208
+ params
209
+ }));
210
+ }, [navigation, effectiveOrgName, routeOrgName]);
58
211
  const handleSubmit = useCallback(async (attachments) => {
59
212
  if (!canSubmit || isLoading || disabled) return;
60
213
  const submission = {
@@ -62,74 +215,82 @@ function HomeScreenContent({
62
215
  query: trimmedQuery,
63
216
  attachments
64
217
  };
65
- if (activeMode === "deep-search" && onSubmitProp) {
218
+ if (onSubmitProp) {
66
219
  onSubmitProp(submission);
67
- setValue("");
68
- return;
69
220
  }
70
- if (onSubmitProp && activeMode === "chat") {
71
- onSubmitProp(submission);
72
- setValue("");
221
+ if (!effectiveOrgName || !effectiveProjectId) {
222
+ console.warn("[HomeScreen] orgName/projectId not ready \u2014 skipping submit.");
73
223
  return;
74
224
  }
75
- if (!activeSessionId) {
76
- const newSessionId = v4();
77
- const title = activeMode === "deep-search" ? "Deep Search" : "New Chat";
78
- try {
79
- await createSession({
80
- id: newSessionId,
81
- title
82
- });
83
- setActiveSessionId(newSessionId);
84
- setValue("");
85
- sendMessage(trimmedQuery, void 0, newSessionId);
86
- } catch (err) {
87
- console.error("[HomeScreen] Failed to create session:", err);
88
- }
89
- } else {
90
- setValue("");
91
- sendMessage(trimmedQuery);
92
- }
93
- }, [canSubmit, isLoading, disabled, activeMode, trimmedQuery, activeSessionId, onSubmitProp, createSession, sendMessage]);
94
- const handleNewChat = useCallback(() => {
95
- setActiveSessionId(null);
225
+ const requestedChannelId = v4();
226
+ const title = buildChannelTitle(activeMode, requestedChannelId);
227
+ const queryToForward = trimmedQuery;
228
+ const attachmentsToForward = attachments;
96
229
  setValue("");
97
- }, []);
230
+ void createChannel({
231
+ id: requestedChannelId,
232
+ title,
233
+ isShared: false,
234
+ sharedSlug: null,
235
+ isArchived: false,
236
+ isPinned: false,
237
+ model: null,
238
+ systemPrompt: null,
239
+ orgName: effectiveOrgName,
240
+ projectId: effectiveProjectId
241
+ }).catch((err) => {
242
+ console.error("[HomeScreen] createChannel failed:", err);
243
+ });
244
+ navigateToChat(requestedChannelId, queryToForward, activeMode, attachmentsToForward);
245
+ }, [canSubmit, isLoading, disabled, activeMode, trimmedQuery, onSubmitProp, effectiveOrgName, effectiveProjectId, createChannel, navigateToChat]);
246
+ const surfaceColor = isDark ? "#0f172a" : mobileTokens.color.surface;
247
+ const primaryTextColor = isDark ? "#e5e7eb" : mobileTokens.color.text;
248
+ const secondaryTextColor = isDark ? "#94a3b8" : mobileTokens.color.textMuted;
249
+ const contentMaxWidth = Math.min(720, Math.max(360, screenWidth - 24));
98
250
  useEffect(() => {
99
- navigation.setOptions({
100
- headerRight: () => /* @__PURE__ */ jsx(Pressable, { onPress: handleNewChat, style: ({
101
- pressed
102
- }) => [styles.newChatButton, pressed && styles.newChatButtonPressed], accessibilityLabel: "New chat", children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "chat-plus-outline", size: 26, color: "#000" }) })
251
+ var _a2, _b2, _c2;
252
+ const currentOrgName = ((_b2 = (_a2 = route == null ? void 0 : route.params) == null ? void 0 : _a2.orgName) == null ? void 0 : _b2.trim()) || "";
253
+ if (!effectiveOrgName || currentOrgName === effectiveOrgName) return;
254
+ (_c2 = navigation.setParams) == null ? void 0 : _c2.call(navigation, {
255
+ orgName: effectiveOrgName
103
256
  });
104
- }, [navigation, handleNewChat]);
105
- const handleSendMessage = useCallback(async (text) => {
106
- if (!text.trim() || isLoading || disabled) return;
107
- const submission = {
108
- mode: activeMode,
109
- query: text.trim()
110
- };
111
- if (activeMode === "deep-search" && onSubmitProp) {
112
- onSubmitProp(submission);
113
- return;
114
- }
115
- if (!activeSessionId) {
116
- const newSessionId = v4();
117
- const title = activeMode === "deep-search" ? "Deep Search" : "New Chat";
118
- try {
119
- await createSession({
120
- id: newSessionId,
121
- title
122
- });
123
- setActiveSessionId(newSessionId);
124
- sendMessage(text.trim(), void 0, newSessionId);
125
- } catch (err) {
126
- console.error("[HomeScreen] Failed to create session:", err);
127
- }
128
- } else {
129
- sendMessage(text.trim());
130
- }
131
- }, [isLoading, disabled, activeSessionId, activeMode, onSubmitProp, createSession, sendMessage]);
132
- const leftItems = getDefaultLeftItems({
257
+ }, [navigation, (_d = route == null ? void 0 : route.params) == null ? void 0 : _d.orgName, effectiveOrgName]);
258
+ useEffect(() => {
259
+ var _a2, _b2, _c2;
260
+ const currentOrgName = ((_b2 = (_a2 = route == null ? void 0 : route.params) == null ? void 0 : _a2.orgName) == null ? void 0 : _b2.trim()) || "";
261
+ if (hasRehydratedOrgRef.current || currentOrgName || !effectiveOrgName) return;
262
+ hasRehydratedOrgRef.current = true;
263
+ (_c2 = navigation.getParent()) == null ? void 0 : _c2.dispatch(CommonActions.navigate("MainStack", {
264
+ screen: "MainStack.Layout.Home",
265
+ params: {
266
+ orgName: effectiveOrgName
267
+ },
268
+ merge: true,
269
+ key: Date.now().toString()
270
+ }));
271
+ }, [navigation, (_e = route == null ? void 0 : route.params) == null ? void 0 : _e.orgName, effectiveOrgName]);
272
+ const handleValueChange = useCallback((e) => {
273
+ setValue(e.nativeEvent.text);
274
+ }, []);
275
+ const handleMicPress = useCallback(() => {
276
+ if (hasQuery) return;
277
+ setVoiceError(null);
278
+ Keyboard.dismiss();
279
+ setShowAudioRecorder(true);
280
+ }, [hasQuery]);
281
+ const handleTranscriptionComplete = useCallback((text) => {
282
+ const cleaned = (text != null ? text : "").trim();
283
+ setShowAudioRecorder(false);
284
+ if (!cleaned) return;
285
+ setValue((prev) => prev.trim().length > 0 ? `${prev.trim()} ${cleaned}` : cleaned);
286
+ }, []);
287
+ const handleRecorderCancel = useCallback(() => {
288
+ setShowAudioRecorder(false);
289
+ }, []);
290
+ const handleRecorderError = useCallback((error) => {
291
+ setVoiceError(error);
292
+ }, []);
293
+ const leftItems = useMemo(() => getDefaultLeftItems({
133
294
  search: {
134
295
  active: activeMode === "chat",
135
296
  onClick: () => handleModeSwitch("chat")
@@ -139,10 +300,12 @@ function HomeScreenContent({
139
300
  onClick: () => handleModeSwitch("deep-search")
140
301
  },
141
302
  lightbulb: {
142
- enabled: false
303
+ onClick: () => {
304
+ console.log("build mode");
305
+ }
143
306
  }
144
- });
145
- const rightItems = getDefaultRightItems({
307
+ }), [activeMode, handleModeSwitch]);
308
+ const rightItems = useMemo(() => getDefaultRightItems({
146
309
  tag: {
147
310
  enabled: false
148
311
  },
@@ -150,75 +313,166 @@ function HomeScreenContent({
150
313
  enabled: false
151
314
  },
152
315
  camera: {
153
- onClick: () => console.log("camera")
316
+ enabled: false
154
317
  },
155
318
  image: {
156
- onClick: () => console.log("image")
319
+ enabled: false
157
320
  },
158
321
  attach: {
159
- onClick: () => console.log("attach")
322
+ enabled: false
160
323
  }
161
- });
162
- return /* @__PURE__ */ jsx(SafeAreaView, { style: {
324
+ }), []);
325
+ const inputConfig = useMemo(() => ({
326
+ value,
327
+ onChange: handleValueChange,
328
+ placeholder: inputPlaceholder,
329
+ disabled: isLoading || disabled
330
+ }), [value, handleValueChange, inputPlaceholder, isLoading, disabled]);
331
+ const micSendButton = useMemo(() => ({
332
+ hasContent: canSubmit,
333
+ onSend: () => handleSubmit(),
334
+ onMic: handleMicPress,
335
+ disabled: isLoading || disabled,
336
+ isLoading
337
+ }), [canSubmit, handleSubmit, handleMicPress, isLoading, disabled]);
338
+ return /* @__PURE__ */ jsx(SafeAreaView, { edges: ["left", "right", "bottom"], style: {
163
339
  flex: 1,
164
- backgroundColor: "#fff"
165
- }, children: /* @__PURE__ */ jsxs(Box, { flex: 1, width: "100%", children: [
166
- chatError && /* @__PURE__ */ jsx(Box, { mb: "$2", mx: "$4", p: "$3", bg: "$gray200", borderRadius: "$md", children: /* @__PURE__ */ jsx(Text, { fontSize: "$sm", color: "$gray900", children: chatError }) }),
167
- hasMessages || response ? /* @__PURE__ */ jsx(Box, { flex: 1, width: "100%", alignSelf: "stretch", children: /* @__PURE__ */ jsx(MessagesContainerUI, { mode: "plan", showBackButton: false, onBackPress: handleNewChat, compactTop: true, messagesContainerStyle: {
168
- paddingHorizontal: 0,
169
- paddingTop: 0,
170
- margin: 0
171
- }, listContentStyle: {
172
- paddingTop: 0,
173
- margin: 0
174
- }, messages: messages.map((msg, index) => ({
175
- id: `msg-${index}-${msg.role}`,
176
- role: msg.role,
177
- content: msg.content,
178
- metadata: msg.metadata
179
- })), streamingContent: response, currentUser: {
180
- id: "user"
181
- }, onSend: handleSendMessage, disabled: isLoading || disabled, isLoading, onStop: isStreaming ? cancel : onStop, renderPlanInputToolbar: ({
182
- value: value2,
183
- onChange,
184
- onSend,
185
- disabled: inputDisabled
186
- }) => /* @__PURE__ */ jsx(InputToolBar, { inputConfig: {
187
- value: value2,
188
- onChange: (e) => onChange(e.nativeEvent.text),
189
- placeholder: inputPlaceholder,
190
- disabled: inputDisabled
191
- }, leftItems, rightItems, templateButton: null, templateModalConfig: null, micSendButton: {
192
- hasContent: value2.trim().length > 0,
193
- onSend: () => onSend(value2.trim()),
194
- onMic: () => console.log("mic"),
195
- disabled: inputDisabled,
196
- isLoading,
197
- onStop: isStreaming ? cancel : onStop
198
- } }), renderBuildInputToolbar: () => null }) }) : /* @__PURE__ */ jsx(Box, { flex: 1, justifyContent: "center", alignItems: "stretch", p: "$4", children: /* @__PURE__ */ jsx(InputToolBar, { inputConfig: {
199
- value,
200
- onChange: (e) => setValue(e.nativeEvent.text),
201
- placeholder: inputPlaceholder,
202
- disabled: isLoading || disabled
203
- }, leftItems, rightItems, templateButton: null, templateModalConfig: null, micSendButton: {
204
- hasContent: canSubmit,
205
- onSend: () => handleSubmit(),
206
- onMic: () => console.log("mic"),
207
- disabled: isLoading || disabled,
208
- isLoading,
209
- onStop
210
- } }) })
211
- ] }) });
340
+ backgroundColor: surfaceColor
341
+ }, children: /* @__PURE__ */ jsx(TouchableWithoutFeedback, { onPress: Keyboard.dismiss, accessible: false, children: /* @__PURE__ */ jsxs(Box, { flex: 1, width: "100%", position: "relative", children: [
342
+ /* @__PURE__ */ jsx(EmptyStateSection, { isDark, secondaryTextColor, primaryTextColor, activeMode, onModeSwitch: handleModeSwitch }),
343
+ /* @__PURE__ */ jsx(View, { style: [styles.bottomComposerWrap, {
344
+ bottom: Math.max(0, keyboardHeight - insets.bottom),
345
+ paddingBottom: Math.max(insets.bottom - 6, 2)
346
+ }], children: /* @__PURE__ */ jsxs(View, { style: [styles.bottomComposerInner, {
347
+ width: contentMaxWidth
348
+ }], children: [
349
+ voiceError ? /* @__PURE__ */ jsx(View, { style: [styles.voiceErrorBanner, {
350
+ backgroundColor: isDark ? "#2b1a1d" : "#fef2f2",
351
+ borderColor: isDark ? "#7f1d1d" : "#fecaca"
352
+ }], children: /* @__PURE__ */ jsx(Text, { style: [styles.voiceErrorText, {
353
+ color: isDark ? "#fecaca" : "#991b1b"
354
+ }], children: voiceError }) }) : null,
355
+ showAudioRecorder ? (
356
+ /*
357
+ * Render-time JS errors thrown by `useAudioRecorder`
358
+ * (e.g. expo-audio native module missing, recorder
359
+ * constructor throws in a release build) are caught
360
+ * by the boundary and converted into a soft cancel
361
+ * via the same handlers the panel itself uses on
362
+ * runtime errors. Without this, a throw during the
363
+ * panel's render phase kills the JS thread in
364
+ * release / TestFlight.
365
+ */
366
+ /* @__PURE__ */ jsx(MicErrorBoundary, { onCancel: handleRecorderCancel, onError: handleRecorderError, children: /* @__PURE__ */ jsx(AudioRecorderPanel, { isDark, onTranscriptionComplete: handleTranscriptionComplete, onCancel: handleRecorderCancel, onError: handleRecorderError }) })
367
+ ) : /* @__PURE__ */ jsx(InputToolBar, { inputConfig, leftItems, rightItems, templateButton: null, templateModalConfig: null, micSendButton })
368
+ ] }) })
369
+ ] }) }) });
212
370
  }
213
371
  const styles = StyleSheet.create({
214
- newChatButton: {
372
+ emptyCenterTitleWrap: {
373
+ flex: 1,
374
+ alignItems: "center",
375
+ justifyContent: "flex-start",
376
+ paddingHorizontal: 24,
377
+ paddingTop: 88,
378
+ paddingBottom: 52,
379
+ maxWidth: 520,
380
+ alignSelf: "center"
381
+ },
382
+ emptyEyebrow: {
383
+ fontSize: 12,
384
+ fontWeight: "600",
385
+ letterSpacing: 0.4,
386
+ textTransform: "uppercase",
387
+ marginBottom: 10
388
+ },
389
+ emptyCenterTitle: {
390
+ marginTop: 2,
391
+ fontSize: 30,
392
+ fontWeight: "700",
393
+ textAlign: "center",
394
+ letterSpacing: -0.5
395
+ },
396
+ emptySubtitle: {
397
+ marginTop: 12,
398
+ fontSize: 14,
399
+ lineHeight: 22,
400
+ textAlign: "center",
401
+ paddingHorizontal: 16,
402
+ maxWidth: 360
403
+ },
404
+ bottomComposerWrap: {
405
+ position: "absolute",
406
+ width: "100%",
407
+ left: 0,
408
+ right: 0,
409
+ bottom: 0,
410
+ alignItems: "center",
411
+ justifyContent: "flex-end",
412
+ shadowColor: "#0f172a",
413
+ shadowOpacity: 0.08,
414
+ shadowRadius: 8,
415
+ shadowOffset: {
416
+ width: 0,
417
+ height: -2
418
+ },
419
+ backgroundColor: "transparent",
420
+ elevation: 6
421
+ },
422
+ bottomComposerInner: {
423
+ paddingHorizontal: 14,
424
+ paddingTop: 10,
425
+ paddingBottom: 4
426
+ },
427
+ voiceErrorBanner: {
428
+ marginBottom: 8,
429
+ paddingHorizontal: 12,
430
+ paddingVertical: 8,
431
+ borderRadius: 10,
432
+ borderWidth: 1
433
+ },
434
+ voiceErrorText: {
435
+ fontSize: 12,
436
+ fontWeight: "500"
437
+ },
438
+ emptyModePillRow: {
439
+ flexDirection: "row",
440
+ alignItems: "center",
441
+ gap: 8,
442
+ marginBottom: 22,
443
+ borderRadius: 16,
215
444
  padding: 6,
216
- marginRight: 4,
445
+ borderWidth: 1,
446
+ shadowColor: "#312e81",
447
+ shadowOpacity: 0.08,
448
+ shadowRadius: 8,
449
+ shadowOffset: {
450
+ width: 0,
451
+ height: 3
452
+ },
453
+ elevation: 3
454
+ },
455
+ emptyModePill: {
456
+ flexDirection: "row",
217
457
  alignItems: "center",
218
- justifyContent: "center"
458
+ gap: 4,
459
+ paddingHorizontal: 12,
460
+ paddingVertical: 7,
461
+ borderRadius: 11
462
+ },
463
+ emptyModePillActive: {
464
+ shadowColor: "#312e81",
465
+ shadowOpacity: 0.18,
466
+ shadowRadius: 6,
467
+ shadowOffset: {
468
+ width: 0,
469
+ height: 2
470
+ },
471
+ elevation: 2
219
472
  },
220
- newChatButtonPressed: {
221
- opacity: 0.6
473
+ emptyModePillLabel: {
474
+ fontSize: 12,
475
+ fontWeight: "600"
222
476
  }
223
477
  });
224
478
  const HomeScreen = (props) => /* @__PURE__ */ jsx(HomeScreenContent, __spreadValues({}, props));export{HomeScreen as default};//# sourceMappingURL=HomeScreen.js.map