@adminide-stack/yantra-mobile 12.0.43-alpha.4 → 12.0.43-alpha.7

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.
@@ -1,4 +1,4 @@
1
- import {jsxs,Fragment,jsx}from'react/jsx-runtime';import {useState,useCallback,useMemo}from'react';import {Pressable,StyleSheet,Text,useWindowDimensions,Modal,View,TextInput,ScrollView}from'react-native';import {useNavigation,useRoute,CommonActions}from'@react-navigation/native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {useSafeAreaInsets}from'react-native-safe-area-context';import {v4}from'uuid';import {groupMobileApps,MOBILE_APP_CATALOG}from'../../features/apps/mobileAppCatalog.js';import {useChatMutations}from'../../hooks/useChatApi.js';import {mobileTokens}from'../../theme/mobileTokens.js';var __defProp = Object.defineProperty;
1
+ import {jsxs,Fragment,jsx}from'react/jsx-runtime';import {useState,useCallback,useMemo}from'react';import {Pressable,StyleSheet,Text,useWindowDimensions,Modal,View,TextInput,ScrollView}from'react-native';import {useNavigation,useRoute,CommonActions}from'@react-navigation/native';import {MaterialCommunityIcons}from'@expo/vector-icons';import {useSafeAreaInsets}from'react-native-safe-area-context';import {v4}from'uuid';import {config}from'../../config/env-config.js';import {resolveSurfaceUrl}from'../../features/apps/resolveSurfaceUrl.js';import {groupMobileApps,MOBILE_APP_CATALOG}from'../../features/apps/mobileAppCatalog.js';import {useChatMutations}from'../../hooks/useChatApi.js';import {mobileTokens}from'../../theme/mobileTokens.js';var __defProp = Object.defineProperty;
2
2
  var __defProps = Object.defineProperties;
3
3
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
@@ -76,9 +76,12 @@ function AppsMenuSheet({
76
76
  channelId
77
77
  };
78
78
  if (app.nativeRoute === "webbuilder") {
79
+ const surfaceUrl = resolveSurfaceUrl(app, config);
79
80
  navigation.dispatch(CommonActions.navigate({
80
81
  name: "MainStack.WebBuilder",
81
- params
82
+ params: surfaceUrl ? __spreadProps(__spreadValues({}, params), {
83
+ url: surfaceUrl
84
+ }) : params
82
85
  }));
83
86
  return;
84
87
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AppsMenu.js","sources":["../../../src/components/AppsMenu/AppsMenu.tsx"],"sourcesContent":["/**\n * Apps launcher for the mobile header. Mirrors the browser ChatTopBar Apps menu:\n * one trigger, grouped catalog, search, then navigate into a native surface or chat.\n *\n * The trigger is a separate component so Apollo/chat hooks cannot prevent the\n * header control from mounting.\n */\nimport React, { useCallback, useMemo, useState } from 'react';\nimport { Modal, Pressable, ScrollView, StyleSheet, Text, TextInput, View, useWindowDimensions } from 'react-native';\nimport { CommonActions, useNavigation, useRoute } from '@react-navigation/native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { v4 as uuidv4 } from 'uuid';\nimport { groupMobileApps, MOBILE_APP_CATALOG, type MobileAppItem } from '../../features/apps/mobileAppCatalog';\nimport { useChatMutations } from '../../hooks/useChatApi';\nimport { mobileTokens } from '../../theme/mobileTokens';\n\nexport type AppsMenuProps = {\n isDark: boolean;\n compact?: boolean;\n orgName?: string | null;\n};\n\nfunction buildChannelTitle(channelId: string): string {\n return `chat-channel-${channelId}`;\n}\n\nfunction AppsMenuTrigger({ isDark, compact, onPress }: { isDark: boolean; compact: boolean; onPress: () => void }) {\n const ink = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n\n return (\n <Pressable\n onPress={onPress}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Apps\"\n hitSlop={6}\n style={({ pressed }) => [styles.trigger, pressed && styles.triggerPressed]}\n >\n <MaterialCommunityIcons name=\"view-grid-outline\" size={18} color={ink} />\n {compact ? null : (\n <Text style={[styles.triggerLabel, { color: ink }]} numberOfLines={1}>\n Apps\n </Text>\n )}\n <MaterialCommunityIcons name=\"chevron-down\" size={14} color={muted} />\n </Pressable>\n );\n}\n\nfunction AppsMenuSheet({\n isDark,\n orgName: orgNameProp,\n onClose,\n}: {\n isDark: boolean;\n orgName?: string | null;\n onClose: () => void;\n}) {\n const navigation = useNavigation<any>();\n const route = useRoute<any>();\n const insets = useSafeAreaInsets();\n const { height: windowHeight } = useWindowDimensions();\n const { createChannel } = useChatMutations();\n const [query, setQuery] = useState('');\n\n const orgName = useMemo(() => {\n if (typeof orgNameProp === 'string' && orgNameProp.trim()) return orgNameProp.trim();\n const raw = (route?.params?.orgName as string | undefined) ?? '';\n return typeof raw === 'string' && raw.trim() ? raw.trim() : null;\n }, [orgNameProp, route?.params?.orgName]);\n\n const grouped = useMemo(() => groupMobileApps(MOBILE_APP_CATALOG, query), [query]);\n\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const foreground = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const surface = isDark ? '#111827' : mobileTokens.color.surface;\n const sheetBg = isDark ? '#0f172a' : mobileTokens.color.surface;\n const borderColor = isDark ? 'rgba(148,163,184,0.22)' : mobileTokens.color.border;\n const fieldBg = isDark ? '#1e293b' : mobileTokens.color.surfaceMuted;\n const accent = isDark ? '#a5b4fc' : mobileTokens.color.primary;\n const accentSoft = isDark ? 'rgba(99,102,241,0.18)' : mobileTokens.color.primarySoft;\n\n const openApp = useCallback(\n (app: MobileAppItem) => {\n onClose();\n const channelId = uuidv4();\n const params: Record<string, unknown> = {\n orgName: orgName ?? undefined,\n channelId,\n };\n\n if (app.nativeRoute === 'webbuilder') {\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.WebBuilder',\n params,\n }),\n );\n return;\n }\n\n void createChannel({\n id: channelId,\n title: buildChannelTitle(channelId),\n isShared: false,\n sharedSlug: null,\n isArchived: false,\n isPinned: false,\n model: null,\n systemPrompt: null,\n orgName,\n } as any).catch((err) => {\n console.error('[AppsMenu] createChannel failed:', err);\n });\n\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.Chat',\n params: {\n ...params,\n initialQuery: app.prompt,\n initialMode: 'chat',\n },\n }),\n );\n },\n [createChannel, navigation, onClose, orgName],\n );\n\n return (\n <Modal visible animationType=\"slide\" transparent onRequestClose={onClose}>\n <View style={styles.modalRoot}>\n <Pressable style={styles.backdrop} onPress={onClose} accessibilityLabel=\"Close apps\" />\n <View\n style={[\n styles.sheet,\n {\n backgroundColor: sheetBg,\n maxHeight: Math.round(windowHeight * 0.86),\n paddingBottom: Math.max(insets.bottom, 12),\n },\n ]}\n >\n <View style={styles.handleWrap}>\n <View style={[styles.handle, { backgroundColor: borderColor }]} />\n </View>\n <View style={styles.header}>\n <Text style={[styles.title, { color: foreground }]}>Apps</Text>\n <Pressable onPress={onClose} hitSlop={10} accessibilityLabel=\"Close\" accessibilityRole=\"button\">\n <MaterialCommunityIcons name=\"close\" size={22} color={muted} />\n </Pressable>\n </View>\n <View style={[styles.searchWrap, { backgroundColor: fieldBg, borderColor }]}>\n <MaterialCommunityIcons name=\"magnify\" size={18} color={muted} />\n <TextInput\n value={query}\n onChangeText={setQuery}\n placeholder=\"Search apps\"\n placeholderTextColor={muted}\n autoCorrect={false}\n autoCapitalize=\"none\"\n style={[styles.searchInput, { color: foreground }]}\n />\n </View>\n <ScrollView keyboardShouldPersistTaps=\"handled\" contentContainerStyle={styles.list}>\n {grouped.length === 0 ? (\n <Text style={[styles.empty, { color: muted }]}>No apps match that search.</Text>\n ) : (\n grouped.map((group) => (\n <View key={group.label} style={styles.group}>\n <Text style={[styles.groupLabel, { color: muted }]}>{group.label}</Text>\n <View style={styles.groupGrid}>\n {group.items.map((app) => (\n <Pressable\n key={app.key}\n onPress={() => openApp(app)}\n accessibilityRole=\"button\"\n accessibilityLabel={app.label}\n style={({ pressed }) => [\n styles.appTile,\n {\n backgroundColor: surface,\n borderColor,\n },\n pressed && { backgroundColor: accentSoft },\n ]}\n >\n <View style={[styles.appIcon, { backgroundColor: accentSoft }]}>\n <MaterialCommunityIcons name={app.icon} size={18} color={accent} />\n </View>\n <Text\n style={[styles.appLabel, { color: foreground }]}\n numberOfLines={2}\n >\n {app.label}\n </Text>\n </Pressable>\n ))}\n </View>\n </View>\n ))\n )}\n </ScrollView>\n </View>\n </View>\n </Modal>\n );\n}\n\nexport function AppsMenu({ isDark, compact = false, orgName }: AppsMenuProps) {\n const [open, setOpen] = useState(false);\n const close = useCallback(() => setOpen(false), []);\n\n return (\n <>\n <AppsMenuTrigger isDark={isDark} compact={compact} onPress={() => setOpen(true)} />\n {open ? <AppsMenuSheet isDark={isDark} orgName={orgName} onClose={close} /> : null}\n </>\n );\n}\n\nconst styles = StyleSheet.create({\n trigger: {\n flexDirection: 'row',\n alignItems: 'center',\n flexShrink: 0,\n gap: 4,\n height: 36,\n paddingHorizontal: 6,\n borderRadius: 10,\n },\n triggerPressed: {\n opacity: 0.7,\n },\n triggerLabel: {\n fontSize: 13,\n fontWeight: '600',\n letterSpacing: -0.2,\n },\n modalRoot: {\n flex: 1,\n justifyContent: 'flex-end',\n },\n backdrop: {\n ...StyleSheet.absoluteFillObject,\n backgroundColor: 'rgba(15, 23, 42, 0.36)',\n },\n sheet: {\n borderTopLeftRadius: 18,\n borderTopRightRadius: 18,\n width: '100%',\n overflow: 'hidden',\n },\n handleWrap: {\n alignItems: 'center',\n paddingTop: 8,\n paddingBottom: 4,\n },\n handle: {\n width: 36,\n height: 4,\n borderRadius: 999,\n },\n header: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingHorizontal: 16,\n paddingBottom: 8,\n },\n title: {\n fontSize: 20,\n fontWeight: '700',\n letterSpacing: -0.4,\n },\n searchWrap: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 8,\n marginHorizontal: 16,\n marginBottom: 8,\n borderWidth: 1,\n borderRadius: 12,\n paddingHorizontal: 12,\n minHeight: 42,\n },\n searchInput: {\n flex: 1,\n fontSize: 15,\n paddingVertical: 8,\n },\n list: {\n paddingHorizontal: 16,\n paddingTop: 8,\n paddingBottom: 20,\n gap: 16,\n },\n group: {\n gap: 8,\n },\n groupLabel: {\n fontSize: 11,\n fontWeight: '600',\n letterSpacing: 0.7,\n textTransform: 'uppercase',\n },\n groupGrid: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n gap: 8,\n },\n appTile: {\n width: '31%',\n flexGrow: 1,\n minWidth: 96,\n maxWidth: '32.5%',\n borderWidth: 1,\n borderRadius: 14,\n paddingHorizontal: 10,\n paddingVertical: 12,\n gap: 8,\n },\n appIcon: {\n width: 32,\n height: 32,\n borderRadius: 10,\n alignItems: 'center',\n justifyContent: 'center',\n },\n appLabel: {\n fontSize: 13,\n fontWeight: '600',\n lineHeight: 17,\n },\n empty: {\n textAlign: 'center',\n paddingVertical: 28,\n fontSize: 14,\n },\n});\n\nexport default AppsMenu;\n"],"names":["_a","uuidv4"],"mappings":"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"}
1
+ {"version":3,"file":"AppsMenu.js","sources":["../../../src/components/AppsMenu/AppsMenu.tsx"],"sourcesContent":["/**\n * Apps launcher for the mobile header. Mirrors the browser ChatTopBar Apps menu:\n * one trigger, grouped catalog, search, then navigate into a native surface or chat.\n *\n * The trigger is a separate component so Apollo/chat hooks cannot prevent the\n * header control from mounting.\n */\nimport React, { useCallback, useMemo, useState } from 'react';\nimport { Modal, Pressable, ScrollView, StyleSheet, Text, TextInput, View, useWindowDimensions } from 'react-native';\nimport { CommonActions, useNavigation, useRoute } from '@react-navigation/native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\nimport { useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { v4 as uuidv4 } from 'uuid';\nimport { config } from '../../config/env-config';\nimport { resolveSurfaceUrl } from '../../features/apps/resolveSurfaceUrl';\nimport { groupMobileApps, MOBILE_APP_CATALOG, type MobileAppItem } from '../../features/apps/mobileAppCatalog';\nimport { useChatMutations } from '../../hooks/useChatApi';\nimport { mobileTokens } from '../../theme/mobileTokens';\n\nexport type AppsMenuProps = {\n isDark: boolean;\n compact?: boolean;\n orgName?: string | null;\n};\n\nfunction buildChannelTitle(channelId: string): string {\n return `chat-channel-${channelId}`;\n}\n\nfunction AppsMenuTrigger({ isDark, compact, onPress }: { isDark: boolean; compact: boolean; onPress: () => void }) {\n const ink = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n\n return (\n <Pressable\n onPress={onPress}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Apps\"\n hitSlop={6}\n style={({ pressed }) => [styles.trigger, pressed && styles.triggerPressed]}\n >\n <MaterialCommunityIcons name=\"view-grid-outline\" size={18} color={ink} />\n {compact ? null : (\n <Text style={[styles.triggerLabel, { color: ink }]} numberOfLines={1}>\n Apps\n </Text>\n )}\n <MaterialCommunityIcons name=\"chevron-down\" size={14} color={muted} />\n </Pressable>\n );\n}\n\nfunction AppsMenuSheet({\n isDark,\n orgName: orgNameProp,\n onClose,\n}: {\n isDark: boolean;\n orgName?: string | null;\n onClose: () => void;\n}) {\n const navigation = useNavigation<any>();\n const route = useRoute<any>();\n const insets = useSafeAreaInsets();\n const { height: windowHeight } = useWindowDimensions();\n const { createChannel } = useChatMutations();\n const [query, setQuery] = useState('');\n\n const orgName = useMemo(() => {\n if (typeof orgNameProp === 'string' && orgNameProp.trim()) return orgNameProp.trim();\n const raw = (route?.params?.orgName as string | undefined) ?? '';\n return typeof raw === 'string' && raw.trim() ? raw.trim() : null;\n }, [orgNameProp, route?.params?.orgName]);\n\n const grouped = useMemo(() => groupMobileApps(MOBILE_APP_CATALOG, query), [query]);\n\n const muted = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n const foreground = isDark ? '#e2e8f0' : mobileTokens.color.text;\n const surface = isDark ? '#111827' : mobileTokens.color.surface;\n const sheetBg = isDark ? '#0f172a' : mobileTokens.color.surface;\n const borderColor = isDark ? 'rgba(148,163,184,0.22)' : mobileTokens.color.border;\n const fieldBg = isDark ? '#1e293b' : mobileTokens.color.surfaceMuted;\n const accent = isDark ? '#a5b4fc' : mobileTokens.color.primary;\n const accentSoft = isDark ? 'rgba(99,102,241,0.18)' : mobileTokens.color.primarySoft;\n\n const openApp = useCallback(\n (app: MobileAppItem) => {\n onClose();\n const channelId = uuidv4();\n const params: Record<string, unknown> = {\n orgName: orgName ?? undefined,\n channelId,\n };\n\n if (app.nativeRoute === 'webbuilder') {\n // The WebBuilder screen is the shared surface shell, not a\n // web-builder-only route: it takes `url` and does the rest (token\n // mint, bridge injection, embed=mobile, retry). Passing the app's\n // own surface origin is what makes Canvas open as a surface\n // instead of falling through to the prompt shim below.\n const surfaceUrl = resolveSurfaceUrl(app, config);\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.WebBuilder',\n params: surfaceUrl ? { ...params, url: surfaceUrl } : params,\n }),\n );\n return;\n }\n\n void createChannel({\n id: channelId,\n title: buildChannelTitle(channelId),\n isShared: false,\n sharedSlug: null,\n isArchived: false,\n isPinned: false,\n model: null,\n systemPrompt: null,\n orgName,\n } as any).catch((err) => {\n console.error('[AppsMenu] createChannel failed:', err);\n });\n\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.Chat',\n params: {\n ...params,\n initialQuery: app.prompt,\n initialMode: 'chat',\n },\n }),\n );\n },\n [createChannel, navigation, onClose, orgName],\n );\n\n return (\n <Modal visible animationType=\"slide\" transparent onRequestClose={onClose}>\n <View style={styles.modalRoot}>\n <Pressable style={styles.backdrop} onPress={onClose} accessibilityLabel=\"Close apps\" />\n <View\n style={[\n styles.sheet,\n {\n backgroundColor: sheetBg,\n maxHeight: Math.round(windowHeight * 0.86),\n paddingBottom: Math.max(insets.bottom, 12),\n },\n ]}\n >\n <View style={styles.handleWrap}>\n <View style={[styles.handle, { backgroundColor: borderColor }]} />\n </View>\n <View style={styles.header}>\n <Text style={[styles.title, { color: foreground }]}>Apps</Text>\n <Pressable onPress={onClose} hitSlop={10} accessibilityLabel=\"Close\" accessibilityRole=\"button\">\n <MaterialCommunityIcons name=\"close\" size={22} color={muted} />\n </Pressable>\n </View>\n <View style={[styles.searchWrap, { backgroundColor: fieldBg, borderColor }]}>\n <MaterialCommunityIcons name=\"magnify\" size={18} color={muted} />\n <TextInput\n value={query}\n onChangeText={setQuery}\n placeholder=\"Search apps\"\n placeholderTextColor={muted}\n autoCorrect={false}\n autoCapitalize=\"none\"\n style={[styles.searchInput, { color: foreground }]}\n />\n </View>\n <ScrollView keyboardShouldPersistTaps=\"handled\" contentContainerStyle={styles.list}>\n {grouped.length === 0 ? (\n <Text style={[styles.empty, { color: muted }]}>No apps match that search.</Text>\n ) : (\n grouped.map((group) => (\n <View key={group.label} style={styles.group}>\n <Text style={[styles.groupLabel, { color: muted }]}>{group.label}</Text>\n <View style={styles.groupGrid}>\n {group.items.map((app) => (\n <Pressable\n key={app.key}\n onPress={() => openApp(app)}\n accessibilityRole=\"button\"\n accessibilityLabel={app.label}\n style={({ pressed }) => [\n styles.appTile,\n {\n backgroundColor: surface,\n borderColor,\n },\n pressed && { backgroundColor: accentSoft },\n ]}\n >\n <View style={[styles.appIcon, { backgroundColor: accentSoft }]}>\n <MaterialCommunityIcons name={app.icon} size={18} color={accent} />\n </View>\n <Text\n style={[styles.appLabel, { color: foreground }]}\n numberOfLines={2}\n >\n {app.label}\n </Text>\n </Pressable>\n ))}\n </View>\n </View>\n ))\n )}\n </ScrollView>\n </View>\n </View>\n </Modal>\n );\n}\n\nexport function AppsMenu({ isDark, compact = false, orgName }: AppsMenuProps) {\n const [open, setOpen] = useState(false);\n const close = useCallback(() => setOpen(false), []);\n\n return (\n <>\n <AppsMenuTrigger isDark={isDark} compact={compact} onPress={() => setOpen(true)} />\n {open ? <AppsMenuSheet isDark={isDark} orgName={orgName} onClose={close} /> : null}\n </>\n );\n}\n\nconst styles = StyleSheet.create({\n trigger: {\n flexDirection: 'row',\n alignItems: 'center',\n flexShrink: 0,\n gap: 4,\n height: 36,\n paddingHorizontal: 6,\n borderRadius: 10,\n },\n triggerPressed: {\n opacity: 0.7,\n },\n triggerLabel: {\n fontSize: 13,\n fontWeight: '600',\n letterSpacing: -0.2,\n },\n modalRoot: {\n flex: 1,\n justifyContent: 'flex-end',\n },\n backdrop: {\n ...StyleSheet.absoluteFillObject,\n backgroundColor: 'rgba(15, 23, 42, 0.36)',\n },\n sheet: {\n borderTopLeftRadius: 18,\n borderTopRightRadius: 18,\n width: '100%',\n overflow: 'hidden',\n },\n handleWrap: {\n alignItems: 'center',\n paddingTop: 8,\n paddingBottom: 4,\n },\n handle: {\n width: 36,\n height: 4,\n borderRadius: 999,\n },\n header: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingHorizontal: 16,\n paddingBottom: 8,\n },\n title: {\n fontSize: 20,\n fontWeight: '700',\n letterSpacing: -0.4,\n },\n searchWrap: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 8,\n marginHorizontal: 16,\n marginBottom: 8,\n borderWidth: 1,\n borderRadius: 12,\n paddingHorizontal: 12,\n minHeight: 42,\n },\n searchInput: {\n flex: 1,\n fontSize: 15,\n paddingVertical: 8,\n },\n list: {\n paddingHorizontal: 16,\n paddingTop: 8,\n paddingBottom: 20,\n gap: 16,\n },\n group: {\n gap: 8,\n },\n groupLabel: {\n fontSize: 11,\n fontWeight: '600',\n letterSpacing: 0.7,\n textTransform: 'uppercase',\n },\n groupGrid: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n gap: 8,\n },\n appTile: {\n width: '31%',\n flexGrow: 1,\n minWidth: 96,\n maxWidth: '32.5%',\n borderWidth: 1,\n borderRadius: 14,\n paddingHorizontal: 10,\n paddingVertical: 12,\n gap: 8,\n },\n appIcon: {\n width: 32,\n height: 32,\n borderRadius: 10,\n alignItems: 'center',\n justifyContent: 'center',\n },\n appLabel: {\n fontSize: 13,\n fontWeight: '600',\n lineHeight: 17,\n },\n empty: {\n textAlign: 'center',\n paddingVertical: 28,\n fontSize: 14,\n },\n});\n\nexport default AppsMenu;\n"],"names":["_a","uuidv4"],"mappings":"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"}
@@ -29,6 +29,18 @@ const baseConfig = cleanEnv(env, {
29
29
  WEB_BUILDER_URL: str({
30
30
  default: "http://localhost:5174/"
31
31
  }),
32
+ /** Standalone Canvas surface embedded in the same WebView shell. */
33
+ CANVAS_SURFACE_URL: str({
34
+ default: "http://localhost:5175/"
35
+ }),
36
+ /**
37
+ * Origin template for every other deployed surface: `{slug}` is the app's
38
+ * `surfaceSlug`. One var instead of 20+ near-identical URLs, and it keeps the
39
+ * environment (dev cluster / prod) in one place.
40
+ */
41
+ SURFACE_URL_TEMPLATE: str({
42
+ default: "https://{slug}-surface.yantra-app-v1.cdebase.dev/"
43
+ }),
32
44
  APP_NAME: str({
33
45
  default: "Yantra"
34
46
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"env-config.js","sources":["../../src/config/env-config.ts"],"sourcesContent":["import { str, cleanEnv, bool, num } from 'envalid';\n\nconst env = (process as { APP_ENV?: NodeJS.ProcessEnv; env?: NodeJS.ProcessEnv }).APP_ENV || process.env;\n\nconst baseConfig = cleanEnv(env, {\n GRAPHQL_URL: str({ default: 'http://localhost:8080/graphql' }),\n CLIENT_URL: str({ default: 'http://localhost:3000' }),\n /** Standalone Web Builder surface embedded in the mobile WebView shell. */\n WEB_BUILDER_URL: str({ default: 'http://localhost:5174/' }),\n APP_NAME: str({ default: 'Yantra' }),\n GROQ_API_KEY: str({ default: '' }),\n CDECLI_AGENT_ENDPOINT: str({ default: 'https://cdecli-agent.cdebase.dev' }),\n CDECLI_AGENT_AUTH_TOKEN: str({ default: '' }),\n /** Seconds to wait for CDeCLI stream completion before timing out (then fallback chat API runs). Min 15, max 600. */\n /** Aligned with web `useCdecliChannel` (120s). Mobile hook uses the same constant inline. */\n CDECLI_CHAT_RESPONSE_TIMEOUT_SEC: num({ default: 120 }),\n BACKEND_URL: str({ default: '' }),\n USE_PROXY_STAGING_GATEWAY: bool({ default: false }),\n PROXY_STAGING_GATEWAY_URL: str({ default: '' }),\n});\n\nfunction resolveAgentGatewayGraphqlUrl(): string {\n if (baseConfig.USE_PROXY_STAGING_GATEWAY && baseConfig.PROXY_STAGING_GATEWAY_URL) {\n return baseConfig.PROXY_STAGING_GATEWAY_URL;\n }\n if (baseConfig.GRAPHQL_URL) return baseConfig.GRAPHQL_URL;\n if (baseConfig.BACKEND_URL) return `${baseConfig.BACKEND_URL.replace(/\\/$/, '')}/graphql`;\n return '/graphql';\n}\n\nfunction resolveBaseWsUrl(graphqlUrl: string): string {\n const base = graphqlUrl.replace(/\\/graphql$/, '');\n return base.replace(/^http/, 'ws');\n}\n\nfunction resolveAgentGatewayWsUrl(graphqlUrl: string): string {\n return `${resolveBaseWsUrl(graphqlUrl)}/ws/openclaw-chat`;\n}\n\nconst agentGatewayGraphqlUrl = resolveAgentGatewayGraphqlUrl();\n\nconst clampedCdecliTimeoutSec = Math.min(600, Math.max(15, Math.round(baseConfig.CDECLI_CHAT_RESPONSE_TIMEOUT_SEC)));\n\nexport const config = {\n ...baseConfig,\n CDECLI_CHAT_RESPONSE_TIMEOUT_SEC: clampedCdecliTimeoutSec,\n AGENT_GATEWAY_GRAPHQL_URL: agentGatewayGraphqlUrl,\n AGENT_GATEWAY_WS_URL: resolveAgentGatewayWsUrl(agentGatewayGraphqlUrl),\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AACA,MAAM,GAAA,GAAO,OAGV,CAAA,OAAA,IAAW,OAAQ,CAAA,GAAA;AACtB,MAAM,UAAA,GAAa,SAAS,GAAK,EAAA;AAAA,EAC/B,aAAa,GAAI,CAAA;AAAA,IACf,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,YAAY,GAAI,CAAA;AAAA,IACd,OAAS,EAAA;AAAA,GACV,CAAA;AAAA;AAAA,EAED,iBAAiB,GAAI,CAAA;AAAA,IACnB,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,UAAU,GAAI,CAAA;AAAA,IACZ,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,cAAc,GAAI,CAAA;AAAA,IAChB,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,uBAAuB,GAAI,CAAA;AAAA,IACzB,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,yBAAyB,GAAI,CAAA;AAAA,IAC3B,OAAS,EAAA;AAAA,GACV,CAAA;AAAA;AAAA;AAAA,EAGD,kCAAkC,GAAI,CAAA;AAAA,IACpC,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,aAAa,GAAI,CAAA;AAAA,IACf,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,2BAA2B,IAAK,CAAA;AAAA,IAC9B,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,2BAA2B,GAAI,CAAA;AAAA,IAC7B,OAAS,EAAA;AAAA,GACV;AACH,CAAC,CAAA;AACD,SAAS,6BAAwC,GAAA;AAC/C,EAAI,IAAA,UAAA,CAAW,yBAA6B,IAAA,UAAA,CAAW,yBAA2B,EAAA;AAChF,IAAA,OAAO,UAAW,CAAA,yBAAA;AAAA;AAEpB,EAAI,IAAA,UAAA,CAAW,WAAa,EAAA,OAAO,UAAW,CAAA,WAAA;AAC9C,EAAI,IAAA,UAAA,CAAW,aAAoB,OAAA,CAAA,EAAG,WAAW,WAAY,CAAA,OAAA,CAAQ,KAAO,EAAA,EAAE,CAAC,CAAA,QAAA,CAAA;AAC/E,EAAO,OAAA,UAAA;AACT;AACA,SAAS,iBAAiB,UAA4B,EAAA;AACpD,EAAA,MAAM,IAAO,GAAA,UAAA,CAAW,OAAQ,CAAA,YAAA,EAAc,EAAE,CAAA;AAChD,EAAO,OAAA,IAAA,CAAK,OAAQ,CAAA,OAAA,EAAS,IAAI,CAAA;AACnC;AACA,SAAS,yBAAyB,UAA4B,EAAA;AAC5D,EAAO,OAAA,CAAA,EAAG,gBAAiB,CAAA,UAAU,CAAC,CAAA,iBAAA,CAAA;AACxC;AACA,MAAM,yBAAyB,6BAA8B,EAAA;AAC7D,MAAM,uBAA0B,GAAA,IAAA,CAAK,GAAI,CAAA,GAAA,EAAK,IAAK,CAAA,GAAA,CAAI,EAAI,EAAA,IAAA,CAAK,KAAM,CAAA,UAAA,CAAW,gCAAgC,CAAC,CAAC,CAAA;AACtG,MAAA,MAAA,GAAS,iCACjB,UADiB,CAAA,EAAA;AAAA,EAEpB,gCAAkC,EAAA,uBAAA;AAAA,EAClC,yBAA2B,EAAA,sBAAA;AAAA,EAC3B,oBAAA,EAAsB,yBAAyB,sBAAsB;AACvE,CAAA"}
1
+ {"version":3,"file":"env-config.js","sources":["../../src/config/env-config.ts"],"sourcesContent":["import { str, cleanEnv, bool, num } from 'envalid';\n\nconst env = (process as { APP_ENV?: NodeJS.ProcessEnv; env?: NodeJS.ProcessEnv }).APP_ENV || process.env;\n\nconst baseConfig = cleanEnv(env, {\n GRAPHQL_URL: str({ default: 'http://localhost:8080/graphql' }),\n CLIENT_URL: str({ default: 'http://localhost:3000' }),\n /** Standalone Web Builder surface embedded in the mobile WebView shell. */\n WEB_BUILDER_URL: str({ default: 'http://localhost:5174/' }),\n /** Standalone Canvas surface embedded in the same WebView shell. */\n CANVAS_SURFACE_URL: str({ default: 'http://localhost:5175/' }),\n /**\n * Origin template for every other deployed surface: `{slug}` is the app's\n * `surfaceSlug`. One var instead of 20+ near-identical URLs, and it keeps the\n * environment (dev cluster / prod) in one place.\n */\n SURFACE_URL_TEMPLATE: str({ default: 'https://{slug}-surface.yantra-app-v1.cdebase.dev/' }),\n APP_NAME: str({ default: 'Yantra' }),\n GROQ_API_KEY: str({ default: '' }),\n CDECLI_AGENT_ENDPOINT: str({ default: 'https://cdecli-agent.cdebase.dev' }),\n CDECLI_AGENT_AUTH_TOKEN: str({ default: '' }),\n /** Seconds to wait for CDeCLI stream completion before timing out (then fallback chat API runs). Min 15, max 600. */\n /** Aligned with web `useCdecliChannel` (120s). Mobile hook uses the same constant inline. */\n CDECLI_CHAT_RESPONSE_TIMEOUT_SEC: num({ default: 120 }),\n BACKEND_URL: str({ default: '' }),\n USE_PROXY_STAGING_GATEWAY: bool({ default: false }),\n PROXY_STAGING_GATEWAY_URL: str({ default: '' }),\n});\n\nfunction resolveAgentGatewayGraphqlUrl(): string {\n if (baseConfig.USE_PROXY_STAGING_GATEWAY && baseConfig.PROXY_STAGING_GATEWAY_URL) {\n return baseConfig.PROXY_STAGING_GATEWAY_URL;\n }\n if (baseConfig.GRAPHQL_URL) return baseConfig.GRAPHQL_URL;\n if (baseConfig.BACKEND_URL) return `${baseConfig.BACKEND_URL.replace(/\\/$/, '')}/graphql`;\n return '/graphql';\n}\n\nfunction resolveBaseWsUrl(graphqlUrl: string): string {\n const base = graphqlUrl.replace(/\\/graphql$/, '');\n return base.replace(/^http/, 'ws');\n}\n\nfunction resolveAgentGatewayWsUrl(graphqlUrl: string): string {\n return `${resolveBaseWsUrl(graphqlUrl)}/ws/openclaw-chat`;\n}\n\nconst agentGatewayGraphqlUrl = resolveAgentGatewayGraphqlUrl();\n\nconst clampedCdecliTimeoutSec = Math.min(600, Math.max(15, Math.round(baseConfig.CDECLI_CHAT_RESPONSE_TIMEOUT_SEC)));\n\nexport const config = {\n ...baseConfig,\n CDECLI_CHAT_RESPONSE_TIMEOUT_SEC: clampedCdecliTimeoutSec,\n AGENT_GATEWAY_GRAPHQL_URL: agentGatewayGraphqlUrl,\n AGENT_GATEWAY_WS_URL: resolveAgentGatewayWsUrl(agentGatewayGraphqlUrl),\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AACA,MAAM,GAAA,GAAO,OAGV,CAAA,OAAA,IAAW,OAAQ,CAAA,GAAA;AACtB,MAAM,UAAA,GAAa,SAAS,GAAK,EAAA;AAAA,EAC/B,aAAa,GAAI,CAAA;AAAA,IACf,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,YAAY,GAAI,CAAA;AAAA,IACd,OAAS,EAAA;AAAA,GACV,CAAA;AAAA;AAAA,EAED,iBAAiB,GAAI,CAAA;AAAA,IACnB,OAAS,EAAA;AAAA,GACV,CAAA;AAAA;AAAA,EAED,oBAAoB,GAAI,CAAA;AAAA,IACtB,OAAS,EAAA;AAAA,GACV,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMD,sBAAsB,GAAI,CAAA;AAAA,IACxB,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,UAAU,GAAI,CAAA;AAAA,IACZ,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,cAAc,GAAI,CAAA;AAAA,IAChB,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,uBAAuB,GAAI,CAAA;AAAA,IACzB,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,yBAAyB,GAAI,CAAA;AAAA,IAC3B,OAAS,EAAA;AAAA,GACV,CAAA;AAAA;AAAA;AAAA,EAGD,kCAAkC,GAAI,CAAA;AAAA,IACpC,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,aAAa,GAAI,CAAA;AAAA,IACf,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,2BAA2B,IAAK,CAAA;AAAA,IAC9B,OAAS,EAAA;AAAA,GACV,CAAA;AAAA,EACD,2BAA2B,GAAI,CAAA;AAAA,IAC7B,OAAS,EAAA;AAAA,GACV;AACH,CAAC,CAAA;AACD,SAAS,6BAAwC,GAAA;AAC/C,EAAI,IAAA,UAAA,CAAW,yBAA6B,IAAA,UAAA,CAAW,yBAA2B,EAAA;AAChF,IAAA,OAAO,UAAW,CAAA,yBAAA;AAAA;AAEpB,EAAI,IAAA,UAAA,CAAW,WAAa,EAAA,OAAO,UAAW,CAAA,WAAA;AAC9C,EAAI,IAAA,UAAA,CAAW,aAAoB,OAAA,CAAA,EAAG,WAAW,WAAY,CAAA,OAAA,CAAQ,KAAO,EAAA,EAAE,CAAC,CAAA,QAAA,CAAA;AAC/E,EAAO,OAAA,UAAA;AACT;AACA,SAAS,iBAAiB,UAA4B,EAAA;AACpD,EAAA,MAAM,IAAO,GAAA,UAAA,CAAW,OAAQ,CAAA,YAAA,EAAc,EAAE,CAAA;AAChD,EAAO,OAAA,IAAA,CAAK,OAAQ,CAAA,OAAA,EAAS,IAAI,CAAA;AACnC;AACA,SAAS,yBAAyB,UAA4B,EAAA;AAC5D,EAAO,OAAA,CAAA,EAAG,gBAAiB,CAAA,UAAU,CAAC,CAAA,iBAAA,CAAA;AACxC;AACA,MAAM,yBAAyB,6BAA8B,EAAA;AAC7D,MAAM,uBAA0B,GAAA,IAAA,CAAK,GAAI,CAAA,GAAA,EAAK,IAAK,CAAA,GAAA,CAAI,EAAI,EAAA,IAAA,CAAK,KAAM,CAAA,UAAA,CAAW,gCAAgC,CAAC,CAAC,CAAA;AACtG,MAAA,MAAA,GAAS,iCACjB,UADiB,CAAA,EAAA;AAAA,EAEpB,gCAAkC,EAAA,uBAAA;AAAA,EAClC,yBAA2B,EAAA,sBAAA;AAAA,EAC3B,oBAAA,EAAsB,yBAAyB,sBAAsB;AACvE,CAAA"}
@@ -3,44 +3,59 @@ const MOBILE_APP_CATALOG = [{
3
3
  label: "Design",
4
4
  icon: "palette-outline",
5
5
  group: "Create",
6
- prompt: "Design a 10-slide pitch deck for a coffee subscription startup"
6
+ prompt: "Design a 10-slide pitch deck for a coffee subscription startup",
7
+ nativeRoute: "webbuilder",
8
+ surfaceSlug: "design"
7
9
  }, {
8
10
  key: "canvas",
9
11
  label: "Canvas",
10
12
  icon: "view-grid-outline",
11
13
  group: "Create",
12
- prompt: "Open a canvas and help me lay out the assets for this project."
14
+ prompt: "Open a canvas and help me lay out the assets for this project.",
15
+ nativeRoute: "webbuilder",
16
+ surfaceUrlKey: "CANVAS_SURFACE_URL",
17
+ surfaceSlug: "canvas"
13
18
  }, {
14
19
  key: "webbuilder",
15
20
  label: "Web Builder",
16
21
  icon: "application-outline",
17
22
  group: "Create",
18
23
  prompt: "Build a landing page for my bakery with a menu and a contact form",
19
- nativeRoute: "webbuilder"
24
+ nativeRoute: "webbuilder",
25
+ surfaceUrlKey: "WEB_BUILDER_URL",
26
+ surfaceSlug: "webbuilder"
20
27
  }, {
21
28
  key: "paper2poster",
22
29
  label: "Paper 2 Poster",
23
30
  icon: "presentation",
24
31
  group: "Create",
25
- prompt: "Turn this research paper into a conference poster I can edit."
32
+ prompt: "Turn this research paper into a conference poster I can edit.",
33
+ nativeRoute: "webbuilder",
34
+ surfaceSlug: "paper2poster"
26
35
  }, {
27
36
  key: "codezen",
28
37
  label: "Codezen",
29
38
  icon: "code-braces",
30
39
  group: "Create",
31
- prompt: "Clone my repository and fix the failing test"
40
+ prompt: "Clone my repository and fix the failing test",
41
+ nativeRoute: "webbuilder",
42
+ surfaceSlug: "codezen"
32
43
  }, {
33
44
  key: "character",
34
45
  label: "Characters",
35
46
  icon: "drama-masks",
36
47
  group: "Create",
37
- prompt: "Create a stoic philosophy mentor character I can chat with"
48
+ prompt: "Create a stoic philosophy mentor character I can chat with",
49
+ nativeRoute: "webbuilder",
50
+ surfaceSlug: "character"
38
51
  }, {
39
52
  key: "workflow",
40
53
  label: "Workflow",
41
54
  icon: "sitemap",
42
55
  group: "Automate",
43
- prompt: "Build a workflow that runs every morning and sends me a summary of what changed."
56
+ prompt: "Build a workflow that runs every morning and sends me a summary of what changed.",
57
+ nativeRoute: "webbuilder",
58
+ surfaceSlug: "workflow"
44
59
  }, {
45
60
  key: "computer",
46
61
  label: "Computer",
@@ -52,91 +67,121 @@ const MOBILE_APP_CATALOG = [{
52
67
  label: "CRM",
53
68
  icon: "account-group-outline",
54
69
  group: "Sell",
55
- prompt: "Look at my pipeline and tell me which deals are going cold and what I should send them."
70
+ prompt: "Look at my pipeline and tell me which deals are going cold and what I should send them.",
71
+ nativeRoute: "webbuilder",
72
+ surfaceSlug: "crm"
56
73
  }, {
57
74
  key: "salesiq",
58
75
  label: "SalesIQ",
59
76
  icon: "radar",
60
77
  group: "Sell",
61
- prompt: "Show me who is on my website right now"
78
+ prompt: "Show me who is on my website right now",
79
+ nativeRoute: "webbuilder",
80
+ surfaceSlug: "salesiq"
62
81
  }, {
63
82
  key: "inbox",
64
83
  label: "Inbox",
65
84
  icon: "inbox-outline",
66
85
  group: "Sell",
67
- prompt: "Go through my inbox, tell me what actually needs a reply, and draft those replies."
86
+ prompt: "Go through my inbox, tell me what actually needs a reply, and draft those replies.",
87
+ nativeRoute: "webbuilder",
88
+ surfaceSlug: "inbox"
68
89
  }, {
69
90
  key: "mailcampaign",
70
91
  label: "Mail Campaigns",
71
92
  icon: "bullhorn-outline",
72
93
  group: "Sell",
73
- prompt: "Draft an email campaign announcing what we shipped this month."
94
+ prompt: "Draft an email campaign announcing what we shipped this month.",
95
+ nativeRoute: "webbuilder",
96
+ surfaceSlug: "mailcampaign"
74
97
  }, {
75
98
  key: "expenses",
76
99
  label: "Expenses",
77
100
  icon: "receipt-outline",
78
101
  group: "Money",
79
- prompt: "Summarise my spend this month and flag anything unusual."
102
+ prompt: "Summarise my spend this month and flag anything unusual.",
103
+ nativeRoute: "webbuilder",
104
+ surfaceSlug: "expenses"
80
105
  }, {
81
106
  key: "cards-wallet",
82
107
  label: "Cards & Wallet",
83
108
  icon: "credit-card-outline",
84
109
  group: "Money",
85
- prompt: "Issue a $200 virtual card for monthly ad spend"
110
+ prompt: "Issue a $200 virtual card for monthly ad spend",
111
+ nativeRoute: "webbuilder",
112
+ surfaceSlug: "cards-wallet"
86
113
  }, {
87
114
  key: "billing",
88
115
  label: "Billing",
89
116
  icon: "currency-usd",
90
117
  group: "Money",
91
- prompt: "Create an invoice for a $2,400 consulting project"
118
+ prompt: "Create an invoice for a $2,400 consulting project",
119
+ nativeRoute: "webbuilder",
120
+ surfaceSlug: "billing"
92
121
  }, {
93
122
  key: "kpi-motivation",
94
123
  label: "KPI Motivation",
95
124
  icon: "trophy-outline",
96
125
  group: "Team",
97
- prompt: "Set up a weekly sales KPI scoreboard for my team"
126
+ prompt: "Set up a weekly sales KPI scoreboard for my team",
127
+ nativeRoute: "webbuilder",
128
+ surfaceSlug: "kpi-motivation"
98
129
  }, {
99
130
  key: "issue-ticket",
100
131
  label: "Issue Ticket",
101
132
  icon: "bug-outline",
102
133
  group: "Team",
103
- prompt: "Create a bug board and triage my open issues"
134
+ prompt: "Create a bug board and triage my open issues",
135
+ nativeRoute: "webbuilder",
136
+ surfaceSlug: "issues"
104
137
  }, {
105
138
  key: "notebook",
106
139
  label: "Study",
107
140
  icon: "school-outline",
108
141
  group: "Team",
109
- prompt: "Make a study guide from my lecture notes"
142
+ prompt: "Make a study guide from my lecture notes",
143
+ nativeRoute: "webbuilder",
144
+ surfaceSlug: "notebooklm"
110
145
  }, {
111
146
  key: "resume",
112
147
  label: "Resume",
113
148
  icon: "file-account-outline",
114
149
  group: "Team",
115
- prompt: "Draft a resume for a senior product designer with 8 years of experience"
150
+ prompt: "Draft a resume for a senior product designer with 8 years of experience",
151
+ nativeRoute: "webbuilder",
152
+ surfaceSlug: "resume"
116
153
  }, {
117
154
  key: "job-search",
118
155
  label: "Job Search",
119
156
  icon: "briefcase-outline",
120
157
  group: "Team",
121
- prompt: "Find remote senior backend engineer roles and tailor my resume for one"
158
+ prompt: "Find remote senior backend engineer roles and tailor my resume for one",
159
+ nativeRoute: "webbuilder",
160
+ surfaceSlug: "job-search"
122
161
  }, {
123
162
  key: "shop",
124
163
  label: "Shop",
125
164
  icon: "cart-outline",
126
165
  group: "More",
127
- prompt: "Compare the best options for what I need and show me the tradeoffs."
166
+ prompt: "Compare the best options for what I need and show me the tradeoffs.",
167
+ nativeRoute: "webbuilder",
168
+ surfaceSlug: "shopping"
128
169
  }, {
129
170
  key: "travel",
130
171
  label: "Travel",
131
172
  icon: "airplane",
132
173
  group: "More",
133
- prompt: "Plan a 4-day trip for me: flights, somewhere to stay, and what to do each day."
174
+ prompt: "Plan a 4-day trip for me: flights, somewhere to stay, and what to do each day.",
175
+ nativeRoute: "webbuilder",
176
+ surfaceSlug: "travel"
134
177
  }, {
135
178
  key: "social-events",
136
179
  label: "yantra.live",
137
180
  icon: "ticket-outline",
138
181
  group: "More",
139
- prompt: "What concerts are happening nearby this weekend?"
182
+ prompt: "What concerts are happening nearby this weekend?",
183
+ nativeRoute: "webbuilder",
184
+ surfaceSlug: "social-events"
140
185
  }];
141
186
  const APP_GROUP_ORDER = ["Create", "Automate", "Sell", "Money", "Team", "More"];
142
187
  function matchesAppQuery(label, query) {
@@ -1 +1 @@
1
- {"version":3,"file":"mobileAppCatalog.js","sources":["../../../src/features/apps/mobileAppCatalog.ts"],"sourcesContent":["import type { ComponentProps } from 'react';\nimport type { MaterialCommunityIcons } from '@expo/vector-icons';\n\ntype IconName = ComponentProps<typeof MaterialCommunityIcons>['name'];\n\nexport type AppGroupId = 'Create' | 'Automate' | 'Sell' | 'Money' | 'Team' | 'More';\n\nexport type MobileAppItem = {\n key: string;\n label: string;\n icon: IconName;\n group: AppGroupId;\n /** Prompt sent as the first chat turn when the app has no native screen. */\n prompt: string;\n /** Native stack route, if this surface already exists on mobile. */\n nativeRoute?: 'webbuilder';\n};\n\n/**\n * Mobile Apps launcher. Labels, groups, and prompts stay in lockstep with the\n * browser ChatTopBar Apps menu (`packages-modules/account/browser`).\n */\nexport const MOBILE_APP_CATALOG: readonly MobileAppItem[] = [\n {\n key: 'design',\n label: 'Design',\n icon: 'palette-outline',\n group: 'Create',\n prompt: 'Design a 10-slide pitch deck for a coffee subscription startup',\n },\n {\n key: 'canvas',\n label: 'Canvas',\n icon: 'view-grid-outline',\n group: 'Create',\n prompt: 'Open a canvas and help me lay out the assets for this project.',\n },\n {\n key: 'webbuilder',\n label: 'Web Builder',\n icon: 'application-outline',\n group: 'Create',\n prompt: 'Build a landing page for my bakery with a menu and a contact form',\n nativeRoute: 'webbuilder',\n },\n {\n key: 'paper2poster',\n label: 'Paper 2 Poster',\n icon: 'presentation',\n group: 'Create',\n prompt: 'Turn this research paper into a conference poster I can edit.',\n },\n {\n key: 'codezen',\n label: 'Codezen',\n icon: 'code-braces',\n group: 'Create',\n prompt: 'Clone my repository and fix the failing test',\n },\n {\n key: 'character',\n label: 'Characters',\n icon: 'drama-masks',\n group: 'Create',\n prompt: 'Create a stoic philosophy mentor character I can chat with',\n },\n {\n key: 'workflow',\n label: 'Workflow',\n icon: 'sitemap',\n group: 'Automate',\n prompt: 'Build a workflow that runs every morning and sends me a summary of what changed.',\n },\n {\n key: 'computer',\n label: 'Computer',\n icon: 'monitor',\n group: 'Automate',\n prompt: 'Open a browser and compare the top 5 CRM tools with screenshots',\n },\n {\n key: 'crm',\n label: 'CRM',\n icon: 'account-group-outline',\n group: 'Sell',\n prompt: 'Look at my pipeline and tell me which deals are going cold and what I should send them.',\n },\n {\n key: 'salesiq',\n label: 'SalesIQ',\n icon: 'radar',\n group: 'Sell',\n prompt: 'Show me who is on my website right now',\n },\n {\n key: 'inbox',\n label: 'Inbox',\n icon: 'inbox-outline',\n group: 'Sell',\n prompt: 'Go through my inbox, tell me what actually needs a reply, and draft those replies.',\n },\n {\n key: 'mailcampaign',\n label: 'Mail Campaigns',\n icon: 'bullhorn-outline',\n group: 'Sell',\n prompt: 'Draft an email campaign announcing what we shipped this month.',\n },\n {\n key: 'expenses',\n label: 'Expenses',\n icon: 'receipt-outline',\n group: 'Money',\n prompt: 'Summarise my spend this month and flag anything unusual.',\n },\n {\n key: 'cards-wallet',\n label: 'Cards & Wallet',\n icon: 'credit-card-outline',\n group: 'Money',\n prompt: 'Issue a $200 virtual card for monthly ad spend',\n },\n {\n key: 'billing',\n label: 'Billing',\n icon: 'currency-usd',\n group: 'Money',\n prompt: 'Create an invoice for a $2,400 consulting project',\n },\n {\n key: 'kpi-motivation',\n label: 'KPI Motivation',\n icon: 'trophy-outline',\n group: 'Team',\n prompt: 'Set up a weekly sales KPI scoreboard for my team',\n },\n {\n key: 'issue-ticket',\n label: 'Issue Ticket',\n icon: 'bug-outline',\n group: 'Team',\n prompt: 'Create a bug board and triage my open issues',\n },\n {\n key: 'notebook',\n label: 'Study',\n icon: 'school-outline',\n group: 'Team',\n prompt: 'Make a study guide from my lecture notes',\n },\n {\n key: 'resume',\n label: 'Resume',\n icon: 'file-account-outline',\n group: 'Team',\n prompt: 'Draft a resume for a senior product designer with 8 years of experience',\n },\n {\n key: 'job-search',\n label: 'Job Search',\n icon: 'briefcase-outline',\n group: 'Team',\n prompt: 'Find remote senior backend engineer roles and tailor my resume for one',\n },\n {\n key: 'shop',\n label: 'Shop',\n icon: 'cart-outline',\n group: 'More',\n prompt: 'Compare the best options for what I need and show me the tradeoffs.',\n },\n {\n key: 'travel',\n label: 'Travel',\n icon: 'airplane',\n group: 'More',\n prompt: 'Plan a 4-day trip for me: flights, somewhere to stay, and what to do each day.',\n },\n {\n key: 'social-events',\n label: 'yantra.live',\n icon: 'ticket-outline',\n group: 'More',\n prompt: 'What concerts are happening nearby this weekend?',\n },\n];\n\nexport const APP_GROUP_ORDER: readonly AppGroupId[] = ['Create', 'Automate', 'Sell', 'Money', 'Team', 'More'];\n\nexport function matchesAppQuery(label: string, query: string): boolean {\n const q = query.toLowerCase().replace(/[^a-z0-9]/g, '');\n if (!q) return true;\n return label\n .toLowerCase()\n .replace(/[^a-z0-9]/g, '')\n .includes(q);\n}\n\nexport function groupMobileApps(items: readonly MobileAppItem[], query: string) {\n const hits = items.filter((item) => matchesAppQuery(item.label, query));\n return APP_GROUP_ORDER.map((label) => ({\n label,\n items: hits.filter((item) => item.group === label),\n })).filter((group) => group.items.length > 0);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mobileAppCatalog.js","sources":["../../../src/features/apps/mobileAppCatalog.ts"],"sourcesContent":["import type { ComponentProps } from 'react';\nimport type { MaterialCommunityIcons } from '@expo/vector-icons';\n\ntype IconName = ComponentProps<typeof MaterialCommunityIcons>['name'];\n\nexport type AppGroupId = 'Create' | 'Automate' | 'Sell' | 'Money' | 'Team' | 'More';\n\nexport type MobileAppItem = {\n key: string;\n label: string;\n icon: IconName;\n group: AppGroupId;\n /** Prompt sent as the first chat turn when the app has no native screen. */\n prompt: string;\n /**\n * Which surface host opens this app, if it has one. `webbuilder` is the\n * historical name of the shared WebView surface shell (`screens/WebBuilder`),\n * which is not web-builder-specific: it takes a `url` route param, mints the\n * system token, injects the bridge + cdecli token, stamps `embed=mobile` and\n * owns the timeout/retry UI. Anything with a deployed surface SPA can use it.\n */\n nativeRoute?: 'webbuilder';\n /**\n * Deployed surface SPA for this app, as the `<slug>-surface` name. Resolved\n * against SURFACE_URL_TEMPLATE so one env var covers every surface and stays\n * per-environment, instead of 20+ near-identical URLs in eas.json.\n *\n * The slug is the SURFACE's name, which is not always the tile key\n * (issue-ticket -> issues, shop -> shopping, notebook -> notebooklm).\n */\n surfaceSlug?: string;\n /**\n * Explicit env override, for the two surfaces that already had a dedicated\n * var and are the ones people actually run locally. Wins over `surfaceSlug`.\n */\n surfaceUrlKey?: 'WEB_BUILDER_URL' | 'CANVAS_SURFACE_URL';\n};\n\n/**\n * Mobile Apps launcher. Labels, groups, and prompts stay in lockstep with the\n * browser ChatTopBar Apps menu (`packages-modules/account/browser`).\n */\nexport const MOBILE_APP_CATALOG: readonly MobileAppItem[] = [\n {\n key: 'design',\n label: 'Design',\n icon: 'palette-outline',\n group: 'Create',\n prompt: 'Design a 10-slide pitch deck for a coffee subscription startup',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'design',\n },\n {\n key: 'canvas',\n label: 'Canvas',\n icon: 'view-grid-outline',\n group: 'Create',\n prompt: 'Open a canvas and help me lay out the assets for this project.',\n nativeRoute: 'webbuilder',\n surfaceUrlKey: 'CANVAS_SURFACE_URL',\n surfaceSlug: 'canvas',\n },\n {\n key: 'webbuilder',\n label: 'Web Builder',\n icon: 'application-outline',\n group: 'Create',\n prompt: 'Build a landing page for my bakery with a menu and a contact form',\n nativeRoute: 'webbuilder',\n surfaceUrlKey: 'WEB_BUILDER_URL',\n surfaceSlug: 'webbuilder',\n },\n {\n key: 'paper2poster',\n label: 'Paper 2 Poster',\n icon: 'presentation',\n group: 'Create',\n prompt: 'Turn this research paper into a conference poster I can edit.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'paper2poster',\n },\n {\n key: 'codezen',\n label: 'Codezen',\n icon: 'code-braces',\n group: 'Create',\n prompt: 'Clone my repository and fix the failing test',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'codezen',\n },\n {\n key: 'character',\n label: 'Characters',\n icon: 'drama-masks',\n group: 'Create',\n prompt: 'Create a stoic philosophy mentor character I can chat with',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'character',\n },\n {\n key: 'workflow',\n label: 'Workflow',\n icon: 'sitemap',\n group: 'Automate',\n prompt: 'Build a workflow that runs every morning and sends me a summary of what changed.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'workflow',\n },\n {\n key: 'computer',\n label: 'Computer',\n icon: 'monitor',\n group: 'Automate',\n prompt: 'Open a browser and compare the top 5 CRM tools with screenshots',\n },\n {\n key: 'crm',\n label: 'CRM',\n icon: 'account-group-outline',\n group: 'Sell',\n prompt: 'Look at my pipeline and tell me which deals are going cold and what I should send them.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'crm',\n },\n {\n key: 'salesiq',\n label: 'SalesIQ',\n icon: 'radar',\n group: 'Sell',\n prompt: 'Show me who is on my website right now',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'salesiq',\n },\n {\n key: 'inbox',\n label: 'Inbox',\n icon: 'inbox-outline',\n group: 'Sell',\n prompt: 'Go through my inbox, tell me what actually needs a reply, and draft those replies.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'inbox',\n },\n {\n key: 'mailcampaign',\n label: 'Mail Campaigns',\n icon: 'bullhorn-outline',\n group: 'Sell',\n prompt: 'Draft an email campaign announcing what we shipped this month.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'mailcampaign',\n },\n {\n key: 'expenses',\n label: 'Expenses',\n icon: 'receipt-outline',\n group: 'Money',\n prompt: 'Summarise my spend this month and flag anything unusual.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'expenses',\n },\n {\n key: 'cards-wallet',\n label: 'Cards & Wallet',\n icon: 'credit-card-outline',\n group: 'Money',\n prompt: 'Issue a $200 virtual card for monthly ad spend',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'cards-wallet',\n },\n {\n key: 'billing',\n label: 'Billing',\n icon: 'currency-usd',\n group: 'Money',\n prompt: 'Create an invoice for a $2,400 consulting project',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'billing',\n },\n {\n key: 'kpi-motivation',\n label: 'KPI Motivation',\n icon: 'trophy-outline',\n group: 'Team',\n prompt: 'Set up a weekly sales KPI scoreboard for my team',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'kpi-motivation',\n },\n {\n key: 'issue-ticket',\n label: 'Issue Ticket',\n icon: 'bug-outline',\n group: 'Team',\n prompt: 'Create a bug board and triage my open issues',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'issues',\n },\n {\n key: 'notebook',\n label: 'Study',\n icon: 'school-outline',\n group: 'Team',\n prompt: 'Make a study guide from my lecture notes',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'notebooklm',\n },\n {\n key: 'resume',\n label: 'Resume',\n icon: 'file-account-outline',\n group: 'Team',\n prompt: 'Draft a resume for a senior product designer with 8 years of experience',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'resume',\n },\n {\n key: 'job-search',\n label: 'Job Search',\n icon: 'briefcase-outline',\n group: 'Team',\n prompt: 'Find remote senior backend engineer roles and tailor my resume for one',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'job-search',\n },\n {\n key: 'shop',\n label: 'Shop',\n icon: 'cart-outline',\n group: 'More',\n prompt: 'Compare the best options for what I need and show me the tradeoffs.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'shopping',\n },\n {\n key: 'travel',\n label: 'Travel',\n icon: 'airplane',\n group: 'More',\n prompt: 'Plan a 4-day trip for me: flights, somewhere to stay, and what to do each day.',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'travel',\n },\n {\n key: 'social-events',\n label: 'yantra.live',\n icon: 'ticket-outline',\n group: 'More',\n prompt: 'What concerts are happening nearby this weekend?',\n nativeRoute: 'webbuilder',\n surfaceSlug: 'social-events',\n },\n];\n\nexport const APP_GROUP_ORDER: readonly AppGroupId[] = ['Create', 'Automate', 'Sell', 'Money', 'Team', 'More'];\n\nexport function matchesAppQuery(label: string, query: string): boolean {\n const q = query.toLowerCase().replace(/[^a-z0-9]/g, '');\n if (!q) return true;\n return label\n .toLowerCase()\n .replace(/[^a-z0-9]/g, '')\n .includes(q);\n}\n\nexport function groupMobileApps(items: readonly MobileAppItem[], query: string) {\n const hits = items.filter((item) => matchesAppQuery(item.label, query));\n return APP_GROUP_ORDER.map((label) => ({\n label,\n items: hits.filter((item) => item.group === label),\n })).filter((group) => group.items.length > 0);\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ function resolveSurfaceUrl(app, config) {
2
+ var _a, _b;
3
+ if (!app.nativeRoute) return void 0;
4
+ if (app.surfaceUrlKey) {
5
+ const explicit = (_a = config[app.surfaceUrlKey]) == null ? void 0 : _a.trim();
6
+ if (explicit) return explicit;
7
+ }
8
+ const template = (_b = config.SURFACE_URL_TEMPLATE) == null ? void 0 : _b.trim();
9
+ if (!template || !app.surfaceSlug) return void 0;
10
+ if (!template.includes("{slug}")) return void 0;
11
+ return template.replace(/\{slug\}/g, app.surfaceSlug);
12
+ }export{resolveSurfaceUrl};//# sourceMappingURL=resolveSurfaceUrl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveSurfaceUrl.js","sources":["../../../src/features/apps/resolveSurfaceUrl.ts"],"sourcesContent":["/**\n * Which URL the shared WebView surface shell should open for a launcher tile.\n *\n * Explicit env key wins (the two surfaces with a dedicated var, which are the\n * ones run locally), then the `{slug}` template that covers every deployed\n * surface. Returning undefined means \"no surface\" — the caller falls back to\n * seeding the tile's chat prompt, which is what every tile did before.\n */\nimport type { MobileAppItem } from './mobileAppCatalog';\n\nexport interface SurfaceUrlConfig {\n WEB_BUILDER_URL?: string;\n CANVAS_SURFACE_URL?: string;\n SURFACE_URL_TEMPLATE?: string;\n}\n\nexport function resolveSurfaceUrl(app: MobileAppItem, config: SurfaceUrlConfig): string | undefined {\n if (!app.nativeRoute) return undefined;\n\n if (app.surfaceUrlKey) {\n const explicit = config[app.surfaceUrlKey]?.trim();\n\n if (explicit) return explicit;\n }\n\n const template = config.SURFACE_URL_TEMPLATE?.trim();\n\n if (!template || !app.surfaceSlug) return undefined;\n // A template without the placeholder would silently point every surface at\n // the same origin, which is worse than opening none.\n if (!template.includes('{slug}')) return undefined;\n\n return template.replace(/\\{slug\\}/g, app.surfaceSlug);\n}\n"],"names":[],"mappings":"AAcgB,SAAA,iBAAA,CAAkB,KAAoB,MAA8C,EAAA;AAdpG,EAAA,IAAA,EAAA,EAAA,EAAA;AAeE,EAAI,IAAA,CAAC,GAAI,CAAA,WAAA,EAAoB,OAAA,MAAA;AAC7B,EAAA,IAAI,IAAI,aAAe,EAAA;AACrB,IAAA,MAAM,QAAW,GAAA,CAAA,EAAA,GAAA,MAAA,CAAO,GAAI,CAAA,aAAa,MAAxB,IAA2B,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,EAAA;AAC5C,IAAA,IAAI,UAAiB,OAAA,QAAA;AAAA;AAEvB,EAAM,MAAA,QAAA,GAAA,CAAW,EAAO,GAAA,MAAA,CAAA,oBAAA,KAAP,IAA6B,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,EAAA;AAC9C,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,GAAA,CAAI,aAAoB,OAAA,MAAA;AAG1C,EAAA,IAAI,CAAC,QAAA,CAAS,QAAS,CAAA,QAAQ,GAAU,OAAA,MAAA;AACzC,EAAA,OAAO,QAAS,CAAA,OAAA,CAAQ,WAAa,EAAA,GAAA,CAAI,WAAW,CAAA;AACtD"}
@@ -0,0 +1,106 @@
1
+ import {useState,useCallback,useMemo}from'react';var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ const PICKER_QUALITY = 0.7;
21
+ const MAX_BYTES = 4 * 1024 * 1024;
22
+ const MIN_BYTES = 64;
23
+ function base64Bytes(base64) {
24
+ const padding = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0;
25
+ return Math.floor(base64.length * 3 / 4) - padding;
26
+ }
27
+ function toAttachment(asset, index) {
28
+ var _a, _b, _c;
29
+ const base64 = (_a = asset.base64) == null ? void 0 : _a.trim();
30
+ if (!base64) return null;
31
+ const size = base64Bytes(base64);
32
+ if (size < MIN_BYTES || size > MAX_BYTES) return null;
33
+ const mimeType = ((_b = asset.mimeType) == null ? void 0 : _b.trim()) || "image/jpeg";
34
+ const name = ((_c = asset.fileName) == null ? void 0 : _c.trim()) || `image-${Date.now()}-${index}.jpg`;
35
+ return {
36
+ // Local id only — the gateway assigns its own.
37
+ id: `img-${Date.now()}-${index}`,
38
+ name,
39
+ type: "file",
40
+ mimeType,
41
+ dataUrl: `data:${mimeType};base64,${base64}`,
42
+ size
43
+ };
44
+ }
45
+ function loadPicker() {
46
+ return require("expo-image-picker");
47
+ }
48
+ function useImageAttachments() {
49
+ const [pending, setPending] = useState([]);
50
+ const [busy, setBusy] = useState(false);
51
+ const [error, setError] = useState(null);
52
+ const run = useCallback(async (mode) => {
53
+ var _a;
54
+ setError(null);
55
+ setBusy(true);
56
+ try {
57
+ const picker = loadPicker();
58
+ const permission = mode === "camera" ? await picker.requestCameraPermissionsAsync() : await picker.requestMediaLibraryPermissionsAsync();
59
+ if (!permission.granted) {
60
+ setError(mode === "camera" ? "Camera access is off for Yantra. Turn it on in Settings to attach a photo." : "Photo access is off for Yantra. Turn it on in Settings to attach an image.");
61
+ return;
62
+ }
63
+ const options = {
64
+ // `base64` is what the message carries; `quality` + the picker's
65
+ // own resize keep it small enough to travel inline.
66
+ base64: true,
67
+ quality: PICKER_QUALITY,
68
+ allowsMultipleSelection: mode === "library",
69
+ mediaTypes: ["images"],
70
+ // Selection limit mirrors MAX_BYTES: four 1280px JPEGs still fit
71
+ // comfortably inside a single turn.
72
+ selectionLimit: 4,
73
+ exif: false
74
+ };
75
+ const result = mode === "camera" ? await picker.launchCameraAsync(__spreadProps(__spreadValues({}, options), {
76
+ allowsMultipleSelection: false
77
+ })) : await picker.launchImageLibraryAsync(options);
78
+ if (result.canceled) return;
79
+ const mapped = ((_a = result.assets) != null ? _a : []).map((asset, i) => toAttachment(asset, i)).filter((a) => a !== null);
80
+ if (mapped.length === 0) {
81
+ setError("That image was too large to attach. Try a smaller one.");
82
+ return;
83
+ }
84
+ setPending((prev) => [...prev, ...mapped]);
85
+ } catch (e) {
86
+ setError(e instanceof Error ? e.message : "Could not attach that image.");
87
+ } finally {
88
+ setBusy(false);
89
+ }
90
+ }, []);
91
+ const pickFromLibrary = useCallback(() => run("library"), [run]);
92
+ const captureFromCamera = useCallback(() => run("camera"), [run]);
93
+ const remove = useCallback((id) => setPending((prev) => prev.filter((a) => a.id !== id)), []);
94
+ const clear = useCallback(() => setPending([]), []);
95
+ const forSend = useCallback(() => pending.length > 0 ? pending : void 0, [pending]);
96
+ return useMemo(() => ({
97
+ pending,
98
+ busy,
99
+ error,
100
+ pickFromLibrary,
101
+ captureFromCamera,
102
+ remove,
103
+ clear,
104
+ forSend
105
+ }), [pending, busy, error, pickFromLibrary, captureFromCamera, remove, clear, forSend]);
106
+ }export{useImageAttachments};//# sourceMappingURL=useImageAttachments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useImageAttachments.js","sources":["../../../src/features/attachments/useImageAttachments.ts"],"sourcesContent":["/**\n * Image attachments for the native composer.\n *\n * The transport was already there — `useChatStream.sendMessage(content,\n * attachments)` carries `MessageAttachment[]` and the gateway media lane is\n * covered by `aiwork/e2e-tests/gateway-media-upload.spec.ts`. What was missing\n * was any way to produce one on a phone: the composer shipped with\n * `image`/`camera`/`attach` hard-disabled, and nothing in the mobile package\n * touched `expo-image-picker` even though it is a dependency and the photo and\n * camera permission strings are already declared in `app.json`.\n *\n * Payload size is the whole game here. A modern iPhone photo is ~3-5 MB and\n * ~4000px wide; base64 inflates that by a third, and it travels inline on the\n * chat message. So we ask the picker to downscale and re-encode before we ever\n * see the bytes, then hard-reject anything still oversized rather than let a\n * send hang on a slow uplink.\n */\nimport { useCallback, useMemo, useState } from 'react';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\n\n/** Longest edge, in px, we send. Plenty for a model to read; ~10x smaller than source. */\nconst MAX_EDGE = 1280;\n/** JPEG quality handed to the picker (0-1). */\nconst PICKER_QUALITY = 0.7;\n/** Refuse anything above this after re-encoding — a send is better failed than hung. */\nconst MAX_BYTES = 4 * 1024 * 1024;\n/** Nothing sensible is this small; treat as a failed decode. */\nconst MIN_BYTES = 64;\n\nexport interface ImageAttachmentsApi {\n /** Attachments staged for the next send. */\n pending: MessageAttachment[];\n /** True while the picker/encode is in flight, for the toolbar spinner. */\n busy: boolean;\n /** Human-readable failure for the composer's error banner, or null. */\n error: string | null;\n pickFromLibrary: () => Promise<void>;\n captureFromCamera: () => Promise<void>;\n remove: (id: string) => void;\n clear: () => void;\n /** Pass to `sendMessage` — undefined when empty, which is what it expects. */\n forSend: () => MessageAttachment[] | undefined;\n}\n\ntype PickedAsset = {\n uri?: string | null;\n base64?: string | null;\n mimeType?: string | null;\n fileName?: string | null;\n fileSize?: number | null;\n width?: number | null;\n height?: number | null;\n};\n\n/** Base64 decodes to 3 bytes per 4 chars, minus `=` padding. */\nfunction base64Bytes(base64: string): number {\n const padding = base64.endsWith('==') ? 2 : base64.endsWith('=') ? 1 : 0;\n return Math.floor((base64.length * 3) / 4) - padding;\n}\n\nfunction toAttachment(asset: PickedAsset, index: number): MessageAttachment | null {\n const base64 = asset.base64?.trim();\n if (!base64) return null;\n const size = base64Bytes(base64);\n if (size < MIN_BYTES || size > MAX_BYTES) return null;\n const mimeType = asset.mimeType?.trim() || 'image/jpeg';\n const name = asset.fileName?.trim() || `image-${Date.now()}-${index}.jpg`;\n return {\n // Local id only — the gateway assigns its own.\n id: `img-${Date.now()}-${index}`,\n name,\n type: 'file',\n mimeType,\n dataUrl: `data:${mimeType};base64,${base64}`,\n size,\n };\n}\n\n/**\n * Lazily required so a unit test or a non-Expo bundle importing this hook does\n * not hard-fail on the native module.\n */\nfunction loadPicker() {\n // eslint-disable-next-line @typescript-eslint/no-require-imports, global-require\n return require('expo-image-picker') as typeof import('expo-image-picker');\n}\n\nexport function useImageAttachments(): ImageAttachmentsApi {\n const [pending, setPending] = useState<MessageAttachment[]>([]);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const run = useCallback(async (mode: 'library' | 'camera') => {\n setError(null);\n setBusy(true);\n try {\n const picker = loadPicker();\n\n const permission =\n mode === 'camera'\n ? await picker.requestCameraPermissionsAsync()\n : await picker.requestMediaLibraryPermissionsAsync();\n if (!permission.granted) {\n setError(\n mode === 'camera'\n ? 'Camera access is off for Yantra. Turn it on in Settings to attach a photo.'\n : 'Photo access is off for Yantra. Turn it on in Settings to attach an image.',\n );\n return;\n }\n\n const options = {\n // `base64` is what the message carries; `quality` + the picker's\n // own resize keep it small enough to travel inline.\n base64: true,\n quality: PICKER_QUALITY,\n allowsMultipleSelection: mode === 'library',\n mediaTypes: ['images'] as const,\n // Selection limit mirrors MAX_BYTES: four 1280px JPEGs still fit\n // comfortably inside a single turn.\n selectionLimit: 4,\n exif: false,\n };\n\n const result =\n mode === 'camera'\n ? await picker.launchCameraAsync({ ...options, allowsMultipleSelection: false })\n : await picker.launchImageLibraryAsync(options);\n\n if (result.canceled) return;\n\n const mapped = (result.assets ?? [])\n .map((asset, i) => toAttachment(asset as PickedAsset, i))\n .filter((a): a is MessageAttachment => a !== null);\n\n if (mapped.length === 0) {\n setError('That image was too large to attach. Try a smaller one.');\n return;\n }\n setPending((prev) => [...prev, ...mapped]);\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Could not attach that image.');\n } finally {\n setBusy(false);\n }\n }, []);\n\n const pickFromLibrary = useCallback(() => run('library'), [run]);\n const captureFromCamera = useCallback(() => run('camera'), [run]);\n const remove = useCallback((id: string) => setPending((prev) => prev.filter((a) => a.id !== id)), []);\n const clear = useCallback(() => setPending([]), []);\n const forSend = useCallback(() => (pending.length > 0 ? pending : undefined), [pending]);\n\n return useMemo(\n () => ({ pending, busy, error, pickFromLibrary, captureFromCamera, remove, clear, forSend }),\n [pending, busy, error, pickFromLibrary, captureFromCamera, remove, clear, forSend],\n );\n}\n\nexport const IMAGE_ATTACHMENT_LIMITS = { MAX_EDGE, MAX_BYTES, PICKER_QUALITY } as const;\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import {jsxs,jsx}from'react/jsx-runtime';import {useMemo,useEffect,useState,useRef,useCallback}from'react';import {useColorScheme,useWindowDimensions,Keyboard,StyleSheet,View}from'react-native';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 {MessagesContainerUI}from'@messenger-box/platform-mobile';import {useCdecliConnection}from'../../contexts/CdecliConnectionContext.js';import {useChatStream}from'../../hooks/useChatStream.js';import {useKeyboardBottomOffset}from'../../hooks/useKeyboardBottomOffset.js';import {KeyboardComposerDock}from'../../components/KeyboardComposerDock.js';import {YantraBrandLoader,YANTRA_LOADER_SIZE_COMPACT}from'../../components/YantraBrandLoader.js';import ThinkingIndicator from'../../components/ThinkingIndicator.js';import {mobileTokens}from'../../theme/mobileTokens.js';import DeepSearchModal from'../Home/components/DeepSearchModal.js';import {normalizeSummaryText,extractDeepSearchSources}from'../Home/deepSearchUtils.js';import {AudioRecorderPanel}from'../../features/audio-input/AudioRecorderPanel.js';import {MicErrorBoundary}from'../../features/audio-input/MicErrorBoundary.js';import {requestMicPermission}from'../../features/audio-input/useAudioPermission.js';var __defProp = Object.defineProperty;
1
+ import {jsxs,jsx}from'react/jsx-runtime';import {useMemo,useEffect,useState,useRef,useCallback}from'react';import {useColorScheme,useWindowDimensions,Keyboard,StyleSheet,View}from'react-native';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 {MessagesContainerUI}from'@messenger-box/platform-mobile';import {useCdecliConnection}from'../../contexts/CdecliConnectionContext.js';import {useChatStream}from'../../hooks/useChatStream.js';import {useKeyboardBottomOffset}from'../../hooks/useKeyboardBottomOffset.js';import {KeyboardComposerDock}from'../../components/KeyboardComposerDock.js';import {YantraBrandLoader,YANTRA_LOADER_SIZE_COMPACT}from'../../components/YantraBrandLoader.js';import ThinkingIndicator from'../../components/ThinkingIndicator.js';import {mobileTokens}from'../../theme/mobileTokens.js';import DeepSearchModal from'../Home/components/DeepSearchModal.js';import {normalizeSummaryText,extractDeepSearchSources}from'../Home/deepSearchUtils.js';import {AudioRecorderPanel}from'../../features/audio-input/AudioRecorderPanel.js';import {useImageAttachments}from'../../features/attachments/useImageAttachments.js';import {MicErrorBoundary}from'../../features/audio-input/MicErrorBoundary.js';import {requestMicPermission}from'../../features/audio-input/useAudioPermission.js';var __defProp = Object.defineProperty;
2
2
  var __defProps = Object.defineProperties;
3
3
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
@@ -79,6 +79,7 @@ function ChatScreen() {
79
79
  sendMessage,
80
80
  cancel
81
81
  } = chat;
82
+ const imageAttachments = useImageAttachments();
82
83
  const [value, setValue] = useState("");
83
84
  const valueRef = useRef(value);
84
85
  valueRef.current = value;
@@ -133,8 +134,9 @@ function ChatScreen() {
133
134
  if (isDeepSearchMode) {
134
135
  setIsDeepSearchModalOpen(true);
135
136
  }
136
- void sendMessage(t, void 0, channelId);
137
- }, [channelId, sendMessage, isDeepSearchMode, isBuildMode, navigation, params.orgName]);
137
+ void sendMessage(t, imageAttachments.forSend(), channelId);
138
+ imageAttachments.clear();
139
+ }, [channelId, sendMessage, isDeepSearchMode, isBuildMode, navigation, params.orgName, imageAttachments]);
138
140
  const handleValueChange = useCallback((e) => {
139
141
  var _a2, _b2;
140
142
  setValue((_b2 = (_a2 = e == null ? void 0 : e.nativeEvent) == null ? void 0 : _a2.text) != null ? _b2 : "");
@@ -244,16 +246,28 @@ function ChatScreen() {
244
246
  chip: {
245
247
  enabled: false
246
248
  },
249
+ // Attaching an image was disabled here even though the transport
250
+ // (`sendMessage(content, attachments)`) and the gateway media lane
251
+ // already carried it, and `expo-image-picker` was already a
252
+ // dependency with its permission strings declared in app.json.
247
253
  camera: {
248
- enabled: false
254
+ enabled: true,
255
+ loading: imageAttachments.busy,
256
+ onClick: () => {
257
+ void imageAttachments.captureFromCamera();
258
+ }
249
259
  },
250
260
  image: {
251
- enabled: false
261
+ enabled: true,
262
+ loading: imageAttachments.busy,
263
+ onClick: () => {
264
+ void imageAttachments.pickFromLibrary();
265
+ }
252
266
  },
253
267
  attach: {
254
268
  enabled: false
255
269
  }
256
- }), []);
270
+ }), [imageAttachments]);
257
271
  const inputPlaceholder = isDeepSearchMode ? "Research anything..." : isBuildMode ? "Describe an app to build..." : "Ask anything...";
258
272
  const inputConfig = useMemo(() => ({
259
273
  value,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/screens/Chat/index.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Keyboard, StyleSheet, TextInput, View, useColorScheme, useWindowDimensions } from 'react-native';\nimport { Box, InputToolBar, Text, getDefaultLeftItems, getDefaultRightItems } from '@admin-layout/gluestack-ui-mobile';\nimport { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { useNavigation, useRoute, CommonActions } from '@react-navigation/native';\nimport { MessagesContainerUI } from '@messenger-box/platform-mobile';\nimport { useCdecliConnection } from '../../contexts/CdecliConnectionContext';\nimport { useChatStream, type UseChatStreamRouting } from '../../hooks/useChatStream';\nimport { useKeyboardBottomOffset } from '../../hooks/useKeyboardBottomOffset';\nimport { KeyboardComposerDock } from '../../components/KeyboardComposerDock';\nimport { YantraBrandLoader, YANTRA_LOADER_SIZE_COMPACT } from '../../components/YantraBrandLoader';\nimport ThinkingIndicator from '../../components/ThinkingIndicator';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport DeepSearchModal from '../Home/components/DeepSearchModal';\nimport { extractDeepSearchSources, normalizeSummaryText, type DeepSearchSourceItem } from '../Home/deepSearchUtils';\nimport type { ModeSubmission, RoutingMode } from '../Home/types';\nimport { AudioRecorderPanel } from '../../features/audio-input/AudioRecorderPanel';\nimport { MicErrorBoundary } from '../../features/audio-input/MicErrorBoundary';\nimport { requestMicPermission } from '../../features/audio-input/useAudioPermission';\n\n/** Route params passed by Home (or by deep-link) when entering the Chat surface. */\nexport interface ChatScreenRouteParams {\n /** Channel id is required — the screen is keyed on the conversation. */\n channelId: string;\n /** Org slug used by gateway/account context. */\n orgName?: string | null;\n /**\n * First user message to auto-fire when the screen mounts. Home generates\n * this when the user submits from the empty composer so the assistant\n * starts streaming on Chat without an extra round trip.\n */\n initialQuery?: string | null;\n /**\n * Seed for the composer's mode (`'chat'` | `'deep-search'` | `'build'`).\n *\n * Set by `HomeScreen` to carry the user's last selection across the\n * navigation hop (\"research from home → research-shaped composer on chat\").\n * `ChatHistoryScreen` does NOT forward this — revisits always land on the\n * default `'chat'` mode, matching Home's defaults, and the user is free to\n * switch from there. Build-mode send hands off to Web Builder.\n *\n * After mount, this param is purely a seed: the screen keeps its own\n * `activeMode` so the user can toggle freely while inside the thread.\n */\n initialMode?: RoutingMode;\n /** Optional attachments forwarded with the initial message. */\n initialAttachments?: ModeSubmission['attachments'];\n}\n\n/** Stable prop identities — a fresh object/function per render defeats the\n * memoisation inside MessagesContainerUI during streaming. */\nconst CHAT_CURRENT_USER = { id: 'user' } as const;\nconst renderNoToolbar = () => null;\n\nexport default function ChatScreen() {\n const navigation = useNavigation<any>();\n const route = useRoute<any>();\n\n const params = (route?.params ?? {}) as Partial<ChatScreenRouteParams>;\n const channelId = useMemo(() => {\n const raw = typeof params.channelId === 'string' ? params.channelId.trim() : '';\n return raw.length > 0 ? raw : null;\n }, [params.channelId]);\n const initialQuery = useMemo(() => {\n const raw = typeof params.initialQuery === 'string' ? params.initialQuery.trim() : '';\n return raw.length > 0 ? raw : null;\n }, [params.initialQuery]);\n const initialAttachments = params.initialAttachments;\n\n const colorScheme = useColorScheme();\n const isDark = colorScheme === 'dark';\n const { width: screenWidth } = useWindowDimensions();\n const contentMaxWidth = Math.min(720, Math.max(360, screenWidth - 24));\n\n const surfaceColor = isDark ? '#0f172a' : mobileTokens.color.surface;\n const secondaryTextColor = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n\n const insets = useSafeAreaInsets();\n const { keyboardHeight, keyboardVisible } = useKeyboardBottomOffset();\n\n /**\n * Gateway + chat stream routing.\n *\n * The CDeCLI lifecycle is owned app-wide by `CdecliConnectionProvider`,\n * so we just register this screen's channelId and read the shared status.\n * This avoids racing `gatewayConnect` mutations with the header's\n * `GatewayConnector` (which previously ran its own `useCdecliAutoConnect`\n * and could clobber the chat session binding).\n */\n const cdecli = useCdecliConnection();\n const effectivePersistenceMode = cdecli.persistenceMode ?? 'backend';\n\n useEffect(() => {\n if (!channelId) return undefined;\n cdecli.setActiveChannelId(channelId);\n return () => {\n cdecli.setActiveChannelId(undefined);\n };\n }, [channelId, cdecli.setActiveChannelId]);\n\n const chatRouting: UseChatStreamRouting = useMemo(\n () => ({\n channelConnected: cdecli.channelConnected,\n accountId: cdecli.accountId,\n persistenceMode: effectivePersistenceMode,\n }),\n [cdecli.channelConnected, cdecli.accountId, effectivePersistenceMode],\n );\n\n const chat = useChatStream(channelId, chatRouting);\n\n /**\n * Gifted-shaped transcript rows, memoised on `messages` alone.\n *\n * This screen re-renders on every streamed token — `useChatStream` does\n * `setResponse((r) => r + text)` per delta. Building this array inline in\n * the JSX therefore handed `PlanModeView` a fresh `messages` identity on\n * every token, which invalidated its own `useMemo([messages, …])`, re-mapped\n * every row, and re-rendered every bubble. Assistant bubbles render through\n * `react-native-markdown-display`, so that meant re-parsing the markdown of\n * the whole thread once per token — O(messages) parses per delta, on the JS\n * thread, which is exactly when the UI has to stay responsive.\n *\n * `messages` is already stable upstream (`useChatApi` memoises it on the\n * Apollo result), so this only rebuilds when a message is actually added or\n * changed.\n */\n const transcriptRows = useMemo(\n () =>\n chat.messages.map((msg, index) => ({\n id: `msg-${index}-${msg.role}`,\n role: msg.role,\n content: msg.content,\n metadata: (msg as { metadata?: unknown }).metadata,\n })),\n [chat.messages],\n );\n const { messages, response, error: chatError, isLoading, isStreaming, messagesLoading, sendMessage, cancel } = chat;\n\n /*\n * Composer state — kept local so it doesn't leak across navigations.\n *\n * `valueRef` mirrors the controlled `value` so `handleSend` can read the\n * latest text without taking a dependency on it. Without this, `handleSend`\n * (and therefore `micSendButton.onSend`) would be recreated on every\n * keystroke, which is unnecessary churn for `InputToolBar`.\n *\n * `inputRef` is forwarded to InputToolBar's TextInput so we can call\n * `.clear()` imperatively after sending. On iOS, the native text buffer\n * can stay desynced from the controlled `value` for a frame when a state\n * update is followed by an async dispatch in the same gesture — the\n * \"send-and-clear\" race. The imperative clear closes that gap deterministically.\n */\n const [value, setValue] = useState('');\n const valueRef = useRef(value);\n valueRef.current = value;\n const inputRef = useRef<TextInput>(null);\n const trimmed = value.trim();\n const hasQuery = trimmed.length > 0;\n const canSubmit = hasQuery && Boolean(channelId);\n\n /**\n * Composer mode is FREELY user-controlled, mirroring `HomeScreen`.\n *\n * Seed:\n * • From Home (which forwards `initialMode` alongside `initialQuery`):\n * start in whatever mode the user picked there so the \"research from\n * home → research-shaped chat\" hand-off feels continuous.\n * • From ChatHistory (which intentionally does NOT pass `initialMode`):\n * default to `'chat'`, same as Home's empty composer.\n *\n * Post-mount this is a normal local state — the search/zap pills toggle\n * it on tap, and every place that previously branched on\n * `params.initialMode` now branches on `activeMode` instead.\n */\n const [activeMode, setActiveMode] = useState<RoutingMode>(() =>\n params.initialMode === 'deep-search' ? 'deep-search' : params.initialMode === 'build' ? 'build' : 'chat',\n );\n const handleModeSwitch = useCallback((mode: RoutingMode) => {\n setActiveMode(mode);\n }, []);\n const isDeepSearchMode = activeMode === 'deep-search';\n const isBuildMode = activeMode === 'build';\n\n /**\n * Inline voice recorder state — parity with HomeScreen and the web\n * `YantraSearchComposer.showAudioRecorder` flow. When active, the panel\n * fully replaces the InputToolBar so the toolbar's mic→send button\n * doesn't compete with the panel's own send/cancel affordances.\n */\n const [showAudioRecorder, setShowAudioRecorder] = useState(false);\n const [voiceError, setVoiceError] = useState<string | null>(null);\n\n /**\n * Auto-fire the initial query once when the screen mounts on a fresh channel.\n * Home creates the channel optimistically and forwards the user prompt here so\n * the first assistant token arrives without an extra interaction.\n *\n * Wait for CDeCLI to finish connecting (or fail) before auto-firing — chat is\n * cdecli-only and `sendMessage` rejects sends while the gateway is disconnected.\n */\n const autoFiredRef = useRef(false);\n useEffect(() => {\n if (autoFiredRef.current) return;\n if (!channelId || !initialQuery) return;\n if (cdecli.status !== 'connected' && cdecli.status !== 'error') return;\n\n autoFiredRef.current = true;\n // Deep-search auto-fire from Home: open the structured modal at the\n // same instant we kick off the send so the user sees the research view\n // streaming in rather than raw assistant turns. Tied to the\n // sendMessage call (same event) to avoid a race where the modal opens\n // before/after the actual send.\n //\n // We branch on the LOCAL `isDeepSearchMode` instead of\n // `params.initialMode`. At auto-fire time they're equal (the local\n // state was seeded from the param), and using the local state means\n // future toggles drive the same code path consistently.\n if (isDeepSearchMode) {\n setIsDeepSearchModalOpen(true);\n }\n void sendMessage(initialQuery, initialAttachments as any, channelId);\n try {\n navigation.setParams({ initialQuery: null, initialAttachments: null });\n } catch {\n /* setParams may be unavailable in tests; clearing is best-effort. */\n }\n }, [channelId, initialQuery, initialAttachments, sendMessage, navigation, cdecli.status, isDeepSearchMode]);\n\n const handleSend = useCallback(\n (text?: string) => {\n const t = (text ?? valueRef.current).trim();\n if (!t || !channelId) return;\n // Clear both ways: the controlled state (so React's model stays\n // consistent on next render) AND the native buffer via the ref\n // (so the visible text disappears on the same frame the user\n // pressed send, even before React flushes).\n setValue('');\n inputRef.current?.clear();\n\n // Build mode: hand off to Web Builder on this channel (web `/c/:id/webbuilder`).\n if (isBuildMode) {\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.WebBuilder',\n params: {\n ...(params.orgName ? { orgName: params.orgName } : {}),\n channelId,\n message: t,\n },\n }),\n );\n return;\n }\n\n // Deep-search mode: every new query pops the structured research\n // modal back open (parity with the previous Home flow, where every\n // submit re-opened the DeepSearchModal). Without this, a user who\n // closed the modal once would see plain assistant turns for every\n // subsequent send. Reads the LOCAL `isDeepSearchMode` so the user\n // can toggle modes mid-thread and have sends behave accordingly.\n if (isDeepSearchMode) {\n setIsDeepSearchModalOpen(true);\n }\n void sendMessage(t, undefined, channelId);\n },\n [channelId, sendMessage, isDeepSearchMode, isBuildMode, navigation, params.orgName],\n );\n\n const handleValueChange = useCallback((e: any) => {\n setValue(e?.nativeEvent?.text ?? '');\n }, []);\n\n /**\n * Mic affordance — web parity (`handleMicClick` in `YantraSearchComposer.tsx`).\n * The shared `MicSendButton` in `InputToolBar.tsx` only routes to `onMic`\n * when the input has no content, so we only need to handle the empty-input\n * case here.\n *\n * Permission is requested HERE, before the panel mounts. The previous flow\n * flipped `showAudioRecorder=true` immediately, which mounted\n * `AudioRecorderPanel` and constructed the native `AVAudioRecorder` via\n * `useAudioRecorder()` during the panel's render phase — before iOS had\n * granted mic access. On SDK 53 + `newArchEnabled: true` + Hermes that\n * ordering hard-crashes TestFlight builds even though it works in Expo Go\n * (Expo Go pre-caches permission). Asking up front means iOS shows the\n * system alert first and the panel only mounts (and therefore the native\n * recorder is only allocated) once permission is granted.\n *\n * `expo-audio` is lazy-imported so a missing/broken native module surfaces\n * as a user-visible banner instead of a synchronous TurboModule crash.\n */\n const handleMicPress = useCallback(() => {\n if (hasQuery) return;\n setVoiceError(null);\n Keyboard.dismiss();\n void (async () => {\n const { granted, error } = await requestMicPermission();\n if (!granted) {\n setVoiceError(error || 'Microphone is not available.');\n return;\n }\n setShowAudioRecorder(true);\n })();\n }, [hasQuery]);\n\n /**\n * On a successful Whisper round-trip, paste the transcript into the input\n * field, close the recorder, and let the user review/send manually. Matches\n * web's `handleTranscriptionComplete`: we deliberately do NOT auto-fire\n * `sendMessage` because the user often wants to edit the dictation first.\n */\n const handleTranscriptionComplete = useCallback((text: string) => {\n const cleaned = (text ?? '').trim();\n setShowAudioRecorder(false);\n if (!cleaned) return;\n setValue((prev) => {\n const next = prev.trim().length > 0 ? `${prev.trim()} ${cleaned}` : cleaned;\n /*\n * Keep `inputRef`'s native text in sync with our controlled value\n * for the same reason `handleSend` does (the iOS native buffer\n * can lag the React state across a single gesture). `setNativeProps`\n * is the safe way to do this without re-rendering.\n */\n requestAnimationFrame(() => {\n inputRef.current?.setNativeProps?.({ text: next });\n inputRef.current?.focus?.();\n });\n return next;\n });\n }, []);\n\n const handleRecorderCancel = useCallback(() => {\n setShowAudioRecorder(false);\n }, []);\n\n const handleRecorderError = useCallback((error: string) => {\n setVoiceError(error);\n }, []);\n\n const waitingForAssistant = useMemo(() => {\n if ((!isLoading && !isStreaming) || messages.length === 0) return false;\n if ((response ?? '').trim()) return false;\n return messages[messages.length - 1]?.role === 'user';\n }, [isLoading, isStreaming, messages, response]);\n\n const composerScrollBottomPadding = 24 + (keyboardVisible ? keyboardHeight : 0);\n\n /*\n * NOTE: the previous read-only `isDeepSearchChannel` derivation has been\n * removed. Mode is now a freely-toggleable local state (`activeMode`)\n * driven by tapping the search/zap pills, mirroring HomeScreen. All\n * downstream branches use `isDeepSearchMode` declared with the rest of\n * the composer state above.\n */\n\n /**\n * Deep-search overlay state.\n *\n * Restored from the previous Home-screen flow (commit history): a deep-search\n * channel renders the structured `DeepSearchModal` (query / live summary /\n * sources / research process) on top of the regular Chat conversation. Closing\n * the modal reveals the same channel's MessagesContainerUI underneath so the\n * user can still see the raw turns.\n *\n * Trigger semantics — IMPORTANT:\n * • Opens ONLY when a request is actually fired in this session:\n * - Home → Chat auto-fire of `initialQuery`\n * - User sends a new message in a deep-search channel from the composer\n * - Explicit retry from inside the modal\n * • Does NOT open on plain entry from ChatHistoryScreen. That's a revisit\n * of an already-completed thread — no new API call, nothing live to\n * stream, so popping the modal would just be a confusing flash. The\n * user still sees the deep-search rendering in the chat conversation\n * underneath, and any new send re-opens the live view.\n *\n * Local UI state (accordions, open flag) lives here; data state (query /\n * summary / sources) is DERIVED from the chat stream, not stored separately,\n * so there's no drift between the modal and the underlying conversation.\n */\n const [isDeepSearchModalOpen, setIsDeepSearchModalOpen] = useState(false);\n const [researchProcessOpen, setResearchProcessOpen] = useState(true);\n const [sourcesAccordionOpen, setSourcesAccordionOpen] = useState(true);\n\n /**\n * Modal data is always scoped to the CURRENT run, not the whole channel.\n * In a multi-turn deep-search channel each send is its own \"run\": one user\n * query → one assistant summary. If we sourced from \"first user message\" /\n * \"any assistant message\", a follow-up send would keep showing the previous\n * run's query and stale sources during the transient window between the new\n * user message being appended and the first stream token arriving.\n *\n * Cursor: the LAST user message in the thread. The assistant content for\n * the current run is either:\n * • `response` while the stream is filling (token-by-token), OR\n * • the assistant message that comes AFTER the last user (run complete), OR\n * • empty — covers the brief \"user message appended, no response yet\"\n * window so the modal flips to \"Running...\" with no stale body.\n */\n const lastUserIndex = useMemo(() => {\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n if (messages[i]?.role === 'user') return i;\n }\n return -1;\n }, [messages]);\n\n const deepSearchQuery = useMemo(() => {\n if (lastUserIndex >= 0) {\n const txt = messages[lastUserIndex]?.content?.trim();\n if (txt) return txt;\n }\n return initialQuery ?? null;\n }, [messages, lastUserIndex, initialQuery]);\n\n const latestAssistantContent = useMemo(() => {\n if (response && response.trim()) return response;\n if (lastUserIndex < 0) return '';\n // Look for an assistant turn strictly AFTER the last user message.\n // Anything before it belongs to a prior run and must not leak into\n // the modal for the current one.\n for (let i = lastUserIndex + 1; i < messages.length; i += 1) {\n if (messages[i]?.role === 'assistant') {\n return messages[i]?.content ?? '';\n }\n }\n return '';\n }, [response, messages, lastUserIndex]);\n\n const deepSearchSummary = useMemo(() => normalizeSummaryText(latestAssistantContent), [latestAssistantContent]);\n const deepSearchSources: DeepSearchSourceItem[] = useMemo(\n () => extractDeepSearchSources(latestAssistantContent),\n [latestAssistantContent],\n );\n\n const handleDeepSearchClose = useCallback(() => {\n if (isStreaming) cancel();\n setIsDeepSearchModalOpen(false);\n }, [isStreaming, cancel]);\n\n const handleDeepSearchRetry = useCallback(() => {\n if (!deepSearchQuery || isStreaming || !channelId) return;\n void sendMessage(deepSearchQuery, undefined, channelId);\n }, [deepSearchQuery, isStreaming, channelId, sendMessage]);\n const leftItems = useMemo(\n () =>\n getDefaultLeftItems({\n search: { active: activeMode === 'chat', onClick: () => handleModeSwitch('chat') },\n zap: { active: activeMode === 'deep-search', onClick: () => handleModeSwitch('deep-search') },\n lightbulb: {\n active: activeMode === 'build',\n onClick: () => handleModeSwitch('build'),\n },\n }),\n [activeMode, handleModeSwitch],\n );\n const rightItems = useMemo(\n () =>\n getDefaultRightItems({\n tag: { enabled: false },\n chip: { enabled: false },\n camera: { enabled: false },\n image: { enabled: false },\n attach: { enabled: false },\n }),\n [],\n );\n /**\n * Composer placeholder.\n *\n * Mirrors Home so the composer feels like the same affordance across the\n * \"first message\" and \"continuing thread\" surfaces — only the surrounding\n * UI changes, the input stays a stable anchor. We intentionally do NOT\n * surface a \"Loading conversation…\" state in the placeholder: the message\n * list already shows a dedicated hydrating loader, and switching the\n * placeholder for ~1 frame creates a visible flash on every entry.\n */\n const inputPlaceholder = isDeepSearchMode\n ? 'Research anything...'\n : isBuildMode\n ? 'Describe an app to build...'\n : 'Ask anything...';\n\n const inputConfig = useMemo(\n () => ({\n value,\n onChange: handleValueChange,\n placeholder: inputPlaceholder,\n disabled: !channelId,\n inputRef,\n returnKeyType: 'send',\n blurOnSubmit: false,\n onSubmitEditing: () => handleSend(),\n }),\n [value, handleValueChange, inputPlaceholder, channelId, handleSend],\n );\n const micSendButton = useMemo(\n () => ({\n hasContent: hasQuery,\n onSend: () => handleSend(),\n onMic: handleMicPress,\n disabled: !channelId,\n // Empty + streaming → Stop. Typed follow-up → Send (steer). Never lock the composer.\n isLoading: canSubmit ? false : isLoading,\n onStop: isStreaming && !canSubmit ? cancel : undefined,\n steerable: isLoading || isStreaming,\n }),\n [canSubmit, handleSend, handleMicPress, isLoading, channelId, isStreaming, cancel, hasQuery],\n );\n\n /**\n * Loader visibility:\n * - `isHydrating`: Apollo channel history is being fetched and we have nothing to show yet.\n * - `isWaitingForGateway`: Home navigated us here with an `initialQuery`, but CDeCLI is still\n * establishing the workspace session, so the auto-fire is deferred. Show a \"Connecting…\"\n * placeholder instead of an empty thread so the user doesn't think their send was dropped.\n */\n const isHydrating = messagesLoading && messages.length === 0 && !response;\n const isWaitingForGateway =\n !autoFiredRef.current &&\n !!channelId &&\n !!initialQuery &&\n cdecli.status !== 'connected' &&\n cdecli.status !== 'error';\n const showSendingLoader = waitingForAssistant;\n const pinSendingLoaderNearComposer = messages.length > 0 || Boolean((response ?? '').trim());\n\n return (\n <SafeAreaView edges={['left', 'right']} style={{ flex: 1, backgroundColor: surfaceColor }}>\n <Box flex={1} width=\"100%\" position=\"relative\">\n {(chatError || cdecli.error) && (\n <Box\n mb=\"$2\"\n mx=\"$4\"\n p=\"$3\"\n borderRadius=\"$md\"\n style={{\n backgroundColor: isDark ? '#2b1a1d' : '#fef2f2',\n borderWidth: 1,\n borderColor: isDark ? '#7f1d1d' : '#fecaca',\n }}\n >\n <Text fontSize=\"$sm\" style={{ color: isDark ? '#fecaca' : '#991b1b' }}>\n {chatError || cdecli.error}\n </Text>\n </Box>\n )}\n {!channelId ? (\n <Box flex={1} alignItems=\"center\" justifyContent=\"center\">\n <YantraBrandLoader size={YANTRA_LOADER_SIZE_COMPACT} />\n <Text style={[styles.statusText, { color: secondaryTextColor }]}>No channel selected</Text>\n </Box>\n ) : isHydrating ? (\n /**\n * Channel hydration (entering Chat from history or a deep\n * link) reuses the same `ThinkingIndicator` row as the\n * chat-history list — thin spinning arc + muted caption.\n * Keeps the loading vocabulary consistent across screens\n * and avoids the previous branded loader + \"Loading\n * conversation\" copy that read as a different state.\n */\n <Box flex={1} alignItems=\"center\" justifyContent=\"center\">\n <ThinkingIndicator color={secondaryTextColor} />\n </Box>\n ) : isWaitingForGateway ? (\n <Box flex={1} alignItems=\"center\" justifyContent=\"center\">\n <YantraBrandLoader size={YANTRA_LOADER_SIZE_COMPACT} />\n <Text style={[styles.statusText, { color: secondaryTextColor }]}>Connecting gateway…</Text>\n </Box>\n ) : (\n <Box flex={1} width=\"100%\" alignSelf=\"stretch\">\n <MessagesContainerUI\n mode=\"chat\"\n showBackButton={false}\n compactTop\n messagesContainerStyle={{\n paddingHorizontal: 0,\n paddingTop: 0,\n paddingBottom: composerScrollBottomPadding,\n margin: 0,\n marginTop: 0,\n alignSelf: 'center',\n width: contentMaxWidth,\n }}\n listContentStyle={{\n paddingTop: 0,\n paddingBottom: composerScrollBottomPadding,\n margin: 0,\n marginTop: 0,\n width: contentMaxWidth,\n alignSelf: 'center',\n justifyContent: 'flex-end',\n }}\n messages={transcriptRows}\n streamingContent={response}\n currentUser={CHAT_CURRENT_USER}\n onSend={handleSend}\n disabled={!channelId}\n isLoading={isLoading}\n onStop={isStreaming ? cancel : undefined}\n renderPlanInputToolbar={renderNoToolbar}\n renderBuildInputToolbar={renderNoToolbar}\n />\n </Box>\n )}\n {showSendingLoader && !pinSendingLoaderNearComposer ? (\n <View pointerEvents=\"none\" style={styles.sendingLoaderEmptyState}>\n <ThinkingIndicator color={secondaryTextColor} />\n </View>\n ) : null}\n <KeyboardComposerDock closedInset={insets.bottom} keyboardVisible={keyboardVisible}>\n {showSendingLoader && pinSendingLoaderNearComposer ? (\n <View pointerEvents=\"none\" style={styles.sendingLoaderInDock}>\n <ThinkingIndicator color={secondaryTextColor} />\n </View>\n ) : null}\n <View style={[styles.bottomComposerInner, { width: contentMaxWidth }]}>\n {voiceError ? (\n <View\n style={[\n styles.voiceErrorBanner,\n {\n backgroundColor: isDark ? '#2b1a1d' : '#fef2f2',\n borderColor: isDark ? '#7f1d1d' : '#fecaca',\n },\n ]}\n >\n <Text style={[styles.voiceErrorText, { color: isDark ? '#fecaca' : '#991b1b' }]}>\n {voiceError}\n </Text>\n </View>\n ) : null}\n {showAudioRecorder ? (\n /*\n * Render-time JS errors thrown by `useAudioRecorder`\n * (e.g. expo-audio native module missing, recorder\n * constructor throws in a release build) are caught\n * by the boundary and converted into a soft cancel\n * via the same handlers the panel itself uses on\n * runtime errors. Without this, a throw during the\n * panel's render phase kills the JS thread in\n * release / TestFlight.\n */\n <MicErrorBoundary onCancel={handleRecorderCancel} onError={handleRecorderError}>\n <AudioRecorderPanel\n isDark={isDark}\n onTranscriptionComplete={handleTranscriptionComplete}\n onCancel={handleRecorderCancel}\n onError={handleRecorderError}\n />\n </MicErrorBoundary>\n ) : (\n <InputToolBar\n inputConfig={inputConfig}\n leftItems={leftItems}\n rightItems={rightItems}\n templateButton={null}\n templateModalConfig={null}\n micSendButton={micSendButton}\n />\n )}\n </View>\n </KeyboardComposerDock>\n </Box>\n {/*\n * DeepSearchModal is rendered OUTSIDE the keyboard-dismiss wrapper so\n * taps inside the modal don't dismiss the keyboard, and it's a native\n * <Modal> internally so it correctly sits on top of the Chat surface\n * (composer included) on both iOS and Android.\n */}\n {isDeepSearchMode ? (\n <DeepSearchModal\n visible={isDeepSearchModalOpen}\n query={deepSearchQuery}\n summaryText={deepSearchSummary}\n sources={deepSearchSources}\n isStreaming={isStreaming}\n researchProcessOpen={researchProcessOpen}\n sourcesAccordionOpen={sourcesAccordionOpen}\n onToggleResearchProcess={() => setResearchProcessOpen((prev) => !prev)}\n onToggleSourcesAccordion={() => setSourcesAccordionOpen((prev) => !prev)}\n onRetry={handleDeepSearchRetry}\n onStop={cancel}\n onClose={handleDeepSearchClose}\n />\n ) : null}\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n statusText: {\n marginTop: 14,\n fontSize: 13,\n fontWeight: '500',\n },\n bottomComposerInner: {\n paddingHorizontal: 14,\n paddingTop: 10,\n paddingBottom: 4,\n },\n voiceErrorBanner: {\n marginBottom: 8,\n paddingHorizontal: 12,\n paddingVertical: 8,\n borderRadius: 10,\n borderWidth: 1,\n },\n voiceErrorText: {\n fontSize: 12,\n fontWeight: '500',\n },\n sendingLoaderEmptyState: {\n position: 'absolute',\n left: 0,\n right: 0,\n top: 0,\n bottom: 0,\n justifyContent: 'center',\n alignItems: 'center',\n zIndex: 40,\n },\n sendingLoaderInDock: {\n alignItems: 'center',\n justifyContent: 'flex-end',\n paddingBottom: 8,\n },\n});\n"],"names":["_a","_b"],"mappings":";;;;;;;;;;;;;;;;;;;AAmDA,MAAM,iBAAoB,GAAA;AAAA,EACxB,EAAI,EAAA;AACN,CAAA;AACA,MAAM,kBAAkB,MAAM,IAAA;AAC9B,SAAwB,UAAa,GAAA;AAvDrC,EAAA,IAAA,EAAA,EAAA,EAAA;AAwDE,EAAA,MAAM,aAAa,aAAmB,EAAA;AACtC,EAAA,MAAM,QAAQ,QAAc,EAAA;AAC5B,EAAA,MAAM,MAAU,GAAA,CAAA,EAAA,GAAA,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAO,MAAP,KAAA,IAAA,GAAA,EAAA,GAAiB,EAAC;AAClC,EAAM,MAAA,SAAA,GAAY,QAAQ,MAAM;AAC9B,IAAM,MAAA,GAAA,GAAM,OAAO,MAAO,CAAA,SAAA,KAAc,WAAW,MAAO,CAAA,SAAA,CAAU,MAAS,GAAA,EAAA;AAC7E,IAAO,OAAA,GAAA,CAAI,MAAS,GAAA,CAAA,GAAI,GAAM,GAAA,IAAA;AAAA,GAC7B,EAAA,CAAC,MAAO,CAAA,SAAS,CAAC,CAAA;AACrB,EAAM,MAAA,YAAA,GAAe,QAAQ,MAAM;AACjC,IAAM,MAAA,GAAA,GAAM,OAAO,MAAO,CAAA,YAAA,KAAiB,WAAW,MAAO,CAAA,YAAA,CAAa,MAAS,GAAA,EAAA;AACnF,IAAO,OAAA,GAAA,CAAI,MAAS,GAAA,CAAA,GAAI,GAAM,GAAA,IAAA;AAAA,GAC7B,EAAA,CAAC,MAAO,CAAA,YAAY,CAAC,CAAA;AACxB,EAAA,MAAM,qBAAqB,MAAO,CAAA,kBAAA;AAClC,EAAA,MAAM,cAAc,cAAe,EAAA;AACnC,EAAA,MAAM,SAAS,WAAgB,KAAA,MAAA;AAC/B,EAAM,MAAA;AAAA,IACJ,KAAO,EAAA;AAAA,MACL,mBAAoB,EAAA;AACxB,EAAM,MAAA,eAAA,GAAkB,KAAK,GAAI,CAAA,GAAA,EAAK,KAAK,GAAI,CAAA,GAAA,EAAK,WAAc,GAAA,EAAE,CAAC,CAAA;AACrE,EAAA,MAAM,YAAe,GAAA,MAAA,GAAS,SAAY,GAAA,YAAA,CAAa,KAAM,CAAA,OAAA;AAC7D,EAAA,MAAM,kBAAqB,GAAA,MAAA,GAAS,SAAY,GAAA,YAAA,CAAa,KAAM,CAAA,SAAA;AACnE,EAAA,MAAM,SAAS,iBAAkB,EAAA;AACjC,EAAM,MAAA;AAAA,IACJ,cAAA;AAAA,IACA;AAAA,MACE,uBAAwB,EAAA;AAW5B,EAAA,MAAM,SAAS,mBAAoB,EAAA;AACnC,EAAM,MAAA,wBAAA,GAAA,CAA2B,EAAO,GAAA,MAAA,CAAA,eAAA,KAAP,IAA0B,GAAA,EAAA,GAAA,SAAA;AAC3D,EAAA,SAAA,CAAU,MAAM;AACd,IAAI,IAAA,CAAC,WAAkB,OAAA,MAAA;AACvB,IAAA,MAAA,CAAO,mBAAmB,SAAS,CAAA;AACnC,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,mBAAmB,MAAS,CAAA;AAAA,KACrC;AAAA,GACC,EAAA,CAAC,SAAW,EAAA,MAAA,CAAO,kBAAkB,CAAC,CAAA;AACzC,EAAM,MAAA,WAAA,GAAoC,QAAQ,OAAO;AAAA,IACvD,kBAAkB,MAAO,CAAA,gBAAA;AAAA,IACzB,WAAW,MAAO,CAAA,SAAA;AAAA,IAClB,eAAiB,EAAA;AAAA,MACf,CAAC,MAAA,CAAO,kBAAkB,MAAO,CAAA,SAAA,EAAW,wBAAwB,CAAC,CAAA;AACzE,EAAM,MAAA,IAAA,GAAO,aAAc,CAAA,SAAA,EAAW,WAAW,CAAA;AAkBjD,EAAM,MAAA,cAAA,GAAiB,QAAQ,MAAM,IAAA,CAAK,SAAS,GAAI,CAAA,CAAC,KAAK,KAAW,MAAA;AAAA,IACtE,EAAI,EAAA,CAAA,IAAA,EAAO,KAAK,CAAA,CAAA,EAAI,IAAI,IAAI,CAAA,CAAA;AAAA,IAC5B,MAAM,GAAI,CAAA,IAAA;AAAA,IACV,SAAS,GAAI,CAAA,OAAA;AAAA,IACb,UAAW,GAER,CAAA;AAAA,GACH,CAAA,CAAA,EAAG,CAAC,IAAA,CAAK,QAAQ,CAAC,CAAA;AACpB,EAAM,MAAA;AAAA,IACJ,QAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAO,EAAA,SAAA;AAAA,IACP,SAAA;AAAA,IACA,WAAA;AAAA,IACA,eAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACE,GAAA,IAAA;AAgBJ,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,EAAE,CAAA;AACrC,EAAM,MAAA,QAAA,GAAW,OAAO,KAAK,CAAA;AAC7B,EAAA,QAAA,CAAS,OAAU,GAAA,KAAA;AACnB,EAAM,MAAA,QAAA,GAAW,OAAkB,IAAI,CAAA;AACvC,EAAM,MAAA,OAAA,GAAU,MAAM,IAAK,EAAA;AAC3B,EAAM,MAAA,QAAA,GAAW,QAAQ,MAAS,GAAA,CAAA;AAClC,EAAM,MAAA,SAAA,GAAY,QAAY,IAAA,OAAA,CAAQ,SAAS,CAAA;AAgB/C,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAsB,MAAM,MAAA,CAAO,WAAgB,KAAA,aAAA,GAAgB,aAAgB,GAAA,MAAA,CAAO,WAAgB,KAAA,OAAA,GAAU,UAAU,MAAM,CAAA;AACxK,EAAM,MAAA,gBAAA,GAAmB,WAAY,CAAA,CAAC,IAAsB,KAAA;AAC1D,IAAA,aAAA,CAAc,IAAI,CAAA;AAAA,GACpB,EAAG,EAAE,CAAA;AACL,EAAA,MAAM,mBAAmB,UAAe,KAAA,aAAA;AACxC,EAAA,MAAM,cAAc,UAAe,KAAA,OAAA;AAQnC,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAI,SAAS,KAAK,CAAA;AAChE,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAwB,IAAI,CAAA;AAUhE,EAAM,MAAA,YAAA,GAAe,OAAO,KAAK,CAAA;AACjC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,aAAa,OAAS,EAAA;AAC1B,IAAI,IAAA,CAAC,SAAa,IAAA,CAAC,YAAc,EAAA;AACjC,IAAA,IAAI,MAAO,CAAA,MAAA,KAAW,WAAe,IAAA,MAAA,CAAO,WAAW,OAAS,EAAA;AAChE,IAAA,YAAA,CAAa,OAAU,GAAA,IAAA;AAWvB,IAAA,IAAI,gBAAkB,EAAA;AACpB,MAAA,wBAAA,CAAyB,IAAI,CAAA;AAAA;AAE/B,IAAK,KAAA,WAAA,CAAY,YAAc,EAAA,kBAAA,EAA2B,SAAS,CAAA;AACnE,IAAI,IAAA;AACF,MAAA,UAAA,CAAW,SAAU,CAAA;AAAA,QACnB,YAAc,EAAA,IAAA;AAAA,QACd,kBAAoB,EAAA;AAAA,OACrB,CAAA;AAAA,KACK,CAAA,OAAA,CAAA,EAAA;AAAA;AAER,GACF,EAAG,CAAC,SAAA,EAAW,YAAc,EAAA,kBAAA,EAAoB,aAAa,UAAY,EAAA,MAAA,CAAO,MAAQ,EAAA,gBAAgB,CAAC,CAAA;AAC1G,EAAM,MAAA,UAAA,GAAa,WAAY,CAAA,CAAC,IAAkB,KAAA;AAvOpD,IAAAA,IAAAA,GAAAA;AAwOI,IAAA,MAAM,CAAK,GAAA,CAAA,IAAA,IAAA,IAAA,GAAA,IAAA,GAAQ,QAAS,CAAA,OAAA,EAAS,IAAK,EAAA;AAC1C,IAAI,IAAA,CAAC,CAAK,IAAA,CAAC,SAAW,EAAA;AAKtB,IAAA,QAAA,CAAS,EAAE,CAAA;AACX,IAAA,CAAAA,GAAA,GAAA,QAAA,CAAS,OAAT,KAAA,IAAA,GAAA,MAAA,GAAAA,GAAkB,CAAA,KAAA,EAAA;AAGlB,IAAA,IAAI,WAAa,EAAA;AACf,MAAW,UAAA,CAAA,QAAA,CAAS,cAAc,QAAS,CAAA;AAAA,QACzC,IAAM,EAAA,sBAAA;AAAA,QACN,MAAA,EAAQ,aACF,CAAA,cAAA,CAAA,EAAA,EAAA,MAAA,CAAO,OAAU,GAAA;AAAA,UACnB,SAAS,MAAO,CAAA;AAAA,SAClB,GAAI,EAHE,CAAA,EAAA;AAAA,UAIN,SAAA;AAAA,UACA,OAAS,EAAA;AAAA,SACX;AAAA,OACD,CAAC,CAAA;AACF,MAAA;AAAA;AASF,IAAA,IAAI,gBAAkB,EAAA;AACpB,MAAA,wBAAA,CAAyB,IAAI,CAAA;AAAA;AAE/B,IAAK,KAAA,WAAA,CAAY,CAAG,EAAA,MAAA,EAAW,SAAS,CAAA;AAAA,GAC1C,EAAG,CAAC,SAAW,EAAA,WAAA,EAAa,kBAAkB,WAAa,EAAA,UAAA,EAAY,MAAO,CAAA,OAAO,CAAC,CAAA;AACtF,EAAM,MAAA,iBAAA,GAAoB,WAAY,CAAA,CAAC,CAAW,KAAA;AA3QpD,IAAA,IAAAA,GAAAC,EAAAA,GAAAA;AA4QI,IAASA,QAAAA,CAAAA,CAAAA,GAAAA,GAAAA,CAAAD,MAAA,CAAG,IAAA,IAAA,GAAA,MAAA,GAAA,CAAA,CAAA,WAAA,KAAH,gBAAAA,GAAgB,CAAA,IAAA,KAAhB,IAAAC,GAAAA,GAAAA,GAAwB,EAAE,CAAA;AAAA,GACrC,EAAG,EAAE,CAAA;AAqBL,EAAM,MAAA,cAAA,GAAiB,YAAY,MAAM;AACvC,IAAA,IAAI,QAAU,EAAA;AACd,IAAA,aAAA,CAAc,IAAI,CAAA;AAClB,IAAA,QAAA,CAAS,OAAQ,EAAA;AACjB,IAAA,KAAA,CAAM,YAAY;AAChB,MAAM,MAAA;AAAA,QACJ,OAAA;AAAA,QACA;AAAA,OACF,GAAI,MAAM,oBAAqB,EAAA;AAC/B,MAAA,IAAI,CAAC,OAAS,EAAA;AACZ,QAAA,aAAA,CAAc,SAAS,8BAA8B,CAAA;AACrD,QAAA;AAAA;AAEF,MAAA,oBAAA,CAAqB,IAAI,CAAA;AAAA,KACxB,GAAA;AAAA,GACL,EAAG,CAAC,QAAQ,CAAC,CAAA;AAQb,EAAM,MAAA,2BAAA,GAA8B,WAAY,CAAA,CAAC,IAAiB,KAAA;AAChE,IAAM,MAAA,OAAA,GAAA,CAAW,IAAQ,IAAA,IAAA,GAAA,IAAA,GAAA,EAAA,EAAI,IAAK,EAAA;AAClC,IAAA,oBAAA,CAAqB,KAAK,CAAA;AAC1B,IAAA,IAAI,CAAC,OAAS,EAAA;AACd,IAAA,QAAA,CAAS,CAAQ,IAAA,KAAA;AACf,MAAA,MAAM,IAAO,GAAA,IAAA,CAAK,IAAK,EAAA,CAAE,MAAS,GAAA,CAAA,GAAI,CAAG,EAAA,IAAA,CAAK,IAAK,EAAC,CAAI,CAAA,EAAA,OAAO,CAAK,CAAA,GAAA,OAAA;AAOpE,MAAA,qBAAA,CAAsB,MAAM;AArUlC,QAAA,IAAAD,KAAAC,GAAA,EAAA,EAAA,EAAA,EAAA;AAsUQ,QAAAA,CAAAA,GAAAA,GAAAA,CAAAD,GAAA,GAAA,QAAA,CAAS,OAAT,KAAA,IAAA,GAAA,MAAA,GAAAA,IAAkB,cAAlB,KAAA,IAAA,GAAA,MAAA,GAAAC,GAAA,CAAA,IAAA,CAAAD,GAAmC,EAAA;AAAA,UACjC,IAAM,EAAA;AAAA,SACR,CAAA;AACA,QAAS,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,QAAA,CAAA,OAAA,KAAT,mBAAkB,KAAlB,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,EAAA,CAAA;AAAA,OACD,CAAA;AACD,MAAO,OAAA,IAAA;AAAA,KACR,CAAA;AAAA,GACH,EAAG,EAAE,CAAA;AACL,EAAM,MAAA,oBAAA,GAAuB,YAAY,MAAM;AAC7C,IAAA,oBAAA,CAAqB,KAAK,CAAA;AAAA,GAC5B,EAAG,EAAE,CAAA;AACL,EAAM,MAAA,mBAAA,GAAsB,WAAY,CAAA,CAAC,KAAkB,KAAA;AACzD,IAAA,aAAA,CAAc,KAAK,CAAA;AAAA,GACrB,EAAG,EAAE,CAAA;AACL,EAAM,MAAA,mBAAA,GAAsB,QAAQ,MAAM;AApV5C,IAAAA,IAAAA,GAAAA;AAqVI,IAAA,IAAI,CAAC,SAAa,IAAA,CAAC,eAAe,QAAS,CAAA,MAAA,KAAW,GAAU,OAAA,KAAA;AAChE,IAAA,IAAA,CAAK,QAAY,IAAA,IAAA,GAAA,QAAA,GAAA,EAAA,EAAI,IAAK,EAAA,EAAU,OAAA,KAAA;AACpC,IAAOA,OAAAA,CAAAA,CAAAA,GAAAA,GAAA,SAAS,QAAS,CAAA,MAAA,GAAS,CAAC,CAA5B,KAAA,IAAA,GAAA,MAAA,GAAAA,IAA+B,IAAS,MAAA,MAAA;AAAA,KAC9C,CAAC,SAAA,EAAW,WAAa,EAAA,QAAA,EAAU,QAAQ,CAAC,CAAA;AAC/C,EAAM,MAAA,2BAAA,GAA8B,EAAM,IAAA,eAAA,GAAkB,cAAiB,GAAA,CAAA,CAAA;AAkC7E,EAAA,MAAM,CAAC,qBAAA,EAAuB,wBAAwB,CAAA,GAAI,SAAS,KAAK,CAAA;AACxE,EAAA,MAAM,CAAC,mBAAA,EAAqB,sBAAsB,CAAA,GAAI,SAAS,IAAI,CAAA;AACnE,EAAA,MAAM,CAAC,oBAAA,EAAsB,uBAAuB,CAAA,GAAI,SAAS,IAAI,CAAA;AAiBrE,EAAM,MAAA,aAAA,GAAgB,QAAQ,MAAM;AA9YtC,IAAAA,IAAAA,GAAAA;AA+YI,IAAA,KAAA,IAAS,IAAI,QAAS,CAAA,MAAA,GAAS,GAAG,CAAK,IAAA,CAAA,EAAG,KAAK,CAAG,EAAA;AAChD,MAAIA,IAAAA,CAAAA,CAAAA,GAAAA,GAAA,SAAS,CAAC,CAAA,KAAV,gBAAAA,GAAa,CAAA,IAAA,MAAS,QAAe,OAAA,CAAA;AAAA;AAE3C,IAAO,OAAA,EAAA;AAAA,GACT,EAAG,CAAC,QAAQ,CAAC,CAAA;AACb,EAAM,MAAA,eAAA,GAAkB,QAAQ,MAAM;AApZxC,IAAA,IAAAA,GAAAC,EAAAA,GAAAA;AAqZI,IAAA,IAAI,iBAAiB,CAAG,EAAA;AACtB,MAAM,MAAA,GAAA,GAAA,CAAMA,GAAAD,GAAAA,CAAAA,GAAAA,GAAA,QAAS,CAAA,aAAa,MAAtB,IAAAA,GAAAA,MAAAA,GAAAA,GAAAA,CAAyB,OAAzB,KAAA,IAAA,GAAA,MAAA,GAAAC,GAAkC,CAAA,IAAA,EAAA;AAC9C,MAAA,IAAI,KAAY,OAAA,GAAA;AAAA;AAElB,IAAA,OAAO,YAAgB,IAAA,IAAA,GAAA,YAAA,GAAA,IAAA;AAAA,GACtB,EAAA,CAAC,QAAU,EAAA,aAAA,EAAe,YAAY,CAAC,CAAA;AAC1C,EAAM,MAAA,sBAAA,GAAyB,QAAQ,MAAM;AA3Z/C,IAAA,IAAAD,KAAAC,GAAA,EAAA,EAAA;AA4ZI,IAAA,IAAI,QAAY,IAAA,QAAA,CAAS,IAAK,EAAA,EAAU,OAAA,QAAA;AACxC,IAAI,IAAA,aAAA,GAAgB,GAAU,OAAA,EAAA;AAI9B,IAAA,KAAA,IAAS,IAAI,aAAgB,GAAA,CAAA,EAAG,IAAI,QAAS,CAAA,MAAA,EAAQ,KAAK,CAAG,EAAA;AAC3D,MAAA,IAAA,CAAA,CAAID,MAAA,QAAS,CAAA,CAAC,MAAV,IAAAA,GAAAA,MAAAA,GAAAA,GAAAA,CAAa,UAAS,WAAa,EAAA;AACrC,QAAO,OAAA,CAAA,EAAA,GAAA,CAAAC,MAAA,QAAS,CAAA,CAAC,MAAV,IAAAA,GAAAA,MAAAA,GAAAA,GAAAA,CAAa,YAAb,IAAwB,GAAA,EAAA,GAAA,EAAA;AAAA;AACjC;AAEF,IAAO,OAAA,EAAA;AAAA,GACN,EAAA,CAAC,QAAU,EAAA,QAAA,EAAU,aAAa,CAAC,CAAA;AACtC,EAAM,MAAA,iBAAA,GAAoB,QAAQ,MAAM,oBAAA,CAAqB,sBAAsB,CAAG,EAAA,CAAC,sBAAsB,CAAC,CAAA;AAC9G,EAAM,MAAA,iBAAA,GAA4C,QAAQ,MAAM,wBAAA,CAAyB,sBAAsB,CAAG,EAAA,CAAC,sBAAsB,CAAC,CAAA;AAC1I,EAAM,MAAA,qBAAA,GAAwB,YAAY,MAAM;AAC9C,IAAA,IAAI,aAAoB,MAAA,EAAA;AACxB,IAAA,wBAAA,CAAyB,KAAK,CAAA;AAAA,GAC7B,EAAA,CAAC,WAAa,EAAA,MAAM,CAAC,CAAA;AACxB,EAAM,MAAA,qBAAA,GAAwB,YAAY,MAAM;AAC9C,IAAA,IAAI,CAAC,eAAA,IAAmB,WAAe,IAAA,CAAC,SAAW,EAAA;AACnD,IAAK,KAAA,WAAA,CAAY,eAAiB,EAAA,MAAA,EAAW,SAAS,CAAA;AAAA,KACrD,CAAC,eAAA,EAAiB,WAAa,EAAA,SAAA,EAAW,WAAW,CAAC,CAAA;AACzD,EAAM,MAAA,SAAA,GAAY,OAAQ,CAAA,MAAM,mBAAoB,CAAA;AAAA,IAClD,MAAQ,EAAA;AAAA,MACN,QAAQ,UAAe,KAAA,MAAA;AAAA,MACvB,OAAA,EAAS,MAAM,gBAAA,CAAiB,MAAM;AAAA,KACxC;AAAA,IACA,GAAK,EAAA;AAAA,MACH,QAAQ,UAAe,KAAA,aAAA;AAAA,MACvB,OAAA,EAAS,MAAM,gBAAA,CAAiB,aAAa;AAAA,KAC/C;AAAA,IACA,SAAW,EAAA;AAAA,MACT,QAAQ,UAAe,KAAA,OAAA;AAAA,MACvB,OAAA,EAAS,MAAM,gBAAA,CAAiB,OAAO;AAAA;AACzC,GACD,CAAA,EAAG,CAAC,UAAA,EAAY,gBAAgB,CAAC,CAAA;AAClC,EAAM,MAAA,UAAA,GAAa,OAAQ,CAAA,MAAM,oBAAqB,CAAA;AAAA,IACpD,GAAK,EAAA;AAAA,MACH,OAAS,EAAA;AAAA,KACX;AAAA,IACA,IAAM,EAAA;AAAA,MACJ,OAAS,EAAA;AAAA,KACX;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,OAAS,EAAA;AAAA,KACX;AAAA,IACA,KAAO,EAAA;AAAA,MACL,OAAS,EAAA;AAAA,KACX;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,OAAS,EAAA;AAAA;AACX,GACD,CAAG,EAAA,EAAE,CAAA;AAWN,EAAA,MAAM,gBAAmB,GAAA,gBAAA,GAAmB,sBAAyB,GAAA,WAAA,GAAc,6BAAgC,GAAA,iBAAA;AACnH,EAAM,MAAA,WAAA,GAAc,QAAQ,OAAO;AAAA,IACjC,KAAA;AAAA,IACA,QAAU,EAAA,iBAAA;AAAA,IACV,WAAa,EAAA,gBAAA;AAAA,IACb,UAAU,CAAC,SAAA;AAAA,IACX,QAAA;AAAA,IACA,aAAe,EAAA,MAAA;AAAA,IACf,YAAc,EAAA,KAAA;AAAA,IACd,eAAA,EAAiB,MAAM,UAAW;AAAA,MAChC,CAAC,KAAA,EAAO,mBAAmB,gBAAkB,EAAA,SAAA,EAAW,UAAU,CAAC,CAAA;AACvE,EAAM,MAAA,aAAA,GAAgB,QAAQ,OAAO;AAAA,IACnC,UAAY,EAAA,QAAA;AAAA,IACZ,MAAA,EAAQ,MAAM,UAAW,EAAA;AAAA,IACzB,KAAO,EAAA,cAAA;AAAA,IACP,UAAU,CAAC,SAAA;AAAA;AAAA,IAEX,SAAA,EAAW,YAAY,KAAQ,GAAA,SAAA;AAAA,IAC/B,MAAQ,EAAA,WAAA,IAAe,CAAC,SAAA,GAAY,MAAS,GAAA,MAAA;AAAA,IAC7C,WAAW,SAAa,IAAA;AAAA,GAC1B,CAAA,EAAI,CAAC,SAAA,EAAW,UAAY,EAAA,cAAA,EAAgB,WAAW,SAAW,EAAA,WAAA,EAAa,MAAQ,EAAA,QAAQ,CAAC,CAAA;AAShG,EAAA,MAAM,WAAc,GAAA,eAAA,IAAmB,QAAS,CAAA,MAAA,KAAW,KAAK,CAAC,QAAA;AACjE,EAAA,MAAM,mBAAsB,GAAA,CAAC,YAAa,CAAA,OAAA,IAAW,CAAC,CAAC,SAAA,IAAa,CAAC,CAAC,YAAgB,IAAA,MAAA,CAAO,MAAW,KAAA,WAAA,IAAe,OAAO,MAAW,KAAA,OAAA;AACzI,EAAA,MAAM,iBAAoB,GAAA,mBAAA;AAC1B,EAAM,MAAA,4BAAA,GAA+B,SAAS,MAAS,GAAA,CAAA,IAAK,SAAS,QAAY,IAAA,IAAA,GAAA,QAAA,GAAA,EAAA,EAAI,MAAM,CAAA;AAC3F,EAAA,4BAAQ,YAAa,EAAA,EAAA,KAAA,EAAO,CAAC,MAAQ,EAAA,OAAO,GAAG,KAAO,EAAA;AAAA,IACpD,IAAM,EAAA,CAAA;AAAA,IACN,eAAiB,EAAA;AAAA,GAET,EAAA,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,OAAI,IAAM,EAAA,CAAA,EAAG,KAAM,EAAA,MAAA,EAAO,UAAS,UAC9B,EAAA,QAAA,EAAA;AAAA,MAAA,CAAA,SAAA,IAAa,MAAO,CAAA,KAAA,qBAAW,GAAA,CAAA,GAAA,EAAA,EAAI,EAAG,EAAA,IAAA,EAAK,EAAG,EAAA,IAAA,EAAK,CAAE,EAAA,IAAA,EAAK,YAAa,EAAA,KAAA,EAAM,KAAO,EAAA;AAAA,QAC9F,eAAA,EAAiB,SAAS,SAAY,GAAA,SAAA;AAAA,QACtC,WAAa,EAAA,CAAA;AAAA,QACb,WAAA,EAAa,SAAS,SAAY,GAAA;AAAA,OAElB,EAAA,QAAA,kBAAA,GAAA,CAAC,IAAK,EAAA,EAAA,QAAA,EAAS,OAAM,KAAO,EAAA;AAAA,QAC1C,KAAA,EAAO,SAAS,SAAY,GAAA;AAAA,OAET,EAAA,QAAA,EAAA,SAAA,IAAa,MAAO,CAAA,KAAA,EACzB,CACJ,EAAA,CAAA;AAAA,MACH,CAAC,4BAAa,IAAA,CAAA,GAAA,EAAA,EAAI,MAAM,CAAG,EAAA,UAAA,EAAW,QAAS,EAAA,cAAA,EAAe,QACvD,EAAA,QAAA,EAAA;AAAA,wBAAC,GAAA,CAAA,iBAAA,EAAA,EAAkB,MAAM,0BAA4B,EAAA,CAAA;AAAA,wBACpD,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,UAAY,EAAA;AAAA,UAC/C,KAAO,EAAA;AAAA,SACR,GAAG,QAAmB,EAAA,qBAAA,EAAA;AAAA,OAAA,EACX,CAAS,GAAA,WAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAStB,GAAA,CAAA,GAAA,EAAA,EAAI,IAAM,EAAA,CAAA,EAAG,UAAW,EAAA,QAAA,EAAS,cAAe,EAAA,QAAA,EAC/B,QAAC,kBAAA,GAAA,CAAA,iBAAA,EAAA,EAAkB,KAAO,EAAA,kBAAA,EAAoB,CAClD,EAAA;AAAA,UAAU,mBAAA,wBAAuB,GAAI,EAAA,EAAA,IAAA,EAAM,GAAG,UAAW,EAAA,QAAA,EAAS,gBAAe,QAC7E,EAAA,QAAA,EAAA;AAAA,wBAAC,GAAA,CAAA,iBAAA,EAAA,EAAkB,MAAM,0BAA4B,EAAA,CAAA;AAAA,wBACpD,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,UAAY,EAAA;AAAA,UAC/C,KAAO,EAAA;AAAA,SACR,GAAG,QAAmB,EAAA,0BAAA,EAAA;AAAA,OAAA,EACX,oBAAU,GAAA,CAAA,GAAA,EAAA,EAAI,IAAM,EAAA,CAAA,EAAG,OAAM,MAAO,EAAA,SAAA,EAAU,SAC1C,EAAA,QAAA,kBAAA,GAAA,CAAC,uBAAoB,IAAK,EAAA,MAAA,EAAO,gBAAgB,KAAO,EAAA,UAAA,EAAU,MAAC,sBAAwB,EAAA;AAAA,QACzG,iBAAmB,EAAA,CAAA;AAAA,QACnB,UAAY,EAAA,CAAA;AAAA,QACZ,aAAe,EAAA,2BAAA;AAAA,QACf,MAAQ,EAAA,CAAA;AAAA,QACR,SAAW,EAAA,CAAA;AAAA,QACX,SAAW,EAAA,QAAA;AAAA,QACX,KAAO,EAAA;AAAA,SACN,gBAAkB,EAAA;AAAA,QACnB,UAAY,EAAA,CAAA;AAAA,QACZ,aAAe,EAAA,2BAAA;AAAA,QACf,MAAQ,EAAA,CAAA;AAAA,QACR,SAAW,EAAA,CAAA;AAAA,QACX,KAAO,EAAA,eAAA;AAAA,QACP,SAAW,EAAA,QAAA;AAAA,QACX,cAAgB,EAAA;AAAA,OAClB,EAAG,UAAU,cAAgB,EAAA,gBAAA,EAAkB,UAAU,WAAa,EAAA,iBAAA,EAAmB,QAAQ,UAAY,EAAA,QAAA,EAAU,CAAC,SAAW,EAAA,SAAA,EAAsB,QAAQ,WAAc,GAAA,MAAA,GAAS,QAAW,sBAAwB,EAAA,eAAA,EAAiB,uBAAyB,EAAA,eAAA,EAAiB,CAC1Q,EAAA,CAAA;AAAA,MACH,iBAAqB,IAAA,CAAC,4BAA+B,mBAAA,GAAA,CAAC,QAAK,aAAc,EAAA,MAAA,EAAO,KAAO,EAAA,MAAA,CAAO,yBACvF,QAAC,kBAAA,GAAA,CAAA,iBAAA,EAAA,EAAkB,KAAO,EAAA,kBAAA,EAAoB,GAClD,CAAU,GAAA,IAAA;AAAA,sBACb,IAAA,CAAA,oBAAA,EAAA,EAAqB,WAAa,EAAA,MAAA,CAAO,QAAQ,eAC7C,EAAA,QAAA,EAAA;AAAA,QAAA,iBAAA,IAAqB,4BAA+B,mBAAA,GAAA,CAAC,IAAK,EAAA,EAAA,aAAA,EAAc,MAAO,EAAA,KAAA,EAAO,MAAO,CAAA,mBAAA,EACtF,QAAC,kBAAA,GAAA,CAAA,iBAAA,EAAA,EAAkB,KAAO,EAAA,kBAAA,EAAoB,GAClD,CAAU,GAAA,IAAA;AAAA,wBACb,IAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,mBAAqB,EAAA;AAAA,UACpD,KAAO,EAAA;AAAA,SACR,CACgB,EAAA,QAAA,EAAA;AAAA,UAAA,UAAA,mBAAc,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,gBAAkB,EAAA;AAAA,YACjE,eAAA,EAAiB,SAAS,SAAY,GAAA,SAAA;AAAA,YACtC,WAAA,EAAa,SAAS,SAAY,GAAA;AAAA,WACnC,CACqB,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAK,KAAO,EAAA,CAAC,OAAO,cAAgB,EAAA;AAAA,YACvD,KAAA,EAAO,SAAS,SAAY,GAAA;AAAA,WAC7B,CAAA,EACwB,QACL,EAAA,UAAA,EAAA,CAAA,EACJ,CAAU,GAAA,IAAA;AAAA,UACb,iBAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAWd,GAAA,CAAA,gBAAA,EAAA,EAAiB,QAAU,EAAA,oBAAA,EAAsB,SAAS,mBACrC,EAAA,QAAA,kBAAA,GAAA,CAAC,kBAAmB,EAAA,EAAA,MAAA,EAAgB,yBAAyB,2BAA6B,EAAA,QAAA,EAAU,oBAAsB,EAAA,OAAA,EAAS,qBAAqB,CAC5J,EAAA;AAAA,8BAAuB,GAAA,CAAC,gBAAa,WAA0B,EAAA,SAAA,EAAsB,YAAwB,cAAgB,EAAA,IAAA,EAAM,mBAAqB,EAAA,IAAA,EAAM,aAA8B,EAAA;AAAA,SACpM,EAAA;AAAA,OACJ,EAAA;AAAA,KACJ,EAAA,CAAA;AAAA,IAOC,gBAAmB,mBAAA,GAAA,CAAC,eAAgB,EAAA,EAAA,OAAA,EAAS,uBAAuB,KAAO,EAAA,eAAA,EAAiB,WAAa,EAAA,iBAAA,EAAmB,SAAS,iBAAmB,EAAA,WAAA,EAA0B,mBAA0C,EAAA,oBAAA,EAA4C,yBAAyB,MAAM,sBAAA,CAAuB,CAAQ,IAAA,KAAA,CAAC,IAAI,CAAA,EAAG,wBAA0B,EAAA,MAAM,wBAAwB,CAAQ,IAAA,KAAA,CAAC,IAAI,CAAA,EAAG,SAAS,qBAAuB,EAAA,MAAA,EAAQ,MAAQ,EAAA,OAAA,EAAS,uBAAuB,CAAK,GAAA;AAAA,GAChf,EAAA,CAAA;AACR;AACA,MAAM,MAAA,GAAS,WAAW,MAAO,CAAA;AAAA,EAC/B,UAAY,EAAA;AAAA,IACV,SAAW,EAAA,EAAA;AAAA,IACX,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA,GACd;AAAA,EACA,mBAAqB,EAAA;AAAA,IACnB,iBAAmB,EAAA,EAAA;AAAA,IACnB,UAAY,EAAA,EAAA;AAAA,IACZ,aAAe,EAAA;AAAA,GACjB;AAAA,EACA,gBAAkB,EAAA;AAAA,IAChB,YAAc,EAAA,CAAA;AAAA,IACd,iBAAmB,EAAA,EAAA;AAAA,IACnB,eAAiB,EAAA,CAAA;AAAA,IACjB,YAAc,EAAA,EAAA;AAAA,IACd,WAAa,EAAA;AAAA,GACf;AAAA,EACA,cAAgB,EAAA;AAAA,IACd,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA,GACd;AAAA,EACA,uBAAyB,EAAA;AAAA,IACvB,QAAU,EAAA,UAAA;AAAA,IACV,IAAM,EAAA,CAAA;AAAA,IACN,KAAO,EAAA,CAAA;AAAA,IACP,GAAK,EAAA,CAAA;AAAA,IACL,MAAQ,EAAA,CAAA;AAAA,IACR,cAAgB,EAAA,QAAA;AAAA,IAChB,UAAY,EAAA,QAAA;AAAA,IACZ,MAAQ,EAAA;AAAA,GACV;AAAA,EACA,mBAAqB,EAAA;AAAA,IACnB,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA,UAAA;AAAA,IAChB,aAAe,EAAA;AAAA;AAEnB,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/screens/Chat/index.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Keyboard, StyleSheet, TextInput, View, useColorScheme, useWindowDimensions } from 'react-native';\nimport { Box, InputToolBar, Text, getDefaultLeftItems, getDefaultRightItems } from '@admin-layout/gluestack-ui-mobile';\nimport { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';\nimport { useNavigation, useRoute, CommonActions } from '@react-navigation/native';\nimport { MessagesContainerUI } from '@messenger-box/platform-mobile';\nimport { useCdecliConnection } from '../../contexts/CdecliConnectionContext';\nimport { useChatStream, type UseChatStreamRouting } from '../../hooks/useChatStream';\nimport { useKeyboardBottomOffset } from '../../hooks/useKeyboardBottomOffset';\nimport { KeyboardComposerDock } from '../../components/KeyboardComposerDock';\nimport { YantraBrandLoader, YANTRA_LOADER_SIZE_COMPACT } from '../../components/YantraBrandLoader';\nimport ThinkingIndicator from '../../components/ThinkingIndicator';\nimport { mobileTokens } from '../../theme/mobileTokens';\nimport DeepSearchModal from '../Home/components/DeepSearchModal';\nimport { extractDeepSearchSources, normalizeSummaryText, type DeepSearchSourceItem } from '../Home/deepSearchUtils';\nimport type { ModeSubmission, RoutingMode } from '../Home/types';\nimport { AudioRecorderPanel } from '../../features/audio-input/AudioRecorderPanel';\nimport { useImageAttachments } from '../../features/attachments/useImageAttachments';\nimport { MicErrorBoundary } from '../../features/audio-input/MicErrorBoundary';\nimport { requestMicPermission } from '../../features/audio-input/useAudioPermission';\n\n/** Route params passed by Home (or by deep-link) when entering the Chat surface. */\nexport interface ChatScreenRouteParams {\n /** Channel id is required — the screen is keyed on the conversation. */\n channelId: string;\n /** Org slug used by gateway/account context. */\n orgName?: string | null;\n /**\n * First user message to auto-fire when the screen mounts. Home generates\n * this when the user submits from the empty composer so the assistant\n * starts streaming on Chat without an extra round trip.\n */\n initialQuery?: string | null;\n /**\n * Seed for the composer's mode (`'chat'` | `'deep-search'` | `'build'`).\n *\n * Set by `HomeScreen` to carry the user's last selection across the\n * navigation hop (\"research from home → research-shaped composer on chat\").\n * `ChatHistoryScreen` does NOT forward this — revisits always land on the\n * default `'chat'` mode, matching Home's defaults, and the user is free to\n * switch from there. Build-mode send hands off to Web Builder.\n *\n * After mount, this param is purely a seed: the screen keeps its own\n * `activeMode` so the user can toggle freely while inside the thread.\n */\n initialMode?: RoutingMode;\n /** Optional attachments forwarded with the initial message. */\n initialAttachments?: ModeSubmission['attachments'];\n}\n\n/** Stable prop identities — a fresh object/function per render defeats the\n * memoisation inside MessagesContainerUI during streaming. */\nconst CHAT_CURRENT_USER = { id: 'user' } as const;\nconst renderNoToolbar = () => null;\n\nexport default function ChatScreen() {\n const navigation = useNavigation<any>();\n const route = useRoute<any>();\n\n const params = (route?.params ?? {}) as Partial<ChatScreenRouteParams>;\n const channelId = useMemo(() => {\n const raw = typeof params.channelId === 'string' ? params.channelId.trim() : '';\n return raw.length > 0 ? raw : null;\n }, [params.channelId]);\n const initialQuery = useMemo(() => {\n const raw = typeof params.initialQuery === 'string' ? params.initialQuery.trim() : '';\n return raw.length > 0 ? raw : null;\n }, [params.initialQuery]);\n const initialAttachments = params.initialAttachments;\n\n const colorScheme = useColorScheme();\n const isDark = colorScheme === 'dark';\n const { width: screenWidth } = useWindowDimensions();\n const contentMaxWidth = Math.min(720, Math.max(360, screenWidth - 24));\n\n const surfaceColor = isDark ? '#0f172a' : mobileTokens.color.surface;\n const secondaryTextColor = isDark ? '#94a3b8' : mobileTokens.color.textMuted;\n\n const insets = useSafeAreaInsets();\n const { keyboardHeight, keyboardVisible } = useKeyboardBottomOffset();\n\n /**\n * Gateway + chat stream routing.\n *\n * The CDeCLI lifecycle is owned app-wide by `CdecliConnectionProvider`,\n * so we just register this screen's channelId and read the shared status.\n * This avoids racing `gatewayConnect` mutations with the header's\n * `GatewayConnector` (which previously ran its own `useCdecliAutoConnect`\n * and could clobber the chat session binding).\n */\n const cdecli = useCdecliConnection();\n const effectivePersistenceMode = cdecli.persistenceMode ?? 'backend';\n\n useEffect(() => {\n if (!channelId) return undefined;\n cdecli.setActiveChannelId(channelId);\n return () => {\n cdecli.setActiveChannelId(undefined);\n };\n }, [channelId, cdecli.setActiveChannelId]);\n\n const chatRouting: UseChatStreamRouting = useMemo(\n () => ({\n channelConnected: cdecli.channelConnected,\n accountId: cdecli.accountId,\n persistenceMode: effectivePersistenceMode,\n }),\n [cdecli.channelConnected, cdecli.accountId, effectivePersistenceMode],\n );\n\n const chat = useChatStream(channelId, chatRouting);\n\n /**\n * Gifted-shaped transcript rows, memoised on `messages` alone.\n *\n * This screen re-renders on every streamed token — `useChatStream` does\n * `setResponse((r) => r + text)` per delta. Building this array inline in\n * the JSX therefore handed `PlanModeView` a fresh `messages` identity on\n * every token, which invalidated its own `useMemo([messages, …])`, re-mapped\n * every row, and re-rendered every bubble. Assistant bubbles render through\n * `react-native-markdown-display`, so that meant re-parsing the markdown of\n * the whole thread once per token — O(messages) parses per delta, on the JS\n * thread, which is exactly when the UI has to stay responsive.\n *\n * `messages` is already stable upstream (`useChatApi` memoises it on the\n * Apollo result), so this only rebuilds when a message is actually added or\n * changed.\n */\n const transcriptRows = useMemo(\n () =>\n chat.messages.map((msg, index) => ({\n id: `msg-${index}-${msg.role}`,\n role: msg.role,\n content: msg.content,\n metadata: (msg as { metadata?: unknown }).metadata,\n })),\n [chat.messages],\n );\n const { messages, response, error: chatError, isLoading, isStreaming, messagesLoading, sendMessage, cancel } = chat;\n\n const imageAttachments = useImageAttachments();\n\n /*\n * Composer state — kept local so it doesn't leak across navigations.\n *\n * `valueRef` mirrors the controlled `value` so `handleSend` can read the\n * latest text without taking a dependency on it. Without this, `handleSend`\n * (and therefore `micSendButton.onSend`) would be recreated on every\n * keystroke, which is unnecessary churn for `InputToolBar`.\n *\n * `inputRef` is forwarded to InputToolBar's TextInput so we can call\n * `.clear()` imperatively after sending. On iOS, the native text buffer\n * can stay desynced from the controlled `value` for a frame when a state\n * update is followed by an async dispatch in the same gesture — the\n * \"send-and-clear\" race. The imperative clear closes that gap deterministically.\n */\n const [value, setValue] = useState('');\n const valueRef = useRef(value);\n valueRef.current = value;\n const inputRef = useRef<TextInput>(null);\n const trimmed = value.trim();\n const hasQuery = trimmed.length > 0;\n const canSubmit = hasQuery && Boolean(channelId);\n\n /**\n * Composer mode is FREELY user-controlled, mirroring `HomeScreen`.\n *\n * Seed:\n * • From Home (which forwards `initialMode` alongside `initialQuery`):\n * start in whatever mode the user picked there so the \"research from\n * home → research-shaped chat\" hand-off feels continuous.\n * • From ChatHistory (which intentionally does NOT pass `initialMode`):\n * default to `'chat'`, same as Home's empty composer.\n *\n * Post-mount this is a normal local state — the search/zap pills toggle\n * it on tap, and every place that previously branched on\n * `params.initialMode` now branches on `activeMode` instead.\n */\n const [activeMode, setActiveMode] = useState<RoutingMode>(() =>\n params.initialMode === 'deep-search' ? 'deep-search' : params.initialMode === 'build' ? 'build' : 'chat',\n );\n const handleModeSwitch = useCallback((mode: RoutingMode) => {\n setActiveMode(mode);\n }, []);\n const isDeepSearchMode = activeMode === 'deep-search';\n const isBuildMode = activeMode === 'build';\n\n /**\n * Inline voice recorder state — parity with HomeScreen and the web\n * `YantraSearchComposer.showAudioRecorder` flow. When active, the panel\n * fully replaces the InputToolBar so the toolbar's mic→send button\n * doesn't compete with the panel's own send/cancel affordances.\n */\n const [showAudioRecorder, setShowAudioRecorder] = useState(false);\n const [voiceError, setVoiceError] = useState<string | null>(null);\n\n /**\n * Auto-fire the initial query once when the screen mounts on a fresh channel.\n * Home creates the channel optimistically and forwards the user prompt here so\n * the first assistant token arrives without an extra interaction.\n *\n * Wait for CDeCLI to finish connecting (or fail) before auto-firing — chat is\n * cdecli-only and `sendMessage` rejects sends while the gateway is disconnected.\n */\n const autoFiredRef = useRef(false);\n useEffect(() => {\n if (autoFiredRef.current) return;\n if (!channelId || !initialQuery) return;\n if (cdecli.status !== 'connected' && cdecli.status !== 'error') return;\n\n autoFiredRef.current = true;\n // Deep-search auto-fire from Home: open the structured modal at the\n // same instant we kick off the send so the user sees the research view\n // streaming in rather than raw assistant turns. Tied to the\n // sendMessage call (same event) to avoid a race where the modal opens\n // before/after the actual send.\n //\n // We branch on the LOCAL `isDeepSearchMode` instead of\n // `params.initialMode`. At auto-fire time they're equal (the local\n // state was seeded from the param), and using the local state means\n // future toggles drive the same code path consistently.\n if (isDeepSearchMode) {\n setIsDeepSearchModalOpen(true);\n }\n void sendMessage(initialQuery, initialAttachments as any, channelId);\n try {\n navigation.setParams({ initialQuery: null, initialAttachments: null });\n } catch {\n /* setParams may be unavailable in tests; clearing is best-effort. */\n }\n }, [channelId, initialQuery, initialAttachments, sendMessage, navigation, cdecli.status, isDeepSearchMode]);\n\n const handleSend = useCallback(\n (text?: string) => {\n const t = (text ?? valueRef.current).trim();\n if (!t || !channelId) return;\n // Clear both ways: the controlled state (so React's model stays\n // consistent on next render) AND the native buffer via the ref\n // (so the visible text disappears on the same frame the user\n // pressed send, even before React flushes).\n setValue('');\n inputRef.current?.clear();\n\n // Build mode: hand off to Web Builder on this channel (web `/c/:id/webbuilder`).\n if (isBuildMode) {\n navigation.dispatch(\n CommonActions.navigate({\n name: 'MainStack.WebBuilder',\n params: {\n ...(params.orgName ? { orgName: params.orgName } : {}),\n channelId,\n message: t,\n },\n }),\n );\n return;\n }\n\n // Deep-search mode: every new query pops the structured research\n // modal back open (parity with the previous Home flow, where every\n // submit re-opened the DeepSearchModal). Without this, a user who\n // closed the modal once would see plain assistant turns for every\n // subsequent send. Reads the LOCAL `isDeepSearchMode` so the user\n // can toggle modes mid-thread and have sends behave accordingly.\n if (isDeepSearchMode) {\n setIsDeepSearchModalOpen(true);\n }\n void sendMessage(t, imageAttachments.forSend(), channelId);\n imageAttachments.clear();\n },\n [channelId, sendMessage, isDeepSearchMode, isBuildMode, navigation, params.orgName, imageAttachments],\n );\n\n const handleValueChange = useCallback((e: any) => {\n setValue(e?.nativeEvent?.text ?? '');\n }, []);\n\n /**\n * Mic affordance — web parity (`handleMicClick` in `YantraSearchComposer.tsx`).\n * The shared `MicSendButton` in `InputToolBar.tsx` only routes to `onMic`\n * when the input has no content, so we only need to handle the empty-input\n * case here.\n *\n * Permission is requested HERE, before the panel mounts. The previous flow\n * flipped `showAudioRecorder=true` immediately, which mounted\n * `AudioRecorderPanel` and constructed the native `AVAudioRecorder` via\n * `useAudioRecorder()` during the panel's render phase — before iOS had\n * granted mic access. On SDK 53 + `newArchEnabled: true` + Hermes that\n * ordering hard-crashes TestFlight builds even though it works in Expo Go\n * (Expo Go pre-caches permission). Asking up front means iOS shows the\n * system alert first and the panel only mounts (and therefore the native\n * recorder is only allocated) once permission is granted.\n *\n * `expo-audio` is lazy-imported so a missing/broken native module surfaces\n * as a user-visible banner instead of a synchronous TurboModule crash.\n */\n const handleMicPress = useCallback(() => {\n if (hasQuery) return;\n setVoiceError(null);\n Keyboard.dismiss();\n void (async () => {\n const { granted, error } = await requestMicPermission();\n if (!granted) {\n setVoiceError(error || 'Microphone is not available.');\n return;\n }\n setShowAudioRecorder(true);\n })();\n }, [hasQuery]);\n\n /**\n * On a successful Whisper round-trip, paste the transcript into the input\n * field, close the recorder, and let the user review/send manually. Matches\n * web's `handleTranscriptionComplete`: we deliberately do NOT auto-fire\n * `sendMessage` because the user often wants to edit the dictation first.\n */\n const handleTranscriptionComplete = useCallback((text: string) => {\n const cleaned = (text ?? '').trim();\n setShowAudioRecorder(false);\n if (!cleaned) return;\n setValue((prev) => {\n const next = prev.trim().length > 0 ? `${prev.trim()} ${cleaned}` : cleaned;\n /*\n * Keep `inputRef`'s native text in sync with our controlled value\n * for the same reason `handleSend` does (the iOS native buffer\n * can lag the React state across a single gesture). `setNativeProps`\n * is the safe way to do this without re-rendering.\n */\n requestAnimationFrame(() => {\n inputRef.current?.setNativeProps?.({ text: next });\n inputRef.current?.focus?.();\n });\n return next;\n });\n }, []);\n\n const handleRecorderCancel = useCallback(() => {\n setShowAudioRecorder(false);\n }, []);\n\n const handleRecorderError = useCallback((error: string) => {\n setVoiceError(error);\n }, []);\n\n const waitingForAssistant = useMemo(() => {\n if ((!isLoading && !isStreaming) || messages.length === 0) return false;\n if ((response ?? '').trim()) return false;\n return messages[messages.length - 1]?.role === 'user';\n }, [isLoading, isStreaming, messages, response]);\n\n const composerScrollBottomPadding = 24 + (keyboardVisible ? keyboardHeight : 0);\n\n /*\n * NOTE: the previous read-only `isDeepSearchChannel` derivation has been\n * removed. Mode is now a freely-toggleable local state (`activeMode`)\n * driven by tapping the search/zap pills, mirroring HomeScreen. All\n * downstream branches use `isDeepSearchMode` declared with the rest of\n * the composer state above.\n */\n\n /**\n * Deep-search overlay state.\n *\n * Restored from the previous Home-screen flow (commit history): a deep-search\n * channel renders the structured `DeepSearchModal` (query / live summary /\n * sources / research process) on top of the regular Chat conversation. Closing\n * the modal reveals the same channel's MessagesContainerUI underneath so the\n * user can still see the raw turns.\n *\n * Trigger semantics — IMPORTANT:\n * • Opens ONLY when a request is actually fired in this session:\n * - Home → Chat auto-fire of `initialQuery`\n * - User sends a new message in a deep-search channel from the composer\n * - Explicit retry from inside the modal\n * • Does NOT open on plain entry from ChatHistoryScreen. That's a revisit\n * of an already-completed thread — no new API call, nothing live to\n * stream, so popping the modal would just be a confusing flash. The\n * user still sees the deep-search rendering in the chat conversation\n * underneath, and any new send re-opens the live view.\n *\n * Local UI state (accordions, open flag) lives here; data state (query /\n * summary / sources) is DERIVED from the chat stream, not stored separately,\n * so there's no drift between the modal and the underlying conversation.\n */\n const [isDeepSearchModalOpen, setIsDeepSearchModalOpen] = useState(false);\n const [researchProcessOpen, setResearchProcessOpen] = useState(true);\n const [sourcesAccordionOpen, setSourcesAccordionOpen] = useState(true);\n\n /**\n * Modal data is always scoped to the CURRENT run, not the whole channel.\n * In a multi-turn deep-search channel each send is its own \"run\": one user\n * query → one assistant summary. If we sourced from \"first user message\" /\n * \"any assistant message\", a follow-up send would keep showing the previous\n * run's query and stale sources during the transient window between the new\n * user message being appended and the first stream token arriving.\n *\n * Cursor: the LAST user message in the thread. The assistant content for\n * the current run is either:\n * • `response` while the stream is filling (token-by-token), OR\n * • the assistant message that comes AFTER the last user (run complete), OR\n * • empty — covers the brief \"user message appended, no response yet\"\n * window so the modal flips to \"Running...\" with no stale body.\n */\n const lastUserIndex = useMemo(() => {\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n if (messages[i]?.role === 'user') return i;\n }\n return -1;\n }, [messages]);\n\n const deepSearchQuery = useMemo(() => {\n if (lastUserIndex >= 0) {\n const txt = messages[lastUserIndex]?.content?.trim();\n if (txt) return txt;\n }\n return initialQuery ?? null;\n }, [messages, lastUserIndex, initialQuery]);\n\n const latestAssistantContent = useMemo(() => {\n if (response && response.trim()) return response;\n if (lastUserIndex < 0) return '';\n // Look for an assistant turn strictly AFTER the last user message.\n // Anything before it belongs to a prior run and must not leak into\n // the modal for the current one.\n for (let i = lastUserIndex + 1; i < messages.length; i += 1) {\n if (messages[i]?.role === 'assistant') {\n return messages[i]?.content ?? '';\n }\n }\n return '';\n }, [response, messages, lastUserIndex]);\n\n const deepSearchSummary = useMemo(() => normalizeSummaryText(latestAssistantContent), [latestAssistantContent]);\n const deepSearchSources: DeepSearchSourceItem[] = useMemo(\n () => extractDeepSearchSources(latestAssistantContent),\n [latestAssistantContent],\n );\n\n const handleDeepSearchClose = useCallback(() => {\n if (isStreaming) cancel();\n setIsDeepSearchModalOpen(false);\n }, [isStreaming, cancel]);\n\n const handleDeepSearchRetry = useCallback(() => {\n if (!deepSearchQuery || isStreaming || !channelId) return;\n void sendMessage(deepSearchQuery, undefined, channelId);\n }, [deepSearchQuery, isStreaming, channelId, sendMessage]);\n const leftItems = useMemo(\n () =>\n getDefaultLeftItems({\n search: { active: activeMode === 'chat', onClick: () => handleModeSwitch('chat') },\n zap: { active: activeMode === 'deep-search', onClick: () => handleModeSwitch('deep-search') },\n lightbulb: {\n active: activeMode === 'build',\n onClick: () => handleModeSwitch('build'),\n },\n }),\n [activeMode, handleModeSwitch],\n );\n const rightItems = useMemo(\n () =>\n getDefaultRightItems({\n tag: { enabled: false },\n chip: { enabled: false },\n // Attaching an image was disabled here even though the transport\n // (`sendMessage(content, attachments)`) and the gateway media lane\n // already carried it, and `expo-image-picker` was already a\n // dependency with its permission strings declared in app.json.\n camera: {\n enabled: true,\n loading: imageAttachments.busy,\n onClick: () => {\n void imageAttachments.captureFromCamera();\n },\n },\n image: {\n enabled: true,\n loading: imageAttachments.busy,\n onClick: () => {\n void imageAttachments.pickFromLibrary();\n },\n },\n attach: { enabled: false },\n }),\n [imageAttachments],\n );\n /**\n * Composer placeholder.\n *\n * Mirrors Home so the composer feels like the same affordance across the\n * \"first message\" and \"continuing thread\" surfaces — only the surrounding\n * UI changes, the input stays a stable anchor. We intentionally do NOT\n * surface a \"Loading conversation…\" state in the placeholder: the message\n * list already shows a dedicated hydrating loader, and switching the\n * placeholder for ~1 frame creates a visible flash on every entry.\n */\n const inputPlaceholder = isDeepSearchMode\n ? 'Research anything...'\n : isBuildMode\n ? 'Describe an app to build...'\n : 'Ask anything...';\n\n const inputConfig = useMemo(\n () => ({\n value,\n onChange: handleValueChange,\n placeholder: inputPlaceholder,\n disabled: !channelId,\n inputRef,\n returnKeyType: 'send',\n blurOnSubmit: false,\n onSubmitEditing: () => handleSend(),\n }),\n [value, handleValueChange, inputPlaceholder, channelId, handleSend],\n );\n const micSendButton = useMemo(\n () => ({\n hasContent: hasQuery,\n onSend: () => handleSend(),\n onMic: handleMicPress,\n disabled: !channelId,\n // Empty + streaming → Stop. Typed follow-up → Send (steer). Never lock the composer.\n isLoading: canSubmit ? false : isLoading,\n onStop: isStreaming && !canSubmit ? cancel : undefined,\n steerable: isLoading || isStreaming,\n }),\n [canSubmit, handleSend, handleMicPress, isLoading, channelId, isStreaming, cancel, hasQuery],\n );\n\n /**\n * Loader visibility:\n * - `isHydrating`: Apollo channel history is being fetched and we have nothing to show yet.\n * - `isWaitingForGateway`: Home navigated us here with an `initialQuery`, but CDeCLI is still\n * establishing the workspace session, so the auto-fire is deferred. Show a \"Connecting…\"\n * placeholder instead of an empty thread so the user doesn't think their send was dropped.\n */\n const isHydrating = messagesLoading && messages.length === 0 && !response;\n const isWaitingForGateway =\n !autoFiredRef.current &&\n !!channelId &&\n !!initialQuery &&\n cdecli.status !== 'connected' &&\n cdecli.status !== 'error';\n const showSendingLoader = waitingForAssistant;\n const pinSendingLoaderNearComposer = messages.length > 0 || Boolean((response ?? '').trim());\n\n return (\n <SafeAreaView edges={['left', 'right']} style={{ flex: 1, backgroundColor: surfaceColor }}>\n <Box flex={1} width=\"100%\" position=\"relative\">\n {(chatError || cdecli.error) && (\n <Box\n mb=\"$2\"\n mx=\"$4\"\n p=\"$3\"\n borderRadius=\"$md\"\n style={{\n backgroundColor: isDark ? '#2b1a1d' : '#fef2f2',\n borderWidth: 1,\n borderColor: isDark ? '#7f1d1d' : '#fecaca',\n }}\n >\n <Text fontSize=\"$sm\" style={{ color: isDark ? '#fecaca' : '#991b1b' }}>\n {chatError || cdecli.error}\n </Text>\n </Box>\n )}\n {!channelId ? (\n <Box flex={1} alignItems=\"center\" justifyContent=\"center\">\n <YantraBrandLoader size={YANTRA_LOADER_SIZE_COMPACT} />\n <Text style={[styles.statusText, { color: secondaryTextColor }]}>No channel selected</Text>\n </Box>\n ) : isHydrating ? (\n /**\n * Channel hydration (entering Chat from history or a deep\n * link) reuses the same `ThinkingIndicator` row as the\n * chat-history list — thin spinning arc + muted caption.\n * Keeps the loading vocabulary consistent across screens\n * and avoids the previous branded loader + \"Loading\n * conversation\" copy that read as a different state.\n */\n <Box flex={1} alignItems=\"center\" justifyContent=\"center\">\n <ThinkingIndicator color={secondaryTextColor} />\n </Box>\n ) : isWaitingForGateway ? (\n <Box flex={1} alignItems=\"center\" justifyContent=\"center\">\n <YantraBrandLoader size={YANTRA_LOADER_SIZE_COMPACT} />\n <Text style={[styles.statusText, { color: secondaryTextColor }]}>Connecting gateway…</Text>\n </Box>\n ) : (\n <Box flex={1} width=\"100%\" alignSelf=\"stretch\">\n <MessagesContainerUI\n mode=\"chat\"\n showBackButton={false}\n compactTop\n messagesContainerStyle={{\n paddingHorizontal: 0,\n paddingTop: 0,\n paddingBottom: composerScrollBottomPadding,\n margin: 0,\n marginTop: 0,\n alignSelf: 'center',\n width: contentMaxWidth,\n }}\n listContentStyle={{\n paddingTop: 0,\n paddingBottom: composerScrollBottomPadding,\n margin: 0,\n marginTop: 0,\n width: contentMaxWidth,\n alignSelf: 'center',\n justifyContent: 'flex-end',\n }}\n messages={transcriptRows}\n streamingContent={response}\n currentUser={CHAT_CURRENT_USER}\n onSend={handleSend}\n disabled={!channelId}\n isLoading={isLoading}\n onStop={isStreaming ? cancel : undefined}\n renderPlanInputToolbar={renderNoToolbar}\n renderBuildInputToolbar={renderNoToolbar}\n />\n </Box>\n )}\n {showSendingLoader && !pinSendingLoaderNearComposer ? (\n <View pointerEvents=\"none\" style={styles.sendingLoaderEmptyState}>\n <ThinkingIndicator color={secondaryTextColor} />\n </View>\n ) : null}\n <KeyboardComposerDock closedInset={insets.bottom} keyboardVisible={keyboardVisible}>\n {showSendingLoader && pinSendingLoaderNearComposer ? (\n <View pointerEvents=\"none\" style={styles.sendingLoaderInDock}>\n <ThinkingIndicator color={secondaryTextColor} />\n </View>\n ) : null}\n <View style={[styles.bottomComposerInner, { width: contentMaxWidth }]}>\n {voiceError ? (\n <View\n style={[\n styles.voiceErrorBanner,\n {\n backgroundColor: isDark ? '#2b1a1d' : '#fef2f2',\n borderColor: isDark ? '#7f1d1d' : '#fecaca',\n },\n ]}\n >\n <Text style={[styles.voiceErrorText, { color: isDark ? '#fecaca' : '#991b1b' }]}>\n {voiceError}\n </Text>\n </View>\n ) : null}\n {showAudioRecorder ? (\n /*\n * Render-time JS errors thrown by `useAudioRecorder`\n * (e.g. expo-audio native module missing, recorder\n * constructor throws in a release build) are caught\n * by the boundary and converted into a soft cancel\n * via the same handlers the panel itself uses on\n * runtime errors. Without this, a throw during the\n * panel's render phase kills the JS thread in\n * release / TestFlight.\n */\n <MicErrorBoundary onCancel={handleRecorderCancel} onError={handleRecorderError}>\n <AudioRecorderPanel\n isDark={isDark}\n onTranscriptionComplete={handleTranscriptionComplete}\n onCancel={handleRecorderCancel}\n onError={handleRecorderError}\n />\n </MicErrorBoundary>\n ) : (\n <InputToolBar\n inputConfig={inputConfig}\n leftItems={leftItems}\n rightItems={rightItems}\n templateButton={null}\n templateModalConfig={null}\n micSendButton={micSendButton}\n />\n )}\n </View>\n </KeyboardComposerDock>\n </Box>\n {/*\n * DeepSearchModal is rendered OUTSIDE the keyboard-dismiss wrapper so\n * taps inside the modal don't dismiss the keyboard, and it's a native\n * <Modal> internally so it correctly sits on top of the Chat surface\n * (composer included) on both iOS and Android.\n */}\n {isDeepSearchMode ? (\n <DeepSearchModal\n visible={isDeepSearchModalOpen}\n query={deepSearchQuery}\n summaryText={deepSearchSummary}\n sources={deepSearchSources}\n isStreaming={isStreaming}\n researchProcessOpen={researchProcessOpen}\n sourcesAccordionOpen={sourcesAccordionOpen}\n onToggleResearchProcess={() => setResearchProcessOpen((prev) => !prev)}\n onToggleSourcesAccordion={() => setSourcesAccordionOpen((prev) => !prev)}\n onRetry={handleDeepSearchRetry}\n onStop={cancel}\n onClose={handleDeepSearchClose}\n />\n ) : null}\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n statusText: {\n marginTop: 14,\n fontSize: 13,\n fontWeight: '500',\n },\n bottomComposerInner: {\n paddingHorizontal: 14,\n paddingTop: 10,\n paddingBottom: 4,\n },\n voiceErrorBanner: {\n marginBottom: 8,\n paddingHorizontal: 12,\n paddingVertical: 8,\n borderRadius: 10,\n borderWidth: 1,\n },\n voiceErrorText: {\n fontSize: 12,\n fontWeight: '500',\n },\n sendingLoaderEmptyState: {\n position: 'absolute',\n left: 0,\n right: 0,\n top: 0,\n bottom: 0,\n justifyContent: 'center',\n alignItems: 'center',\n zIndex: 40,\n },\n sendingLoaderInDock: {\n alignItems: 'center',\n justifyContent: 'flex-end',\n paddingBottom: 8,\n },\n});\n"],"names":["_a","_b"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminide-stack/yantra-mobile",
3
- "version": "12.0.43-alpha.4",
3
+ "version": "12.0.43-alpha.7",
4
4
  "description": "Sample core for higher packages to depend on",
5
5
  "license": "ISC",
6
6
  "author": "CDMBase LLC",
@@ -56,5 +56,5 @@
56
56
  "typescript": {
57
57
  "definition": "lib/index.d.ts"
58
58
  },
59
- "gitHead": "a3dd83b9101f370ec4cbc7b2d78da3c4e05cbb06"
59
+ "gitHead": "255d8ae3d8c1044a63affc6c66f49b2bb113e2fe"
60
60
  }