@adminide-stack/yantra-mobile 12.0.44-alpha.15 → 12.0.44-alpha.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/lib/bridge/handlers/NavigationBridgeHandler.js +3 -1
  2. package/lib/bridge/handlers/NavigationBridgeHandler.js.map +1 -1
  3. package/lib/components/CustomDrawer.js +122 -82
  4. package/lib/components/CustomDrawer.js.map +1 -1
  5. package/lib/components/NavigationHeader/NavigationHeader.js +16 -30
  6. package/lib/components/NavigationHeader/NavigationHeader.js.map +1 -1
  7. package/lib/compute.js +54 -5
  8. package/lib/compute.js.map +1 -1
  9. package/lib/features/apps/AppsCatalog.js +200 -0
  10. package/lib/features/apps/AppsCatalog.js.map +1 -0
  11. package/lib/features/apps/resolveSurfaceUrl.js +22 -2
  12. package/lib/features/apps/resolveSurfaceUrl.js.map +1 -1
  13. package/lib/features/attachments/ComposerAttachmentBar.js +64 -0
  14. package/lib/features/attachments/ComposerAttachmentBar.js.map +1 -0
  15. package/lib/features/attachments/MessageAttachmentPreviews.js +77 -0
  16. package/lib/features/attachments/MessageAttachmentPreviews.js.map +1 -0
  17. package/lib/features/attachments/attachmentPreviewUri.js +9 -0
  18. package/lib/features/attachments/attachmentPreviewUri.js.map +1 -0
  19. package/lib/features/attachments/buildGatewayMedia.js +118 -0
  20. package/lib/features/attachments/buildGatewayMedia.js.map +1 -0
  21. package/lib/features/attachments/composerAttachmentHandoff.js +15 -0
  22. package/lib/features/attachments/composerAttachmentHandoff.js.map +1 -0
  23. package/lib/features/attachments/displayUserMessageText.js +19 -0
  24. package/lib/features/attachments/displayUserMessageText.js.map +1 -0
  25. package/lib/features/attachments/historyAttachmentLabel.js +51 -0
  26. package/lib/features/attachments/historyAttachmentLabel.js.map +1 -0
  27. package/lib/features/attachments/isImageAttachment.js +7 -0
  28. package/lib/features/attachments/isImageAttachment.js.map +1 -0
  29. package/lib/features/attachments/preserveAttachmentPreviews.js +41 -0
  30. package/lib/features/attachments/preserveAttachmentPreviews.js.map +1 -0
  31. package/lib/features/attachments/uploadChatAttachments.js +102 -0
  32. package/lib/features/attachments/uploadChatAttachments.js.map +1 -0
  33. package/lib/features/attachments/useImageAttachments.js +102 -7
  34. package/lib/features/attachments/useImageAttachments.js.map +1 -1
  35. package/lib/features/canvas/nativeViewerRegistry.js +8 -1
  36. package/lib/features/canvas/nativeViewerRegistry.js.map +1 -1
  37. package/lib/features/canvas/surfaceIndex.js +25 -0
  38. package/lib/features/canvas/surfaceIndex.js.map +1 -0
  39. package/lib/features/canvas/useCanvasSession.js +57 -0
  40. package/lib/features/canvas/useCanvasSession.js.map +1 -0
  41. package/lib/features/chat/ChatTranscript.js +198 -0
  42. package/lib/features/chat/ChatTranscript.js.map +1 -0
  43. package/lib/hooks/useCdecliChannel.js +5 -3
  44. package/lib/hooks/useCdecliChannel.js.map +1 -1
  45. package/lib/hooks/useChatApi.js +32 -15
  46. package/lib/hooks/useChatApi.js.map +1 -1
  47. package/lib/hooks/useChatStream.js +35 -8
  48. package/lib/hooks/useChatStream.js.map +1 -1
  49. package/lib/index.js +1 -1
  50. package/lib/index.js.map +1 -1
  51. package/lib/routes.json +56 -4
  52. package/lib/screens/Apps/index.js +20 -0
  53. package/lib/screens/Apps/index.js.map +1 -0
  54. package/lib/screens/CanvasBoard/index.js +20 -15
  55. package/lib/screens/CanvasBoard/index.js.map +1 -1
  56. package/lib/screens/Chat/index.js +39 -62
  57. package/lib/screens/Chat/index.js.map +1 -1
  58. package/lib/screens/ChatHistory/index.js +2 -8
  59. package/lib/screens/ChatHistory/index.js.map +1 -1
  60. package/lib/screens/Home/HomeScreen.js +57 -21
  61. package/lib/screens/Home/HomeScreen.js.map +1 -1
  62. package/lib/screens/Home/components/ChatHistoryLanding.js +15 -9
  63. package/lib/screens/Home/components/ChatHistoryLanding.js.map +1 -1
  64. package/lib/screens/WebBuilder/index.js.map +1 -1
  65. package/lib/utils/navigateToNewChatHome.js +40 -0
  66. package/lib/utils/navigateToNewChatHome.js.map +1 -0
  67. package/package.json +2 -2
  68. package/lib/components/AppsMenu/AppsMenu.js +0 -295
  69. package/lib/components/AppsMenu/AppsMenu.js.map +0 -1
  70. package/lib/components/NavigationHeader/ChatHistoryToggleMobile.js +0 -6
  71. package/lib/components/NavigationHeader/ChatHistoryToggleMobile.js.map +0 -1
  72. package/lib/features/canvas/canvasCore.js +0 -41
  73. package/lib/features/canvas/canvasCore.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"useChatStream.js","sources":["../../src/hooks/useChatStream.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useChatMutations, useChatMessages } from './useChatApi';\nimport { isNoActiveSessionError, useCdecliChannel } from './useCdecliChannel';\nimport { usePrerequisiteIds } from './usePrerequisiteIds';\n\n/** Agent returned an error while the cdecli-serve channel stayed connected (e.g. bad LLM API key). */\nfunction isCdecliAgentFailureOutput(text: string): boolean {\n const t = text.trim();\n if (!t) return false;\n return (\n /⚠\\s*Error:/.test(t) ||\n /LLM stream error/i.test(t) ||\n /Incorrect API key/i.test(t) ||\n /invalid_api_key/i.test(t) ||\n /authentication_error/i.test(t)\n );\n}\n\nexport interface MessageAttachment {\n id: string;\n name: string;\n type: 'file' | 'screenshot';\n dataUrl?: string;\n mimeType?: string;\n size?: number;\n url?: string;\n}\n\nexport interface ChatMessage {\n role: 'user' | 'assistant';\n content: string;\n attachments?: MessageAttachment[];\n metadata?: {\n tokenUsage?: { inputTokens: number; outputTokens: number; totalTokens: number };\n model?: string;\n };\n}\n\n/** Mobile chat routes exclusively through CDeCLI (messenger-gateway). */\nexport interface UseChatStreamRouting {\n channelConnected: boolean;\n accountId: string;\n /** When `'backend'`, the gateway persists posts — skip client `saveMessages`. */\n persistenceMode?: 'backend' | 'frontend';\n}\n\nexport function useChatStream(\n sessionId: string | null,\n routing: UseChatStreamRouting = {\n channelConnected: false,\n accountId: 'default',\n persistenceMode: 'backend',\n },\n) {\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [response, setResponse] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const isSendingRef = useRef(false);\n /** Follow-ups typed before cdecli has an active session. Flushed after the first token. */\n const pendingSteersRef = useRef<string[]>([]);\n /** True once this turn has produced at least one stream chunk (steer is valid). */\n const sessionLiveRef = useRef(false);\n const flushPendingSteersRef = useRef<() => Promise<void>>(async () => {});\n const sendMessageRef = useRef<\n (\n content: string,\n attachments?: MessageAttachment[],\n sessionIdOverride?: string | null,\n alreadyVisible?: boolean,\n ) => Promise<void>\n >(async () => {});\n\n /** Ensures GraphQL stream subscriptions use the id from createChannel+send before the next parent render. */\n const [cdecliStreamOverrideId, setCdecliStreamOverrideId] = useState<string | undefined>(undefined);\n const userMsgForSaveRef = useRef<ChatMessage | null>(null);\n const saveSessionIdRef = useRef<string | null>(null);\n /** Blocks duplicate cdecli `onComplete` from appending assistant twice / saving twice per send. */\n const cdecliRoundHandledRef = useRef(false);\n const routingRef = useRef(routing);\n routingRef.current = routing;\n\n const { saveMessages } = useChatMutations();\n const { accountUserId } = usePrerequisiteIds();\n const {\n messages: backendMessages,\n loading: backendMessagesLoading,\n messagesLoaded: backendMessagesLoaded,\n } = useChatMessages(sessionId);\n const lastHydratedSessionIdRef = useRef<string | null>(null);\n\n const streamChannelId = sessionId || cdecliStreamOverrideId;\n\n const finalizeCdecliRound = useCallback((assistantContent?: string) => {\n saveSessionIdRef.current = null;\n userMsgForSaveRef.current = null;\n sessionLiveRef.current = false;\n setResponse('');\n setIsLoading(false);\n setIsStreaming(false);\n isSendingRef.current = false;\n if (assistantContent !== undefined) {\n setMessages((prev) => [...prev, { role: 'assistant' as const, content: assistantContent }]);\n }\n }, []);\n\n const cdecliCallbacks = useMemo(\n () => ({\n onChunk: (text: string) => {\n setResponse((r) => r + text);\n if (!sessionLiveRef.current) {\n sessionLiveRef.current = true;\n void flushPendingSteersRef.current();\n }\n },\n onComplete: (text: string) => {\n if (cdecliRoundHandledRef.current) {\n return;\n }\n\n if (isCdecliAgentFailureOutput(text)) {\n cdecliRoundHandledRef.current = true;\n pendingSteersRef.current = [];\n setError('CDeCLI agent error. Check gateway status and server-side LLM configuration.');\n finalizeCdecliRound(text);\n return;\n }\n\n cdecliRoundHandledRef.current = true;\n\n const sid = saveSessionIdRef.current;\n const um = userMsgForSaveRef.current;\n const leftover = pendingSteersRef.current;\n pendingSteersRef.current = [];\n saveSessionIdRef.current = null;\n userMsgForSaveRef.current = null;\n sessionLiveRef.current = false;\n\n setMessages((prev) => [...prev, { role: 'assistant' as const, content: text }]);\n setResponse('');\n setIsLoading(false);\n setIsStreaming(false);\n isSendingRef.current = false;\n\n const rt = routingRef.current;\n const persistClientSide = rt.persistenceMode !== 'backend';\n\n if (sid && um && persistClientSide) {\n saveMessages({\n sessionId: sid,\n ...(accountUserId ? { createdBy: accountUserId } : {}),\n userMessage: {\n content: um.content,\n attachments: um.attachments?.map((a) => ({\n id: a.id,\n name: a.name,\n type: a.type,\n mimeType: a.mimeType,\n size: a.size,\n url: a.url,\n })),\n },\n assistantMessage: {\n content: text,\n tokenCount: undefined,\n model: 'cdecli-serve',\n },\n }).catch((e) => {\n console.error('[useChatStream] saveMessages (cdecli):', e);\n });\n }\n\n if (leftover.length > 0) {\n const [first, ...rest] = leftover;\n pendingSteersRef.current = rest;\n queueMicrotask(() => {\n void sendMessageRef.current(first, undefined, sid, true);\n });\n }\n },\n onError: (err: string) => {\n if (cdecliRoundHandledRef.current) return;\n cdecliRoundHandledRef.current = true;\n pendingSteersRef.current = [];\n setError(err || 'CDeCLI stream error.');\n finalizeCdecliRound();\n },\n }),\n [saveMessages, accountUserId, finalizeCdecliRound],\n );\n\n const {\n sendMessage: sendCdecliMessage,\n steer: steerCdecliMessage,\n cancel: cancelCdecliTurn,\n } = useCdecliChannel(routing.channelConnected, routing.accountId, streamChannelId, cdecliCallbacks);\n\n const flushPendingSteers = useCallback(async () => {\n if (!sessionLiveRef.current || !isSendingRef.current) return;\n const sid = saveSessionIdRef.current;\n if (!sid) return;\n\n while (pendingSteersRef.current.length > 0 && sessionLiveRef.current && isSendingRef.current) {\n const next = pendingSteersRef.current[0];\n const result = await steerCdecliMessage(next, sid);\n if (result.ok) {\n pendingSteersRef.current.shift();\n continue;\n }\n if (isNoActiveSessionError(result.error)) {\n return;\n }\n pendingSteersRef.current.shift();\n setError(result.error || 'Could not send follow-up. Try again.');\n return;\n }\n }, [steerCdecliMessage]);\n\n flushPendingSteersRef.current = flushPendingSteers;\n\n useEffect(() => {\n if (sessionId && cdecliStreamOverrideId && sessionId === cdecliStreamOverrideId) {\n setCdecliStreamOverrideId(undefined);\n }\n }, [sessionId, cdecliStreamOverrideId]);\n\n useEffect(() => {\n if (isSendingRef.current) return;\n\n if (!sessionId) {\n setMessages([]);\n setResponse('');\n lastHydratedSessionIdRef.current = null;\n return;\n }\n\n const sessionChanged = lastHydratedSessionIdRef.current !== sessionId;\n if (sessionChanged) {\n setMessages([]);\n setResponse('');\n lastHydratedSessionIdRef.current = sessionId;\n }\n\n if (backendMessagesLoaded) {\n const formatted: ChatMessage[] = (backendMessages ?? []).map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: msg.content ?? '',\n metadata: msg.tokenCount\n ? {\n tokenUsage: {\n inputTokens: 0,\n outputTokens: msg.tokenCount,\n totalTokens: msg.tokenCount,\n },\n model: msg.model,\n }\n : undefined,\n }));\n setMessages(formatted);\n setResponse('');\n }\n }, [sessionId, backendMessages, backendMessagesLoaded]);\n\n const sendMessage = useCallback(\n async (\n content: string,\n attachments?: MessageAttachment[],\n sessionIdOverride?: string | null,\n alreadyVisible = false,\n ) => {\n if (!content.trim()) return;\n\n const effectiveSessionId = sessionIdOverride !== undefined ? sessionIdOverride : sessionId;\n const rt = routingRef.current;\n const trimmed = content.trim();\n\n const userMessage: ChatMessage = {\n role: 'user',\n content: trimmed,\n attachments,\n };\n\n /**\n * A turn is already in flight. Keep the follow-up visible and queue it.\n * cdecli rejects steer until the agent session exists (\"no active session\"),\n * which is after the first token. Flush then. Never error/LogBox for that race.\n */\n if (isSendingRef.current) {\n if (!rt.channelConnected || !effectiveSessionId) {\n setError(\n !rt.channelConnected\n ? 'CDeCLI is not connected yet. Check gateway status in the header.'\n : 'Missing chat session id.',\n );\n return;\n }\n setMessages((prev) => [...prev, userMessage]);\n setError(null);\n pendingSteersRef.current = [...pendingSteersRef.current, trimmed];\n void flushPendingSteers();\n return;\n }\n\n isSendingRef.current = true;\n sessionLiveRef.current = false;\n if (!alreadyVisible) {\n setMessages((prev) => [...prev, userMessage]);\n }\n setResponse('');\n setIsLoading(true);\n setIsStreaming(true);\n setError(null);\n userMsgForSaveRef.current = userMessage;\n saveSessionIdRef.current = effectiveSessionId ?? null;\n cdecliRoundHandledRef.current = false;\n\n if (!rt.channelConnected) {\n setError('CDeCLI is not connected yet. Check gateway status in the header.');\n if (!alreadyVisible) setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n return;\n }\n if (!effectiveSessionId) {\n setError('Missing chat session id.');\n if (!alreadyVisible) setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n return;\n }\n\n if (sessionIdOverride) {\n setCdecliStreamOverrideId(sessionIdOverride);\n await new Promise<void>((resolve) => {\n setTimeout(resolve, 0);\n });\n }\n\n const ok = await sendCdecliMessage(trimmed, effectiveSessionId);\n if (!ok && !cdecliRoundHandledRef.current) {\n cdecliRoundHandledRef.current = true;\n setError('Failed to send message via CDeCLI. Check gateway connection.');\n if (!alreadyVisible) setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n }\n },\n [sessionId, sendCdecliMessage, flushPendingSteers],\n );\n\n sendMessageRef.current = sendMessage;\n\n const cancel = useCallback(() => {\n pendingSteersRef.current = [];\n sessionLiveRef.current = false;\n const sid = saveSessionIdRef.current ?? sessionId;\n void cancelCdecliTurn(sid ?? 'messenger');\n if (!cdecliRoundHandledRef.current) {\n cdecliRoundHandledRef.current = true;\n finalizeCdecliRound();\n }\n }, [cancelCdecliTurn, finalizeCdecliRound, sessionId]);\n\n const clearMessages = useCallback(() => {\n setMessages([]);\n setResponse('');\n setError(null);\n }, []);\n\n const messagesLoading = !!sessionId && backendMessagesLoading && !backendMessagesLoaded;\n\n return {\n messages,\n response,\n error,\n isLoading,\n isStreaming,\n messagesLoading,\n hasMessages: messages.length > 0 || !!response,\n sendMessage,\n cancel,\n clearMessages,\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useChatStream.js","sources":["../../src/hooks/useChatStream.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n useCreateAccountChatFileDownloadLinksMutation,\n useCreateAccountChatFileUploadLinksMutation,\n} from 'common/graphql';\nimport { useChatMutations, useChatMessages } from './useChatApi';\nimport { isNoActiveSessionError, useCdecliChannel } from './useCdecliChannel';\nimport { usePrerequisiteIds } from './usePrerequisiteIds';\nimport { buildGatewayMediaPreferUrls } from '../features/attachments/buildGatewayMedia';\nimport { preserveAttachmentPreviews } from '../features/attachments/preserveAttachmentPreviews';\n\n/** Agent returned an error while the cdecli-serve channel stayed connected (e.g. bad LLM API key). */\nfunction isCdecliAgentFailureOutput(text: string): boolean {\n const t = text.trim();\n if (!t) return false;\n return (\n /⚠\\s*Error:/.test(t) ||\n /LLM stream error/i.test(t) ||\n /Incorrect API key/i.test(t) ||\n /invalid_api_key/i.test(t) ||\n /authentication_error/i.test(t)\n );\n}\n\nexport interface MessageAttachment {\n id: string;\n name: string;\n type: 'file' | 'screenshot';\n dataUrl?: string;\n mimeType?: string;\n size?: number;\n url?: string;\n}\n\nexport interface ChatMessage {\n role: 'user' | 'assistant';\n content: string;\n attachments?: MessageAttachment[];\n metadata?: {\n tokenUsage?: { inputTokens: number; outputTokens: number; totalTokens: number };\n model?: string;\n };\n}\n\n/** Mobile chat routes exclusively through CDeCLI (messenger-gateway). */\nexport interface UseChatStreamRouting {\n channelConnected: boolean;\n accountId: string;\n /** When `'backend'`, the gateway persists posts — skip client `saveMessages`. */\n persistenceMode?: 'backend' | 'frontend';\n}\n\nexport function useChatStream(\n sessionId: string | null,\n routing: UseChatStreamRouting = {\n channelConnected: false,\n accountId: 'default',\n persistenceMode: 'backend',\n },\n) {\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [response, setResponse] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const isSendingRef = useRef(false);\n /** Follow-ups typed before cdecli has an active session. Flushed after the first token. */\n const pendingSteersRef = useRef<string[]>([]);\n /** True once this turn has produced at least one stream chunk (steer is valid). */\n const sessionLiveRef = useRef(false);\n const flushPendingSteersRef = useRef<() => Promise<void>>(async () => {});\n const sendMessageRef = useRef<\n (\n content: string,\n attachments?: MessageAttachment[],\n sessionIdOverride?: string | null,\n alreadyVisible?: boolean,\n ) => Promise<void>\n >(async () => {});\n\n /** Ensures GraphQL stream subscriptions use the id from createChannel+send before the next parent render. */\n const [cdecliStreamOverrideId, setCdecliStreamOverrideId] = useState<string | undefined>(undefined);\n const userMsgForSaveRef = useRef<ChatMessage | null>(null);\n const saveSessionIdRef = useRef<string | null>(null);\n /** Blocks duplicate cdecli `onComplete` from appending assistant twice / saving twice per send. */\n const cdecliRoundHandledRef = useRef(false);\n const routingRef = useRef(routing);\n routingRef.current = routing;\n\n const { saveMessages } = useChatMutations();\n const { accountUserId } = usePrerequisiteIds();\n const [createAccountChatFileUploadLinksMutation] = useCreateAccountChatFileUploadLinksMutation();\n const [createAccountChatFileDownloadLinksMutation] = useCreateAccountChatFileDownloadLinksMutation();\n const {\n messages: backendMessages,\n loading: backendMessagesLoading,\n messagesLoaded: backendMessagesLoaded,\n } = useChatMessages(sessionId);\n const lastHydratedSessionIdRef = useRef<string | null>(null);\n\n const streamChannelId = sessionId || cdecliStreamOverrideId;\n\n const finalizeCdecliRound = useCallback((assistantContent?: string) => {\n saveSessionIdRef.current = null;\n userMsgForSaveRef.current = null;\n sessionLiveRef.current = false;\n setResponse('');\n setIsLoading(false);\n setIsStreaming(false);\n isSendingRef.current = false;\n if (assistantContent !== undefined) {\n setMessages((prev) => [...prev, { role: 'assistant' as const, content: assistantContent }]);\n }\n }, []);\n\n const cdecliCallbacks = useMemo(\n () => ({\n onChunk: (text: string) => {\n setResponse((r) => r + text);\n if (!sessionLiveRef.current) {\n sessionLiveRef.current = true;\n void flushPendingSteersRef.current();\n }\n },\n onComplete: (text: string) => {\n if (cdecliRoundHandledRef.current) {\n return;\n }\n\n if (isCdecliAgentFailureOutput(text)) {\n cdecliRoundHandledRef.current = true;\n pendingSteersRef.current = [];\n setError('CDeCLI agent error. Check gateway status and server-side LLM configuration.');\n finalizeCdecliRound(text);\n return;\n }\n\n cdecliRoundHandledRef.current = true;\n\n const sid = saveSessionIdRef.current;\n const um = userMsgForSaveRef.current;\n const leftover = pendingSteersRef.current;\n pendingSteersRef.current = [];\n saveSessionIdRef.current = null;\n userMsgForSaveRef.current = null;\n sessionLiveRef.current = false;\n\n setMessages((prev) => [...prev, { role: 'assistant' as const, content: text }]);\n setResponse('');\n setIsLoading(false);\n setIsStreaming(false);\n isSendingRef.current = false;\n\n const rt = routingRef.current;\n const persistClientSide = rt.persistenceMode !== 'backend';\n\n if (sid && um && persistClientSide) {\n saveMessages({\n sessionId: sid,\n ...(accountUserId ? { createdBy: accountUserId } : {}),\n userMessage: {\n content: um.content,\n attachments: um.attachments?.map((a) => ({\n id: a.id,\n name: a.name,\n type: a.type,\n mimeType: a.mimeType,\n size: a.size,\n url: a.url,\n })),\n },\n assistantMessage: {\n content: text,\n tokenCount: undefined,\n model: 'cdecli-serve',\n },\n }).catch((e) => {\n console.error('[useChatStream] saveMessages (cdecli):', e);\n });\n }\n\n if (leftover.length > 0) {\n const [first, ...rest] = leftover;\n pendingSteersRef.current = rest;\n queueMicrotask(() => {\n void sendMessageRef.current(first, undefined, sid, true);\n });\n }\n },\n onError: (err: string) => {\n if (cdecliRoundHandledRef.current) return;\n cdecliRoundHandledRef.current = true;\n pendingSteersRef.current = [];\n setError(err || 'CDeCLI stream error.');\n finalizeCdecliRound();\n },\n }),\n [saveMessages, accountUserId, finalizeCdecliRound],\n );\n\n const {\n sendMessage: sendCdecliMessage,\n steer: steerCdecliMessage,\n cancel: cancelCdecliTurn,\n } = useCdecliChannel(routing.channelConnected, routing.accountId, streamChannelId, cdecliCallbacks);\n\n const flushPendingSteers = useCallback(async () => {\n if (!sessionLiveRef.current || !isSendingRef.current) return;\n const sid = saveSessionIdRef.current;\n if (!sid) return;\n\n while (pendingSteersRef.current.length > 0 && sessionLiveRef.current && isSendingRef.current) {\n const next = pendingSteersRef.current[0];\n const result = await steerCdecliMessage(next, sid);\n if (result.ok) {\n pendingSteersRef.current.shift();\n continue;\n }\n if (isNoActiveSessionError(result.error)) {\n return;\n }\n pendingSteersRef.current.shift();\n setError(result.error || 'Could not send follow-up. Try again.');\n return;\n }\n }, [steerCdecliMessage]);\n\n flushPendingSteersRef.current = flushPendingSteers;\n\n useEffect(() => {\n if (sessionId && cdecliStreamOverrideId && sessionId === cdecliStreamOverrideId) {\n setCdecliStreamOverrideId(undefined);\n }\n }, [sessionId, cdecliStreamOverrideId]);\n\n useEffect(() => {\n if (isSendingRef.current) return;\n\n if (!sessionId) {\n setMessages([]);\n setResponse('');\n lastHydratedSessionIdRef.current = null;\n return;\n }\n\n const sessionChanged = lastHydratedSessionIdRef.current !== sessionId;\n if (sessionChanged) {\n setMessages([]);\n setResponse('');\n lastHydratedSessionIdRef.current = sessionId;\n }\n\n if (backendMessagesLoaded) {\n const formatted: ChatMessage[] = (backendMessages ?? []).map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: msg.content ?? '',\n attachments: msg.attachments?.map((a) => ({\n id: a.id,\n name: a.name,\n type: a.type === 'screenshot' ? 'screenshot' : 'file',\n mimeType: a.mimeType,\n size: a.size,\n url: a.url,\n })),\n metadata: msg.tokenCount\n ? {\n tokenUsage: {\n inputTokens: 0,\n outputTokens: msg.tokenCount,\n totalTokens: msg.tokenCount,\n },\n model: msg.model,\n }\n : undefined,\n }));\n setMessages((prev) => preserveAttachmentPreviews(prev, formatted));\n setResponse('');\n }\n }, [sessionId, backendMessages, backendMessagesLoaded]);\n\n const sendMessage = useCallback(\n async (\n content: string,\n attachments?: MessageAttachment[],\n sessionIdOverride?: string | null,\n alreadyVisible = false,\n ) => {\n if (!content.trim() && !attachments?.length) return;\n\n const effectiveSessionId = sessionIdOverride !== undefined ? sessionIdOverride : sessionId;\n const rt = routingRef.current;\n const trimmed = content.trim();\n const sendText =\n trimmed ||\n (attachments?.length\n ? `Attached: ${attachments\n .map((a) => a.name)\n .filter(Boolean)\n .join(', ')}`\n : '');\n\n const userMessage: ChatMessage = {\n role: 'user',\n content: sendText,\n attachments,\n };\n\n /**\n * A turn is already in flight. Keep the follow-up visible and queue it.\n * cdecli rejects steer until the agent session exists (\"no active session\"),\n * which is after the first token. Flush then. Never error/LogBox for that race.\n */\n if (isSendingRef.current) {\n if (!rt.channelConnected || !effectiveSessionId) {\n setError(\n !rt.channelConnected\n ? 'CDeCLI is not connected yet. Check gateway status in the header.'\n : 'Missing chat session id.',\n );\n return;\n }\n setMessages((prev) => [...prev, userMessage]);\n setError(null);\n pendingSteersRef.current = [...pendingSteersRef.current, sendText];\n void flushPendingSteers();\n return;\n }\n\n isSendingRef.current = true;\n sessionLiveRef.current = false;\n if (!alreadyVisible) {\n setMessages((prev) => [...prev, userMessage]);\n }\n setResponse('');\n setIsLoading(true);\n setIsStreaming(true);\n setError(null);\n userMsgForSaveRef.current = userMessage;\n saveSessionIdRef.current = effectiveSessionId ?? null;\n cdecliRoundHandledRef.current = false;\n\n if (!rt.channelConnected) {\n setError('CDeCLI is not connected yet. Check gateway status in the header.');\n if (!alreadyVisible) setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n return;\n }\n if (!effectiveSessionId) {\n setError('Missing chat session id.');\n if (!alreadyVisible) setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n return;\n }\n\n if (sessionIdOverride) {\n setCdecliStreamOverrideId(sessionIdOverride);\n await new Promise<void>((resolve) => {\n setTimeout(resolve, 0);\n });\n }\n\n const ok = await sendCdecliMessage(\n sendText,\n effectiveSessionId,\n await buildGatewayMediaPreferUrls(\n attachments,\n async (filenames) => {\n const result = await createAccountChatFileUploadLinksMutation({ variables: { filenames } });\n return result.data?.createAccountChatFileUploadLinks || [];\n },\n async (urls) => {\n const result = await createAccountChatFileDownloadLinksMutation({ variables: { urls } });\n return result.data?.createAccountChatFileDownloadLinks || [];\n },\n ),\n );\n if (!ok && !cdecliRoundHandledRef.current) {\n cdecliRoundHandledRef.current = true;\n setError('Failed to send message via CDeCLI. Check gateway connection.');\n if (!alreadyVisible) setMessages((p) => p.slice(0, -1));\n isSendingRef.current = false;\n setIsLoading(false);\n setIsStreaming(false);\n userMsgForSaveRef.current = null;\n saveSessionIdRef.current = null;\n }\n },\n [\n sessionId,\n sendCdecliMessage,\n flushPendingSteers,\n createAccountChatFileUploadLinksMutation,\n createAccountChatFileDownloadLinksMutation,\n ],\n );\n\n sendMessageRef.current = sendMessage;\n\n const cancel = useCallback(() => {\n pendingSteersRef.current = [];\n sessionLiveRef.current = false;\n const sid = saveSessionIdRef.current ?? sessionId;\n void cancelCdecliTurn(sid ?? 'messenger');\n if (!cdecliRoundHandledRef.current) {\n cdecliRoundHandledRef.current = true;\n finalizeCdecliRound();\n }\n }, [cancelCdecliTurn, finalizeCdecliRound, sessionId]);\n\n const clearMessages = useCallback(() => {\n setMessages([]);\n setResponse('');\n setError(null);\n }, []);\n\n const messagesLoading = !!sessionId && backendMessagesLoading && !backendMessagesLoaded;\n\n return {\n messages,\n response,\n error,\n isLoading,\n isStreaming,\n messagesLoading,\n hasMessages: messages.length > 0 || !!response,\n sendMessage,\n cancel,\n clearMessages,\n };\n}\n"],"names":[],"mappings":"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"}
package/lib/index.js CHANGED
@@ -1 +1 @@
1
- import {Feature}from'@common-stack/client-react';import YantraMobileModule from'./module.js';export{default as Home}from'./screens/Home/HomeScreen.js';export{default as NewChat}from'./screens/NewChat/index.js';export{default as ChatHistory}from'./screens/ChatHistory/index.js';export{default as WebBuilder}from'./screens/WebBuilder/index.js';export{GatewayContextProvider,useGatewayContext}from'./contexts/GatewayContext.js';export{CdecliConnectionProvider,useCdecliConnection}from'./contexts/CdecliConnectionContext.js';export{BUILTIN_MOBILE_GATEWAYS,MAX_CONCURRENT_TASKS,STORAGE_KEYS}from'./config/constants.js';export{config}from'./config/env-config.js';export{useCdecliAutoConnect}from'./hooks/useCdecliAutoConnect.js';export{useObtainSystemToken}from'./hooks/useObtainSystemToken.js';export{appendSurfaceAuthParams,buildCdecliTokenInjection,buildSurfaceGateRecoveryScript,mintSurfaceSystemToken,resolveSurfaceCatalogBackend}from'./hooks/mintSurfaceSystemToken.js';export{isInstanceNotFoundError,useGatewayConnection}from'./hooks/useGatewayConnection.js';export{usePrerequisiteIds}from'./hooks/usePrerequisiteIds.js';export{useWorkspaceProvisioner}from'./hooks/useWorkspaceProvisioner.js';export{useGatewayRegistry}from'./hooks/useGatewayRegistry.js';export{agentSessionManager}from'./services/agentSessionManager.js';export{ensureGatewayApiKeys,resetGatewayApiKeyBridge}from'./services/gatewayApiKeyBridge.js';export{GatewayClient}from'./services/gatewayClient.js';export{BRIDGE_PROTOCOL_VERSION,BRIDGE_READY_ACTION,DEFAULT_BRIDGE_TIMEOUT_MS,DEFAULT_CHUNK_SIZE,MessageType}from'./bridge/types.js';export{WebViewManager}from'./bridge/WebViewManager.js';export{NativeWebViewBridge}from'./bridge/NativeWebViewBridge.js';export{TypedBridge}from'./bridge/TypedBridge.js';export{CancellableRequest}from'./bridge/CancellableRequest.js';export{ChunkedMessageHandler}from'./bridge/ChunkedMessageHandler.js';export{BridgeDebugger}from'./bridge/BridgeDebugger.js';export{WEB_BRIDGE_BOOTSTRAP}from'./bridge/webBridgeBootstrap.js';export{AuthenticatedFetch}from'./bridge/AuthenticatedFetch.js';export{AuthBridgeHandler}from'./bridge/handlers/AuthBridgeHandler.js';export{NavigationBridgeHandler}from'./bridge/handlers/NavigationBridgeHandler.js';export{AnalyticsBridgeHandler}from'./bridge/handlers/AnalyticsBridgeHandler.js';export{getPackagerHost,resolveMobileWebUrl}from'./bridge/resolveMobileWebUrl.js';export{YANTRA_LOADER_SIZE_COMPACT,YANTRA_LOADER_SIZE_DEFAULT,YantraBrandLoader}from'./components/YantraBrandLoader.js';export{default as CustomDrawer}from'./components/CustomDrawer.js';export{getNativeCanvasViewer,registerNativeCanvasViewer}from'./features/canvas/nativeViewerRegistry.js';export{resolveSurfaceAuthGraphqlUrl}from'./hooks/resolveSurfaceAuthGraphqlUrl.js';var index = new Feature(YantraMobileModule);export{index as default};//# sourceMappingURL=index.js.map
1
+ import {Feature}from'@common-stack/client-react';import YantraMobileModule from'./module.js';export{default as Home}from'./screens/Home/HomeScreen.js';export{default as NewChat}from'./screens/NewChat/index.js';export{default as ChatHistory}from'./screens/ChatHistory/index.js';export{default as Apps}from'./screens/Apps/index.js';export{default as WebBuilder}from'./screens/WebBuilder/index.js';export{GatewayContextProvider,useGatewayContext}from'./contexts/GatewayContext.js';export{CdecliConnectionProvider,useCdecliConnection}from'./contexts/CdecliConnectionContext.js';export{BUILTIN_MOBILE_GATEWAYS,MAX_CONCURRENT_TASKS,STORAGE_KEYS}from'./config/constants.js';export{config}from'./config/env-config.js';export{useCdecliAutoConnect}from'./hooks/useCdecliAutoConnect.js';export{useObtainSystemToken}from'./hooks/useObtainSystemToken.js';export{appendSurfaceAuthParams,buildCdecliTokenInjection,buildSurfaceGateRecoveryScript,mintSurfaceSystemToken,resolveSurfaceCatalogBackend}from'./hooks/mintSurfaceSystemToken.js';export{isInstanceNotFoundError,useGatewayConnection}from'./hooks/useGatewayConnection.js';export{usePrerequisiteIds}from'./hooks/usePrerequisiteIds.js';export{useWorkspaceProvisioner}from'./hooks/useWorkspaceProvisioner.js';export{useGatewayRegistry}from'./hooks/useGatewayRegistry.js';export{agentSessionManager}from'./services/agentSessionManager.js';export{ensureGatewayApiKeys,resetGatewayApiKeyBridge}from'./services/gatewayApiKeyBridge.js';export{GatewayClient}from'./services/gatewayClient.js';export{BRIDGE_PROTOCOL_VERSION,BRIDGE_READY_ACTION,DEFAULT_BRIDGE_TIMEOUT_MS,DEFAULT_CHUNK_SIZE,MessageType}from'./bridge/types.js';export{WebViewManager}from'./bridge/WebViewManager.js';export{NativeWebViewBridge}from'./bridge/NativeWebViewBridge.js';export{TypedBridge}from'./bridge/TypedBridge.js';export{CancellableRequest}from'./bridge/CancellableRequest.js';export{ChunkedMessageHandler}from'./bridge/ChunkedMessageHandler.js';export{BridgeDebugger}from'./bridge/BridgeDebugger.js';export{WEB_BRIDGE_BOOTSTRAP}from'./bridge/webBridgeBootstrap.js';export{AuthenticatedFetch}from'./bridge/AuthenticatedFetch.js';export{AuthBridgeHandler}from'./bridge/handlers/AuthBridgeHandler.js';export{NavigationBridgeHandler}from'./bridge/handlers/NavigationBridgeHandler.js';export{AnalyticsBridgeHandler}from'./bridge/handlers/AnalyticsBridgeHandler.js';export{getPackagerHost,resolveMobileWebUrl}from'./bridge/resolveMobileWebUrl.js';export{YANTRA_LOADER_SIZE_COMPACT,YANTRA_LOADER_SIZE_DEFAULT,YantraBrandLoader}from'./components/YantraBrandLoader.js';export{default as CustomDrawer}from'./components/CustomDrawer.js';export{getNativeCanvasExperience,getNativeCanvasViewer,registerNativeCanvasExperience,registerNativeCanvasViewer}from'./features/canvas/nativeViewerRegistry.js';export{resolveSurfaceAuthGraphqlUrl}from'./hooks/resolveSurfaceAuthGraphqlUrl.js';var index = new Feature(YantraMobileModule);export{index as default};//# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { Feature } from '@common-stack/client-react';\nimport YantraMobileModule from './module';\n\nexport default new Feature(YantraMobileModule);\nexport * from './screens';\nexport { GatewayContextProvider, useGatewayContext } from './contexts/GatewayContext';\nexport { CdecliConnectionProvider, useCdecliConnection } from './contexts/CdecliConnectionContext';\nexport * from './config/constants';\nexport { config } from './config/env-config';\nexport { useCdecliAutoConnect } from './hooks/useCdecliAutoConnect';\nexport { useObtainSystemToken } from './hooks/useObtainSystemToken';\nexport {\n mintSurfaceSystemToken,\n appendSurfaceAuthParams,\n buildCdecliTokenInjection,\n buildSurfaceGateRecoveryScript,\n resolveSurfaceCatalogBackend,\n resolveSurfaceAuthGraphqlUrl,\n} from './hooks/mintSurfaceSystemToken';\nexport { useGatewayConnection, isInstanceNotFoundError } from './hooks/useGatewayConnection';\nexport { usePrerequisiteIds } from './hooks/usePrerequisiteIds';\nexport { useWorkspaceProvisioner } from './hooks/useWorkspaceProvisioner';\nexport { useGatewayRegistry } from './hooks/useGatewayRegistry';\nexport * from './services';\nexport * from './bridge';\nexport {\n YantraBrandLoader,\n YANTRA_LOADER_SIZE_DEFAULT,\n YANTRA_LOADER_SIZE_COMPACT,\n} from './components/YantraBrandLoader';\nexport { default as CustomDrawer } from './components/CustomDrawer';\n// The canvas viewer seam. Exported from the index on purpose: the app (the MF\n// host) registers the federated viewer here and the CanvasBoard screen reads\n// it. Reachability from this entry is what makes rollup emit the registry as a\n// real shared module - as an internal-only file, `registerNativeCanvasViewer`\n// is never called inside the package, so rollup tree-shakes it and constant-\n// folds the screen down to its fallback branch.\nexport { registerNativeCanvasViewer, getNativeCanvasViewer } from './features/canvas/nativeViewerRegistry';\n"],"names":[],"mappings":"ktFAEA,YAAe,IAAI,QAAQ,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { Feature } from '@common-stack/client-react';\nimport YantraMobileModule from './module';\n\nexport default new Feature(YantraMobileModule);\nexport * from './screens';\nexport { GatewayContextProvider, useGatewayContext } from './contexts/GatewayContext';\nexport { CdecliConnectionProvider, useCdecliConnection } from './contexts/CdecliConnectionContext';\nexport * from './config/constants';\nexport { config } from './config/env-config';\nexport { useCdecliAutoConnect } from './hooks/useCdecliAutoConnect';\nexport { useObtainSystemToken } from './hooks/useObtainSystemToken';\nexport {\n mintSurfaceSystemToken,\n appendSurfaceAuthParams,\n buildCdecliTokenInjection,\n buildSurfaceGateRecoveryScript,\n resolveSurfaceCatalogBackend,\n resolveSurfaceAuthGraphqlUrl,\n} from './hooks/mintSurfaceSystemToken';\nexport { useGatewayConnection, isInstanceNotFoundError } from './hooks/useGatewayConnection';\nexport { usePrerequisiteIds } from './hooks/usePrerequisiteIds';\nexport { useWorkspaceProvisioner } from './hooks/useWorkspaceProvisioner';\nexport { useGatewayRegistry } from './hooks/useGatewayRegistry';\nexport * from './services';\nexport * from './bridge';\nexport {\n YantraBrandLoader,\n YANTRA_LOADER_SIZE_DEFAULT,\n YANTRA_LOADER_SIZE_COMPACT,\n} from './components/YantraBrandLoader';\nexport { default as CustomDrawer } from './components/CustomDrawer';\n// The canvas viewer seam. Exported from the index on purpose: the app (the MF\n// host) registers the federated viewer here and the CanvasBoard screen reads\n// it. Reachability from this entry is what makes rollup emit the registry as a\n// real shared module - as an internal-only file, `registerNativeCanvasViewer`\n// is never called inside the package, so rollup tree-shakes it and constant-\n// folds the screen down to its fallback branch.\nexport {\n registerNativeCanvasViewer,\n getNativeCanvasViewer,\n registerNativeCanvasExperience,\n getNativeCanvasExperience,\n} from './features/canvas/nativeViewerRegistry';\n"],"names":[],"mappings":"g0FAEA,YAAe,IAAI,QAAQ,kBAAkB,CAAA"}
package/lib/routes.json CHANGED
@@ -22,8 +22,8 @@
22
22
  "showFilter": true,
23
23
  "isSearchBack": false,
24
24
  "showGateway": true,
25
- "showApps": true,
26
- "showHistory": true,
25
+ "showApps": false,
26
+ "showHistory": false,
27
27
  "showNewChat": true
28
28
  }
29
29
  },
@@ -72,8 +72,8 @@
72
72
  "isSearchBack": false,
73
73
  "showBack": true,
74
74
  "showGateway": true,
75
- "showApps": true,
76
- "showHistory": true,
75
+ "showApps": false,
76
+ "showHistory": false,
77
77
  "showNewChat": true
78
78
  }
79
79
  },
@@ -147,6 +147,58 @@
147
147
  "hasComponent": true
148
148
  }
149
149
  },
150
+ {
151
+ "/:orgName/apps": {
152
+ "key": "apps",
153
+ "path": "/:orgName/apps",
154
+ "name": "Apps",
155
+ "exact": true,
156
+ "priority": 3,
157
+ "hideInMenu": true,
158
+ "auth": true,
159
+ "menu_position": "side",
160
+ "importPaths": {
161
+ "navigationHeader": "@adminide-stack/yantra-mobile/lib/components/NavigationHeader/NavigationHeader.js"
162
+ },
163
+ "customHeader": {
164
+ "name": "NavigationHeader",
165
+ "component": "$.importPaths.navigationHeader",
166
+ "props": {
167
+ "showTitle": true,
168
+ "showToggle": false,
169
+ "showFilter": false,
170
+ "isSearchBack": false,
171
+ "showBack": true,
172
+ "showGateway": false,
173
+ "showApps": false,
174
+ "showHistory": false,
175
+ "showNewChat": false
176
+ }
177
+ },
178
+ "props": {
179
+ "initialParams": {
180
+ "orgName": null
181
+ },
182
+ "options": {
183
+ "title": "Apps",
184
+ "headerTintColor": "black",
185
+ "headerTitleStyle": {
186
+ "fontWeight": "bold"
187
+ },
188
+ "drawerItemStyle": {
189
+ "display": "none"
190
+ },
191
+ "headerTitleAlign": "left",
192
+ "gestureEnabled": false,
193
+ "swipeEnabled": false,
194
+ "animation": "fade",
195
+ "animationTypeForReplace": "pop"
196
+ }
197
+ },
198
+ "componentPath": "@adminide-stack/yantra-mobile/lib/screens/Apps/index.js",
199
+ "hasComponent": true
200
+ }
201
+ },
150
202
  {
151
203
  "/:orgName/c/canvas-native": {
152
204
  "key": "canvas-native",
@@ -0,0 +1,20 @@
1
+ import {jsx}from'react/jsx-runtime';import {useMemo}from'react';import {useColorScheme,StyleSheet}from'react-native';import {SafeAreaView}from'react-native-safe-area-context';import {useRoute}from'@react-navigation/native';import {AppsCatalog}from'../../features/apps/AppsCatalog.js';import {mobileTokens}from'../../theme/mobileTokens.js';function AppsScreen() {
2
+ var _a;
3
+ const route = useRoute();
4
+ const colorScheme = useColorScheme();
5
+ const isDark = colorScheme === "dark";
6
+ const orgName = useMemo(() => {
7
+ var _a2, _b;
8
+ const raw = (_b = (_a2 = route == null ? void 0 : route.params) == null ? void 0 : _a2.orgName) != null ? _b : "";
9
+ return typeof raw === "string" && raw.trim() ? raw.trim() : null;
10
+ }, [(_a = route == null ? void 0 : route.params) == null ? void 0 : _a.orgName]);
11
+ const surfaceColor = isDark ? "#0f172a" : mobileTokens.color.bg;
12
+ return /* @__PURE__ */ jsx(SafeAreaView, { edges: ["left", "right", "bottom"], style: [styles.container, {
13
+ backgroundColor: surfaceColor
14
+ }], children: /* @__PURE__ */ jsx(AppsCatalog, { orgName }) });
15
+ }
16
+ const styles = StyleSheet.create({
17
+ container: {
18
+ flex: 1
19
+ }
20
+ });export{AppsScreen as default};//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../src/screens/Apps/index.tsx"],"sourcesContent":["/**\n * Standalone Apps catalog screen.\n *\n * Header chrome (back, title) is owned by `NavigationHeader` via\n * `customHeader.props` in `compute.ts`.\n */\nimport React, { useMemo } from 'react';\nimport { StyleSheet, useColorScheme } from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\nimport { useRoute } from '@react-navigation/native';\nimport { AppsCatalog } from '../../features/apps/AppsCatalog';\nimport { mobileTokens } from '../../theme/mobileTokens';\n\nexport interface AppsRouteParams {\n orgName?: string | null;\n}\n\nexport default function AppsScreen() {\n const route = useRoute<any>();\n const colorScheme = useColorScheme();\n const isDark = colorScheme === 'dark';\n\n const orgName = useMemo(() => {\n const raw = (route?.params?.orgName as string | undefined) ?? '';\n return typeof raw === 'string' && raw.trim() ? raw.trim() : null;\n }, [route?.params?.orgName]);\n\n const surfaceColor = isDark ? '#0f172a' : mobileTokens.color.bg;\n\n return (\n <SafeAreaView edges={['left', 'right', 'bottom']} style={[styles.container, { backgroundColor: surfaceColor }]}>\n <AppsCatalog orgName={orgName} />\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n container: {\n flex: 1,\n },\n});\n"],"names":["_a"],"mappings":"mVAeA,SAAwB,UAAa,GAAA;AAfrC,EAAA,IAAA,EAAA;AAgBE,EAAA,MAAM,QAAQ,QAAc,EAAA;AAC5B,EAAA,MAAM,cAAc,cAAe,EAAA;AACnC,EAAA,MAAM,SAAS,WAAgB,KAAA,MAAA;AAC/B,EAAM,MAAA,OAAA,GAAU,QAAQ,MAAM;AAnBhC,IAAA,IAAAA,GAAA,EAAA,EAAA;AAoBI,IAAM,MAAA,GAAA,GAAA,CAAM,MAAAA,GAAA,GAAA,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAO,WAAP,IAAAA,GAAAA,MAAAA,GAAAA,GAAAA,CAAe,YAAf,IAAgD,GAAA,EAAA,GAAA,EAAA;AAC5D,IAAO,OAAA,OAAO,QAAQ,QAAY,IAAA,GAAA,CAAI,MAAS,GAAA,GAAA,CAAI,MAAS,GAAA,IAAA;AAAA,KAC3D,CAAC,CAAA,EAAA,GAAA,KAAA,IAAA,IAAA,GAAA,MAAA,GAAA,KAAA,CAAO,MAAP,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAe,OAAO,CAAC,CAAA;AAC3B,EAAA,MAAM,YAAe,GAAA,MAAA,GAAS,SAAY,GAAA,YAAA,CAAa,KAAM,CAAA,EAAA;AAC7D,EAAO,uBAAA,GAAA,CAAC,YAAa,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,EAAQ,OAAS,EAAA,QAAQ,CAAG,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,SAAW,EAAA;AAAA,IACjF,eAAiB,EAAA;AAAA,GAClB,CAAA,EACS,QAAC,kBAAA,GAAA,CAAA,WAAA,EAAA,EAAY,SAAkB,CACnC,EAAA,CAAA;AACR;AACA,MAAM,MAAA,GAAS,WAAW,MAAO,CAAA;AAAA,EAC/B,SAAW,EAAA;AAAA,IACT,IAAM,EAAA;AAAA;AAEV,CAAC,CAAA"}
@@ -1,25 +1,30 @@
1
- import {jsx,jsxs}from'react/jsx-runtime';import {useMemo}from'react';import {useColorScheme,StyleSheet,View,Text}from'react-native';import {SafeAreaView}from'react-native-safe-area-context';import {useRoute}from'@react-navigation/native';import {getNativeCanvasViewer}from'../../features/canvas/nativeViewerRegistry.js';import {parseBoardState}from'../../features/canvas/canvasCore.js';const EMPTY_BOARD = {
2
- version: 1,
3
- savedAt: 0,
4
- items: [],
5
- zoom: 1
6
- };
7
- function CanvasBoardScreen() {
1
+ import {jsx,jsxs}from'react/jsx-runtime';import {useColorScheme,StyleSheet,View,Text}from'react-native';import {SafeAreaView}from'react-native-safe-area-context';import {useRoute}from'@react-navigation/native';import {getNativeCanvasExperience}from'../../features/canvas/nativeViewerRegistry.js';import {useCanvasSession}from'../../features/canvas/useCanvasSession.js';function CanvasBoardScreen() {
8
2
  const route = useRoute();
9
3
  const isDark = useColorScheme() === "dark";
10
- const Viewer = getNativeCanvasViewer();
11
- const board = useMemo(() => {
12
- var _a, _b;
13
- const raw = (_a = route.params) == null ? void 0 : _a.board;
14
- return (_b = raw ? parseBoardState(raw) : null) != null ? _b : EMPTY_BOARD;
15
- }, [route.params]);
16
- if (!Viewer) {
4
+ const Experience = getNativeCanvasExperience();
5
+ const {
6
+ token,
7
+ indexUrl,
8
+ error,
9
+ ready
10
+ } = useCanvasSession();
11
+ const params = route.params;
12
+ const channelId = typeof (params == null ? void 0 : params.channelId) === "string" ? params.channelId : void 0;
13
+ if (!Experience) {
17
14
  return /* @__PURE__ */ jsx(SafeAreaView, { style: [styles.fill, isDark && styles.fillDark], children: /* @__PURE__ */ jsxs(View, { style: styles.center, children: [
18
15
  /* @__PURE__ */ jsx(Text, { style: [styles.title, isDark && styles.textLight], children: "Native canvas unavailable" }),
19
16
  /* @__PURE__ */ jsx(Text, { style: [styles.detail, isDark && styles.textMuted], children: "This build does not carry the federation host runtime." })
20
17
  ] }) });
21
18
  }
22
- return /* @__PURE__ */ jsx(SafeAreaView, { style: [styles.fill, isDark && styles.fillDark], edges: ["left", "right", "bottom"], children: /* @__PURE__ */ jsx(Viewer, { board }) });
19
+ return /* @__PURE__ */ jsx(SafeAreaView, { style: [styles.fill, isDark && styles.fillDark], edges: ["left", "right", "bottom"], children: /* @__PURE__ */ jsx(
20
+ Experience,
21
+ {
22
+ token,
23
+ indexUrl,
24
+ channelId,
25
+ sessionError: ready ? error : null
26
+ }
27
+ ) });
23
28
  }
24
29
  const styles = StyleSheet.create({
25
30
  fill: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/screens/CanvasBoard/index.tsx"],"sourcesContent":["/**\n * Native canvas board screen - the first UI reachable through Module\n * Federation on mobile.\n *\n * Opening this screen is what triggers the federated fetch: the injected\n * viewer component lazy-imports `canvas_native/Viewer`, which the MF runtime\n * resolves against the manifest on the canvas-surface origin and downloads at\n * that moment - the viewer's code is NOT in the app binary. An empty board is\n * the deliberate first scope: it renders the remote's own \"This board is\n * empty.\" UI, which is exactly the observable proof that the remote loaded.\n * Board fetch (surface-index read) is the next slice and slots in as a route\n * param without touching the delivery path.\n */\nimport React, { useMemo } from 'react';\nimport { StyleSheet, Text, View, useColorScheme } from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\nimport { useRoute } from '@react-navigation/native';\nimport { getNativeCanvasViewer } from '../../features/canvas/nativeViewerRegistry';\nimport { parseBoardState, type PersistedCanvasState } from '../../features/canvas/canvasCore';\n\nconst EMPTY_BOARD: PersistedCanvasState = { version: 1, savedAt: 0, items: [], zoom: 1 };\n\nexport interface CanvasBoardRouteParams {\n /** Serialized PersistedCanvasState (v1) to render. Absent -> empty board. */\n board?: unknown;\n}\n\nexport default function CanvasBoardScreen() {\n const route = useRoute();\n const isDark = useColorScheme() === 'dark';\n const Viewer = getNativeCanvasViewer();\n\n const board = useMemo(() => {\n const raw = (route.params as CanvasBoardRouteParams | undefined)?.board;\n return (raw ? parseBoardState(raw) : null) ?? EMPTY_BOARD;\n }, [route.params]);\n\n if (!Viewer) {\n // A build without the federation host (or before App registered the\n // loader). Say so instead of rendering a blank screen.\n return (\n <SafeAreaView style={[styles.fill, isDark && styles.fillDark]}>\n <View style={styles.center}>\n <Text style={[styles.title, isDark && styles.textLight]}>Native canvas unavailable</Text>\n <Text style={[styles.detail, isDark && styles.textMuted]}>\n This build does not carry the federation host runtime.\n </Text>\n </View>\n </SafeAreaView>\n );\n }\n\n return (\n <SafeAreaView style={[styles.fill, isDark && styles.fillDark]} edges={['left', 'right', 'bottom']}>\n <Viewer board={board} />\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n fill: { flex: 1, backgroundColor: '#f8fafc' },\n fillDark: { backgroundColor: '#0f172a' },\n center: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 24 },\n title: { fontSize: 15, fontWeight: '600', color: '#0f172a', marginBottom: 6 },\n detail: { fontSize: 13, color: '#64748b', textAlign: 'center' },\n textLight: { color: '#f8fafc' },\n textMuted: { color: '#94a3b8' },\n});\n"],"names":[],"mappings":"kYAmBA,MAAM,WAAoC,GAAA;AAAA,EACxC,OAAS,EAAA,CAAA;AAAA,EACT,OAAS,EAAA,CAAA;AAAA,EACT,OAAO,EAAC;AAAA,EACR,IAAM,EAAA;AACR,CAAA;AAKA,SAAwB,iBAAoB,GAAA;AAC1C,EAAA,MAAM,QAAQ,QAAS,EAAA;AACvB,EAAM,MAAA,MAAA,GAAS,gBAAqB,KAAA,MAAA;AACpC,EAAA,MAAM,SAAS,qBAAsB,EAAA;AACrC,EAAM,MAAA,KAAA,GAAQ,QAAQ,MAAM;AAjC9B,IAAA,IAAA,EAAA,EAAA,EAAA;AAkCI,IAAM,MAAA,GAAA,GAAA,CAAO,EAAM,GAAA,KAAA,CAAA,MAAA,KAAN,IAAqD,GAAA,MAAA,GAAA,EAAA,CAAA,KAAA;AAClE,IAAA,OAAA,CAAQ,EAAM,GAAA,GAAA,GAAA,eAAA,CAAgB,GAAG,CAAA,GAAI,SAA7B,IAAsC,GAAA,EAAA,GAAA,WAAA;AAAA,GAC7C,EAAA,CAAC,KAAM,CAAA,MAAM,CAAC,CAAA;AACjB,EAAA,IAAI,CAAC,MAAQ,EAAA;AAGX,IAAA,uBAAQ,GAAA,CAAA,YAAA,EAAA,EAAa,KAAO,EAAA,CAAC,OAAO,IAAM,EAAA,MAAA,IAAU,MAAO,CAAA,QAAQ,CACvD,EAAA,QAAA,kBAAA,IAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,OAAO,MAChB,EAAA,QAAA,EAAA;AAAA,sBAAC,GAAA,CAAA,IAAA,EAAA,EAAK,OAAO,CAAC,MAAA,CAAO,OAAO,MAAU,IAAA,MAAA,CAAO,SAAS,CAAA,EAAG,QAAyB,EAAA,2BAAA,EAAA,CAAA;AAAA,sBAClF,GAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,QAAQ,MAAU,IAAA,MAAA,CAAO,SAAS,CAAA,EAAG,QAE1D,EAAA,wDAAA,EAAA;AAAA,KAAA,EACJ,CACJ,EAAA,CAAA;AAAA;AAEV,EAAA,2BAAQ,YAAa,EAAA,EAAA,KAAA,EAAO,CAAC,MAAO,CAAA,IAAA,EAAM,UAAU,MAAO,CAAA,QAAQ,GAAG,KAAO,EAAA,CAAC,QAAQ,OAAS,EAAA,QAAQ,GAC7F,QAAC,kBAAA,GAAA,CAAA,MAAA,EAAA,EAAO,OAAc,CAC1B,EAAA,CAAA;AACR;AACA,MAAM,MAAA,GAAS,WAAW,MAAO,CAAA;AAAA,EAC/B,IAAM,EAAA;AAAA,IACJ,IAAM,EAAA,CAAA;AAAA,IACN,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,QAAU,EAAA;AAAA,IACR,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,CAAA;AAAA,IACN,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA,QAAA;AAAA,IAChB,OAAS,EAAA;AAAA,GACX;AAAA,EACA,KAAO,EAAA;AAAA,IACL,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA,KAAA;AAAA,IACZ,KAAO,EAAA,SAAA;AAAA,IACP,YAAc,EAAA;AAAA,GAChB;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,QAAU,EAAA,EAAA;AAAA,IACV,KAAO,EAAA,SAAA;AAAA,IACP,SAAW,EAAA;AAAA,GACb;AAAA,EACA,SAAW,EAAA;AAAA,IACT,KAAO,EAAA;AAAA,GACT;AAAA,EACA,SAAW,EAAA;AAAA,IACT,KAAO,EAAA;AAAA;AAEX,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/screens/CanvasBoard/index.tsx"],"sourcesContent":["/**\n * Native canvas board screen.\n *\n * The screen is deliberately thin. Opening it triggers the federated fetch of\n * the canvas remote, and the remote owns everything after that: reading the\n * user's boards from the SurfaceChannel index, choosing one, and rendering it.\n * That split is what lets a canvas change ship with `cdecli surfaces deploy\n * canvas` instead of an App Store release.\n *\n * The host contributes the two things the remote cannot know: a token the index\n * accepts, and the index endpoint for this environment.\n */\nimport React from 'react';\nimport { StyleSheet, Text, View, useColorScheme } from 'react-native';\nimport { SafeAreaView } from 'react-native-safe-area-context';\nimport { useRoute } from '@react-navigation/native';\nimport { getNativeCanvasExperience } from '../../features/canvas/nativeViewerRegistry';\nimport { useCanvasSession } from '../../features/canvas/useCanvasSession';\n\nexport interface CanvasBoardRouteParams {\n /** Open a specific board from the index; otherwise the newest one opens. */\n channelId?: string;\n}\n\nexport default function CanvasBoardScreen() {\n const route = useRoute();\n const isDark = useColorScheme() === 'dark';\n const Experience = getNativeCanvasExperience();\n const { token, indexUrl, error, ready } = useCanvasSession();\n\n const params = route.params as CanvasBoardRouteParams | undefined;\n const channelId = typeof params?.channelId === 'string' ? params.channelId : undefined;\n\n if (!Experience) {\n // A build without the federation host (or before App registered it).\n // Say so instead of rendering a blank screen.\n return (\n <SafeAreaView style={[styles.fill, isDark && styles.fillDark]}>\n <View style={styles.center}>\n <Text style={[styles.title, isDark && styles.textLight]}>Native canvas unavailable</Text>\n <Text style={[styles.detail, isDark && styles.textMuted]}>\n This build does not carry the federation host runtime.\n </Text>\n </View>\n </SafeAreaView>\n );\n }\n\n return (\n <SafeAreaView style={[styles.fill, isDark && styles.fillDark]} edges={['left', 'right', 'bottom']}>\n <Experience\n token={token}\n indexUrl={indexUrl}\n channelId={channelId}\n // Until the mint settles, `sessionError` stays null so the remote\n // shows its loading state rather than flashing a failure.\n sessionError={ready ? error : null}\n />\n </SafeAreaView>\n );\n}\n\nconst styles = StyleSheet.create({\n fill: { flex: 1, backgroundColor: '#f8fafc' },\n fillDark: { backgroundColor: '#0f172a' },\n center: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 24 },\n title: { fontSize: 15, fontWeight: '600', color: '#0f172a', marginBottom: 6 },\n detail: { fontSize: 13, color: '#64748b', textAlign: 'center' },\n textLight: { color: '#f8fafc' },\n textMuted: { color: '#94a3b8' },\n});\n"],"names":[],"mappings":"iXAsBA,SAAwB,iBAAoB,GAAA;AAC1C,EAAA,MAAM,QAAQ,QAAS,EAAA;AACvB,EAAM,MAAA,MAAA,GAAS,gBAAqB,KAAA,MAAA;AACpC,EAAA,MAAM,aAAa,yBAA0B,EAAA;AAC7C,EAAM,MAAA;AAAA,IACJ,KAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,MACE,gBAAiB,EAAA;AACrB,EAAA,MAAM,SAAS,KAAM,CAAA,MAAA;AACrB,EAAA,MAAM,YAAY,QAAO,MAAA,IAAA,IAAA,GAAA,MAAA,GAAA,MAAA,CAAQ,SAAc,CAAA,KAAA,QAAA,GAAW,OAAO,SAAY,GAAA,MAAA;AAC7E,EAAA,IAAI,CAAC,UAAY,EAAA;AAGf,IAAA,uBAAQ,GAAA,CAAA,YAAA,EAAA,EAAa,KAAO,EAAA,CAAC,OAAO,IAAM,EAAA,MAAA,IAAU,MAAO,CAAA,QAAQ,CACvD,EAAA,QAAA,kBAAA,IAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,OAAO,MAChB,EAAA,QAAA,EAAA;AAAA,sBAAC,GAAA,CAAA,IAAA,EAAA,EAAK,OAAO,CAAC,MAAA,CAAO,OAAO,MAAU,IAAA,MAAA,CAAO,SAAS,CAAA,EAAG,QAAyB,EAAA,2BAAA,EAAA,CAAA;AAAA,sBAClF,GAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,QAAQ,MAAU,IAAA,MAAA,CAAO,SAAS,CAAA,EAAG,QAE1D,EAAA,wDAAA,EAAA;AAAA,KAAA,EACJ,CACJ,EAAA,CAAA;AAAA;AAEV,EAAA,uBAAQ,GAAA,CAAA,YAAA,EAAA,EAAa,KAAO,EAAA,CAAC,OAAO,IAAM,EAAA,MAAA,IAAU,MAAO,CAAA,QAAQ,GAAG,KAAO,EAAA,CAAC,MAAQ,EAAA,OAAA,EAAS,QAAQ,CAC7F,EAAA,QAAA,kBAAA,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MAAW,KAAA;AAAA,MAAc,QAAA;AAAA,MAAoB,SAAA;AAAA,MAGtD,YAAA,EAAc,QAAQ,KAAQ,GAAA;AAAA;AAAA,GAC1B,EAAA,CAAA;AACR;AACA,MAAM,MAAA,GAAS,WAAW,MAAO,CAAA;AAAA,EAC/B,IAAM,EAAA;AAAA,IACJ,IAAM,EAAA,CAAA;AAAA,IACN,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,QAAU,EAAA;AAAA,IACR,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,CAAA;AAAA,IACN,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA,QAAA;AAAA,IAChB,OAAS,EAAA;AAAA,GACX;AAAA,EACA,KAAO,EAAA;AAAA,IACL,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA,KAAA;AAAA,IACZ,KAAO,EAAA,SAAA;AAAA,IACP,YAAc,EAAA;AAAA,GAChB;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,QAAU,EAAA,EAAA;AAAA,IACV,KAAO,EAAA,SAAA;AAAA,IACP,SAAW,EAAA;AAAA,GACb;AAAA,EACA,SAAW,EAAA;AAAA,IACT,KAAO,EAAA;AAAA,GACT;AAAA,EACA,SAAW,EAAA;AAAA,IACT,KAAO,EAAA;AAAA;AAEX,CAAC,CAAA"}
@@ -1,4 +1,4 @@
1
- import {jsx,jsxs}from'react/jsx-runtime';import {useMemo,useEffect,useCallback,useState,useRef}from'react';import {useColorScheme,useWindowDimensions,Keyboard,TouchableWithoutFeedback,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 {MessageActionBar}from'../../features/chat/MessageActionBar.js';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;
1
+ import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {useMemo,useEffect,useCallback,useState,useRef}from'react';import {useColorScheme,useWindowDimensions,Keyboard,TouchableWithoutFeedback,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 {MessageActionBar}from'../../features/chat/MessageActionBar.js';import {ChatTranscript}from'../../features/chat/ChatTranscript.js';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 {ComposerAttachmentBar}from'../../features/attachments/ComposerAttachmentBar.js';import {hasComposerAttachments,takeComposerAttachments}from'../../features/attachments/composerAttachmentHandoff.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;
@@ -17,10 +17,6 @@ var __spreadValues = (a, b) => {
17
17
  return a;
18
18
  };
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
- const CHAT_CURRENT_USER = {
21
- id: "user"
22
- };
23
- const renderNoToolbar = () => null;
24
20
  function ChatScreen() {
25
21
  var _a, _b;
26
22
  const navigation = useNavigation();
@@ -67,6 +63,7 @@ function ChatScreen() {
67
63
  id: `msg-${index}-${msg.role}`,
68
64
  role: msg.role,
69
65
  content: msg.content,
66
+ attachments: msg.attachments,
70
67
  metadata: msg.metadata
71
68
  })), [chat.messages]);
72
69
  const {
@@ -80,22 +77,19 @@ function ChatScreen() {
80
77
  cancel
81
78
  } = chat;
82
79
  const regenerateFrom = useCallback((messageId) => {
83
- var _a2;
80
+ var _a2, _b2;
84
81
  const match = /^msg-(\d+)-assistant$/.exec(messageId);
85
82
  if (!match || !channelId) return;
86
83
  for (let i = Number(match[1]) - 1; i >= 0; i -= 1) {
87
84
  const prior = chat.messages[i];
88
- if ((prior == null ? void 0 : prior.role) === "user" && ((_a2 = prior.content) == null ? void 0 : _a2.trim())) {
89
- void chat.sendMessage(prior.content, void 0, channelId);
85
+ if ((prior == null ? void 0 : prior.role) === "user" && (((_a2 = prior.content) == null ? void 0 : _a2.trim()) || ((_b2 = prior.attachments) == null ? void 0 : _b2.length))) {
86
+ void chat.sendMessage(prior.content, prior.attachments, channelId);
90
87
  return;
91
88
  }
92
89
  }
93
90
  }, [chat, channelId]);
94
91
  const chatBusy = isLoading || isStreaming;
95
92
  const renderMessageActions = useCallback((message) => message.role === "assistant" ? /* @__PURE__ */ jsx(MessageActionBar, { text: message.content, onRegenerate: chatBusy ? void 0 : () => regenerateFrom(message.id) }) : null, [chatBusy, regenerateFrom]);
96
- const messageActionsSlot = {
97
- renderMessageActions
98
- };
99
93
  const imageAttachments = useImageAttachments();
100
94
  const [value, setValue] = useState("");
101
95
  const valueRef = useRef(value);
@@ -103,7 +97,8 @@ function ChatScreen() {
103
97
  const inputRef = useRef(null);
104
98
  const trimmed = value.trim();
105
99
  const hasQuery = trimmed.length > 0;
106
- const canSubmit = hasQuery && Boolean(channelId);
100
+ const hasAttachments = imageAttachments.pending.length > 0;
101
+ const canSubmit = (hasQuery || hasAttachments) && Boolean(channelId);
107
102
  const [activeMode, setActiveMode] = useState(() => params.initialMode === "deep-search" ? "deep-search" : params.initialMode === "build" ? "build" : "chat");
108
103
  const handleModeSwitch = useCallback((mode) => {
109
104
  setActiveMode(mode);
@@ -115,13 +110,15 @@ function ChatScreen() {
115
110
  const autoFiredRef = useRef(false);
116
111
  useEffect(() => {
117
112
  if (autoFiredRef.current) return;
118
- if (!channelId || !initialQuery) return;
113
+ if (!channelId) return;
119
114
  if (cdecli.status !== "connected" && cdecli.status !== "error") return;
115
+ const stashed = hasComposerAttachments(channelId) ? takeComposerAttachments(channelId) : void 0;
116
+ if (!initialQuery && !(stashed == null ? void 0 : stashed.length)) return;
120
117
  autoFiredRef.current = true;
121
118
  if (isDeepSearchMode) {
122
119
  setIsDeepSearchModalOpen(true);
123
120
  }
124
- void sendMessage(initialQuery, initialAttachments, channelId);
121
+ void sendMessage(initialQuery != null ? initialQuery : "", stashed, channelId);
125
122
  try {
126
123
  navigation.setParams({
127
124
  initialQuery: null,
@@ -132,8 +129,9 @@ function ChatScreen() {
132
129
  }, [channelId, initialQuery, initialAttachments, sendMessage, navigation, cdecli.status, isDeepSearchMode]);
133
130
  const handleSend = useCallback((text) => {
134
131
  var _a2;
132
+ const pending = imageAttachments.forSend();
135
133
  const t = (text != null ? text : valueRef.current).trim();
136
- if (!t || !channelId) return;
134
+ if (!t && !(pending == null ? void 0 : pending.length) || !channelId) return;
137
135
  setValue("");
138
136
  (_a2 = inputRef.current) == null ? void 0 : _a2.clear();
139
137
  if (isBuildMode) {
@@ -151,7 +149,7 @@ function ChatScreen() {
151
149
  if (isDeepSearchMode) {
152
150
  setIsDeepSearchModalOpen(true);
153
151
  }
154
- void sendMessage(t, imageAttachments.forSend(), channelId);
152
+ void sendMessage(t, pending, channelId);
155
153
  imageAttachments.clear();
156
154
  }, [channelId, sendMessage, isDeepSearchMode, isBuildMode, navigation, params.orgName, imageAttachments]);
157
155
  const handleValueChange = useCallback((e) => {
@@ -269,20 +267,24 @@ function ChatScreen() {
269
267
  // dependency with its permission strings declared in app.json.
270
268
  camera: {
271
269
  enabled: true,
272
- loading: imageAttachments.busy,
270
+ loading: imageAttachments.busyKind === "camera",
273
271
  onClick: () => {
274
272
  void imageAttachments.captureFromCamera();
275
273
  }
276
274
  },
277
275
  image: {
278
276
  enabled: true,
279
- loading: imageAttachments.busy,
277
+ loading: imageAttachments.busyKind === "library",
280
278
  onClick: () => {
281
279
  void imageAttachments.pickFromLibrary();
282
280
  }
283
281
  },
284
282
  attach: {
285
- enabled: false
283
+ enabled: true,
284
+ loading: imageAttachments.busyKind === "documents",
285
+ onClick: () => {
286
+ void imageAttachments.pickDocuments();
287
+ }
286
288
  }
287
289
  }), [imageAttachments]);
288
290
  const inputPlaceholder = isDeepSearchMode ? "Research anything..." : isBuildMode ? "Describe an app to build..." : "Ask anything...";
@@ -297,7 +299,7 @@ function ChatScreen() {
297
299
  onSubmitEditing: () => handleSend()
298
300
  }), [value, handleValueChange, inputPlaceholder, channelId, handleSend]);
299
301
  const micSendButton = useMemo(() => ({
300
- hasContent: hasQuery,
302
+ hasContent: hasQuery || hasAttachments,
301
303
  onSend: () => handleSend(),
302
304
  onMic: handleMicPress,
303
305
  disabled: !channelId,
@@ -305,9 +307,9 @@ function ChatScreen() {
305
307
  isLoading: canSubmit ? false : isLoading,
306
308
  onStop: isStreaming && !canSubmit ? cancel : void 0,
307
309
  steerable: isLoading || isStreaming
308
- }), [canSubmit, handleSend, handleMicPress, isLoading, channelId, isStreaming, cancel, hasQuery]);
310
+ }), [canSubmit, handleSend, handleMicPress, isLoading, channelId, isStreaming, cancel, hasQuery, hasAttachments]);
309
311
  const isHydrating = messagesLoading && messages.length === 0 && !response;
310
- const isWaitingForGateway = !autoFiredRef.current && !!channelId && !!initialQuery && cdecli.status !== "connected" && cdecli.status !== "error";
312
+ const isWaitingForGateway = !autoFiredRef.current && !!channelId && (!!initialQuery || hasComposerAttachments(channelId)) && cdecli.status !== "connected" && cdecli.status !== "error";
311
313
  const showSendingLoader = waitingForAssistant;
312
314
  const pinSendingLoaderNearComposer = messages.length > 0 || Boolean((response != null ? response : "").trim());
313
315
  return /* @__PURE__ */ jsxs(SafeAreaView, { edges: ["left", "right"], style: {
@@ -342,55 +344,27 @@ function ChatScreen() {
342
344
  /* @__PURE__ */ jsx(Text, { style: [styles.statusText, {
343
345
  color: secondaryTextColor
344
346
  }], children: "Connecting gateway\u2026" })
345
- ] }) : /* @__PURE__ */ jsx(Box, { flex: 1, width: "100%", alignSelf: "stretch", children: /* @__PURE__ */ jsx(
346
- MessagesContainerUI,
347
- __spreadProps(__spreadValues({
348
- mode: "chat",
349
- showBackButton: false,
350
- compactTop: true,
351
- isKeyboardInternallyHandled: false
352
- }, messageActionsSlot), {
353
- messagesContainerStyle: {
354
- paddingHorizontal: 0,
355
- paddingTop: 0,
356
- paddingBottom: composerScrollBottomPadding,
357
- margin: 0,
358
- marginTop: 0,
359
- alignSelf: "center",
360
- width: contentMaxWidth
361
- },
362
- listContentStyle: {
363
- paddingTop: 0,
364
- paddingBottom: composerScrollBottomPadding,
365
- margin: 0,
366
- marginTop: 0,
367
- width: contentMaxWidth,
368
- alignSelf: "center",
369
- justifyContent: "flex-end"
370
- },
371
- messages: transcriptRows,
372
- streamingContent: response,
373
- currentUser: CHAT_CURRENT_USER,
374
- onSend: handleSend,
375
- disabled: !channelId,
376
- isLoading,
377
- onStop: isStreaming ? cancel : void 0,
378
- renderPlanInputToolbar: renderNoToolbar,
379
- renderBuildInputToolbar: renderNoToolbar
380
- })
381
- ) }),
347
+ ] }) : /* @__PURE__ */ jsx(Box, { flex: 1, width: "100%", alignSelf: "stretch", children: /* @__PURE__ */ jsx(ChatTranscript, { messages: transcriptRows, streamingContent: response, renderMessageActions, isDark, listContentStyle: {
348
+ paddingTop: 0,
349
+ paddingBottom: composerScrollBottomPadding,
350
+ margin: 0,
351
+ marginTop: 0,
352
+ width: contentMaxWidth,
353
+ alignSelf: "center",
354
+ justifyContent: "flex-end"
355
+ } }) }),
382
356
  showSendingLoader && !pinSendingLoaderNearComposer ? /* @__PURE__ */ jsx(View, { pointerEvents: "none", style: styles.sendingLoaderEmptyState, children: /* @__PURE__ */ jsx(ThinkingIndicator, { color: secondaryTextColor }) }) : null,
383
357
  /* @__PURE__ */ jsxs(KeyboardComposerDock, { closedInset: insets.bottom, keyboardVisible, children: [
384
358
  showSendingLoader && pinSendingLoaderNearComposer ? /* @__PURE__ */ jsx(View, { pointerEvents: "none", style: styles.sendingLoaderInDock, children: /* @__PURE__ */ jsx(ThinkingIndicator, { color: secondaryTextColor }) }) : null,
385
359
  /* @__PURE__ */ jsxs(View, { style: [styles.bottomComposerInner, {
386
360
  width: contentMaxWidth
387
361
  }], children: [
388
- voiceError ? /* @__PURE__ */ jsx(View, { style: [styles.voiceErrorBanner, {
362
+ voiceError || imageAttachments.error ? /* @__PURE__ */ jsx(View, { style: [styles.voiceErrorBanner, {
389
363
  backgroundColor: isDark ? "#2b1a1d" : "#fef2f2",
390
364
  borderColor: isDark ? "#7f1d1d" : "#fecaca"
391
365
  }], children: /* @__PURE__ */ jsx(Text, { style: [styles.voiceErrorText, {
392
366
  color: isDark ? "#fecaca" : "#991b1b"
393
- }], children: voiceError }) }) : null,
367
+ }], children: voiceError || imageAttachments.error }) }) : null,
394
368
  showAudioRecorder ? (
395
369
  /*
396
370
  * Render-time JS errors thrown by `useAudioRecorder`
@@ -403,7 +377,10 @@ function ChatScreen() {
403
377
  * release / TestFlight.
404
378
  */
405
379
  /* @__PURE__ */ jsx(MicErrorBoundary, { onCancel: handleRecorderCancel, onError: handleRecorderError, children: /* @__PURE__ */ jsx(AudioRecorderPanel, { isDark, onTranscriptionComplete: handleTranscriptionComplete, onCancel: handleRecorderCancel, onError: handleRecorderError }) })
406
- ) : /* @__PURE__ */ jsx(InputToolBar, { inputConfig, leftItems, rightItems, templateButton: null, templateModalConfig: null, micSendButton })
380
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
381
+ /* @__PURE__ */ jsx(ComposerAttachmentBar, { attachments: imageAttachments.pending, onRemove: imageAttachments.remove, isDark }),
382
+ /* @__PURE__ */ jsx(InputToolBar, { inputConfig, leftItems, rightItems, templateButton: null, templateModalConfig: null, micSendButton })
383
+ ] })
407
384
  ] })
408
385
  ] })
409
386
  ] }) }),