@adminide-stack/yantra-mobile 12.0.69-alpha.9 → 12.0.70-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (522) hide show
  1. package/lib/components/GatewayConnector/GatewayConnector.js +2 -2
  2. package/lib/components/GatewayConnector/GatewayConnector.js.map +1 -1
  3. package/lib/components/KeyboardComposerDock.js +8 -1
  4. package/lib/components/KeyboardComposerDock.js.map +1 -1
  5. package/lib/components/NavigationHeader/NavigationHeader.js +2 -2
  6. package/lib/components/NavigationHeader/NavigationHeader.js.map +1 -1
  7. package/lib/config/env-config.js +4 -0
  8. package/lib/config/env-config.js.map +1 -1
  9. package/lib/contexts/ChatLiveStreamContext.js +4 -1
  10. package/lib/contexts/ChatLiveStreamContext.js.map +1 -1
  11. package/lib/features/agent-chat/NativeAgentChat.js +2 -0
  12. package/lib/features/agent-chat/NativeAgentChat.js.map +1 -1
  13. package/lib/features/apps/AppsCatalog.js +2 -2
  14. package/lib/features/apps/AppsCatalog.js.map +1 -1
  15. package/lib/features/audio-input/MicErrorBoundary.js +2 -2
  16. package/lib/features/audio-input/MicErrorBoundary.js.map +1 -1
  17. package/lib/features/canvas/AudioEditorExperience.js +308 -0
  18. package/lib/features/canvas/AudioEditorExperience.js.map +1 -0
  19. package/lib/features/canvas/CanvasAgentChatPane.js +310 -0
  20. package/lib/features/canvas/CanvasAgentChatPane.js.map +1 -0
  21. package/lib/features/canvas/CanvasBoardsGrid.js +414 -0
  22. package/lib/features/canvas/CanvasBoardsGrid.js.map +1 -0
  23. package/lib/features/canvas/CanvasChatResultCard.js +113 -0
  24. package/lib/features/canvas/CanvasChatResultCard.js.map +1 -0
  25. package/lib/features/canvas/CanvasEditToolsPanel.js +179 -0
  26. package/lib/features/canvas/CanvasEditToolsPanel.js.map +1 -0
  27. package/lib/features/canvas/CanvasExperience.js +859 -0
  28. package/lib/features/canvas/CanvasExperience.js.map +1 -0
  29. package/lib/features/canvas/CanvasGeneratePanel.js +514 -0
  30. package/lib/features/canvas/CanvasGeneratePanel.js.map +1 -0
  31. package/lib/features/canvas/CanvasLibrarySheet.js +355 -0
  32. package/lib/features/canvas/CanvasLibrarySheet.js.map +1 -0
  33. package/lib/features/canvas/CanvasLooksPanel.js +184 -0
  34. package/lib/features/canvas/CanvasLooksPanel.js.map +1 -0
  35. package/lib/features/canvas/CanvasTasksPanel.js +138 -0
  36. package/lib/features/canvas/CanvasTasksPanel.js.map +1 -0
  37. package/lib/features/canvas/CanvasTemplatesPanel.js +226 -0
  38. package/lib/features/canvas/CanvasTemplatesPanel.js.map +1 -0
  39. package/lib/features/canvas/CanvasToolDock.js +423 -0
  40. package/lib/features/canvas/CanvasToolDock.js.map +1 -0
  41. package/lib/features/canvas/FrameExtractorExperience.js +242 -0
  42. package/lib/features/canvas/FrameExtractorExperience.js.map +1 -0
  43. package/lib/features/canvas/ImageEditorExperience.js +491 -0
  44. package/lib/features/canvas/ImageEditorExperience.js.map +1 -0
  45. package/lib/features/canvas/InfluencerStudioExperience.js +288 -0
  46. package/lib/features/canvas/InfluencerStudioExperience.js.map +1 -0
  47. package/lib/features/canvas/MoodboardExperience.js +205 -0
  48. package/lib/features/canvas/MoodboardExperience.js.map +1 -0
  49. package/lib/features/canvas/NativeCanvasViewer.js +929 -0
  50. package/lib/features/canvas/NativeCanvasViewer.js.map +1 -0
  51. package/lib/features/canvas/PromoContextFields.js +150 -0
  52. package/lib/features/canvas/PromoContextFields.js.map +1 -0
  53. package/lib/features/canvas/SetStudioExperience.js +323 -0
  54. package/lib/features/canvas/SetStudioExperience.js.map +1 -0
  55. package/lib/features/canvas/VideoClipsExperience.js +175 -0
  56. package/lib/features/canvas/VideoClipsExperience.js.map +1 -0
  57. package/lib/features/canvas/VideoEditExperience.js +824 -0
  58. package/lib/features/canvas/VideoEditExperience.js.map +1 -0
  59. package/lib/features/canvas/VideoEditorExperience.js +3050 -0
  60. package/lib/features/canvas/VideoEditorExperience.js.map +1 -0
  61. package/lib/features/canvas/VideoGeneratorExperience.js +415 -0
  62. package/lib/features/canvas/VideoGeneratorExperience.js.map +1 -0
  63. package/lib/features/canvas/aiEdit.js +53 -0
  64. package/lib/features/canvas/aiEdit.js.map +1 -0
  65. package/lib/features/canvas/canvasAgentChat.js +76 -0
  66. package/lib/features/canvas/canvasAgentChat.js.map +1 -0
  67. package/lib/features/canvas/canvasBoardsCatalog.js +59 -0
  68. package/lib/features/canvas/canvasBoardsCatalog.js.map +1 -0
  69. package/lib/features/canvas/canvasBoardsSnapshot.js +14 -1
  70. package/lib/features/canvas/canvasBoardsSnapshot.js.map +1 -1
  71. package/lib/features/canvas/canvasChatDisplay.js +38 -0
  72. package/lib/features/canvas/canvasChatDisplay.js.map +1 -0
  73. package/lib/features/canvas/canvasChatTemplates.js +219 -0
  74. package/lib/features/canvas/canvasChatTemplates.js.map +1 -0
  75. package/lib/features/canvas/canvasCore.js +138 -1
  76. package/lib/features/canvas/canvasCore.js.map +1 -1
  77. package/lib/features/canvas/canvasEditOps.js +224 -0
  78. package/lib/features/canvas/canvasEditOps.js.map +1 -0
  79. package/lib/features/canvas/canvasTasks.js +187 -0
  80. package/lib/features/canvas/canvasTasks.js.map +1 -0
  81. package/lib/features/canvas/designPromptTemplates.js +3084 -0
  82. package/lib/features/canvas/designPromptTemplates.js.map +1 -0
  83. package/lib/features/canvas/editTools.js +54 -0
  84. package/lib/features/canvas/editTools.js.map +1 -0
  85. package/lib/features/canvas/extendVideo.js +5 -0
  86. package/lib/features/canvas/extendVideo.js.map +1 -0
  87. package/lib/features/canvas/frameExtract.js +33 -0
  88. package/lib/features/canvas/frameExtract.js.map +1 -0
  89. package/lib/features/canvas/generationModels.js +201 -0
  90. package/lib/features/canvas/generationModels.js.map +1 -0
  91. package/lib/features/canvas/influencer/influencerPipeline.js +170 -0
  92. package/lib/features/canvas/influencer/influencerPipeline.js.map +1 -0
  93. package/lib/features/canvas/influencer/productReel.js +72 -0
  94. package/lib/features/canvas/influencer/productReel.js.map +1 -0
  95. package/lib/features/canvas/influencer/reelPlan.js +159 -0
  96. package/lib/features/canvas/influencer/reelPlan.js.map +1 -0
  97. package/lib/features/canvas/moodboardCore.js +13 -0
  98. package/lib/features/canvas/moodboardCore.js.map +1 -0
  99. package/lib/features/canvas/promoProjectImport.js +99 -0
  100. package/lib/features/canvas/promoProjectImport.js.map +1 -0
  101. package/lib/features/canvas/promoVideo.js +312 -0
  102. package/lib/features/canvas/promoVideo.js.map +1 -0
  103. package/lib/features/canvas/recorder/CameraRecorderExperience.js +109 -0
  104. package/lib/features/canvas/recorder/CameraRecorderExperience.js.map +1 -0
  105. package/lib/features/canvas/sessionIdentity.js +28 -1
  106. package/lib/features/canvas/sessionIdentity.js.map +1 -1
  107. package/lib/features/canvas/set/SetViewportWebView.js +133 -0
  108. package/lib/features/canvas/set/SetViewportWebView.js.map +1 -0
  109. package/lib/features/canvas/set/cameraPath.js +194 -0
  110. package/lib/features/canvas/set/cameraPath.js.map +1 -0
  111. package/lib/features/canvas/set/setProject.js +24 -0
  112. package/lib/features/canvas/set/setProject.js.map +1 -0
  113. package/lib/features/canvas/storageLibrary.js +184 -0
  114. package/lib/features/canvas/storageLibrary.js.map +1 -0
  115. package/lib/features/canvas/studioCatalog.js +129 -0
  116. package/lib/features/canvas/studioCatalog.js.map +1 -0
  117. package/lib/features/canvas/studioLooks.js +189 -0
  118. package/lib/features/canvas/studioLooks.js.map +1 -0
  119. package/lib/features/canvas/surfaceIndex.js +63 -1
  120. package/lib/features/canvas/surfaceIndex.js.map +1 -1
  121. package/lib/features/canvas/templateImport/invideoNative.js +221 -0
  122. package/lib/features/canvas/templateImport/invideoNative.js.map +1 -0
  123. package/lib/features/canvas/templateImport/loadTemplate.js +43 -0
  124. package/lib/features/canvas/templateImport/loadTemplate.js.map +1 -0
  125. package/lib/features/canvas/templateImport/renderConfig.js +93 -0
  126. package/lib/features/canvas/templateImport/renderConfig.js.map +1 -0
  127. package/lib/features/canvas/useStudioCatalogTemplates.js +134 -0
  128. package/lib/features/canvas/useStudioCatalogTemplates.js.map +1 -0
  129. package/lib/features/canvas/video3d.js +109 -0
  130. package/lib/features/canvas/video3d.js.map +1 -0
  131. package/lib/features/canvas/videoClips.js +42 -0
  132. package/lib/features/canvas/videoClips.js.map +1 -0
  133. package/lib/features/canvas/videoEditor/agent/AgentCutPane.js +120 -0
  134. package/lib/features/canvas/videoEditor/agent/AgentCutPane.js.map +1 -0
  135. package/lib/features/canvas/videoEditor/agent/agentLoop.js +69 -0
  136. package/lib/features/canvas/videoEditor/agent/agentLoop.js.map +1 -0
  137. package/lib/features/canvas/videoEditor/agent/brainClient.js +45 -0
  138. package/lib/features/canvas/videoEditor/agent/brainClient.js.map +1 -0
  139. package/lib/features/canvas/videoEditor/agent/cutTools.js +129 -0
  140. package/lib/features/canvas/videoEditor/agent/cutTools.js.map +1 -0
  141. package/lib/features/canvas/videoEditor/editorModel.js +346 -0
  142. package/lib/features/canvas/videoEditor/editorModel.js.map +1 -0
  143. package/lib/features/canvas/videoEditor/exportRenderer.js +214 -0
  144. package/lib/features/canvas/videoEditor/exportRenderer.js.map +1 -0
  145. package/lib/features/canvas/videoEditor/filters.js +41 -0
  146. package/lib/features/canvas/videoEditor/filters.js.map +1 -0
  147. package/lib/features/canvas/videoEditor/mediaActions.js +57 -0
  148. package/lib/features/canvas/videoEditor/mediaActions.js.map +1 -0
  149. package/lib/features/canvas/videoEditor/remoteMediaClient.js +129 -0
  150. package/lib/features/canvas/videoEditor/remoteMediaClient.js.map +1 -0
  151. package/lib/features/canvas/videoEditor/solidColorPng.js +115 -0
  152. package/lib/features/canvas/videoEditor/solidColorPng.js.map +1 -0
  153. package/lib/features/canvas/videoEditor/videoEditOps.js +191 -0
  154. package/lib/features/canvas/videoEditor/videoEditOps.js.map +1 -0
  155. package/lib/features/canvas/videoEditor/videoProjectsStore.js +82 -0
  156. package/lib/features/canvas/videoEditor/videoProjectsStore.js.map +1 -0
  157. package/lib/features/canvas/videoRenderer.js +8 -0
  158. package/lib/features/canvas/videoRenderer.js.map +1 -0
  159. package/lib/features/canvas/withRemoteSafeArea.js +2 -2
  160. package/lib/features/canvas/withRemoteSafeArea.js.map +1 -1
  161. package/lib/features/characters/characterStudioProps.js +14 -0
  162. package/lib/features/characters/characterStudioProps.js.map +1 -0
  163. package/lib/features/chat/ChatCodeBlock.js +7 -3
  164. package/lib/features/chat/ChatCodeBlock.js.map +1 -1
  165. package/lib/features/chat/ChatTranscript.js +7 -3
  166. package/lib/features/chat/ChatTranscript.js.map +1 -1
  167. package/lib/features/chat/ChatWidgetCard.js +13 -0
  168. package/lib/features/chat/ChatWidgetCard.js.map +1 -0
  169. package/lib/features/chat/ConnectorConnectCard.js +166 -0
  170. package/lib/features/chat/ConnectorConnectCard.js.map +1 -0
  171. package/lib/features/chat/ConnectorConnectPrompt.js +272 -0
  172. package/lib/features/chat/ConnectorConnectPrompt.js.map +1 -0
  173. package/lib/features/chat/MessageActionBar.js.map +1 -1
  174. package/lib/features/chat/QueuedFollowUps.js +71 -0
  175. package/lib/features/chat/QueuedFollowUps.js.map +1 -0
  176. package/lib/features/chat/chatWidgets.js +37 -0
  177. package/lib/features/chat/chatWidgets.js.map +1 -0
  178. package/lib/features/chat/connectorConnect.js +207 -0
  179. package/lib/features/chat/connectorConnect.js.map +1 -0
  180. package/lib/features/chat/connectorConnectHandbacks.js +55 -0
  181. package/lib/features/chat/connectorConnectHandbacks.js.map +1 -0
  182. package/lib/features/design/DesignEditorExperience.js +643 -0
  183. package/lib/features/design/DesignEditorExperience.js.map +1 -0
  184. package/lib/features/design/DesignExperience.js +444 -0
  185. package/lib/features/design/DesignExperience.js.map +1 -0
  186. package/lib/features/design/designCore.js +298 -0
  187. package/lib/features/design/designCore.js.map +1 -0
  188. package/lib/features/design/designIndex.js +150 -0
  189. package/lib/features/design/designIndex.js.map +1 -0
  190. package/lib/features/design/exportDesign.js +133 -0
  191. package/lib/features/design/exportDesign.js.map +1 -0
  192. package/lib/features/job-search/ApplicationsPanel.js +907 -0
  193. package/lib/features/job-search/ApplicationsPanel.js.map +1 -0
  194. package/lib/features/job-search/ContactsPanel.js +627 -0
  195. package/lib/features/job-search/ContactsPanel.js.map +1 -0
  196. package/lib/features/job-search/InsightsPanel.js +299 -0
  197. package/lib/features/job-search/InsightsPanel.js.map +1 -0
  198. package/lib/features/job-search/InterviewPanel.js +637 -0
  199. package/lib/features/job-search/InterviewPanel.js.map +1 -0
  200. package/lib/features/job-search/JdPastePrompt.js +130 -0
  201. package/lib/features/job-search/JdPastePrompt.js.map +1 -0
  202. package/lib/features/job-search/JobCard.js +199 -0
  203. package/lib/features/job-search/JobCard.js.map +1 -0
  204. package/lib/features/job-search/JobDetailSheet.js +255 -0
  205. package/lib/features/job-search/JobDetailSheet.js.map +1 -0
  206. package/lib/features/job-search/JobSearchAgentChatPane.js +377 -0
  207. package/lib/features/job-search/JobSearchAgentChatPane.js.map +1 -0
  208. package/lib/features/job-search/JobSearchExperience.js +1324 -0
  209. package/lib/features/job-search/JobSearchExperience.js.map +1 -0
  210. package/lib/features/job-search/JobSearchLocationField.js +231 -0
  211. package/lib/features/job-search/JobSearchLocationField.js.map +1 -0
  212. package/lib/features/job-search/ProfilePanel.js +679 -0
  213. package/lib/features/job-search/ProfilePanel.js.map +1 -0
  214. package/lib/features/job-search/RepliesPanel.js +344 -0
  215. package/lib/features/job-search/RepliesPanel.js.map +1 -0
  216. package/lib/features/job-search/SavedPanel.js +297 -0
  217. package/lib/features/job-search/SavedPanel.js.map +1 -0
  218. package/lib/features/job-search/chat/widgetContent.js +29 -0
  219. package/lib/features/job-search/chat/widgetContent.js.map +1 -0
  220. package/lib/features/job-search/cvText.js +91 -0
  221. package/lib/features/job-search/cvText.js.map +1 -0
  222. package/lib/features/job-search/jobAgentSwipe.js +7 -0
  223. package/lib/features/job-search/jobAgentSwipe.js.map +1 -0
  224. package/lib/features/job-search/jobSearchClient.js +184 -0
  225. package/lib/features/job-search/jobSearchClient.js.map +1 -0
  226. package/lib/features/job-search/jobSearchExec.js +14 -0
  227. package/lib/features/job-search/jobSearchExec.js.map +1 -0
  228. package/lib/features/job-search/jobSearchRuntime.js +50 -0
  229. package/lib/features/job-search/jobSearchRuntime.js.map +1 -0
  230. package/lib/features/job-search/jobSearchTheme.js +44 -0
  231. package/lib/features/job-search/jobSearchTheme.js.map +1 -0
  232. package/lib/features/job-search/savedJobs.js +85 -0
  233. package/lib/features/job-search/savedJobs.js.map +1 -0
  234. package/lib/features/job-search/searchHistory.js +117 -0
  235. package/lib/features/job-search/searchHistory.js.map +1 -0
  236. package/lib/features/job-search/types.js +36 -0
  237. package/lib/features/job-search/types.js.map +1 -0
  238. package/lib/features/job-search/useJobSearchSession.js +558 -0
  239. package/lib/features/job-search/useJobSearchSession.js.map +1 -0
  240. package/lib/features/messaging/ChatComponents.js +529 -0
  241. package/lib/features/messaging/ChatComponents.js.map +1 -0
  242. package/lib/features/messaging/ChatInviteDeepLink.js +116 -0
  243. package/lib/features/messaging/ChatInviteDeepLink.js.map +1 -0
  244. package/lib/features/messaging/ContactsScreen.js +288 -0
  245. package/lib/features/messaging/ContactsScreen.js.map +1 -0
  246. package/lib/features/messaging/ConversationListScreen.js +147 -0
  247. package/lib/features/messaging/ConversationListScreen.js.map +1 -0
  248. package/lib/features/messaging/MessageActions.js +290 -0
  249. package/lib/features/messaging/MessageActions.js.map +1 -0
  250. package/lib/features/messaging/NativeChatExperience.js +189 -0
  251. package/lib/features/messaging/NativeChatExperience.js.map +1 -0
  252. package/lib/features/messaging/RegistrationScreen.js +11 -14
  253. package/lib/features/messaging/RegistrationScreen.js.map +1 -1
  254. package/lib/features/messaging/ThreadScreen.js +215 -0
  255. package/lib/features/messaging/ThreadScreen.js.map +1 -0
  256. package/lib/features/messaging/chatInviteLink.js +52 -0
  257. package/lib/features/messaging/chatInviteLink.js.map +1 -0
  258. package/lib/features/messaging/chatModel.js +278 -0
  259. package/lib/features/messaging/chatModel.js.map +1 -0
  260. package/lib/features/messaging/chatOperations.js +106 -1
  261. package/lib/features/messaging/chatOperations.js.map +1 -1
  262. package/lib/features/messaging/emojiCatalog.js +60 -0
  263. package/lib/features/messaging/emojiCatalog.js.map +1 -0
  264. package/lib/features/messaging/emojiKeywords.js +1592 -0
  265. package/lib/features/messaging/emojiKeywords.js.map +1 -0
  266. package/lib/features/messaging/nativeChatChannelQuery.js +27 -0
  267. package/lib/features/messaging/nativeChatChannelQuery.js.map +1 -0
  268. package/lib/features/messaging/phoneNumbers.js +52 -1
  269. package/lib/features/messaging/phoneNumbers.js.map +1 -1
  270. package/lib/features/messaging/sha256.js +68 -0
  271. package/lib/features/messaging/sha256.js.map +1 -0
  272. package/lib/features/messaging/useChatData.js +421 -0
  273. package/lib/features/messaging/useChatData.js.map +1 -0
  274. package/lib/features/messaging/useContactMatches.js +191 -0
  275. package/lib/features/messaging/useContactMatches.js.map +1 -0
  276. package/lib/features/messaging/usePhoneVerification.js +12 -12
  277. package/lib/features/messaging/usePhoneVerification.js.map +1 -1
  278. package/lib/features/messaging/yantraChatOrg.js +8 -3
  279. package/lib/features/messaging/yantraChatOrg.js.map +1 -1
  280. package/lib/features/resume/AnnotateModal.js +100 -0
  281. package/lib/features/resume/AnnotateModal.js.map +1 -0
  282. package/lib/features/resume/AnnotationBar.js +69 -0
  283. package/lib/features/resume/AnnotationBar.js.map +1 -0
  284. package/lib/features/resume/ExportSheet.js +105 -0
  285. package/lib/features/resume/ExportSheet.js.map +1 -0
  286. package/lib/features/resume/ResumeAgentChatPane.js +95 -0
  287. package/lib/features/resume/ResumeAgentChatPane.js.map +1 -0
  288. package/lib/features/resume/ResumeEditor.js +676 -0
  289. package/lib/features/resume/ResumeEditor.js.map +1 -0
  290. package/lib/features/resume/ResumeExperience.js +235 -0
  291. package/lib/features/resume/ResumeExperience.js.map +1 -0
  292. package/lib/features/resume/ResumeListPanel.js +262 -0
  293. package/lib/features/resume/ResumeListPanel.js.map +1 -0
  294. package/lib/features/resume/ResumeToolbar.js +236 -0
  295. package/lib/features/resume/ResumeToolbar.js.map +1 -0
  296. package/lib/features/resume/annotations.js +17 -0
  297. package/lib/features/resume/annotations.js.map +1 -0
  298. package/lib/features/resume/documentCss.js +52 -0
  299. package/lib/features/resume/documentCss.js.map +1 -0
  300. package/lib/features/resume/draft.js +89 -0
  301. package/lib/features/resume/draft.js.map +1 -0
  302. package/lib/features/resume/exportResume.js +43 -0
  303. package/lib/features/resume/exportResume.js.map +1 -0
  304. package/lib/features/resume/pickResumePhoto.js +22 -0
  305. package/lib/features/resume/pickResumePhoto.js.map +1 -0
  306. package/lib/features/resume/renderResume.js +121 -0
  307. package/lib/features/resume/renderResume.js.map +1 -0
  308. package/lib/features/resume/resumeClient.js +69 -0
  309. package/lib/features/resume/resumeClient.js.map +1 -0
  310. package/lib/features/resume/resumeExec.js +14 -0
  311. package/lib/features/resume/resumeExec.js.map +1 -0
  312. package/lib/features/resume/resumeIndex.js +244 -0
  313. package/lib/features/resume/resumeIndex.js.map +1 -0
  314. package/lib/features/resume/resumeRuntime.js +50 -0
  315. package/lib/features/resume/resumeRuntime.js.map +1 -0
  316. package/lib/features/resume/resumeTheme.js +34 -0
  317. package/lib/features/resume/resumeTheme.js.map +1 -0
  318. package/lib/features/resume/resumeToolbox.js +49 -0
  319. package/lib/features/resume/resumeToolbox.js.map +1 -0
  320. package/lib/features/resume/templates.js +90 -0
  321. package/lib/features/resume/templates.js.map +1 -0
  322. package/lib/features/resume/types.js +10 -0
  323. package/lib/features/resume/types.js.map +1 -0
  324. package/lib/features/resume/useResumeSession.js +183 -0
  325. package/lib/features/resume/useResumeSession.js.map +1 -0
  326. package/lib/features/shopping/DealsPanel.js +254 -0
  327. package/lib/features/shopping/DealsPanel.js.map +1 -0
  328. package/lib/features/shopping/HistoryPanel.js +147 -0
  329. package/lib/features/shopping/HistoryPanel.js.map +1 -0
  330. package/lib/features/shopping/OrdersPanel.js +157 -0
  331. package/lib/features/shopping/OrdersPanel.js.map +1 -0
  332. package/lib/features/shopping/ProductCard.js +326 -0
  333. package/lib/features/shopping/ProductCard.js.map +1 -0
  334. package/lib/features/shopping/ProductDetailSheet.js +313 -0
  335. package/lib/features/shopping/ProductDetailSheet.js.map +1 -0
  336. package/lib/features/shopping/ProductFilterBar.js +153 -0
  337. package/lib/features/shopping/ProductFilterBar.js.map +1 -0
  338. package/lib/features/shopping/ProductPhoto.js +27 -0
  339. package/lib/features/shopping/ProductPhoto.js.map +1 -0
  340. package/lib/features/shopping/SavedPanel.js +139 -0
  341. package/lib/features/shopping/SavedPanel.js.map +1 -0
  342. package/lib/features/shopping/ShoppingAgentChatPane.js +436 -0
  343. package/lib/features/shopping/ShoppingAgentChatPane.js.map +1 -0
  344. package/lib/features/shopping/ShoppingExperience.js +888 -0
  345. package/lib/features/shopping/ShoppingExperience.js.map +1 -0
  346. package/lib/features/shopping/TrendingSections.js +199 -0
  347. package/lib/features/shopping/TrendingSections.js.map +1 -0
  348. package/lib/features/shopping/WatchlistPanel.js +148 -0
  349. package/lib/features/shopping/WatchlistPanel.js.map +1 -0
  350. package/lib/features/shopping/catalog.js +238 -0
  351. package/lib/features/shopping/catalog.js.map +1 -0
  352. package/lib/features/shopping/chat/ShoppingChatResultCard.js +175 -0
  353. package/lib/features/shopping/chat/ShoppingChatResultCard.js.map +1 -0
  354. package/lib/features/shopping/chat/streamAssistantReply.js +34 -0
  355. package/lib/features/shopping/chat/streamAssistantReply.js.map +1 -0
  356. package/lib/features/shopping/chat/widgetContent.js +233 -0
  357. package/lib/features/shopping/chat/widgetContent.js.map +1 -0
  358. package/lib/features/shopping/hooks/useTrendingProducts.js +162 -0
  359. package/lib/features/shopping/hooks/useTrendingProducts.js.map +1 -0
  360. package/lib/features/shopping/productImage.js +42 -0
  361. package/lib/features/shopping/productImage.js.map +1 -0
  362. package/lib/features/shopping/savedProducts.js +84 -0
  363. package/lib/features/shopping/savedProducts.js.map +1 -0
  364. package/lib/features/shopping/services/catalogActions.js +166 -0
  365. package/lib/features/shopping/services/catalogActions.js.map +1 -0
  366. package/lib/features/shopping/services/parsePriceCheckIntent.js +58 -0
  367. package/lib/features/shopping/services/parsePriceCheckIntent.js.map +1 -0
  368. package/lib/features/shopping/services/parseShoppingIntent.js +67 -0
  369. package/lib/features/shopping/services/parseShoppingIntent.js.map +1 -0
  370. package/lib/features/shopping/services/productAvailability.js +25 -0
  371. package/lib/features/shopping/services/productAvailability.js.map +1 -0
  372. package/lib/features/shopping/services/productFilters.js +72 -0
  373. package/lib/features/shopping/services/productFilters.js.map +1 -0
  374. package/lib/features/shopping/services/retailerUrl.js +75 -0
  375. package/lib/features/shopping/services/retailerUrl.js.map +1 -0
  376. package/lib/features/shopping/services/shoppingChatReply.js +46 -0
  377. package/lib/features/shopping/services/shoppingChatReply.js.map +1 -0
  378. package/lib/features/shopping/services/shoppingProductSearch.js +336 -0
  379. package/lib/features/shopping/services/shoppingProductSearch.js.map +1 -0
  380. package/lib/features/shopping/services/shoppingSearchConnectorClient.js +41 -0
  381. package/lib/features/shopping/services/shoppingSearchConnectorClient.js.map +1 -0
  382. package/lib/features/shopping/shopAgentSwipe.js +7 -0
  383. package/lib/features/shopping/shopAgentSwipe.js.map +1 -0
  384. package/lib/features/shopping/shoppingCart.js +116 -0
  385. package/lib/features/shopping/shoppingCart.js.map +1 -0
  386. package/lib/features/shopping/shoppingExec.js +14 -0
  387. package/lib/features/shopping/shoppingExec.js.map +1 -0
  388. package/lib/features/shopping/shoppingHistoryStore.js +176 -0
  389. package/lib/features/shopping/shoppingHistoryStore.js.map +1 -0
  390. package/lib/features/shopping/shoppingRuntime.js +63 -0
  391. package/lib/features/shopping/shoppingRuntime.js.map +1 -0
  392. package/lib/features/shopping/timeAgo.js +14 -0
  393. package/lib/features/shopping/timeAgo.js.map +1 -0
  394. package/lib/features/shopping/useShoppingSearch.js +262 -0
  395. package/lib/features/shopping/useShoppingSearch.js.map +1 -0
  396. package/lib/features/travel/BookHeaderGlow.js +48 -0
  397. package/lib/features/travel/BookHeaderGlow.js.map +1 -0
  398. package/lib/features/travel/BookingsPanel.js +29 -0
  399. package/lib/features/travel/BookingsPanel.js.map +1 -0
  400. package/lib/features/travel/DiscoverPanel.js +155 -0
  401. package/lib/features/travel/DiscoverPanel.js.map +1 -0
  402. package/lib/features/travel/FlightCompareBar.js +86 -0
  403. package/lib/features/travel/FlightCompareBar.js.map +1 -0
  404. package/lib/features/travel/FlightDealsBoard.js +100 -0
  405. package/lib/features/travel/FlightDealsBoard.js.map +1 -0
  406. package/lib/features/travel/HistoryPanel.js +82 -0
  407. package/lib/features/travel/HistoryPanel.js.map +1 -0
  408. package/lib/features/travel/PopularDestinations.js +144 -0
  409. package/lib/features/travel/PopularDestinations.js.map +1 -0
  410. package/lib/features/travel/SavedPanel.js +27 -0
  411. package/lib/features/travel/SavedPanel.js.map +1 -0
  412. package/lib/features/travel/TravelAgentChatPane.js +303 -0
  413. package/lib/features/travel/TravelAgentChatPane.js.map +1 -0
  414. package/lib/features/travel/TravelBookHero.js +425 -0
  415. package/lib/features/travel/TravelBookHero.js.map +1 -0
  416. package/lib/features/travel/TravelDatesField.js +234 -0
  417. package/lib/features/travel/TravelDatesField.js.map +1 -0
  418. package/lib/features/travel/TravelDetailSheet.js +106 -0
  419. package/lib/features/travel/TravelDetailSheet.js.map +1 -0
  420. package/lib/features/travel/TravelExperience.js +624 -0
  421. package/lib/features/travel/TravelExperience.js.map +1 -0
  422. package/lib/features/travel/TravelGuestsField.js +85 -0
  423. package/lib/features/travel/TravelGuestsField.js.map +1 -0
  424. package/lib/features/travel/TravelLanding.js +318 -0
  425. package/lib/features/travel/TravelLanding.js.map +1 -0
  426. package/lib/features/travel/TravelLocationField.js +179 -0
  427. package/lib/features/travel/TravelLocationField.js.map +1 -0
  428. package/lib/features/travel/TravelPropertyCard.js +266 -0
  429. package/lib/features/travel/TravelPropertyCard.js.map +1 -0
  430. package/lib/features/travel/TravelPropertyPhoto.js +22 -0
  431. package/lib/features/travel/TravelPropertyPhoto.js.map +1 -0
  432. package/lib/features/travel/TravelRailFlyout.js +79 -0
  433. package/lib/features/travel/TravelRailFlyout.js.map +1 -0
  434. package/lib/features/travel/TravelResultsMap.js +126 -0
  435. package/lib/features/travel/TravelResultsMap.js.map +1 -0
  436. package/lib/features/travel/WorkspacePanel.js +148 -0
  437. package/lib/features/travel/WorkspacePanel.js.map +1 -0
  438. package/lib/features/travel/appNav.js +244 -0
  439. package/lib/features/travel/appNav.js.map +1 -0
  440. package/lib/features/travel/calendarDays.js +50 -0
  441. package/lib/features/travel/calendarDays.js.map +1 -0
  442. package/lib/features/travel/catalog.js +72 -0
  443. package/lib/features/travel/catalog.js.map +1 -0
  444. package/lib/features/travel/chat/TravelChatResultCard.js +107 -0
  445. package/lib/features/travel/chat/TravelChatResultCard.js.map +1 -0
  446. package/lib/features/travel/chat/widgetContent.js +107 -0
  447. package/lib/features/travel/chat/widgetContent.js.map +1 -0
  448. package/lib/features/travel/flightDeals.js +65 -0
  449. package/lib/features/travel/flightDeals.js.map +1 -0
  450. package/lib/features/travel/mapCoordinates.js +36 -0
  451. package/lib/features/travel/mapCoordinates.js.map +1 -0
  452. package/lib/features/travel/parseTravelIntent.js +303 -0
  453. package/lib/features/travel/parseTravelIntent.js.map +1 -0
  454. package/lib/features/travel/savedStays.js +66 -0
  455. package/lib/features/travel/savedStays.js.map +1 -0
  456. package/lib/features/travel/services/flightDealsBoard.js +111 -0
  457. package/lib/features/travel/services/flightDealsBoard.js.map +1 -0
  458. package/lib/features/travel/services/flightSearchConnectorClient.js +42 -0
  459. package/lib/features/travel/services/flightSearchConnectorClient.js.map +1 -0
  460. package/lib/features/travel/services/geocodeLocation.js +79 -0
  461. package/lib/features/travel/services/geocodeLocation.js.map +1 -0
  462. package/lib/features/travel/services/placePredictions.js +113 -0
  463. package/lib/features/travel/services/placePredictions.js.map +1 -0
  464. package/lib/features/travel/services/resolveOriginCity.js +27 -0
  465. package/lib/features/travel/services/resolveOriginCity.js.map +1 -0
  466. package/lib/features/travel/services/resortifiConnectorClient.js +76 -0
  467. package/lib/features/travel/services/resortifiConnectorClient.js.map +1 -0
  468. package/lib/features/travel/services/travelFlightSearch.js +289 -0
  469. package/lib/features/travel/services/travelFlightSearch.js.map +1 -0
  470. package/lib/features/travel/services/travelPropertySearch.js +377 -0
  471. package/lib/features/travel/services/travelPropertySearch.js.map +1 -0
  472. package/lib/features/travel/travelAgentSwipe.js +7 -0
  473. package/lib/features/travel/travelAgentSwipe.js.map +1 -0
  474. package/lib/features/travel/travelExec.js +14 -0
  475. package/lib/features/travel/travelExec.js.map +1 -0
  476. package/lib/features/travel/travelHistoryStore.js +108 -0
  477. package/lib/features/travel/travelHistoryStore.js.map +1 -0
  478. package/lib/features/travel/travelRuntime.js +62 -0
  479. package/lib/features/travel/travelRuntime.js.map +1 -0
  480. package/lib/features/travel/types.js +9 -0
  481. package/lib/features/travel/types.js.map +1 -0
  482. package/lib/features/travel/useTravelSearch.js +330 -0
  483. package/lib/features/travel/useTravelSearch.js.map +1 -0
  484. package/lib/features/travel/workspaceContent.js +548 -0
  485. package/lib/features/travel/workspaceContent.js.map +1 -0
  486. package/lib/hooks/useCdecliChannel.js +128 -6
  487. package/lib/hooks/useCdecliChannel.js.map +1 -1
  488. package/lib/hooks/useChatApi.js +4 -2
  489. package/lib/hooks/useChatApi.js.map +1 -1
  490. package/lib/hooks/useChatStream.js +77 -63
  491. package/lib/hooks/useChatStream.js.map +1 -1
  492. package/lib/hooks/useHostConnectorCard.js +24 -0
  493. package/lib/hooks/useHostConnectorCard.js.map +1 -0
  494. package/lib/hooks/useObtainSystemToken.js +23 -5
  495. package/lib/hooks/useObtainSystemToken.js.map +1 -1
  496. package/lib/hooks/webViewRetentionPolicy.js +1 -0
  497. package/lib/hooks/webViewRetentionPolicy.js.map +1 -1
  498. package/lib/index.js +1 -1
  499. package/lib/index.js.map +1 -1
  500. package/lib/screens/Chat/index.js +51 -22
  501. package/lib/screens/Chat/index.js.map +1 -1
  502. package/lib/screens/ChatNative/index.js +13 -2
  503. package/lib/screens/ChatNative/index.js.map +1 -1
  504. package/lib/screens/Home/HomeScreen.js +3 -3
  505. package/lib/screens/Home/HomeScreen.js.map +1 -1
  506. package/lib/screens/Home/components/ChatHistoryLanding.js +32 -32
  507. package/lib/screens/Home/components/ChatHistoryLanding.js.map +1 -1
  508. package/lib/screens/JobSearchNative/useJobSearchHostChat.js +12 -6
  509. package/lib/screens/JobSearchNative/useJobSearchHostChat.js.map +1 -1
  510. package/lib/screens/ResumeNative/useResumeHostChat.js +12 -6
  511. package/lib/screens/ResumeNative/useResumeHostChat.js.map +1 -1
  512. package/lib/screens/ShoppingNative/useShoppingHostChat.js +12 -6
  513. package/lib/screens/ShoppingNative/useShoppingHostChat.js.map +1 -1
  514. package/lib/screens/TravelNative/useTravelHostChat.js +12 -6
  515. package/lib/screens/TravelNative/useTravelHostChat.js.map +1 -1
  516. package/lib/screens/WebBuilder/WebViewWithNavigation.js +2 -2
  517. package/lib/screens/WebBuilder/WebViewWithNavigation.js.map +1 -1
  518. package/lib/services/brainQuickReply.js +38 -1
  519. package/lib/services/brainQuickReply.js.map +1 -1
  520. package/lib/state/chatThreadMerge.js +6 -1
  521. package/lib/state/chatThreadMerge.js.map +1 -1
  522. package/package.json +6 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConnectorConnectPrompt.js","sources":["../../../src/features/chat/ConnectorConnectPrompt.tsx"],"sourcesContent":["/**\n * <ConnectorConnectPrompt> - owns one `[CONNECTOR_CONNECT]` card: whether the\n * connection is already saved, the web page the action opens, and the reply.\n *\n * The phone cannot host the web's inline vault / connector forms, so the action\n * opens the web page in an in-app browser session (expo-web-browser's auth\n * session, which shares the system browser's sign-in with the web app). The vault\n * form's page (a login, a card, an address) hands the saved credential back\n * through the app's scheme URL (see common's CONNECTOR_CONNECT_APP_RETURN_URL);\n * any other connector's page has no way back, so once the browser closes the card\n * re-reads the vault and only a credential the session created or updated counts.\n * Only then does it reply `[CONNECTOR_CONNECTED:<requestId>:<credentialId>]` -\n * never on a closed browser.\n *\n * The action never runs on a guess about what is saved. It stays disabled until\n * the status read has come back from the server, and at the tap the vault is read\n * once more: the form opens ON the saved login (\"Update\", so an email / username\n * or password edit lands on it) or, only when the server says there is none, as a\n * new one. A read that fails opens nothing - offering \"Save login\" then would save\n * a duplicate next to the login the user meant to edit.\n *\n * Status is the same query (the org's credentials, most recently updated first)\n * and the same match (common's matchConnectorCredentials) the web card uses, so a\n * site login's \"Update\" edits the login the web would edit - and the agent signs in\n * with: the one the agent named when it is the org's and fits, else the most\n * recently updated login for the site. An autofill entry's \"Update\" is only ever\n * the entry the agent named; without one the card adds a new entry. Either is\n * edited in the project it lives in. A catalog connector's page is the web card\n * itself, which picks with the template's formId the phone cannot resolve; the\n * phone sends it only the agent's credentialId.\n *\n * Host-only (Apollo, redux, expo-web-browser): a surface remote gets this card as\n * a render prop from its host screen (useHostConnectorCard), never by import.\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { View, type StyleProp, type ViewStyle } from 'react-native';\nimport * as WebBrowser from 'expo-web-browser';\nimport {\n buildConnectorReply,\n CONNECTOR_CONNECT_APP_RETURN_URL,\n connectorCredentialsVariables,\n credentialsOfOrg,\n parseConnectorConnectAppReturnUrl,\n vaultKindOf,\n type ConnectorConnectHandback,\n type ConnectorConnectOutcome,\n type ConnectorConnectPayload,\n} from 'common';\nimport { useFormBuilderCredentialsQuery } from 'common/graphql';\nimport { config } from '../../config/env-config';\nimport { getPackagerHost, resolveMobileWebUrl } from '../../bridge/resolveMobileWebUrl';\nimport { usePrerequisiteIds } from '../../hooks/usePrerequisiteIds';\nimport { ConnectorConnectCard } from './ConnectorConnectCard';\nimport {\n buildConnectorConnectUrl,\n connectorConnectActionLabel,\n connectorConnectKey,\n connectorConnectName,\n connectorConnectReason,\n decideConnectorConnectOutcome,\n parkedHandbackCredential,\n pendingConnectorConnect,\n pickConnectorConnectCredential,\n snapshotConnectorCredentials,\n type ConnectorConnectBefore,\n type CredentialVersionRow,\n} from './connectorConnect';\nimport {\n beginConnectorConnectSession,\n endConnectorConnectSession,\n peekConnectorConnectHandback,\n subscribeConnectorConnectHandbacks,\n takeConnectorConnectHandback,\n} from './connectorConnectHandbacks';\n\n/** The vault as one read returned it; `ok: false` when the read failed. */\ntype VaultRead = { ok: true; rows: CredentialVersionRow[] } | { ok: false };\n\n/** Where the status read stands: the action waits for `ready`. */\ntype StatusState = 'checking' | 'ready' | 'failed';\n\nconst STATUS_FAILED_NOTE = 'Could not check your saved logins. Tap Try again.';\nconst READ_FAILED_NOTE = 'Could not reach your vault. Try again.';\nconst VERIFY_FAILED_NOTE = 'Could not check whether it saved. Tap Check to look again.';\nconst SEND_FAILED_NOTE = 'Could not reach the chat. Try again.';\n\nexport function ConnectorConnectPrompt({\n payload,\n isDark = false,\n onResolve,\n}: {\n payload: ConnectorConnectPayload;\n isDark?: boolean;\n /** Send the reply for this request; resolves false when it could not go out. */\n onResolve: (outcome: ConnectorConnectOutcome, credentialId?: string) => Promise<boolean>;\n}) {\n const { orgName, projectId, loading: idsLoading } = usePrerequisiteIds();\n // A website login or an autofill entry (a card, an address): the web vault form for that kind.\n const vaultKind = vaultKindOf(payload.connector);\n\n // Same query and variables as the web card's useConnectorCredentialMatch (common's\n // connectorCredentialsVariables: the whole org, most recently updated first), so the\n // Apollo cache and the pick agree across the two.\n const variables = useMemo(() => (orgName ? connectorCredentialsVariables(orgName) : null), [orgName]);\n const { data, loading, error, refetch } = useFormBuilderCredentialsQuery({\n variables: variables ?? undefined,\n skip: !variables,\n fetchPolicy: 'cache-and-network',\n });\n // Only this org's rows (credentialsOfOrg): the server deployed today can answer with the caller's rows of\n // every org, and another org's same-named login must never be the one this card edits.\n const listed = data?.formBuilderCredentials?.data as ReadonlyArray<CredentialVersionRow | null> | undefined;\n const cachedRows = useMemo(() => (listed ? credentialsOfOrg(listed, orgName) : undefined), [listed, orgName]);\n\n // `cache-and-network` paints a cached answer first and keeps `loading` until the\n // server answers; a cached \"not saved\" can be stale, so only the server's\n // answer makes the action live.\n let status: StatusState = 'ready';\n if (!variables) status = idsLoading ? 'checking' : 'failed';\n else if (error) status = 'failed';\n else if (loading || !cachedRows) status = 'checking';\n\n const existing = useMemo(\n () => (status === 'ready' && cachedRows ? (pickConnectorConnectCredential(cachedRows, payload) ?? null) : null),\n [status, cachedRows, payload],\n );\n const connected = Boolean(existing);\n const name = connectorConnectName(payload, connected);\n\n const [busy, setBusy] = useState(false);\n const [note, setNote] = useState<string | null>(null);\n // The vault changed but the reply did not go out: the next tap resends the\n // reply instead of reopening the browser.\n const [unsent, setUnsent] = useState<{ credentialId?: string } | null>(null);\n // The browser closed but the vault could not be re-read: the next tap checks\n // again against the same \"before\", instead of reopening the browser.\n const [unverified, setUnverified] = useState<ConnectorConnectBefore | null>(null);\n const mountedRef = useRef(true);\n useEffect(\n () => () => {\n mountedRef.current = false;\n },\n [],\n );\n\n /** The vault as the server has it now (not the cache). */\n const readVault = useCallback(async (): Promise<VaultRead> => {\n if (!variables) return { ok: false };\n try {\n const result = await refetch(variables);\n const rows = result.data?.formBuilderCredentials?.data;\n if (result.error || !Array.isArray(rows)) return { ok: false };\n return { ok: true, rows: credentialsOfOrg(rows as ReadonlyArray<CredentialVersionRow | null>, orgName) };\n } catch {\n return { ok: false };\n }\n }, [variables, refetch, orgName]);\n\n /** Send the reply; a send that throws counts as not sent, so the card stays. */\n const sendReply = useCallback(\n async (outcome: ConnectorConnectOutcome, credentialId?: string): Promise<boolean> => {\n try {\n return await onResolve(outcome, credentialId);\n } catch {\n return false;\n }\n },\n [onResolve],\n );\n\n /** Reply `connected`; on failure keep the result so the next tap only resends. */\n const replyConnected = useCallback(\n async (credentialId: string | undefined): Promise<string | null> => {\n if (await sendReply('connected', credentialId)) return null;\n if (mountedRef.current) setUnsent({ credentialId });\n return 'Saved, but the chat did not get it. Tap Send to try again.';\n },\n [sendReply],\n );\n\n /** Leave the busy state with `text` under the actions (null clears it). */\n const settle = useCallback((text: string | null) => {\n if (!mountedRef.current) return;\n setNote(text);\n setBusy(false);\n }, []);\n\n /** Decide from a hand-back and a fresh read against `before`, then reply or say why not. */\n const conclude = useCallback(\n async (\n before: ConnectorConnectBefore,\n handback: ConnectorConnectHandback | null,\n wasConnected: boolean,\n ): Promise<void> => {\n const after = await readVault();\n const decision = decideConnectorConnectOutcome({\n requestId: payload.requestId,\n handback,\n before,\n after: after.ok\n ? { rows: after.rows, match: pickConnectorConnectCredential(after.rows, payload) ?? null }\n : null,\n kind: vaultKind?.id,\n });\n if (decision.kind === 'connected') {\n if (mountedRef.current) setUnverified(null);\n settle(await replyConnected(decision.credentialId));\n return;\n }\n if (!after.ok) {\n if (mountedRef.current) setUnverified(before);\n settle(VERIFY_FAILED_NOTE);\n return;\n }\n if (mountedRef.current) setUnverified(null);\n if (wasConnected) settle('No changes were saved.');\n else if (vaultKind) settle(`The ${vaultKind.noun} was not saved.`);\n else settle(`${name} is not connected yet.`);\n },\n [readVault, payload, replyConnected, settle, vaultKind, name],\n );\n\n const handleAction = useCallback(async () => {\n if (busy) return;\n setBusy(true);\n setNote(null);\n if (unsent) {\n setUnsent(null);\n settle(await replyConnected(unsent.credentialId));\n return;\n }\n if (unverified) {\n await conclude(unverified, null, Boolean(unverified.targetId));\n return;\n }\n if (status === 'failed') {\n // \"Try again\": re-read the status; the action goes live once it answers.\n settle((await readVault()).ok ? null : STATUS_FAILED_NOTE);\n return;\n }\n // Read the vault as it is NOW: the form opens on the credential the server\n // has, and the same read is the \"before\" the result is measured against.\n const now = await readVault();\n if (!now.ok) {\n settle(READ_FAILED_NOTE);\n return;\n }\n const current = pickConnectorConnectCredential(now.rows, payload) ?? null;\n const before = snapshotConnectorCredentials(now.rows, current?.id);\n const url = buildConnectorConnectUrl({\n origin: resolveMobileWebUrl(config.CLIENT_URL, getPackagerHost()),\n payload,\n name,\n // A saved login or entry: open the vault form ON it so the edit (email, username or password, a card's\n // expiry) lands on it instead of on a new duplicate, in the project it lives in (the form refuses an entry\n // from another). A catalog connector's page makes this pick itself, with the template's formId.\n credentialId: vaultKind ? current?.id : undefined,\n projectId: vaultKind ? current?.project?.projectId || projectId : undefined,\n });\n let result: WebBrowser.WebBrowserAuthSessionResult;\n beginConnectorConnectSession(payload.requestId);\n try {\n result = await WebBrowser.openAuthSessionAsync(url, CONNECTOR_CONNECT_APP_RETURN_URL);\n } catch {\n settle('Could not open the page. Try again.');\n return;\n } finally {\n endConnectorConnectSession(payload.requestId);\n }\n const handback = result.type === 'success' ? parseConnectorConnectAppReturnUrl(result.url) : null;\n await conclude(before, handback, Boolean(current));\n }, [\n busy,\n unsent,\n unverified,\n status,\n readVault,\n payload,\n name,\n vaultKind,\n projectId,\n conclude,\n replyConnected,\n settle,\n ]);\n\n /**\n * A hand-back that reached the app while no browser session of this card was\n * waiting for it: Android can kill the app behind Custom Tabs, and the return\n * page then cold-starts it with the scheme URL. Anyone can open that URL, so\n * the credential it names is only taken once a fresh read shows it is one this\n * request could have saved, saved just now (parkedHandbackCredential).\n *\n * On a cold start the card mounts before the org is known and cannot read the\n * vault yet, so the hand-back stays parked until a read answers: it is looked\n * at again whenever the status read settles.\n */\n const adoptingRef = useRef(false);\n const adoptParkedHandback = useCallback(async () => {\n if (busy || unsent || !variables || adoptingRef.current) return;\n const handback = peekConnectorConnectHandback(payload.requestId);\n if (!handback?.credentialId) return;\n adoptingRef.current = true;\n try {\n setBusy(true);\n setNote(null);\n const now = await readVault();\n if (!now.ok) {\n // Left parked: the next settled status read tries again.\n settle(null);\n return;\n }\n takeConnectorConnectHandback(payload.requestId);\n if (!parkedHandbackCredential(now.rows, payload, handback.credentialId, Date.now())) {\n settle(null);\n return;\n }\n settle(await replyConnected(handback.credentialId));\n } finally {\n adoptingRef.current = false;\n }\n }, [busy, unsent, variables, payload, readVault, replyConnected, settle]);\n\n const adoptRef = useRef(adoptParkedHandback);\n useEffect(() => {\n adoptRef.current = adoptParkedHandback;\n }, [adoptParkedHandback]);\n useEffect(\n () =>\n subscribeConnectorConnectHandbacks(() => {\n adoptRef.current().catch(() => undefined);\n }),\n [],\n );\n useEffect(() => {\n if (status === 'checking') return;\n adoptRef.current().catch(() => undefined);\n }, [status]);\n\n const handleDismiss = useCallback(async () => {\n if (busy) return;\n setBusy(true);\n settle((await sendReply('declined')) ? null : SEND_FAILED_NOTE);\n }, [busy, sendReply, settle]);\n\n const onActionPress = useCallback(() => {\n handleAction().catch(() => settle(READ_FAILED_NOTE));\n }, [handleAction, settle]);\n const onDismissPress = useCallback(() => {\n handleDismiss().catch(() => settle(SEND_FAILED_NOTE));\n }, [handleDismiss, settle]);\n\n let actionLabel = connectorConnectActionLabel(payload, connected);\n if (unsent) actionLabel = 'Send';\n else if (unverified) actionLabel = 'Check';\n else if (status === 'failed') actionLabel = 'Try again';\n const statusNote = status === 'failed' && !unsent && !unverified ? STATUS_FAILED_NOTE : null;\n\n return (\n <ConnectorConnectCard\n name={name}\n reason={connectorConnectReason(payload, name, connected)}\n icon={vaultKind?.mobileIcon ?? 'power-plug-outline'}\n connected={connected}\n // A saved card or address is not a connection.\n connectedLabel={vaultKind?.autofill ? 'Saved' : undefined}\n actionLabel={actionLabel}\n busy={busy}\n actionPending={!busy && !unsent && !unverified && status === 'checking'}\n note={note ?? statusNote}\n isDark={isDark}\n onAction={onActionPress}\n onDismiss={onDismissPress}\n />\n );\n}\n\n/**\n * The card for the connect request still waiting in `messages`, if any - the\n * one piece both chat screens (the main chat, and the host screens of the native\n * surface chats) render above their composer.\n *\n * The reply goes out through the screen's ordinary send path, as an ASK_USER\n * answer does, and lands in the thread as a user message; that message is what\n * settles the request, so a reloaded thread does not bring the card back\n * (pendingConnectorConnect). The local mark only bridges the moment between the\n * send and the reply showing up, and is keyed on the message as well as the\n * request id, so the same id-less marker in a later turn still gets its card.\n */\nexport function PendingConnectorConnectCard({\n messages,\n send,\n isDark = false,\n style,\n}: {\n /** The raw thread, outbox rows included - a queued reply settles its request too. */\n messages: ReadonlyArray<{ role: string; content: string }>;\n /** Send `text` as the user's next message; resolves false when it could not go out. */\n send: (text: string) => Promise<boolean>;\n isDark?: boolean;\n style?: StyleProp<ViewStyle>;\n}) {\n const pending = useMemo(() => pendingConnectorConnect(messages), [messages]);\n const key = pending ? connectorConnectKey(pending) : null;\n const [resolved, setResolved] = useState<Record<string, boolean>>({});\n\n const handleResolve = useCallback(\n async (outcome: ConnectorConnectOutcome, credentialId?: string): Promise<boolean> => {\n if (!pending || !key) return false;\n const sent = await send(buildConnectorReply(pending.payload.requestId, outcome, credentialId));\n if (!sent) return false;\n setResolved((prev) => ({ ...prev, [key]: true }));\n return true;\n },\n [pending, key, send],\n );\n\n if (!pending || !key || resolved[key]) return null;\n return (\n <View style={style}>\n <ConnectorConnectPrompt key={key} payload={pending.payload} isDark={isDark} onResolve={handleResolve} />\n </View>\n );\n}\n"],"names":["_a","_b"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"MessageActionBar.js","sources":["../../../src/features/chat/MessageActionBar.tsx"],"sourcesContent":["/**\n * Action row under a completed assistant message — the mobile counterpart of\n * the web chat's MessageActionBar (copy / try again / share). Rendered through\n * MessagesContainerUI's `renderMessageActions` slot.\n *\n * Read-aloud is deliberately absent for now: it needs `expo-speech`, a native\n * module the installed binaries don't carry yet. It joins the bar in the build\n * that adds the dependency; everything here works with the current binary.\n */\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n// Clipboard is deprecated in RN core but still functional on 0.79, and the\n// community package is not in the dependency set — using core avoids putting a\n// new native module between the user and a working Copy button.\n// eslint-disable-next-line @typescript-eslint/no-deprecated\nimport { Clipboard, Share, StyleSheet, TouchableOpacity, View } from 'react-native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\n\nexport interface MessageActionBarProps {\n /** The assistant message's text — copied and shared verbatim. */\n text: string;\n /** Re-run the turn that produced this message. Omit to hide the button\n * (e.g. while a turn is streaming, to avoid double-sends). */\n onRegenerate?: () => void;\n}\n\nconst ICON_SIZE = 16;\nconst ICON_COLOR = '#64748b';\nconst COPIED_COLOR = '#10b981';\n\ninterface ActionButtonProps {\n icon: React.ComponentProps<typeof MaterialCommunityIcons>['name'];\n label: string;\n onPress: () => void;\n color?: string;\n}\n\nfunction ActionButton({ icon, label, onPress, color = ICON_COLOR }: ActionButtonProps) {\n return (\n <TouchableOpacity\n onPress={onPress}\n style={styles.button}\n hitSlop={{ top: 8, bottom: 8, left: 6, right: 6 }}\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n >\n <MaterialCommunityIcons name={icon} size={ICON_SIZE} color={color} />\n </TouchableOpacity>\n );\n}\n\nexport function MessageActionBar({ text, onRegenerate }: MessageActionBarProps) {\n const [copied, setCopied] = useState(false);\n const copiedTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(\n () => () => {\n if (copiedTimer.current) clearTimeout(copiedTimer.current);\n },\n [],\n );\n\n const handleCopy = useCallback(() => {\n // eslint-disable-next-line @typescript-eslint/no-deprecated\n Clipboard.setString(text);\n setCopied(true);\n if (copiedTimer.current) clearTimeout(copiedTimer.current);\n copiedTimer.current = setTimeout(() => setCopied(false), 2000);\n }, [text]);\n\n const handleShare = useCallback(() => {\n void Share.share({ message: text });\n }, [text]);\n\n return (\n <View style={styles.row} accessibilityRole=\"toolbar\" accessibilityLabel=\"Message actions\">\n <ActionButton\n icon={copied ? 'check' : 'content-copy'}\n label={copied ? 'Copied' : 'Copy'}\n onPress={handleCopy}\n color={copied ? COPIED_COLOR : ICON_COLOR}\n />\n {onRegenerate ? <ActionButton icon=\"refresh\" label=\"Try again\" onPress={onRegenerate} /> : null}\n <ActionButton icon=\"share-variant-outline\" label=\"Share\" onPress={handleShare} />\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n row: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 4,\n },\n button: {\n height: 28,\n width: 28,\n borderRadius: 8,\n alignItems: 'center',\n justifyContent: 'center',\n },\n});\n\nexport default MessageActionBar;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MessageActionBar.js","sources":["../../../src/features/chat/MessageActionBar.tsx"],"sourcesContent":["/**\n * Action row under a completed assistant message — the mobile counterpart of\n * the web chat's MessageActionBar (copy / try again / share). Rendered through\n * MessagesContainerUI's `renderMessageActions` slot.\n *\n * Read-aloud is deliberately absent for now: it needs `expo-speech`, a native\n * module the installed binaries don't carry yet. It joins the bar in the build\n * that adds the dependency; everything here works with the current binary.\n */\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n// Clipboard is deprecated in RN core but still functional on 0.79, and the\n// community package is not in the dependency set — using core avoids putting a\n// new native module between the user and a working Copy button.\nimport { Clipboard, Share, StyleSheet, TouchableOpacity, View } from 'react-native';\nimport { MaterialCommunityIcons } from '@expo/vector-icons';\n\nexport interface MessageActionBarProps {\n /** The assistant message's text — copied and shared verbatim. */\n text: string;\n /** Re-run the turn that produced this message. Omit to hide the button\n * (e.g. while a turn is streaming, to avoid double-sends). */\n onRegenerate?: () => void;\n}\n\nconst ICON_SIZE = 16;\nconst ICON_COLOR = '#64748b';\nconst COPIED_COLOR = '#10b981';\n\ninterface ActionButtonProps {\n icon: React.ComponentProps<typeof MaterialCommunityIcons>['name'];\n label: string;\n onPress: () => void;\n color?: string;\n}\n\nfunction ActionButton({ icon, label, onPress, color = ICON_COLOR }: ActionButtonProps) {\n return (\n <TouchableOpacity\n onPress={onPress}\n style={styles.button}\n hitSlop={{ top: 8, bottom: 8, left: 6, right: 6 }}\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n >\n <MaterialCommunityIcons name={icon} size={ICON_SIZE} color={color} />\n </TouchableOpacity>\n );\n}\n\nexport function MessageActionBar({ text, onRegenerate }: MessageActionBarProps) {\n const [copied, setCopied] = useState(false);\n const copiedTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(\n () => () => {\n if (copiedTimer.current) clearTimeout(copiedTimer.current);\n },\n [],\n );\n\n const handleCopy = useCallback(() => {\n Clipboard.setString(text);\n setCopied(true);\n if (copiedTimer.current) clearTimeout(copiedTimer.current);\n copiedTimer.current = setTimeout(() => setCopied(false), 2000);\n }, [text]);\n\n const handleShare = useCallback(() => {\n void Share.share({ message: text });\n }, [text]);\n\n return (\n <View style={styles.row} accessibilityRole=\"toolbar\" accessibilityLabel=\"Message actions\">\n <ActionButton\n icon={copied ? 'check' : 'content-copy'}\n label={copied ? 'Copied' : 'Copy'}\n onPress={handleCopy}\n color={copied ? COPIED_COLOR : ICON_COLOR}\n />\n {onRegenerate ? <ActionButton icon=\"refresh\" label=\"Try again\" onPress={onRegenerate} /> : null}\n <ActionButton icon=\"share-variant-outline\" label=\"Share\" onPress={handleShare} />\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n row: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 4,\n },\n button: {\n height: 28,\n width: 28,\n borderRadius: 8,\n alignItems: 'center',\n justifyContent: 'center',\n },\n});\n\nexport default MessageActionBar;\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ import {jsxs,jsx}from'react/jsx-runtime';import {View,StyleSheet,Text,Pressable}from'react-native';import {USER_BUBBLE_BG}from'./ChatTranscript.js';function QueuedFollowUps({
2
+ items,
3
+ onCancel,
4
+ onSendNow,
5
+ isDark
6
+ }) {
7
+ if (items.length === 0) return null;
8
+ const muted = isDark ? "#94a3b8" : "#64748b";
9
+ const action = isDark ? "#93c5fd" : "#2563eb";
10
+ return /* @__PURE__ */ jsxs(View, { style: styles.container, testID: "queued-follow-ups", children: [
11
+ items.map((item) => /* @__PURE__ */ jsxs(View, { style: styles.item, children: [
12
+ /* @__PURE__ */ jsx(View, { style: styles.bubble, children: /* @__PURE__ */ jsx(Text, { style: styles.bubbleText, numberOfLines: 3, children: item.text }) }),
13
+ /* @__PURE__ */ jsxs(View, { style: styles.captionRow, children: [
14
+ /* @__PURE__ */ jsx(Text, { style: [styles.caption, {
15
+ color: muted
16
+ }], children: "Queued \xB7 answered after the current reply" }),
17
+ /* @__PURE__ */ jsx(Pressable, { onPress: () => onCancel(item.id), hitSlop: 8, accessibilityRole: "button", accessibilityLabel: `Cancel queued message: ${item.text}`, style: styles.action, children: /* @__PURE__ */ jsx(Text, { style: [styles.actionText, {
18
+ color: action
19
+ }], children: "Cancel" }) })
20
+ ] })
21
+ ] }, item.id)),
22
+ items.length > 0 ? /* @__PURE__ */ jsx(Pressable, { onPress: onSendNow, hitSlop: 8, accessibilityRole: "button", accessibilityLabel: "Stop the current reply and send the queued messages now", style: [styles.action, styles.sendNow], children: /* @__PURE__ */ jsx(Text, { style: [styles.actionText, {
23
+ color: action
24
+ }], children: "Stop reply and send now" }) }) : null
25
+ ] });
26
+ }
27
+ const styles = StyleSheet.create({
28
+ container: {
29
+ paddingHorizontal: 12,
30
+ paddingBottom: 6,
31
+ alignItems: "flex-end"
32
+ },
33
+ item: {
34
+ alignItems: "flex-end",
35
+ marginBottom: 6,
36
+ maxWidth: "85%"
37
+ },
38
+ // The user's bubble, held back: queued reads as pending, not as delivered.
39
+ bubble: {
40
+ backgroundColor: USER_BUBBLE_BG,
41
+ borderRadius: 16,
42
+ paddingHorizontal: 12,
43
+ paddingVertical: 8,
44
+ opacity: 0.55
45
+ },
46
+ bubbleText: {
47
+ color: "#ffffff",
48
+ fontSize: 15,
49
+ lineHeight: 21
50
+ },
51
+ captionRow: {
52
+ flexDirection: "row",
53
+ alignItems: "center",
54
+ marginTop: 4
55
+ },
56
+ caption: {
57
+ fontSize: 11,
58
+ fontWeight: "500"
59
+ },
60
+ action: {
61
+ paddingHorizontal: 8,
62
+ paddingVertical: 2
63
+ },
64
+ actionText: {
65
+ fontSize: 12,
66
+ fontWeight: "600"
67
+ },
68
+ sendNow: {
69
+ marginTop: -2
70
+ }
71
+ });export{QueuedFollowUps};//# sourceMappingURL=QueuedFollowUps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueuedFollowUps.js","sources":["../../../src/features/chat/QueuedFollowUps.tsx"],"sourcesContent":["/**\n * Messages sent while the agent was busy, waiting their turn above the\n * composer - the way Claude Code shows a message typed mid-turn. Each reads as\n * the user's own bubble held back (the same look as a turn queued for the\n * gateway) and can be cancelled; \"Send now\" stops the running reply so the\n * agent takes them next. The gateway's own status words (a status answer, a\n * long-wait report) are posts in the thread, not repeated here.\n */\nimport React from 'react';\nimport { Pressable, StyleSheet, Text, View } from 'react-native';\nimport type { QueuedFollowUp } from '../../hooks/useChatStream';\nimport { USER_BUBBLE_BG } from './ChatTranscript';\n\nexport interface QueuedFollowUpsProps {\n items: QueuedFollowUp[];\n onCancel: (id: string) => void;\n onSendNow: () => void;\n isDark: boolean;\n}\n\nexport function QueuedFollowUps({ items, onCancel, onSendNow, isDark }: QueuedFollowUpsProps) {\n if (items.length === 0) return null;\n const muted = isDark ? '#94a3b8' : '#64748b';\n const action = isDark ? '#93c5fd' : '#2563eb';\n return (\n <View style={styles.container} testID=\"queued-follow-ups\">\n {items.map((item) => (\n <View key={item.id} style={styles.item}>\n <View style={styles.bubble}>\n <Text style={styles.bubbleText} numberOfLines={3}>\n {item.text}\n </Text>\n </View>\n <View style={styles.captionRow}>\n <Text style={[styles.caption, { color: muted }]}>\n Queued · answered after the current reply\n </Text>\n <Pressable\n onPress={() => onCancel(item.id)}\n hitSlop={8}\n accessibilityRole=\"button\"\n accessibilityLabel={`Cancel queued message: ${item.text}`}\n style={styles.action}\n >\n <Text style={[styles.actionText, { color: action }]}>Cancel</Text>\n </Pressable>\n </View>\n </View>\n ))}\n {items.length > 0 ? (\n <Pressable\n onPress={onSendNow}\n hitSlop={8}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Stop the current reply and send the queued messages now\"\n style={[styles.action, styles.sendNow]}\n >\n <Text style={[styles.actionText, { color: action }]}>Stop reply and send now</Text>\n </Pressable>\n ) : null}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n container: {\n paddingHorizontal: 12,\n paddingBottom: 6,\n alignItems: 'flex-end',\n },\n item: {\n alignItems: 'flex-end',\n marginBottom: 6,\n maxWidth: '85%',\n },\n // The user's bubble, held back: queued reads as pending, not as delivered.\n bubble: {\n backgroundColor: USER_BUBBLE_BG,\n borderRadius: 16,\n paddingHorizontal: 12,\n paddingVertical: 8,\n opacity: 0.55,\n },\n bubbleText: {\n color: '#ffffff',\n fontSize: 15,\n lineHeight: 21,\n },\n captionRow: {\n flexDirection: 'row',\n alignItems: 'center',\n marginTop: 4,\n },\n caption: {\n fontSize: 11,\n fontWeight: '500',\n },\n action: {\n paddingHorizontal: 8,\n paddingVertical: 2,\n },\n actionText: {\n fontSize: 12,\n fontWeight: '600',\n },\n sendNow: {\n marginTop: -2,\n },\n});\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ const WIDGET_FENCE = /```(?:yantra:widget|json)[^\S\n]*\n?([\s\S]*?)```/gi;
2
+ const OPEN_WIDGET_TAIL = /```(?:yantra:widget|json)[^\S\n]*\n?\s*\{\s*"propsComponent"[\s\S]*$/i;
3
+ const OPEN_YANTRA_WIDGET_TAIL = /```yantra:widget[\s\S]*$/i;
4
+ function toWidget(body) {
5
+ var _a, _b, _c;
6
+ let parsed;
7
+ try {
8
+ parsed = JSON.parse(body.trim());
9
+ } catch (e) {
10
+ return null;
11
+ }
12
+ if (!parsed || typeof parsed !== "object") return null;
13
+ const obj = parsed;
14
+ if (typeof obj.propsComponent !== "string" || !obj.propsComponent) return null;
15
+ const attachment = (_c = (_b = (_a = obj.propsConfiguration) == null ? void 0 : _a.contents) == null ? void 0 : _b.attachment) != null ? _c : obj.attachment;
16
+ if (!attachment || typeof attachment !== "object") return null;
17
+ return {
18
+ component: obj.propsComponent,
19
+ attachment
20
+ };
21
+ }
22
+ function splitChatWidgets(content, streaming = false) {
23
+ const widgets = [];
24
+ let text = content.replace(WIDGET_FENCE, (match, body) => {
25
+ const widget = toWidget(body);
26
+ if (!widget) return match;
27
+ widgets.push(widget);
28
+ return "";
29
+ });
30
+ if (streaming) {
31
+ text = text.replace(OPEN_WIDGET_TAIL, "").replace(OPEN_YANTRA_WIDGET_TAIL, "");
32
+ }
33
+ return {
34
+ text: text.replace(/\n{3,}/g, "\n\n").trim(),
35
+ widgets
36
+ };
37
+ }export{splitChatWidgets};//# sourceMappingURL=chatWidgets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chatWidgets.js","sources":["../../../src/features/chat/chatWidgets.ts"],"sourcesContent":["/**\n * Widget envelopes in an assistant reply, for the mobile main chat.\n *\n * Skills end a reply with a card envelope in a fenced block:\n *\n * ```yantra:widget (or ```json)\n * {\"propsComponent\":\"travel\",\"propsConfiguration\":{\"contents\":{\"attachment\":{…}}}}\n * ```\n *\n * The web chat turns that into a card (parseChatWidget). The mobile chat had no\n * parser, so the envelope rendered as a raw JSON code block, and while\n * streaming it grew in place character by character. This pulls every envelope\n * out of the text and returns what the thread should show instead.\n */\n\nexport interface ChatWidget {\n component: string;\n attachment: Record<string, unknown>;\n}\n\nexport interface ChatWidgetSplit {\n /** The reply with every widget envelope removed. */\n text: string;\n widgets: ChatWidget[];\n}\n\nconst WIDGET_FENCE = /```(?:yantra:widget|json)[^\\S\\n]*\\n?([\\s\\S]*?)```/gi;\n/** An envelope still streaming in: an opened widget fence with no closing fence yet. */\nconst OPEN_WIDGET_TAIL = /```(?:yantra:widget|json)[^\\S\\n]*\\n?\\s*\\{\\s*\"propsComponent\"[\\s\\S]*$/i;\n/** The same, before the JSON reaches the component key. */\nconst OPEN_YANTRA_WIDGET_TAIL = /```yantra:widget[\\s\\S]*$/i;\n\nfunction toWidget(body: string): ChatWidget | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(body.trim());\n } catch {\n return null;\n }\n if (!parsed || typeof parsed !== 'object') return null;\n const obj = parsed as {\n propsComponent?: unknown;\n propsConfiguration?: { contents?: { attachment?: unknown } };\n attachment?: unknown;\n };\n if (typeof obj.propsComponent !== 'string' || !obj.propsComponent) return null;\n // Canonical path, tolerating the flatter `attachment` the web parser also accepts.\n const attachment = obj.propsConfiguration?.contents?.attachment ?? obj.attachment;\n if (!attachment || typeof attachment !== 'object') return null;\n return { component: obj.propsComponent, attachment: attachment as Record<string, unknown> };\n}\n\nexport function splitChatWidgets(content: string, streaming = false): ChatWidgetSplit {\n const widgets: ChatWidget[] = [];\n let text = content.replace(WIDGET_FENCE, (match, body: string) => {\n const widget = toWidget(body);\n if (!widget) return match; // an ordinary ```json example stays in the answer\n widgets.push(widget);\n return '';\n });\n if (streaming) {\n // Hide an envelope that is still arriving rather than paint half of it.\n text = text.replace(OPEN_WIDGET_TAIL, '').replace(OPEN_YANTRA_WIDGET_TAIL, '');\n }\n return { text: text.replace(/\\n{3,}/g, '\\n\\n').trim(), widgets };\n}\n"],"names":[],"mappings":"AAwBA,MAAM,YAAe,GAAA,qDAAA;AAErB,MAAM,gBAAmB,GAAA,uEAAA;AAEzB,MAAM,uBAA0B,GAAA,2BAAA;AAChC,SAAS,SAAS,IAAiC,EAAA;AA7BnD,EAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA;AA8BE,EAAI,IAAA,MAAA;AACJ,EAAI,IAAA;AACF,IAAA,MAAA,GAAS,IAAK,CAAA,KAAA,CAAM,IAAK,CAAA,IAAA,EAAM,CAAA;AAAA,GACzB,CAAA,OAAA,CAAA,EAAA;AACN,IAAO,OAAA,IAAA;AAAA;AAET,EAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,UAAiB,OAAA,IAAA;AAClD,EAAA,MAAM,GAAM,GAAA,MAAA;AASZ,EAAA,IAAI,OAAO,GAAI,CAAA,cAAA,KAAmB,YAAY,CAAC,GAAA,CAAI,gBAAuB,OAAA,IAAA;AAE1E,EAAM,MAAA,UAAA,GAAA,CAAa,qBAAI,kBAAJ,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAwB,aAAxB,IAAkC,GAAA,MAAA,GAAA,EAAA,CAAA,UAAA,KAAlC,YAAgD,GAAI,CAAA,UAAA;AACvE,EAAA,IAAI,CAAC,UAAA,IAAc,OAAO,UAAA,KAAe,UAAiB,OAAA,IAAA;AAC1D,EAAO,OAAA;AAAA,IACL,WAAW,GAAI,CAAA,cAAA;AAAA,IACf;AAAA,GACF;AACF;AACgB,SAAA,gBAAA,CAAiB,OAAiB,EAAA,SAAA,GAAY,KAAwB,EAAA;AACpF,EAAA,MAAM,UAAwB,EAAC;AAC/B,EAAA,IAAI,OAAO,OAAQ,CAAA,OAAA,CAAQ,YAAc,EAAA,CAAC,OAAO,IAAiB,KAAA;AAChE,IAAM,MAAA,MAAA,GAAS,SAAS,IAAI,CAAA;AAC5B,IAAI,IAAA,CAAC,QAAe,OAAA,KAAA;AACpB,IAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AACnB,IAAO,OAAA,EAAA;AAAA,GACR,CAAA;AACD,EAAA,IAAI,SAAW,EAAA;AAEb,IAAA,IAAA,GAAO,KAAK,OAAQ,CAAA,gBAAA,EAAkB,EAAE,CAAE,CAAA,OAAA,CAAQ,yBAAyB,EAAE,CAAA;AAAA;AAE/E,EAAO,OAAA;AAAA,IACL,MAAM,IAAK,CAAA,OAAA,CAAQ,SAAW,EAAA,MAAM,EAAE,IAAK,EAAA;AAAA,IAC3C;AAAA,GACF;AACF"}
@@ -0,0 +1,207 @@
1
+ import {parseConnectorConnect,pickConnectorCredential,isSiteLoginRequest,vaultKindOf,autofillCardTitle,VAULT_FORM_KINDS,credentialVaultKind,CONNECTOR_CONNECT_WEB_RETURN_PATH,SITE_LOGIN_CONNECTOR,credentialSavedAt,autofillCardReason}from'common';export{displayConnectorConnectMessages,displayConnectorConnectText}from'common';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 VAULT_NEW_PATH = "/account/connectors/vault/new";
21
+ function pendingConnectorConnect(messages) {
22
+ for (let i = messages.length - 1; i >= 0; i -= 1) {
23
+ const msg = messages[i];
24
+ if (msg.role === "user") return null;
25
+ const payload = msg.role === "assistant" ? parseConnectorConnect(msg.content) : null;
26
+ if (payload) return {
27
+ payload,
28
+ messageIndex: i
29
+ };
30
+ }
31
+ return null;
32
+ }
33
+ function connectorConnectKey(pending) {
34
+ return `${pending.messageIndex}:${pending.payload.requestId}`;
35
+ }
36
+ function readableConnector(connector) {
37
+ const cleaned = connector.replace(/-app-[a-z0-9]+$/i, "").replace(/\s*\((?:app|api|oauth)\)\s*$/i, "").replace(/[_-]+/g, " ").trim();
38
+ return cleaned || connector;
39
+ }
40
+ function connectorConnectName(payload, connected = false) {
41
+ var _a;
42
+ if (payload.title) return payload.title;
43
+ if (isSiteLoginRequest(payload)) return ((_a = payload.form) == null ? void 0 : _a.site) ? `${payload.form.site} login` : "Website login";
44
+ const kind = vaultKindOf(payload.connector);
45
+ if (kind == null ? void 0 : kind.autofill) return autofillCardTitle(kind, connected);
46
+ return readableConnector(payload.connector);
47
+ }
48
+ function connectorConnectReason(payload, name, connected = false) {
49
+ var _a, _b;
50
+ if (payload.reason) return payload.reason;
51
+ if (isSiteLoginRequest(payload)) {
52
+ return `Save your ${(_b = (_a = payload.form) == null ? void 0 : _a.site) != null ? _b : "website"} sign-in to the vault so I can log in on your Computer.`;
53
+ }
54
+ const kind = vaultKindOf(payload.connector);
55
+ if (kind == null ? void 0 : kind.autofill) return autofillCardReason(kind, connected);
56
+ return `Connect ${name} to use it from this chat.`;
57
+ }
58
+ function connectorConnectTarget(payload) {
59
+ var _a, _b, _c, _d;
60
+ const kind = (_a = vaultKindOf(payload.connector)) == null ? void 0 : _a.id;
61
+ const siteLogin = kind === SITE_LOGIN_CONNECTOR;
62
+ return {
63
+ name: connectorConnectName(payload),
64
+ kind,
65
+ siteLogin,
66
+ site: siteLogin ? (_d = (_b = payload.form) == null ? void 0 : _b.site) != null ? _d : (_c = payload.form) == null ? void 0 : _c.loginUrl : void 0,
67
+ credentialId: payload.credentialId
68
+ };
69
+ }
70
+ const matchKey = (name) => (name != null ? name : "").toLowerCase().replace(/[^a-z0-9]/g, "");
71
+ function pickConnectorConnectCredential(rows, payload) {
72
+ const target = connectorConnectTarget(payload);
73
+ if (target.kind) return pickConnectorCredential(rows, target);
74
+ const tried = /* @__PURE__ */ new Set();
75
+ for (const name of [target.name, readableConnector(payload.connector)]) {
76
+ const key = matchKey(name);
77
+ if (key && !tried.has(key)) {
78
+ tried.add(key);
79
+ const hit = pickConnectorCredential(rows, __spreadProps(__spreadValues({}, target), {
80
+ name
81
+ }));
82
+ if (hit) return hit;
83
+ }
84
+ }
85
+ return void 0;
86
+ }
87
+ function connectorConnectActionLabel(payload, connected) {
88
+ var _a, _b;
89
+ if (connected) return "Update";
90
+ return (_b = (_a = vaultKindOf(payload.connector)) == null ? void 0 : _a.actionLabel) != null ? _b : "Connect";
91
+ }
92
+ function toQuery(params) {
93
+ return params.filter((entry) => {
94
+ var _a;
95
+ return Boolean((_a = entry[1]) == null ? void 0 : _a.trim());
96
+ }).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value.trim())}`).join("&");
97
+ }
98
+ const CONNECTORS_PATH = "/account/connectors";
99
+ function buildConnectorConnectUrl({
100
+ origin,
101
+ payload,
102
+ name,
103
+ credentialId,
104
+ projectId
105
+ }) {
106
+ var _a, _b, _c, _d, _e;
107
+ const base = origin.trim().replace(/\/+$/, "");
108
+ const kind = vaultKindOf(payload.connector);
109
+ if (kind == null ? void 0 : kind.autofill) {
110
+ const query = toQuery([["provider", kind.id], ["agent", (_a = payload.form) == null ? void 0 : _a.agentName], ["credentialId", credentialId], ["projectId", credentialId ? projectId : void 0], ["requestId", payload.requestId], ["returnTo", CONNECTOR_CONNECT_WEB_RETURN_PATH]]);
111
+ return `${base}${VAULT_NEW_PATH}?${query}`;
112
+ }
113
+ if (isSiteLoginRequest(payload)) {
114
+ const query = toQuery([["name", name], ["site", (_b = payload.form) == null ? void 0 : _b.site], ["loginUrl", (_c = payload.form) == null ? void 0 : _c.loginUrl], ["agent", (_d = payload.form) == null ? void 0 : _d.agentName], ["credentialId", credentialId], ["projectId", projectId], ["requestId", payload.requestId], ["returnTo", CONNECTOR_CONNECT_WEB_RETURN_PATH]]);
115
+ return `${base}${VAULT_NEW_PATH}?${query}`;
116
+ }
117
+ const aliases = ((_e = payload.aliases) != null ? _e : []).map((alias) => ["aliases", alias]);
118
+ return `${base}${CONNECTORS_PATH}?${toQuery([["connector", payload.connector], ...aliases, ["title", payload.title], ["credentialId", payload.credentialId], ["requestId", payload.requestId], ["returnTo", CONNECTOR_CONNECT_WEB_RETURN_PATH]])}`;
119
+ }
120
+ function credentialFingerprint(row) {
121
+ if (!(row == null ? void 0 : row.id)) return null;
122
+ return `${row.id}@${row.updatedAt == null ? "" : String(row.updatedAt)}`;
123
+ }
124
+ function snapshotConnectorCredentials(rows, targetId) {
125
+ const versions = {};
126
+ for (const row of rows) {
127
+ const fingerprint = credentialFingerprint(row);
128
+ if ((row == null ? void 0 : row.id) && fingerprint) versions[row.id] = fingerprint;
129
+ }
130
+ return {
131
+ versions,
132
+ targetId: targetId != null ? targetId : null
133
+ };
134
+ }
135
+ function decideConnectorConnectOutcome({
136
+ requestId,
137
+ handback,
138
+ before,
139
+ after,
140
+ kind
141
+ }) {
142
+ var _a, _b, _c, _d, _e, _f;
143
+ if (handback && (!handback.requestId || handback.requestId === requestId)) {
144
+ return {
145
+ kind: "connected",
146
+ credentialId: (_c = (_b = handback.credentialId) != null ? _b : (_a = after == null ? void 0 : after.match) == null ? void 0 : _a.id) != null ? _c : void 0
147
+ };
148
+ }
149
+ if (!before || !after) return {
150
+ kind: "unchanged"
151
+ };
152
+ const {
153
+ versions,
154
+ targetId
155
+ } = before;
156
+ const changed = (row) => {
157
+ const now = credentialFingerprint(row);
158
+ return Boolean(now && (row == null ? void 0 : row.id) && versions[row.id] !== now);
159
+ };
160
+ if (targetId) {
161
+ const target = after.rows.find((row) => (row == null ? void 0 : row.id) === targetId);
162
+ if ((target == null ? void 0 : target.status) === "active" && changed(target)) return {
163
+ kind: "connected",
164
+ credentialId: targetId
165
+ };
166
+ }
167
+ if (changed(after.match)) return {
168
+ kind: "connected",
169
+ credentialId: (_d = after.match.id) != null ? _d : void 0
170
+ };
171
+ const createdKind = kind && ((_e = VAULT_FORM_KINDS[kind]) == null ? void 0 : _e.autofill) ? kind : void 0;
172
+ const created = after.rows.filter((row) => Boolean((row == null ? void 0 : row.id) && row.status === "active" && !versions[row.id] && (!createdKind || credentialVaultKind(row) === createdKind)));
173
+ if (created.length === 1) return {
174
+ kind: "connected",
175
+ credentialId: (_f = created[0].id) != null ? _f : void 0
176
+ };
177
+ return {
178
+ kind: "unchanged"
179
+ };
180
+ }
181
+ const PARKED_HANDBACK_MAX_AGE_MS = 30 * 60 * 1e3;
182
+ function parkedHandbackCredential(rows, payload, credentialId, nowMs) {
183
+ var _a;
184
+ if (!credentialId) return null;
185
+ const row = rows.find((r) => (r == null ? void 0 : r.id) === credentialId && r.status === "active");
186
+ if (!row) return null;
187
+ const kind = vaultKindOf(payload.connector);
188
+ let fits;
189
+ if ((kind == null ? void 0 : kind.id) === SITE_LOGIN_CONNECTOR) {
190
+ fits = ((_a = pickConnectorCredential(rows, __spreadProps(__spreadValues({}, connectorConnectTarget(payload)), {
191
+ credentialId
192
+ }))) == null ? void 0 : _a.id) === credentialId;
193
+ } else if (kind) {
194
+ fits = credentialVaultKind(row) === kind.id;
195
+ } else {
196
+ fits = !credentialVaultKind(row);
197
+ }
198
+ if (!fits) return null;
199
+ const savedAt = credentialSavedAt(row);
200
+ return savedAt > 0 && nowMs - savedAt <= PARKED_HANDBACK_MAX_AGE_MS ? row : null;
201
+ }
202
+ function a11yActionLabel(actionLabel, name) {
203
+ const action = actionLabel.toLowerCase();
204
+ const subject = name.toLowerCase().replace(/^your\s+/, "");
205
+ if (action.endsWith(subject) || name.toLowerCase().startsWith(action)) return actionLabel;
206
+ return `${actionLabel} ${name}`;
207
+ }export{CONNECTORS_PATH,PARKED_HANDBACK_MAX_AGE_MS,VAULT_NEW_PATH,a11yActionLabel,buildConnectorConnectUrl,connectorConnectActionLabel,connectorConnectKey,connectorConnectName,connectorConnectReason,connectorConnectTarget,credentialFingerprint,decideConnectorConnectOutcome,parkedHandbackCredential,pendingConnectorConnect,pickConnectorConnectCredential,snapshotConnectorCredentials};//# sourceMappingURL=connectorConnect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connectorConnect.js","sources":["../../../src/features/chat/connectorConnect.ts"],"sourcesContent":["/**\n * The `[CONNECTOR_CONNECT]` card, mobile side.\n *\n * The marker and its replies are parsed by common's CONNECTOR_CONNECT_PROTOCOL,\n * the same module the web chat uses, so every marker shape the model drifts into\n * is read the same way on both. This file holds only what is specific to the\n * phone: which request is still waiting, the card's copy, the web page the card\n * opens (the phone cannot host the web's inline forms, so it opens them in an\n * in-app browser session), and how to tell, once that session ends, whether the\n * vault really changed.\n *\n * Host-only: this module imports `common`, which the federated surface remotes\n * must not bundle. A remote's chat gets its messages already cleaned\n * (displayConnectorConnectMessages) and its card as a host render prop.\n */\nimport {\n autofillCardReason,\n autofillCardTitle,\n CONNECTOR_CONNECT_WEB_RETURN_PATH,\n credentialSavedAt,\n credentialVaultKind,\n isSiteLoginRequest,\n parseConnectorConnect,\n pickConnectorCredential,\n SITE_LOGIN_CONNECTOR,\n VAULT_FORM_KINDS,\n vaultKindOf,\n type ConnectorConnectHandback,\n type ConnectorConnectPayload,\n type ConnectorConnectionTarget,\n type ConnectorCredentialListRow,\n type VaultFormKindId,\n} from 'common';\n\n/** How a transcript shows a thread with connect markers in it - shared with the web host's surface chat. */\nexport { displayConnectorConnectMessages, displayConnectorConnectText } from 'common';\n\n/** forms-stack's \"Save to vault\" page as the web app mounts it (AccountRoutes.AccountConnectorsVaultNew). */\nexport const VAULT_NEW_PATH = '/account/connectors/vault/new';\n\n/** A connect request still waiting on the user, and where it sits in the thread. */\nexport interface PendingConnectorConnect {\n payload: ConnectorConnectPayload;\n /** Index of the assistant message that carried the marker. */\n messageIndex: number;\n}\n\n/**\n * The connect request still awaiting an answer: the newest marker in the\n * assistant messages since the last user message. Any user message after it - the\n * `[CONNECTOR_CONNECTED:…]` / `[CONNECTOR_DECLINED:…]` reply the card sends, or\n * the user simply typing on - settles it, so a reloaded thread never brings back a\n * card that was already answered (the same rule as pendingAskUser).\n */\nexport function pendingConnectorConnect(\n messages: ReadonlyArray<{ role: string; content: string }>,\n): PendingConnectorConnect | null {\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n const msg = messages[i];\n if (msg.role === 'user') return null;\n const payload = msg.role === 'assistant' ? parseConnectorConnect(msg.content) : null;\n if (payload) return { payload, messageIndex: i };\n }\n return null;\n}\n\n/**\n * What a local \"answered\" mark is keyed on. The request id alone is not enough: a\n * marker that carries no id gets one derived from its text, so the same marker\n * repeated in a later turn has the same id, and keying on the id alone would hide\n * that new card too.\n */\nexport function connectorConnectKey(pending: PendingConnectorConnect): string {\n return `${pending.messageIndex}:${pending.payload.requestId}`;\n}\n\n/** A connector key as a readable name: `google-ads` -> `google ads` (the web's cleanup, minus the template lookup). */\nfunction readableConnector(connector: string): string {\n const cleaned = connector\n .replace(/-app-[a-z0-9]+$/i, '')\n .replace(/\\s*\\((?:app|api|oauth)\\)\\s*$/i, '')\n .replace(/[_-]+/g, ' ')\n .trim();\n return cleaned || connector;\n}\n\n/**\n * Card title, and the name a new site login is saved under: \"Amazon login\", \"amazon.com login\", \"openai\". An\n * autofill request the agent gave no title reads \"Add card\", or \"Update card\" once `connected` (the saved entry it\n * names is listed).\n */\nexport function connectorConnectName(payload: ConnectorConnectPayload, connected = false): string {\n if (payload.title) return payload.title;\n if (isSiteLoginRequest(payload)) return payload.form?.site ? `${payload.form.site} login` : 'Website login';\n const kind = vaultKindOf(payload.connector);\n if (kind?.autofill) return autofillCardTitle(kind, connected);\n return readableConnector(payload.connector);\n}\n\n/** The card's one line under the title; the agent's own reason wins. */\nexport function connectorConnectReason(payload: ConnectorConnectPayload, name: string, connected = false): string {\n if (payload.reason) return payload.reason;\n if (isSiteLoginRequest(payload)) {\n return `Save your ${payload.form?.site ?? 'website'} sign-in to the vault so I can log in on your Computer.`;\n }\n const kind = vaultKindOf(payload.connector);\n if (kind?.autofill) return autofillCardReason(kind, connected);\n return `Connect ${name} to use it from this chat.`;\n}\n\n/**\n * What the card looks for in the vault: the web card's target for the same request (common's\n * matchConnectorCredentials), minus the template's formId, which only the web can resolve. A site\n * login takes saved logins for its site only; the credential the agent named wins when it is one\n * of the org's and fits, else the most recently updated match - the row the agent signs in with.\n * An autofill request (a card, an address) takes only the entry of its kind the agent named, and\n * otherwise none: the card adds a new one.\n *\n * For a vault form kind this is the same target the web card builds, so the pick is the web's. For a\n * catalog connector it is only the card's status (\"Connected\" / \"Update\"): without the formId a\n * name-only match can take another connector's credential (\"Azure OpenAI\" for OpenAI) or miss one\n * saved under another name, so the phone never acts on it - the web page it opens picks (see\n * buildConnectorConnectUrl, and pickConnectorConnectCredential for the status).\n */\nexport function connectorConnectTarget(payload: ConnectorConnectPayload): Omit<ConnectorConnectionTarget, 'id'> {\n const kind = vaultKindOf(payload.connector)?.id;\n const siteLogin = kind === SITE_LOGIN_CONNECTOR;\n return {\n name: connectorConnectName(payload),\n kind,\n siteLogin,\n site: siteLogin ? (payload.form?.site ?? payload.form?.loginUrl) : undefined,\n credentialId: payload.credentialId,\n };\n}\n\n/** A name as the matcher compares it (common's matchConnectorCredentials): lower case, letters and digits only. */\nconst matchKey = (name: string | undefined) => (name ?? '').toLowerCase().replace(/[^a-z0-9]/g, '');\n\n/**\n * The saved credential the phone's card stands on for a request - \"Update\" when there is one, and the one the card\n * measures the browser session against - or undefined.\n *\n * A site login: common's pick on connectorConnectTarget, the web card's own target, so the very row the web card\n * and the agent use. A catalog connector: the web card also matches the template's formId, which the phone cannot\n * resolve, so a card titled \"OpenAI API key\" missed the \"OpenAI\" credential the web card finds by formId and showed\n * \"Connect\" where the web shows \"Update\". A credential saved from a template is named for it, so after the card\n * title the phone also looks under the connector the agent named (`openai`, `google-calendar` as \"google\n * calendar\"); the first name that matches wins. Only the phone's label and its after-the-session check rest on\n * this: the web page the card opens makes the pick it edits (buildConnectorConnectUrl).\n */\nexport function pickConnectorConnectCredential<T extends ConnectorCredentialListRow>(\n rows: ReadonlyArray<T | null | undefined>,\n payload: ConnectorConnectPayload,\n): T | undefined {\n const target = connectorConnectTarget(payload);\n // A vault form kind: the web card's own target, so the very row the web card edits (or none, for a new entry).\n if (target.kind) return pickConnectorCredential(rows, target);\n const tried = new Set<string>();\n for (const name of [target.name, readableConnector(payload.connector)]) {\n const key = matchKey(name);\n if (key && !tried.has(key)) {\n tried.add(key);\n const hit = pickConnectorCredential(rows, { ...target, name });\n if (hit) return hit;\n }\n }\n return undefined;\n}\n\n/** The primary action: a saved one is updated in place, a new one saved (\"Save login\", \"Add card\") or connected. */\nexport function connectorConnectActionLabel(payload: ConnectorConnectPayload, connected: boolean): string {\n if (connected) return 'Update';\n return vaultKindOf(payload.connector)?.actionLabel ?? 'Connect';\n}\n\n/** `a=1&b=2`, skipping empty values. Hand-rolled: React Native's URLSearchParams cannot be relied on. */\nfunction toQuery(params: ReadonlyArray<readonly [string, string | null | undefined]>): string {\n return params\n .filter((entry): entry is readonly [string, string] => Boolean(entry[1]?.trim()))\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value.trim())}`)\n .join('&');\n}\n\nexport interface ConnectorConnectUrlInput {\n /** The web app's origin (CLIENT_URL). */\n origin: string;\n payload: ConnectorConnectPayload;\n /** Card title; a site login is saved under it (an autofill entry is named after what it holds). */\n name: string;\n /**\n * A vault form kind only: update THIS saved entry in place (the card's \"Update\"); absent saves a new one. Never\n * sent for a catalog connector, whose page makes the pick itself (see buildConnectorConnectUrl).\n */\n credentialId?: string | null;\n /**\n * A vault form kind only: the project the vault form works in - for an update the project the entry LIVES in\n * (the form refuses to change an entry from any other project, and the card matches the whole org's), and for a\n * new login where it is saved. A new autofill entry is saved where the page's own default project is.\n */\n projectId?: string | null;\n}\n\n/** The web Connectors entry that resolves a connector to its template first (ConnectorsRedirect). */\nexport const CONNECTORS_PATH = '/account/connectors';\n\n/**\n * The web page the card opens.\n *\n * A site login opens forms-stack's \"Save to vault\" page. Given `credentialId` that\n * page UPDATES that credential (username / email and password alike) instead of\n * saving a duplicate next to it. `returnTo` sends it, once saved, to the web\n * return page that hands the credential id back to the app, and `requestId`\n * rides along so the hand-back names the request it answers.\n *\n * An autofill request (a card, an address, a passport) opens the same page with\n * its kind as `provider`, which picks the form's fields; `credentialId` (and the\n * entry's project) only when it updates the entry the agent named, since a new\n * entry is named after what it holds and saved to the page's default project.\n *\n * Any other connector opens the Connectors entry with the agent's `connector` and\n * `aliases` as they came, and the page there is the web card itself\n * (ConnectorCredentialEdit): it resolves them against the org's template pool with\n * the web card's own resolver (useCredentialTemplateByKey), so a display name like\n * \"Google Calendar\" or a drifted key reaches the same template on both, and then\n * makes the web card's pick with the template's formId - which saved credential is\n * this connector's, to update in place, or none, to connect a new one. The phone\n * cannot resolve that formId, so it sends no pick of its own: a name-only pick can be\n * another connector's credential (\"Azure OpenAI\" for OpenAI), which the form would\n * then overwrite, or miss one saved under another name and start a duplicate. Only\n * the agent's own `credentialId` rides along, as the hint the web card honours when\n * it fits. Once saved the page returns through the same return page as the vault\n * form, so the phone learns which credential it was.\n */\nexport function buildConnectorConnectUrl({\n origin,\n payload,\n name,\n credentialId,\n projectId,\n}: ConnectorConnectUrlInput): string {\n const base = origin.trim().replace(/\\/+$/, '');\n const kind = vaultKindOf(payload.connector);\n if (kind?.autofill) {\n const query = toQuery([\n ['provider', kind.id],\n ['agent', payload.form?.agentName],\n ['credentialId', credentialId],\n ['projectId', credentialId ? projectId : undefined],\n ['requestId', payload.requestId],\n ['returnTo', CONNECTOR_CONNECT_WEB_RETURN_PATH],\n ]);\n return `${base}${VAULT_NEW_PATH}?${query}`;\n }\n if (isSiteLoginRequest(payload)) {\n const query = toQuery([\n ['name', name],\n ['site', payload.form?.site],\n ['loginUrl', payload.form?.loginUrl],\n ['agent', payload.form?.agentName],\n ['credentialId', credentialId],\n ['projectId', projectId],\n ['requestId', payload.requestId],\n ['returnTo', CONNECTOR_CONNECT_WEB_RETURN_PATH],\n ]);\n return `${base}${VAULT_NEW_PATH}?${query}`;\n }\n const aliases = (payload.aliases ?? []).map((alias) => ['aliases', alias] as const);\n return `${base}${CONNECTORS_PATH}?${toQuery([\n ['connector', payload.connector],\n ...aliases,\n ['title', payload.title],\n ['credentialId', payload.credentialId],\n ['requestId', payload.requestId],\n ['returnTo', CONNECTOR_CONNECT_WEB_RETURN_PATH],\n ])}`;\n}\n\n/** A saved credential as the card reads it: the matched fields, its version (`updatedAt`) and where it lives. */\nexport type CredentialVersionRow = ConnectorCredentialListRow;\n\n/**\n * A saved credential's identity AND version. An update keeps the id but moves\n * `updatedAt`, so comparing these before and after the browser tells a real save\n * apart from a closed browser.\n */\nexport function credentialFingerprint(row: CredentialVersionRow | null | undefined): string | null {\n if (!row?.id) return null;\n return `${row.id}@${row.updatedAt == null ? '' : String(row.updatedAt)}`;\n}\n\n/** The vault as it stood when the browser opened: every credential's version, and the one being updated. */\nexport interface ConnectorConnectBefore {\n /** Credential id -> fingerprint, for every row the read returned. */\n versions: Record<string, string>;\n /** The credential the card opened the form ON (\"Update\"), if any. */\n targetId?: string | null;\n}\n\n/** Record the vault before the browser opens, so the check afterwards can tell what the session changed. */\nexport function snapshotConnectorCredentials(\n rows: ReadonlyArray<CredentialVersionRow | null | undefined>,\n targetId?: string | null,\n): ConnectorConnectBefore {\n const versions: Record<string, string> = {};\n for (const row of rows) {\n const fingerprint = credentialFingerprint(row);\n if (row?.id && fingerprint) versions[row.id] = fingerprint;\n }\n return { versions, targetId: targetId ?? null };\n}\n\nexport type ConnectorConnectOutcomeDecision =\n | { kind: 'connected'; credentialId?: string }\n /** Nothing changed in the vault: the card stays up, the agent is told nothing. */\n | { kind: 'unchanged' };\n\n/**\n * Whether the browser session produced a connection, and with which credential.\n *\n * 1. The session ended on the app's return URL: the vault page saved, and says\n * which credential. That is the answer, unless it names a different request.\n * 2. Otherwise (the person closed the browser, or the connector's page has no way\n * back to the app) the vault is read again and compared with `before`:\n * - the credential the form was opened ON has a newer version: updated in place\n * (found by id, so an edit that also renamed it still counts);\n * - the credential matching this request (formId / name) is new or newer;\n * - exactly one active credential appeared that was not there before: the\n * session created it, under whatever name the person gave it. For an\n * autofill request (`kind`) only an entry of that kind counts: the vault\n * page saves nothing else, and an entry is named after what it holds.\n * A credential some other flow merely touched is never taken, and a card never\n * claims a connection it cannot see.\n */\nexport function decideConnectorConnectOutcome({\n requestId,\n handback,\n before,\n after,\n kind,\n}: {\n requestId: string;\n handback: ConnectorConnectHandback | null;\n /** The vault before the browser opened; without it nothing but a hand-back counts. */\n before: ConnectorConnectBefore | null;\n /** The vault after the browser closed, re-read from the server; null when that read failed. */\n after: { rows: ReadonlyArray<CredentialVersionRow | null | undefined>; match: CredentialVersionRow | null } | null;\n /** The request's vault form kind (vaultKindOf its connector), if any. */\n kind?: VaultFormKindId;\n}): ConnectorConnectOutcomeDecision {\n if (handback && (!handback.requestId || handback.requestId === requestId)) {\n return { kind: 'connected', credentialId: handback.credentialId ?? after?.match?.id ?? undefined };\n }\n if (!before || !after) return { kind: 'unchanged' };\n const { versions, targetId } = before;\n const changed = (row: CredentialVersionRow | null | undefined): row is CredentialVersionRow => {\n const now = credentialFingerprint(row);\n return Boolean(now && row?.id && versions[row.id] !== now);\n };\n if (targetId) {\n const target = after.rows.find((row) => row?.id === targetId);\n if (target?.status === 'active' && changed(target)) return { kind: 'connected', credentialId: targetId };\n }\n if (changed(after.match)) return { kind: 'connected', credentialId: after.match.id ?? undefined };\n const createdKind = kind && VAULT_FORM_KINDS[kind]?.autofill ? kind : undefined;\n const created = after.rows.filter((row): row is CredentialVersionRow =>\n Boolean(\n row?.id &&\n row.status === 'active' &&\n !versions[row.id] &&\n (!createdKind || credentialVaultKind(row) === createdKind),\n ),\n );\n if (created.length === 1) return { kind: 'connected', credentialId: created[0].id ?? undefined };\n return { kind: 'unchanged' };\n}\n\n/**\n * How long after its save a hand-back that reached the app with no browser session waiting is still taken: the\n * session the app was killed during (Android kills it behind Custom Tabs, and the return page cold-starts it).\n */\nexport const PARKED_HANDBACK_MAX_AGE_MS = 30 * 60 * 1000;\n\n/**\n * The credential a PARKED hand-back names, when it may be taken as this request's answer; null otherwise.\n *\n * Anyone can open the app's scheme URL, and the vault snapshot the card took before the browser opened died with\n * the app, so \"the vault has it\" is not enough. The credential must be:\n * - an ACTIVE credential of the org (`rows` is a fresh read);\n * - one this request could have saved: for a site login, the login the card itself picks for the request with\n * that id named (its site or name; never another site's login or a catalog credential); for an autofill\n * request, an entry of its kind (a new one is named after what it holds, so nothing else can tie it to the\n * request); for a catalog connector, a connector credential, never a vault entry - the phone cannot resolve\n * the template, so a name alone cannot rule a connector credential in or out (see connectorConnectTarget);\n * - saved in the last PARKED_HANDBACK_MAX_AGE_MS, the stand-in for \"changed during the session\": every save on\n * the web page moves `updatedAt`, while an id lifted from anywhere else names a credential saved long ago.\n */\nexport function parkedHandbackCredential(\n rows: ReadonlyArray<CredentialVersionRow | null | undefined>,\n payload: ConnectorConnectPayload,\n credentialId: string | null | undefined,\n nowMs: number,\n): CredentialVersionRow | null {\n if (!credentialId) return null;\n const row = rows.find((r) => r?.id === credentialId && r.status === 'active');\n if (!row) return null;\n const kind = vaultKindOf(payload.connector);\n let fits: boolean;\n if (kind?.id === SITE_LOGIN_CONNECTOR) {\n fits = pickConnectorCredential(rows, { ...connectorConnectTarget(payload), credentialId })?.id === credentialId;\n } else if (kind) {\n fits = credentialVaultKind(row) === kind.id;\n } else {\n fits = !credentialVaultKind(row);\n }\n if (!fits) return null;\n const savedAt = credentialSavedAt(row);\n return savedAt > 0 && nowMs - savedAt <= PARKED_HANDBACK_MAX_AGE_MS ? row : null;\n}\n\n/** The primary action's accessibility label: the action, plus the card's name unless the action already says it. */\nexport function a11yActionLabel(actionLabel: string, name: string): string {\n const action = actionLabel.toLowerCase();\n const subject = name.toLowerCase().replace(/^your\\s+/, '');\n if (action.endsWith(subject) || name.toLowerCase().startsWith(action)) return actionLabel;\n return `${actionLabel} ${name}`;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import {Linking}from'react-native';import {parseConnectorConnectAppReturnUrl}from'common';const PARKED_HANDBACK_MAX_AGE_MS = 30 * 60 * 1e3;
2
+ const parked = /* @__PURE__ */ new Map();
3
+ const activeSessions = /* @__PURE__ */ new Set();
4
+ const listeners = /* @__PURE__ */ new Set();
5
+ let urlSubscription = null;
6
+ function parkConnectorConnectHandback(url, now = Date.now()) {
7
+ const handback = parseConnectorConnectAppReturnUrl(url);
8
+ if (!(handback == null ? void 0 : handback.requestId) || !handback.credentialId || activeSessions.has(handback.requestId)) return false;
9
+ parked.set(handback.requestId, {
10
+ handback,
11
+ at: now
12
+ });
13
+ listeners.forEach((listener) => listener());
14
+ return true;
15
+ }
16
+ function peekConnectorConnectHandback(requestId, now = Date.now()) {
17
+ const entry = parked.get(requestId);
18
+ if (!entry) return null;
19
+ if (now - entry.at > PARKED_HANDBACK_MAX_AGE_MS) {
20
+ parked.delete(requestId);
21
+ return null;
22
+ }
23
+ return entry.handback;
24
+ }
25
+ function takeConnectorConnectHandback(requestId, now = Date.now()) {
26
+ const handback = peekConnectorConnectHandback(requestId, now);
27
+ parked.delete(requestId);
28
+ return handback;
29
+ }
30
+ function beginConnectorConnectSession(requestId) {
31
+ activeSessions.add(requestId);
32
+ }
33
+ function endConnectorConnectSession(requestId) {
34
+ activeSessions.delete(requestId);
35
+ parked.delete(requestId);
36
+ }
37
+ function startListening() {
38
+ if (urlSubscription) return;
39
+ Linking.getInitialURL().then((url) => parkConnectorConnectHandback(url)).catch(() => void 0);
40
+ const subscription = Linking.addEventListener("url", ({
41
+ url
42
+ }) => {
43
+ parkConnectorConnectHandback(url);
44
+ });
45
+ urlSubscription = subscription != null ? subscription : {
46
+ remove: () => void 0
47
+ };
48
+ }
49
+ function subscribeConnectorConnectHandbacks(listener) {
50
+ startListening();
51
+ listeners.add(listener);
52
+ return () => {
53
+ listeners.delete(listener);
54
+ };
55
+ }export{PARKED_HANDBACK_MAX_AGE_MS,beginConnectorConnectSession,endConnectorConnectSession,parkConnectorConnectHandback,peekConnectorConnectHandback,subscribeConnectorConnectHandbacks,takeConnectorConnectHandback};//# sourceMappingURL=connectorConnectHandbacks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connectorConnectHandbacks.js","sources":["../../../src/features/chat/connectorConnectHandbacks.ts"],"sourcesContent":["/**\n * Connect hand-backs that reach the app outside a card's own browser session.\n *\n * A card opens the web vault page with `openAuthSessionAsync` and normally reads\n * the hand-back (`yantraapp://connector-connect?requestId=…&credentialId=…`) off\n * that call's result. On Android the in-app browser runs in Chrome Custom Tabs\n * with the app in the background, and the OS may kill the app there. The return\n * page then cold-starts it with the scheme URL, and no card is waiting: without\n * this, the save would never reach the agent, and the card, once back, would\n * already show the login as saved and take a later \"Update\" for no change.\n *\n * So the URL is parked here, keyed on the request it answers, until the card for\n * that request mounts and takes it (the card still checks the vault before it\n * believes it). The listener starts with the first card, which is enough: the\n * URL that launched the app stays readable through getInitialURL for the life of\n * the process. A URL for a request whose browser session is still open is left\n * to that session (on Android the same URL also arrives as a `url` event).\n */\nimport { Linking } from 'react-native';\nimport { parseConnectorConnectAppReturnUrl, type ConnectorConnectHandback } from 'common';\n\n/** A parked hand-back older than this is dropped: it belongs to a request long settled. */\nexport const PARKED_HANDBACK_MAX_AGE_MS = 30 * 60 * 1000;\n\nconst parked = new Map<string, { handback: ConnectorConnectHandback; at: number }>();\nconst activeSessions = new Set<string>();\nconst listeners = new Set<() => void>();\n/** The one app-wide Linking subscription, started by the first card (null until then). */\nlet urlSubscription: { remove: () => void } | null = null;\n\n/** Park the hand-back `url` carries, if it is one for a request no open session is waiting on. */\nexport function parkConnectorConnectHandback(url: string | null | undefined, now = Date.now()): boolean {\n const handback = parseConnectorConnectAppReturnUrl(url);\n if (!handback?.requestId || !handback.credentialId || activeSessions.has(handback.requestId)) return false;\n parked.set(handback.requestId, { handback, at: now });\n listeners.forEach((listener) => listener());\n return true;\n}\n\n/** The hand-back parked for `requestId`, if a fresh one is there; it stays parked (a stale one is dropped). */\nexport function peekConnectorConnectHandback(requestId: string, now = Date.now()): ConnectorConnectHandback | null {\n const entry = parked.get(requestId);\n if (!entry) return null;\n if (now - entry.at > PARKED_HANDBACK_MAX_AGE_MS) {\n parked.delete(requestId);\n return null;\n }\n return entry.handback;\n}\n\n/** Take (and forget) the hand-back parked for `requestId`, if a fresh one is there. */\nexport function takeConnectorConnectHandback(requestId: string, now = Date.now()): ConnectorConnectHandback | null {\n const handback = peekConnectorConnectHandback(requestId, now);\n parked.delete(requestId);\n return handback;\n}\n\n/** A card's browser session for `requestId` is open: its own result carries the hand-back. */\nexport function beginConnectorConnectSession(requestId: string): void {\n activeSessions.add(requestId);\n}\n\n/** The session ended; its result has been read, so anything parked for it meanwhile is stale. */\nexport function endConnectorConnectSession(requestId: string): void {\n activeSessions.delete(requestId);\n parked.delete(requestId);\n}\n\nfunction startListening(): void {\n if (urlSubscription) return;\n // Cold start: the hand-back that launched the app.\n Linking.getInitialURL()\n .then((url) => parkConnectorConnectHandback(url))\n .catch(() => undefined);\n // Warm: one that arrives while the app runs with no session waiting on it.\n const subscription: { remove: () => void } | undefined = Linking.addEventListener('url', ({ url }) => {\n parkConnectorConnectHandback(url);\n });\n urlSubscription = subscription ?? { remove: () => undefined };\n}\n\n/** Call `listener` whenever a hand-back is parked; starts listening for them on first use. */\nexport function subscribeConnectorConnectHandbacks(listener: () => void): () => void {\n startListening();\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\n/** Test seam: forget everything parked and every open session, and listen afresh (as a new process would). */\nexport function resetConnectorConnectHandbacksForTests(): void {\n parked.clear();\n activeSessions.clear();\n listeners.clear();\n urlSubscription?.remove();\n urlSubscription = null;\n}\n"],"names":[],"mappings":"0FAsBa,MAAA,0BAAA,GAA6B,KAAK,EAAK,GAAA;AACpD,MAAM,MAAA,uBAAa,GAGhB,EAAA;AACH,MAAM,cAAA,uBAAqB,GAAY,EAAA;AACvC,MAAM,SAAA,uBAAgB,GAAgB,EAAA;AAEtC,IAAI,eAEO,GAAA,IAAA;AAGJ,SAAS,4BAA6B,CAAA,GAAA,EAAgC,GAAM,GAAA,IAAA,CAAK,KAAgB,EAAA;AACtG,EAAM,MAAA,QAAA,GAAW,kCAAkC,GAAG,CAAA;AACtD,EAAI,IAAA,EAAC,QAAU,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAA,SAAA,CAAA,IAAa,CAAC,QAAA,CAAS,YAAgB,IAAA,cAAA,CAAe,GAAI,CAAA,QAAA,CAAS,SAAS,CAAA,EAAU,OAAA,KAAA;AACrG,EAAO,MAAA,CAAA,GAAA,CAAI,SAAS,SAAW,EAAA;AAAA,IAC7B,QAAA;AAAA,IACA,EAAI,EAAA;AAAA,GACL,CAAA;AACD,EAAU,SAAA,CAAA,OAAA,CAAQ,CAAY,QAAA,KAAA,QAAA,EAAU,CAAA;AACxC,EAAO,OAAA,IAAA;AACT;AAGO,SAAS,4BAA6B,CAAA,SAAA,EAAmB,GAAM,GAAA,IAAA,CAAK,KAAwC,EAAA;AACjH,EAAM,MAAA,KAAA,GAAQ,MAAO,CAAA,GAAA,CAAI,SAAS,CAAA;AAClC,EAAI,IAAA,CAAC,OAAc,OAAA,IAAA;AACnB,EAAI,IAAA,GAAA,GAAM,KAAM,CAAA,EAAA,GAAK,0BAA4B,EAAA;AAC/C,IAAA,MAAA,CAAO,OAAO,SAAS,CAAA;AACvB,IAAO,OAAA,IAAA;AAAA;AAET,EAAA,OAAO,KAAM,CAAA,QAAA;AACf;AAGO,SAAS,4BAA6B,CAAA,SAAA,EAAmB,GAAM,GAAA,IAAA,CAAK,KAAwC,EAAA;AACjH,EAAM,MAAA,QAAA,GAAW,4BAA6B,CAAA,SAAA,EAAW,GAAG,CAAA;AAC5D,EAAA,MAAA,CAAO,OAAO,SAAS,CAAA;AACvB,EAAO,OAAA,QAAA;AACT;AAGO,SAAS,6BAA6B,SAAyB,EAAA;AACpE,EAAA,cAAA,CAAe,IAAI,SAAS,CAAA;AAC9B;AAGO,SAAS,2BAA2B,SAAyB,EAAA;AAClE,EAAA,cAAA,CAAe,OAAO,SAAS,CAAA;AAC/B,EAAA,MAAA,CAAO,OAAO,SAAS,CAAA;AACzB;AACA,SAAS,cAAuB,GAAA;AAC9B,EAAA,IAAI,eAAiB,EAAA;AAErB,EAAQ,OAAA,CAAA,aAAA,EAAgB,CAAA,IAAA,CAAK,CAAO,GAAA,KAAA,4BAAA,CAA6B,GAAG,CAAC,CAAA,CAAE,KAAM,CAAA,MAAM,MAAS,CAAA;AAE5F,EAAA,MAAM,YAEU,GAAA,OAAA,CAAQ,gBAAiB,CAAA,KAAA,EAAO,CAAC;AAAA,IAC/C;AAAA,GACI,KAAA;AACJ,IAAA,4BAAA,CAA6B,GAAG,CAAA;AAAA,GACjC,CAAA;AACD,EAAA,eAAA,GAAkB,YAAgB,IAAA,IAAA,GAAA,YAAA,GAAA;AAAA,IAChC,QAAQ,MAAM;AAAA,GAChB;AACF;AAGO,SAAS,mCAAmC,QAAkC,EAAA;AACnF,EAAe,cAAA,EAAA;AACf,EAAA,SAAA,CAAU,IAAI,QAAQ,CAAA;AACtB,EAAA,OAAO,MAAM;AACX,IAAA,SAAA,CAAU,OAAO,QAAQ,CAAA;AAAA,GAC3B;AACF"}