@adminide-stack/yantra-mobile 12.0.28-alpha.67 → 12.0.28-alpha.69
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.
- package/lib/api/stt.js +54 -0
- package/lib/api/stt.js.map +1 -0
- package/lib/components/GatewayConnector/GatewayConnector.js +18 -0
- package/lib/components/GatewayConnector/GatewayConnector.js.map +1 -0
- package/lib/components/NavigationHeader/NavigationHeader.js +214 -0
- package/lib/components/NavigationHeader/NavigationHeader.js.map +1 -0
- package/lib/components/ThinkingIndicator.js +55 -0
- package/lib/components/ThinkingIndicator.js.map +1 -0
- package/lib/compute.js +108 -31
- package/lib/compute.js.map +1 -1
- package/lib/contexts/CdecliConnectionContext.js +47 -0
- package/lib/contexts/CdecliConnectionContext.js.map +1 -0
- package/lib/contexts/GatewayContext.js +1 -1
- package/lib/features/audio-input/AudioRecorderPanel.js +231 -0
- package/lib/features/audio-input/AudioRecorderPanel.js.map +1 -0
- package/lib/features/audio-input/MicErrorBoundary.js +34 -0
- package/lib/features/audio-input/MicErrorBoundary.js.map +1 -0
- package/lib/hooks/useCdecliAutoConnect.js +41 -18
- package/lib/hooks/useCdecliAutoConnect.js.map +1 -1
- package/lib/hooks/useChatApi.js +158 -41
- package/lib/hooks/useChatApi.js.map +1 -1
- package/lib/hooks/useChatStream.js +59 -16
- package/lib/hooks/useChatStream.js.map +1 -1
- package/lib/hooks/usePrerequisiteIds.js +8 -12
- package/lib/hooks/usePrerequisiteIds.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/routes.json +112 -0
- package/lib/screens/Chat/index.js +423 -0
- package/lib/screens/Chat/index.js.map +1 -0
- package/lib/screens/ChatHistory/index.js +56 -0
- package/lib/screens/ChatHistory/index.js.map +1 -0
- package/lib/screens/Home/HomeScreen.js +136 -427
- package/lib/screens/Home/HomeScreen.js.map +1 -1
- package/lib/screens/Home/components/ChatHistoryLanding.js +436 -214
- package/lib/screens/Home/components/ChatHistoryLanding.js.map +1 -1
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {jsx,jsxs}from'react/jsx-runtime';import React,{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 {
|
|
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,8 +14,9 @@ var __spreadValues = (a, b) => {
|
|
|
14
14
|
}
|
|
15
15
|
return a;
|
|
16
16
|
};
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
function buildChannelTitle(mode, channelId) {
|
|
18
|
+
return mode === "deep-search" ? `deep-search-${channelId}` : `chat-channel-${channelId}`;
|
|
19
|
+
}
|
|
19
20
|
function organizationFromSettingsValue(settings) {
|
|
20
21
|
if (settings == null) return null;
|
|
21
22
|
if (typeof settings === "string") {
|
|
@@ -50,44 +51,6 @@ function projectFromSettingsValue(settings) {
|
|
|
50
51
|
}
|
|
51
52
|
return null;
|
|
52
53
|
}
|
|
53
|
-
const ChatContentSection = React.memo(function ChatContentSection2({
|
|
54
|
-
contentMaxWidth,
|
|
55
|
-
composerScrollBottomPadding,
|
|
56
|
-
messages,
|
|
57
|
-
response,
|
|
58
|
-
isLoading,
|
|
59
|
-
disabled,
|
|
60
|
-
isStreaming,
|
|
61
|
-
onStop,
|
|
62
|
-
cancel,
|
|
63
|
-
onSend,
|
|
64
|
-
onBackPress
|
|
65
|
-
}) {
|
|
66
|
-
return /* @__PURE__ */ jsx(Box, { flex: 1, width: "100%", alignSelf: "stretch", children: /* @__PURE__ */ jsx(MessagesContainerUI, { mode: "chat", showBackButton: false, onBackPress, compactTop: true, messagesContainerStyle: {
|
|
67
|
-
paddingHorizontal: 0,
|
|
68
|
-
paddingTop: 0,
|
|
69
|
-
paddingBottom: composerScrollBottomPadding,
|
|
70
|
-
margin: 0,
|
|
71
|
-
marginTop: 0,
|
|
72
|
-
alignSelf: "center",
|
|
73
|
-
width: contentMaxWidth
|
|
74
|
-
}, listContentStyle: {
|
|
75
|
-
paddingTop: 0,
|
|
76
|
-
paddingBottom: composerScrollBottomPadding,
|
|
77
|
-
margin: 0,
|
|
78
|
-
marginTop: 0,
|
|
79
|
-
width: contentMaxWidth,
|
|
80
|
-
alignSelf: "center",
|
|
81
|
-
justifyContent: "flex-end"
|
|
82
|
-
}, messages: messages.map((msg, index) => ({
|
|
83
|
-
id: `msg-${index}-${msg.role}`,
|
|
84
|
-
role: msg.role,
|
|
85
|
-
content: msg.content,
|
|
86
|
-
metadata: msg.metadata
|
|
87
|
-
})), streamingContent: response, currentUser: {
|
|
88
|
-
id: "user"
|
|
89
|
-
}, onSend, disabled: isLoading || disabled, isLoading, onStop: isStreaming ? cancel : onStop, renderPlanInputToolbar: () => null, renderBuildInputToolbar: () => null }) });
|
|
90
|
-
});
|
|
91
54
|
const EmptyStateSection = React.memo(function EmptyStateSection2({
|
|
92
55
|
isDark,
|
|
93
56
|
secondaryTextColor,
|
|
@@ -118,6 +81,14 @@ const EmptyStateSection = React.memo(function EmptyStateSection2({
|
|
|
118
81
|
/* @__PURE__ */ jsx(Text, { style: [styles.emptyModePillLabel, {
|
|
119
82
|
color: activeMode === "deep-search" ? "#ffffff" : secondaryTextColor
|
|
120
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" })
|
|
121
92
|
] })
|
|
122
93
|
] }),
|
|
123
94
|
/* @__PURE__ */ jsx(Text, { style: [styles.emptyCenterTitle, {
|
|
@@ -125,48 +96,16 @@ const EmptyStateSection = React.memo(function EmptyStateSection2({
|
|
|
125
96
|
}], children: "How do you want to start?" }),
|
|
126
97
|
/* @__PURE__ */ jsx(Text, { style: [styles.emptySubtitle, {
|
|
127
98
|
color: secondaryTextColor
|
|
128
|
-
}], children: "Use Chat for quick help,
|
|
99
|
+
}], children: "Use Chat for quick help, Deep Search for source-backed answers, or Build to assemble workflows." })
|
|
129
100
|
] }) });
|
|
130
101
|
});
|
|
131
|
-
const HeaderBackButton = React.memo(function HeaderBackButton2({
|
|
132
|
-
color,
|
|
133
|
-
onPress
|
|
134
|
-
}) {
|
|
135
|
-
return /* @__PURE__ */ jsx(Pressable, { onPress, style: ({
|
|
136
|
-
pressed
|
|
137
|
-
}) => [styles.backButton, pressed && styles.newChatButtonPressed], accessibilityLabel: "Back to chat", children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "chevron-left", size: 24, color }) });
|
|
138
|
-
});
|
|
139
|
-
const HeaderRightActions = React.memo(function HeaderRightActions2({
|
|
140
|
-
gatewayToolbarStatus,
|
|
141
|
-
gatewayToolbarError,
|
|
142
|
-
onToggleGateway,
|
|
143
|
-
gatewayToolbarLabel,
|
|
144
|
-
gatewayToolbarTone,
|
|
145
|
-
showChatHistory,
|
|
146
|
-
onOpenChatHistory,
|
|
147
|
-
onNewChat,
|
|
148
|
-
isDark,
|
|
149
|
-
accentColor,
|
|
150
|
-
newChatIconColor
|
|
151
|
-
}) {
|
|
152
|
-
return /* @__PURE__ */ jsxs(View, { style: styles.headerRight, children: [
|
|
153
|
-
/* @__PURE__ */ jsx(GatewayToolbarButtonMobile, { gatewayStatus: gatewayToolbarStatus, gatewayError: gatewayToolbarError, onToggleGateway, disabled: false, statusLabel: gatewayToolbarLabel, tone: gatewayToolbarTone }),
|
|
154
|
-
!showChatHistory ? /* @__PURE__ */ jsx(Pressable, { onPress: onOpenChatHistory, style: ({
|
|
155
|
-
pressed
|
|
156
|
-
}) => [styles.historyHeaderButton, pressed && styles.historyHeaderButtonPressed], accessibilityLabel: "Chat history", accessibilityRole: "button", children: /* @__PURE__ */ jsx(View, { style: [styles.historyHeaderButtonInner, isDark ? styles.historyHeaderButtonInnerDark : null], children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "history", size: 19, color: accentColor }) }) }) : null,
|
|
157
|
-
/* @__PURE__ */ jsx(Pressable, { onPress: onNewChat, style: ({
|
|
158
|
-
pressed
|
|
159
|
-
}) => [styles.newChatButton, pressed && styles.newChatButtonPressed], accessibilityLabel: "New chat", children: /* @__PURE__ */ jsx(View, { style: [styles.newChatButtonInner, isDark ? styles.newChatButtonInnerDark : null], children: /* @__PURE__ */ jsx(MaterialCommunityIcons, { name: "chat-plus-outline", size: 20, color: newChatIconColor }) }) })
|
|
160
|
-
] });
|
|
161
|
-
});
|
|
162
102
|
function HomeScreenContent({
|
|
163
103
|
initialMode = "chat",
|
|
164
104
|
onSubmit: onSubmitProp,
|
|
165
|
-
onStop,
|
|
166
105
|
isLoading: isLoadingProp = false,
|
|
167
106
|
disabled = false
|
|
168
107
|
}) {
|
|
169
|
-
var _a, _b, _c, _d, _e
|
|
108
|
+
var _a, _b, _c, _d, _e;
|
|
170
109
|
const {
|
|
171
110
|
width: screenWidth
|
|
172
111
|
} = useWindowDimensions();
|
|
@@ -174,22 +113,14 @@ function HomeScreenContent({
|
|
|
174
113
|
const isDark = colorScheme === "dark";
|
|
175
114
|
const navigation = useNavigation();
|
|
176
115
|
const route = useRoute();
|
|
177
|
-
const hasRehydratedOrgRef =
|
|
116
|
+
const hasRehydratedOrgRef = useRef(false);
|
|
178
117
|
const [value, setValue] = useState("");
|
|
179
118
|
const [activeMode, setActiveMode] = useState(initialMode);
|
|
180
|
-
const [
|
|
181
|
-
const [
|
|
182
|
-
const [deepSearchQuery, setDeepSearchQuery] = useState(null);
|
|
183
|
-
const [deepSearchSummary, setDeepSearchSummary] = useState("");
|
|
184
|
-
const [deepSearchSources, setDeepSearchSources] = useState([]);
|
|
185
|
-
const [researchProcessOpen, setResearchProcessOpen] = useState(true);
|
|
186
|
-
const [sourcesAccordionOpen, setSourcesAccordionOpen] = useState(true);
|
|
187
|
-
const [showChatHistory, setShowChatHistory] = useState(false);
|
|
188
|
-
const [channelBootstrap, setChannelBootstrap] = useState(false);
|
|
119
|
+
const [showAudioRecorder, setShowAudioRecorder] = useState(false);
|
|
120
|
+
const [voiceError, setVoiceError] = useState(null);
|
|
189
121
|
const {
|
|
190
122
|
createChannel
|
|
191
123
|
} = useChatMutations();
|
|
192
|
-
useChatSessions();
|
|
193
124
|
const {
|
|
194
125
|
orgName: resolvedOrgName,
|
|
195
126
|
projectId
|
|
@@ -223,46 +154,12 @@ function HomeScreenContent({
|
|
|
223
154
|
const routeOrgName = ((_c = (_b = route == null ? void 0 : route.params) == null ? void 0 : _b.orgName) != null ? _c : "").trim() || null;
|
|
224
155
|
const effectiveOrgName = resolvedOrgName || fallbackOrgNameFromSettings || routeOrgName || null;
|
|
225
156
|
const effectiveProjectId = projectId || fallbackProjectIdFromSettings || null;
|
|
226
|
-
const {
|
|
227
|
-
selectedGateway
|
|
228
|
-
} = useGatewayContext();
|
|
229
|
-
const cdecliSelected = (selectedGateway == null ? void 0 : selectedGateway.channelType) === "cdecli-serve";
|
|
230
|
-
const cdecli = useCdecliAutoConnect(cdecliSelected, activeSessionId != null ? activeSessionId : void 0);
|
|
231
|
-
const cdecliConnected = cdecliSelected && cdecli.channelConnected;
|
|
232
|
-
const effectivePersistenceMode = (_e = (_d = cdecli.persistenceMode) != null ? _d : selectedGateway == null ? void 0 : selectedGateway.persistenceMode) != null ? _e : "frontend";
|
|
233
|
-
const chatRouting = useMemo(() => cdecliConnected ? {
|
|
234
|
-
kind: "cdecli",
|
|
235
|
-
channelConnected: cdecli.channelConnected,
|
|
236
|
-
accountId: cdecli.accountId,
|
|
237
|
-
persistenceMode: effectivePersistenceMode
|
|
238
|
-
} : {
|
|
239
|
-
kind: "groq"
|
|
240
|
-
}, [cdecliConnected, cdecli.channelConnected, cdecli.accountId, effectivePersistenceMode]);
|
|
241
|
-
const chat = useChatStream(activeSessionId, chatRouting);
|
|
242
|
-
const {
|
|
243
|
-
messages,
|
|
244
|
-
response,
|
|
245
|
-
error: chatError,
|
|
246
|
-
isLoading: chatLoading,
|
|
247
|
-
isStreaming,
|
|
248
|
-
sendMessage,
|
|
249
|
-
cancel,
|
|
250
|
-
clearMessages
|
|
251
|
-
} = chat;
|
|
252
157
|
const trimmedQuery = value.trim();
|
|
253
158
|
const hasQuery = trimmedQuery.length > 0;
|
|
254
159
|
const canSubmit = hasQuery && Boolean(routeOrgName || effectiveOrgName);
|
|
255
|
-
const isLoading = isLoadingProp
|
|
160
|
+
const isLoading = isLoadingProp;
|
|
256
161
|
const isResearchMode = activeMode === "deep-search";
|
|
257
162
|
const inputPlaceholder = !effectiveOrgName ? "Initializing workspace..." : isResearchMode ? "Research anything..." : "Ask anything...";
|
|
258
|
-
const waitingForAssistant = useMemo(() => {
|
|
259
|
-
var _a2;
|
|
260
|
-
if (!chatLoading && !isStreaming || messages.length === 0) return false;
|
|
261
|
-
return ((_a2 = messages[messages.length - 1]) == null ? void 0 : _a2.role) === "user";
|
|
262
|
-
}, [chatLoading, isStreaming, messages]);
|
|
263
|
-
const pinSendingLoaderNearComposer = useMemo(() => messages.length > 0 || Boolean((response != null ? response : "").trim()), [messages.length, response]);
|
|
264
|
-
const showSendingLoader = !showChatHistory && (channelBootstrap || waitingForAssistant);
|
|
265
|
-
const hasRenderableConversation = messages.length > 0 || isStreaming;
|
|
266
163
|
const insets = useSafeAreaInsets();
|
|
267
164
|
const [keyboardHeight, setKeyboardHeight] = useState(0);
|
|
268
165
|
useEffect(() => {
|
|
@@ -295,14 +192,42 @@ function HomeScreenContent({
|
|
|
295
192
|
const handleModeSwitch = useCallback((mode) => {
|
|
296
193
|
setActiveMode(mode);
|
|
297
194
|
}, []);
|
|
298
|
-
const
|
|
299
|
-
|
|
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]);
|
|
211
|
+
const handleSubmit = useCallback(async (attachments) => {
|
|
212
|
+
if (!canSubmit || isLoading || disabled) return;
|
|
213
|
+
const submission = {
|
|
214
|
+
mode: activeMode,
|
|
215
|
+
query: trimmedQuery,
|
|
216
|
+
attachments
|
|
217
|
+
};
|
|
218
|
+
if (onSubmitProp) {
|
|
219
|
+
onSubmitProp(submission);
|
|
220
|
+
}
|
|
300
221
|
if (!effectiveOrgName || !effectiveProjectId) {
|
|
301
|
-
|
|
222
|
+
console.warn("[HomeScreen] orgName/projectId not ready \u2014 skipping submit.");
|
|
223
|
+
return;
|
|
302
224
|
}
|
|
303
225
|
const requestedChannelId = v4();
|
|
304
|
-
const title =
|
|
305
|
-
const
|
|
226
|
+
const title = buildChannelTitle(activeMode, requestedChannelId);
|
|
227
|
+
const queryToForward = trimmedQuery;
|
|
228
|
+
const attachmentsToForward = attachments;
|
|
229
|
+
setValue("");
|
|
230
|
+
void createChannel({
|
|
306
231
|
id: requestedChannelId,
|
|
307
232
|
title,
|
|
308
233
|
isShared: false,
|
|
@@ -313,76 +238,14 @@ function HomeScreenContent({
|
|
|
313
238
|
systemPrompt: null,
|
|
314
239
|
orgName: effectiveOrgName,
|
|
315
240
|
projectId: effectiveProjectId
|
|
241
|
+
}).catch((err) => {
|
|
242
|
+
console.error("[HomeScreen] createChannel failed:", err);
|
|
316
243
|
});
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}, [activeSessionId, createChannel, effectiveOrgName, effectiveProjectId]);
|
|
320
|
-
const handleSubmit = useCallback(async (attachments) => {
|
|
321
|
-
if (!canSubmit || isLoading || disabled) return;
|
|
322
|
-
const submission = {
|
|
323
|
-
mode: activeMode,
|
|
324
|
-
query: trimmedQuery,
|
|
325
|
-
attachments
|
|
326
|
-
};
|
|
327
|
-
if (activeMode === "deep-search") {
|
|
328
|
-
if (onSubmitProp) {
|
|
329
|
-
onSubmitProp(submission);
|
|
330
|
-
}
|
|
331
|
-
setValue("");
|
|
332
|
-
setDeepSearchQuery(trimmedQuery);
|
|
333
|
-
setDeepSearchSummary("");
|
|
334
|
-
setDeepSearchSources([]);
|
|
335
|
-
setIsDeepSearchModalOpen(true);
|
|
336
|
-
try {
|
|
337
|
-
setChannelBootstrap(true);
|
|
338
|
-
const sessionId = await ensureSessionId("deep-search");
|
|
339
|
-
await sendMessage(trimmedQuery, void 0, sessionId);
|
|
340
|
-
} catch (err) {
|
|
341
|
-
console.error("[HomeScreen] Failed to create deep-search session:", err);
|
|
342
|
-
} finally {
|
|
343
|
-
setChannelBootstrap(false);
|
|
344
|
-
}
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
if (onSubmitProp && activeMode === "chat") {
|
|
348
|
-
onSubmitProp(submission);
|
|
349
|
-
setValue("");
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
try {
|
|
353
|
-
setChannelBootstrap(true);
|
|
354
|
-
const sessionId = await ensureSessionId("chat");
|
|
355
|
-
setValue("");
|
|
356
|
-
await sendMessage(trimmedQuery, void 0, sessionId);
|
|
357
|
-
} catch (err) {
|
|
358
|
-
console.error("[HomeScreen] Failed to create session:", err);
|
|
359
|
-
} finally {
|
|
360
|
-
setChannelBootstrap(false);
|
|
361
|
-
}
|
|
362
|
-
}, [canSubmit, isLoading, disabled, activeMode, trimmedQuery, activeSessionId, onSubmitProp, ensureSessionId, sendMessage]);
|
|
363
|
-
const handleNewChat = useCallback(() => {
|
|
364
|
-
setShowChatHistory(false);
|
|
365
|
-
setActiveSessionId(null);
|
|
366
|
-
setValue("");
|
|
367
|
-
clearMessages();
|
|
368
|
-
}, [clearMessages]);
|
|
369
|
-
const handleOpenChatHistory = useCallback(() => {
|
|
370
|
-
setShowChatHistory(true);
|
|
371
|
-
}, []);
|
|
372
|
-
const handleCloseChatHistory = useCallback(() => {
|
|
373
|
-
setShowChatHistory(false);
|
|
374
|
-
}, []);
|
|
375
|
-
const handleToggleGateway = useCallback(() => {
|
|
376
|
-
}, []);
|
|
377
|
-
const gatewayToolbarStatus = cdecli.status === "connecting" ? "connecting" : cdecli.status === "connected" ? "connected" : cdecli.status === "error" ? "error" : "disconnected";
|
|
378
|
-
const gatewayToolbarTone = "default";
|
|
379
|
-
const gatewayToolbarLabel = cdecli.status === "connecting" ? "Checking..." : void 0;
|
|
380
|
-
const gatewayToolbarError = cdecli.error;
|
|
244
|
+
navigateToChat(requestedChannelId, queryToForward, activeMode, attachmentsToForward);
|
|
245
|
+
}, [canSubmit, isLoading, disabled, activeMode, trimmedQuery, onSubmitProp, effectiveOrgName, effectiveProjectId, createChannel, navigateToChat]);
|
|
381
246
|
const surfaceColor = isDark ? "#0f172a" : mobileTokens.color.surface;
|
|
382
247
|
const primaryTextColor = isDark ? "#e5e7eb" : mobileTokens.color.text;
|
|
383
248
|
const secondaryTextColor = isDark ? "#94a3b8" : mobileTokens.color.textMuted;
|
|
384
|
-
const accentColor = isDark ? "#a5b4fc" : "#4338ca";
|
|
385
|
-
const newChatIconColor = isDark ? "#e5e7eb" : "#000000";
|
|
386
249
|
const contentMaxWidth = Math.min(720, Math.max(360, screenWidth - 24));
|
|
387
250
|
useEffect(() => {
|
|
388
251
|
var _a2, _b2, _c2;
|
|
@@ -391,7 +254,7 @@ function HomeScreenContent({
|
|
|
391
254
|
(_c2 = navigation.setParams) == null ? void 0 : _c2.call(navigation, {
|
|
392
255
|
orgName: effectiveOrgName
|
|
393
256
|
});
|
|
394
|
-
}, [navigation, (
|
|
257
|
+
}, [navigation, (_d = route == null ? void 0 : route.params) == null ? void 0 : _d.orgName, effectiveOrgName]);
|
|
395
258
|
useEffect(() => {
|
|
396
259
|
var _a2, _b2, _c2;
|
|
397
260
|
const currentOrgName = ((_b2 = (_a2 = route == null ? void 0 : route.params) == null ? void 0 : _a2.orgName) == null ? void 0 : _b2.trim()) || "";
|
|
@@ -405,116 +268,47 @@ function HomeScreenContent({
|
|
|
405
268
|
merge: true,
|
|
406
269
|
key: Date.now().toString()
|
|
407
270
|
}));
|
|
408
|
-
}, [navigation, (
|
|
409
|
-
useEffect(() => {
|
|
410
|
-
const headerLeft = showChatHistory ? () => /* @__PURE__ */ jsx(HeaderBackButton, { color: primaryTextColor, onPress: handleCloseChatHistory }) : void 0;
|
|
411
|
-
const headerRight = () => /* @__PURE__ */ jsx(HeaderRightActions, { gatewayToolbarStatus, gatewayToolbarError, onToggleGateway: handleToggleGateway, gatewayToolbarLabel, gatewayToolbarTone, showChatHistory, onOpenChatHistory: handleOpenChatHistory, onNewChat: handleNewChat, isDark, accentColor, newChatIconColor });
|
|
412
|
-
navigation.setOptions({
|
|
413
|
-
drawerLabel: "Chat",
|
|
414
|
-
headerTitle: showChatHistory ? "Chats" : "Yantra",
|
|
415
|
-
headerLeft,
|
|
416
|
-
headerRight
|
|
417
|
-
});
|
|
418
|
-
}, [navigation, showChatHistory, handleCloseChatHistory, handleOpenChatHistory, handleNewChat, handleToggleGateway, gatewayToolbarStatus, gatewayToolbarError, gatewayToolbarLabel, gatewayToolbarTone, primaryTextColor, accentColor, newChatIconColor, isDark]);
|
|
419
|
-
const handleSendMessage = useCallback(async (text) => {
|
|
420
|
-
if (!text.trim() || isLoading || disabled) return;
|
|
421
|
-
const submission = {
|
|
422
|
-
mode: activeMode,
|
|
423
|
-
query: text.trim()
|
|
424
|
-
};
|
|
425
|
-
if (activeMode === "deep-search") {
|
|
426
|
-
if (onSubmitProp) {
|
|
427
|
-
onSubmitProp(submission);
|
|
428
|
-
}
|
|
429
|
-
setDeepSearchQuery(text.trim());
|
|
430
|
-
setDeepSearchSummary("");
|
|
431
|
-
setDeepSearchSources([]);
|
|
432
|
-
setIsDeepSearchModalOpen(true);
|
|
433
|
-
try {
|
|
434
|
-
setChannelBootstrap(true);
|
|
435
|
-
const sessionId = await ensureSessionId("deep-search");
|
|
436
|
-
await sendMessage(text.trim(), void 0, sessionId);
|
|
437
|
-
} catch (err) {
|
|
438
|
-
console.error("[HomeScreen] Failed to create deep-search session:", err);
|
|
439
|
-
} finally {
|
|
440
|
-
setChannelBootstrap(false);
|
|
441
|
-
}
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
|
-
try {
|
|
445
|
-
setChannelBootstrap(true);
|
|
446
|
-
const sessionId = await ensureSessionId("chat");
|
|
447
|
-
await sendMessage(text.trim(), void 0, sessionId);
|
|
448
|
-
} catch (err) {
|
|
449
|
-
console.error("[HomeScreen] Failed to create session:", err);
|
|
450
|
-
} finally {
|
|
451
|
-
setChannelBootstrap(false);
|
|
452
|
-
}
|
|
453
|
-
}, [isLoading, disabled, activeMode, onSubmitProp, ensureSessionId, sendMessage]);
|
|
454
|
-
const latestAssistantMessage = useMemo(() => {
|
|
455
|
-
var _a2, _b2, _c2;
|
|
456
|
-
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
457
|
-
if (((_a2 = messages[i]) == null ? void 0 : _a2.role) === "assistant") return (_c2 = (_b2 = messages[i]) == null ? void 0 : _b2.content) != null ? _c2 : "";
|
|
458
|
-
}
|
|
459
|
-
return "";
|
|
460
|
-
}, [messages]);
|
|
461
|
-
const deepSearchPreviewContent = response || deepSearchSummary;
|
|
462
|
-
const deepSearchPreviewNormalized = useMemo(() => normalizeSummaryText(deepSearchPreviewContent || deepSearchSummary || ""), [deepSearchPreviewContent, deepSearchSummary]);
|
|
463
|
-
const handleDeepSearchClose = useCallback(() => {
|
|
464
|
-
if (isStreaming) {
|
|
465
|
-
cancel();
|
|
466
|
-
}
|
|
467
|
-
setIsDeepSearchModalOpen(false);
|
|
468
|
-
setDeepSearchQuery(null);
|
|
469
|
-
setDeepSearchSummary("");
|
|
470
|
-
setDeepSearchSources([]);
|
|
471
|
-
setResearchProcessOpen(true);
|
|
472
|
-
setSourcesAccordionOpen(true);
|
|
473
|
-
}, [isStreaming, cancel]);
|
|
474
|
-
const handleRetryDeepSearch = useCallback(async () => {
|
|
475
|
-
if (!deepSearchQuery || isStreaming) return;
|
|
476
|
-
try {
|
|
477
|
-
setChannelBootstrap(true);
|
|
478
|
-
const sessionId = await ensureSessionId("deep-search");
|
|
479
|
-
await sendMessage(deepSearchQuery, void 0, sessionId);
|
|
480
|
-
} catch (error) {
|
|
481
|
-
console.error("[HomeScreen] Failed to retry deep-search:", error);
|
|
482
|
-
} finally {
|
|
483
|
-
setChannelBootstrap(false);
|
|
484
|
-
}
|
|
485
|
-
}, [deepSearchQuery, isStreaming, ensureSessionId, sendMessage]);
|
|
271
|
+
}, [navigation, (_e = route == null ? void 0 : route.params) == null ? void 0 : _e.orgName, effectiveOrgName]);
|
|
486
272
|
const handleValueChange = useCallback((e) => {
|
|
487
273
|
setValue(e.nativeEvent.text);
|
|
488
274
|
}, []);
|
|
489
275
|
const handleMicPress = useCallback(() => {
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
276
|
+
if (hasQuery) return;
|
|
277
|
+
setVoiceError(null);
|
|
278
|
+
Keyboard.dismiss();
|
|
279
|
+
void (async () => {
|
|
280
|
+
try {
|
|
281
|
+
const {
|
|
282
|
+
AudioModule
|
|
283
|
+
} = await import('expo-audio');
|
|
284
|
+
if (!AudioModule || typeof AudioModule.requestRecordingPermissionsAsync !== "function") {
|
|
285
|
+
setVoiceError("Voice input is not available on this device.");
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const perm = await AudioModule.requestRecordingPermissionsAsync();
|
|
289
|
+
if (!(perm == null ? void 0 : perm.granted)) {
|
|
290
|
+
setVoiceError("Microphone permission is required for voice input.");
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
setShowAudioRecorder(true);
|
|
294
|
+
} catch (err) {
|
|
295
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
296
|
+
setVoiceError(`Could not start voice input: ${msg}`);
|
|
297
|
+
}
|
|
298
|
+
})();
|
|
299
|
+
}, [hasQuery]);
|
|
300
|
+
const handleTranscriptionComplete = useCallback((text) => {
|
|
301
|
+
const cleaned = (text != null ? text : "").trim();
|
|
302
|
+
setShowAudioRecorder(false);
|
|
303
|
+
if (!cleaned) return;
|
|
304
|
+
setValue((prev) => prev.trim().length > 0 ? `${prev.trim()} ${cleaned}` : cleaned);
|
|
496
305
|
}, []);
|
|
497
|
-
const
|
|
498
|
-
|
|
499
|
-
setActiveSessionId(null);
|
|
500
|
-
setValue("");
|
|
501
|
-
clearMessages();
|
|
502
|
-
}, [clearMessages]);
|
|
503
|
-
const handleToggleResearchProcess = useCallback(() => {
|
|
504
|
-
setResearchProcessOpen((prev) => !prev);
|
|
306
|
+
const handleRecorderCancel = useCallback(() => {
|
|
307
|
+
setShowAudioRecorder(false);
|
|
505
308
|
}, []);
|
|
506
|
-
const
|
|
507
|
-
|
|
309
|
+
const handleRecorderError = useCallback((error) => {
|
|
310
|
+
setVoiceError(error);
|
|
508
311
|
}, []);
|
|
509
|
-
const handleRetryDeepSearchPress = useCallback(() => {
|
|
510
|
-
void handleRetryDeepSearch();
|
|
511
|
-
}, [handleRetryDeepSearch]);
|
|
512
|
-
useEffect(() => {
|
|
513
|
-
if (!deepSearchQuery || isStreaming || !latestAssistantMessage) return;
|
|
514
|
-
setDeepSearchSummary(normalizeSummaryText(latestAssistantMessage));
|
|
515
|
-
setDeepSearchSources(extractDeepSearchSources(latestAssistantMessage));
|
|
516
|
-
}, [deepSearchQuery, isStreaming, latestAssistantMessage]);
|
|
517
|
-
const composerScrollBottomPadding = COMPOSER_SCROLL_RESERVE_PX;
|
|
518
312
|
const leftItems = useMemo(() => getDefaultLeftItems({
|
|
519
313
|
search: {
|
|
520
314
|
active: activeMode === "chat",
|
|
@@ -525,7 +319,9 @@ function HomeScreenContent({
|
|
|
525
319
|
onClick: () => handleModeSwitch("deep-search")
|
|
526
320
|
},
|
|
527
321
|
lightbulb: {
|
|
528
|
-
|
|
322
|
+
onClick: () => {
|
|
323
|
+
console.log("build mode");
|
|
324
|
+
}
|
|
529
325
|
}
|
|
530
326
|
}), [activeMode, handleModeSwitch]);
|
|
531
327
|
const rightItems = useMemo(() => getDefaultRightItems({
|
|
@@ -536,16 +332,13 @@ function HomeScreenContent({
|
|
|
536
332
|
enabled: false
|
|
537
333
|
},
|
|
538
334
|
camera: {
|
|
539
|
-
enabled: false
|
|
540
|
-
onClick: () => console.log("camera")
|
|
335
|
+
enabled: false
|
|
541
336
|
},
|
|
542
337
|
image: {
|
|
543
|
-
enabled: false
|
|
544
|
-
onClick: () => console.log("image")
|
|
338
|
+
enabled: false
|
|
545
339
|
},
|
|
546
340
|
attach: {
|
|
547
|
-
enabled: false
|
|
548
|
-
onClick: () => console.log("attach")
|
|
341
|
+
enabled: false
|
|
549
342
|
}
|
|
550
343
|
}), []);
|
|
551
344
|
const inputConfig = useMemo(() => ({
|
|
@@ -559,136 +352,42 @@ function HomeScreenContent({
|
|
|
559
352
|
onSend: () => handleSubmit(),
|
|
560
353
|
onMic: handleMicPress,
|
|
561
354
|
disabled: isLoading || disabled,
|
|
562
|
-
isLoading
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
return /* @__PURE__ */ jsxs(SafeAreaView, { edges: ["left", "right", "bottom"], style: {
|
|
355
|
+
isLoading
|
|
356
|
+
}), [canSubmit, handleSubmit, handleMicPress, isLoading, disabled]);
|
|
357
|
+
return /* @__PURE__ */ jsx(SafeAreaView, { edges: ["left", "right", "bottom"], style: {
|
|
566
358
|
flex: 1,
|
|
567
359
|
backgroundColor: surfaceColor
|
|
568
|
-
}, children: [
|
|
569
|
-
/* @__PURE__ */ jsx(
|
|
570
|
-
|
|
360
|
+
}, children: /* @__PURE__ */ jsx(TouchableWithoutFeedback, { onPress: Keyboard.dismiss, accessible: false, children: /* @__PURE__ */ jsxs(Box, { flex: 1, width: "100%", position: "relative", children: [
|
|
361
|
+
/* @__PURE__ */ jsx(EmptyStateSection, { isDark, secondaryTextColor, primaryTextColor, activeMode, onModeSwitch: handleModeSwitch }),
|
|
362
|
+
/* @__PURE__ */ jsx(View, { style: [styles.bottomComposerWrap, {
|
|
363
|
+
bottom: Math.max(0, keyboardHeight - insets.bottom),
|
|
364
|
+
paddingBottom: Math.max(insets.bottom - 6, 2)
|
|
365
|
+
}], children: /* @__PURE__ */ jsxs(View, { style: [styles.bottomComposerInner, {
|
|
366
|
+
width: contentMaxWidth
|
|
367
|
+
}], children: [
|
|
368
|
+
voiceError ? /* @__PURE__ */ jsx(View, { style: [styles.voiceErrorBanner, {
|
|
571
369
|
backgroundColor: isDark ? "#2b1a1d" : "#fef2f2",
|
|
572
|
-
borderWidth: 1,
|
|
573
370
|
borderColor: isDark ? "#7f1d1d" : "#fecaca"
|
|
574
|
-
}, children: /* @__PURE__ */ jsx(Text, {
|
|
371
|
+
}], children: /* @__PURE__ */ jsx(Text, { style: [styles.voiceErrorText, {
|
|
575
372
|
color: isDark ? "#fecaca" : "#991b1b"
|
|
576
|
-
}, children:
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
] });
|
|
373
|
+
}], children: voiceError }) }) : null,
|
|
374
|
+
showAudioRecorder ? (
|
|
375
|
+
/*
|
|
376
|
+
* Render-time JS errors thrown by `useAudioRecorder`
|
|
377
|
+
* (e.g. expo-audio native module missing, recorder
|
|
378
|
+
* constructor throws in a release build) are caught
|
|
379
|
+
* by the boundary and converted into a soft cancel
|
|
380
|
+
* via the same handlers the panel itself uses on
|
|
381
|
+
* runtime errors. Without this, a throw during the
|
|
382
|
+
* panel's render phase kills the JS thread in
|
|
383
|
+
* release / TestFlight.
|
|
384
|
+
*/
|
|
385
|
+
/* @__PURE__ */ jsx(MicErrorBoundary, { onCancel: handleRecorderCancel, onError: handleRecorderError, children: /* @__PURE__ */ jsx(AudioRecorderPanel, { isDark, onTranscriptionComplete: handleTranscriptionComplete, onCancel: handleRecorderCancel, onError: handleRecorderError }) })
|
|
386
|
+
) : /* @__PURE__ */ jsx(InputToolBar, { inputConfig, leftItems, rightItems, templateButton: null, templateModalConfig: null, micSendButton })
|
|
387
|
+
] }) })
|
|
388
|
+
] }) }) });
|
|
592
389
|
}
|
|
593
390
|
const styles = StyleSheet.create({
|
|
594
|
-
/** First message / empty screen: loader in the middle of the pane. */
|
|
595
|
-
sendingLoaderEmptyState: {
|
|
596
|
-
position: "absolute",
|
|
597
|
-
left: 0,
|
|
598
|
-
right: 0,
|
|
599
|
-
top: 0,
|
|
600
|
-
bottom: 0,
|
|
601
|
-
justifyContent: "center",
|
|
602
|
-
alignItems: "center",
|
|
603
|
-
zIndex: 40
|
|
604
|
-
},
|
|
605
|
-
/** Active thread: loader just above the input, not over message history. */
|
|
606
|
-
sendingLoaderAboveComposer: {
|
|
607
|
-
position: "absolute",
|
|
608
|
-
left: 0,
|
|
609
|
-
right: 0,
|
|
610
|
-
alignItems: "center",
|
|
611
|
-
justifyContent: "flex-end",
|
|
612
|
-
paddingBottom: 8,
|
|
613
|
-
zIndex: 40
|
|
614
|
-
},
|
|
615
|
-
headerRight: {
|
|
616
|
-
flexDirection: "row",
|
|
617
|
-
alignItems: "center",
|
|
618
|
-
marginRight: 6,
|
|
619
|
-
gap: 6
|
|
620
|
-
},
|
|
621
|
-
historyHeaderButton: {
|
|
622
|
-
marginHorizontal: 0,
|
|
623
|
-
padding: 0,
|
|
624
|
-
borderRadius: 22
|
|
625
|
-
},
|
|
626
|
-
historyHeaderButtonPressed: {
|
|
627
|
-
opacity: 0.72
|
|
628
|
-
},
|
|
629
|
-
historyHeaderButtonInner: {
|
|
630
|
-
width: 32,
|
|
631
|
-
height: 32,
|
|
632
|
-
borderRadius: 16,
|
|
633
|
-
alignItems: "center",
|
|
634
|
-
justifyContent: "center",
|
|
635
|
-
backgroundColor: mobileTokens.color.primarySoft,
|
|
636
|
-
borderWidth: StyleSheet.hairlineWidth,
|
|
637
|
-
borderColor: mobileTokens.color.primaryBorder,
|
|
638
|
-
shadowColor: "#312e81",
|
|
639
|
-
shadowOpacity: 0.1,
|
|
640
|
-
shadowRadius: 5,
|
|
641
|
-
shadowOffset: {
|
|
642
|
-
width: 0,
|
|
643
|
-
height: 2
|
|
644
|
-
},
|
|
645
|
-
elevation: 2
|
|
646
|
-
},
|
|
647
|
-
historyHeaderButtonInnerDark: {
|
|
648
|
-
backgroundColor: "#1e293b",
|
|
649
|
-
borderColor: "rgba(148, 163, 184, 0.35)",
|
|
650
|
-
shadowColor: "#111827"
|
|
651
|
-
},
|
|
652
|
-
newChatButton: {
|
|
653
|
-
padding: 0,
|
|
654
|
-
alignItems: "center",
|
|
655
|
-
justifyContent: "center",
|
|
656
|
-
borderRadius: 22
|
|
657
|
-
},
|
|
658
|
-
newChatButtonInner: {
|
|
659
|
-
width: 32,
|
|
660
|
-
height: 32,
|
|
661
|
-
borderRadius: 16,
|
|
662
|
-
alignItems: "center",
|
|
663
|
-
justifyContent: "center",
|
|
664
|
-
backgroundColor: mobileTokens.color.surface,
|
|
665
|
-
borderWidth: 1,
|
|
666
|
-
borderColor: mobileTokens.color.border,
|
|
667
|
-
shadowColor: "#0f172a",
|
|
668
|
-
shadowOpacity: 0.08,
|
|
669
|
-
shadowRadius: 5,
|
|
670
|
-
shadowOffset: {
|
|
671
|
-
width: 0,
|
|
672
|
-
height: 2
|
|
673
|
-
},
|
|
674
|
-
elevation: 2
|
|
675
|
-
},
|
|
676
|
-
newChatButtonInnerDark: {
|
|
677
|
-
backgroundColor: "#0f172a",
|
|
678
|
-
borderColor: "#334155"
|
|
679
|
-
},
|
|
680
|
-
backButton: {
|
|
681
|
-
marginLeft: 6,
|
|
682
|
-
width: 36,
|
|
683
|
-
height: 36,
|
|
684
|
-
borderRadius: 18,
|
|
685
|
-
alignItems: "center",
|
|
686
|
-
justifyContent: "center",
|
|
687
|
-
backgroundColor: "#f3f4f6"
|
|
688
|
-
},
|
|
689
|
-
newChatButtonPressed: {
|
|
690
|
-
opacity: 0.6
|
|
691
|
-
},
|
|
692
391
|
emptyCenterTitleWrap: {
|
|
693
392
|
flex: 1,
|
|
694
393
|
alignItems: "center",
|
|
@@ -729,7 +428,6 @@ const styles = StyleSheet.create({
|
|
|
729
428
|
bottom: 0,
|
|
730
429
|
alignItems: "center",
|
|
731
430
|
justifyContent: "flex-end",
|
|
732
|
-
// borderTopWidth: 1,
|
|
733
431
|
shadowColor: "#0f172a",
|
|
734
432
|
shadowOpacity: 0.08,
|
|
735
433
|
shadowRadius: 8,
|
|
@@ -745,6 +443,17 @@ const styles = StyleSheet.create({
|
|
|
745
443
|
paddingTop: 10,
|
|
746
444
|
paddingBottom: 4
|
|
747
445
|
},
|
|
446
|
+
voiceErrorBanner: {
|
|
447
|
+
marginBottom: 8,
|
|
448
|
+
paddingHorizontal: 12,
|
|
449
|
+
paddingVertical: 8,
|
|
450
|
+
borderRadius: 10,
|
|
451
|
+
borderWidth: 1
|
|
452
|
+
},
|
|
453
|
+
voiceErrorText: {
|
|
454
|
+
fontSize: 12,
|
|
455
|
+
fontWeight: "500"
|
|
456
|
+
},
|
|
748
457
|
emptyModePillRow: {
|
|
749
458
|
flexDirection: "row",
|
|
750
459
|
alignItems: "center",
|