@bikdotai/bik-component-library 0.0.868-beta.4 → 0.0.868-beta.5

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 (249) hide show
  1. package/dist/cjs/components/bik-copilot/BIKCopilot.js +2 -0
  2. package/dist/cjs/components/bik-copilot/BIKCopilot.js.map +1 -0
  3. package/dist/cjs/components/bik-copilot/ControlledCopilot.js +2 -0
  4. package/dist/cjs/components/bik-copilot/ControlledCopilot.js.map +1 -0
  5. package/dist/cjs/components/bik-copilot/ControlledCopilot.styled.js +27 -0
  6. package/dist/cjs/components/bik-copilot/ControlledCopilot.styled.js.map +1 -0
  7. package/dist/cjs/components/bik-copilot/CopilotBall.js +2 -0
  8. package/dist/cjs/components/bik-copilot/CopilotBall.js.map +1 -0
  9. package/dist/cjs/components/bik-copilot/CopilotBall.styled.js +42 -0
  10. package/dist/cjs/components/bik-copilot/CopilotBall.styled.js.map +1 -0
  11. package/dist/cjs/components/bik-copilot/CopilotFeedbackModal.js +2 -0
  12. package/dist/cjs/components/bik-copilot/CopilotFeedbackModal.js.map +1 -0
  13. package/dist/cjs/components/bik-copilot/CopilotFeedbackModal.styled.js +108 -0
  14. package/dist/cjs/components/bik-copilot/CopilotFeedbackModal.styled.js.map +1 -0
  15. package/dist/cjs/components/bik-copilot/CopilotPanel.js +2 -0
  16. package/dist/cjs/components/bik-copilot/CopilotPanel.js.map +1 -0
  17. package/dist/cjs/components/bik-copilot/CopilotPanel.styled.js +534 -0
  18. package/dist/cjs/components/bik-copilot/CopilotPanel.styled.js.map +1 -0
  19. package/dist/cjs/components/bik-copilot/copilotPlacement.js +2 -0
  20. package/dist/cjs/components/bik-copilot/copilotPlacement.js.map +1 -0
  21. package/dist/cjs/components/bik-copilot/copilotRegenerate.js +2 -0
  22. package/dist/cjs/components/bik-copilot/copilotRegenerate.js.map +1 -0
  23. package/dist/cjs/components/bik-copilot/services/copilotDb.js +2 -0
  24. package/dist/cjs/components/bik-copilot/services/copilotDb.js.map +1 -0
  25. package/dist/cjs/components/bik-copilot/services/copilotFeedbackClient.js +2 -0
  26. package/dist/cjs/components/bik-copilot/services/copilotFeedbackClient.js.map +1 -0
  27. package/dist/cjs/components/bik-copilot/services/copilotIcebreakersClient.js +2 -0
  28. package/dist/cjs/components/bik-copilot/services/copilotIcebreakersClient.js.map +1 -0
  29. package/dist/cjs/components/bik-copilot/services/copilotMessagesClient.js +2 -0
  30. package/dist/cjs/components/bik-copilot/services/copilotMessagesClient.js.map +1 -0
  31. package/dist/cjs/components/bik-copilot/services/copilotPageSession.js +2 -0
  32. package/dist/cjs/components/bik-copilot/services/copilotPageSession.js.map +1 -0
  33. package/dist/cjs/components/bik-copilot/services/copilotSseParser.js +7 -0
  34. package/dist/cjs/components/bik-copilot/services/copilotSseParser.js.map +1 -0
  35. package/dist/cjs/components/bik-copilot/services/copilotStreamClient.js +2 -0
  36. package/dist/cjs/components/bik-copilot/services/copilotStreamClient.js.map +1 -0
  37. package/dist/cjs/components/bik-copilot/useCopilotIcebreakers.js +2 -0
  38. package/dist/cjs/components/bik-copilot/useCopilotIcebreakers.js.map +1 -0
  39. package/dist/cjs/components/bik-copilot/useCopilotStreamChat.js +2 -0
  40. package/dist/cjs/components/bik-copilot/useCopilotStreamChat.js.map +1 -0
  41. package/dist/cjs/components/bik-copilot/useDraggableFloater.js +2 -0
  42. package/dist/cjs/components/bik-copilot/useDraggableFloater.js.map +1 -0
  43. package/dist/cjs/components/bik-copilot/utils/markdown.js +4 -0
  44. package/dist/cjs/components/bik-copilot/utils/markdown.js.map +1 -0
  45. package/dist/cjs/components/bik-copilot/utils/toolCtas.js +2 -0
  46. package/dist/cjs/components/bik-copilot/utils/toolCtas.js.map +1 -0
  47. package/dist/cjs/index.js +1 -1
  48. package/dist/esm/components/ProgressChecklist/ProgressChecklist.style.d.ts +24 -59
  49. package/dist/esm/components/QueryBuilder/components/Connectors/Connector.styled.d.ts +1 -4
  50. package/dist/esm/components/QueryBuilder/components/QueryBuilderNode/Property/PropertyNode.styled.d.ts +1 -4
  51. package/dist/esm/components/QueryBuilder/components/QueryBuilderNode/Property/PropertyNodeUIWrapper.styled.d.ts +3 -10
  52. package/dist/esm/components/QueryBuilder/components/QueryBuilderNodes.styled.d.ts +2 -7
  53. package/dist/esm/components/TablePagination/TablePagination.styled.d.ts +3 -8
  54. package/dist/esm/components/TablePagination/TablePaginationCard.d.ts +2 -4
  55. package/dist/esm/components/TypographyStyle.d.ts +62 -141
  56. package/dist/esm/components/WhatsAppTextEditor/AIRephrase.styled.d.ts +2 -5
  57. package/dist/esm/components/WhatsAppTextEditor/CustomEditor.styled.d.ts +7 -20
  58. package/dist/esm/components/WhatsAppTextEditor/WhatsAppTextEditorHeader.d.ts +1 -3
  59. package/dist/esm/components/access-token-troubleshoot-dialog/AccessTokenTroubleshootDialog.styles.d.ts +9 -26
  60. package/dist/esm/components/accordion/Accordion.style.d.ts +4 -10
  61. package/dist/esm/components/action-button/ActionButton.styled.d.ts +2 -5
  62. package/dist/esm/components/adbanner/Banner.styled.d.ts +20 -88
  63. package/dist/esm/components/add-variableV2/AddVariableBox.styled.d.ts +1 -4
  64. package/dist/esm/components/add-variableV2/AddVariableV2.styled.d.ts +4 -9
  65. package/dist/esm/components/agent-builder/AgentBuilder.styled.d.ts +186 -328
  66. package/dist/esm/components/agent-listing/AgentListing.styled.d.ts +49 -88
  67. package/dist/esm/components/alerts/Alert.styled.d.ts +5 -11
  68. package/dist/esm/components/analytics-card/AnalyticsCard.styled.d.ts +4 -8
  69. package/dist/esm/components/analytics-chips-and-dropdowns/CommonStyles.d.ts +18 -27
  70. package/dist/esm/components/analytics-chips-and-dropdowns/chart/ComparisonBarChart/ComparisonBarChart.styled.d.ts +11 -26
  71. package/dist/esm/components/analytics-chips-and-dropdowns/chart/FunnelChart/FunnelChart.styled.d.ts +11 -26
  72. package/dist/esm/components/analytics-chips-and-dropdowns/chart/HorizontalBarGraph/HorizontalGraph.styles.d.ts +2 -5
  73. package/dist/esm/components/analytics-chips-and-dropdowns/chart/LineChart/LineChart.styled.d.ts +5 -12
  74. package/dist/esm/components/analytics-chips-and-dropdowns/chart/StackedBarChart/StackedBarChart.styles.d.ts +3 -8
  75. package/dist/esm/components/analytics-chips-and-dropdowns/chart/VerticalBarAndLinearGraph/VerticalBarAndLinearGraph.styles.d.ts +6 -17
  76. package/dist/esm/components/analytics-chips-and-dropdowns/chart/VerticalBarGraph/VerticalGraph.styles.d.ts +2 -5
  77. package/dist/esm/components/analytics-chips-and-dropdowns/chart/heatmap/HeatMapStyled.d.ts +11 -28
  78. package/dist/esm/components/analytics-chips-and-dropdowns/chart/heatmap/HeatMapVertical.d.ts +1 -3
  79. package/dist/esm/components/analytics-chips-and-dropdowns/chart/linearChipGroupedChart/LinearChipGroupedChart.styled.d.ts +7 -18
  80. package/dist/esm/components/analytics-chips-and-dropdowns/chart/scoreBlock/ScoreBlock.styled.d.ts +7 -18
  81. package/dist/esm/components/avatar/Avatar.styled.d.ts +2 -4
  82. package/dist/esm/components/bik-chatbot/components/ChatWindow.d.ts +2 -4
  83. package/dist/esm/components/bik-copilot/BIKCopilot.d.ts +31 -0
  84. package/dist/esm/components/bik-copilot/BIKCopilot.js +118 -0
  85. package/dist/esm/components/bik-copilot/BIKCopilot.js.map +1 -0
  86. package/dist/esm/components/bik-copilot/ControlledCopilot.d.ts +14 -0
  87. package/dist/esm/components/bik-copilot/ControlledCopilot.js +174 -0
  88. package/dist/esm/components/bik-copilot/ControlledCopilot.js.map +1 -0
  89. package/dist/esm/components/bik-copilot/ControlledCopilot.styled.d.ts +7 -0
  90. package/dist/esm/components/bik-copilot/ControlledCopilot.styled.js +31 -0
  91. package/dist/esm/components/bik-copilot/ControlledCopilot.styled.js.map +1 -0
  92. package/dist/esm/components/bik-copilot/CopilotBall.d.ts +13 -0
  93. package/dist/esm/components/bik-copilot/CopilotBall.js +50 -0
  94. package/dist/esm/components/bik-copilot/CopilotBall.js.map +1 -0
  95. package/dist/esm/components/bik-copilot/CopilotBall.styled.d.ts +9 -0
  96. package/dist/esm/components/bik-copilot/CopilotBall.styled.js +46 -0
  97. package/dist/esm/components/bik-copilot/CopilotBall.styled.js.map +1 -0
  98. package/dist/esm/components/bik-copilot/CopilotFeedbackModal.d.ts +29 -0
  99. package/dist/esm/components/bik-copilot/CopilotFeedbackModal.js +73 -0
  100. package/dist/esm/components/bik-copilot/CopilotFeedbackModal.js.map +1 -0
  101. package/dist/esm/components/bik-copilot/CopilotFeedbackModal.styled.d.ts +12 -0
  102. package/dist/esm/components/bik-copilot/CopilotFeedbackModal.styled.js +122 -0
  103. package/dist/esm/components/bik-copilot/CopilotFeedbackModal.styled.js.map +1 -0
  104. package/dist/esm/components/bik-copilot/CopilotPanel.d.ts +9 -0
  105. package/dist/esm/components/bik-copilot/CopilotPanel.js +536 -0
  106. package/dist/esm/components/bik-copilot/CopilotPanel.js.map +1 -0
  107. package/dist/esm/components/bik-copilot/CopilotPanel.styled.d.ts +67 -0
  108. package/dist/esm/components/bik-copilot/CopilotPanel.styled.js +573 -0
  109. package/dist/esm/components/bik-copilot/CopilotPanel.styled.js.map +1 -0
  110. package/dist/esm/components/bik-copilot/copilotPlacement.d.ts +24 -0
  111. package/dist/esm/components/bik-copilot/copilotPlacement.js +38 -0
  112. package/dist/esm/components/bik-copilot/copilotPlacement.js.map +1 -0
  113. package/dist/esm/components/bik-copilot/copilotRegenerate.d.ts +22 -0
  114. package/dist/esm/components/bik-copilot/copilotRegenerate.js +6 -0
  115. package/dist/esm/components/bik-copilot/copilotRegenerate.js.map +1 -0
  116. package/dist/esm/components/bik-copilot/index.d.ts +19 -0
  117. package/dist/esm/components/bik-copilot/model.d.ts +804 -0
  118. package/dist/esm/components/bik-copilot/services/copilotDb.d.ts +90 -0
  119. package/dist/esm/components/bik-copilot/services/copilotDb.js +96 -0
  120. package/dist/esm/components/bik-copilot/services/copilotDb.js.map +1 -0
  121. package/dist/esm/components/bik-copilot/services/copilotFeedbackClient.d.ts +15 -0
  122. package/dist/esm/components/bik-copilot/services/copilotFeedbackClient.js +55 -0
  123. package/dist/esm/components/bik-copilot/services/copilotFeedbackClient.js.map +1 -0
  124. package/dist/esm/components/bik-copilot/services/copilotIcebreakersClient.d.ts +11 -0
  125. package/dist/esm/components/bik-copilot/services/copilotIcebreakersClient.js +54 -0
  126. package/dist/esm/components/bik-copilot/services/copilotIcebreakersClient.js.map +1 -0
  127. package/dist/esm/components/bik-copilot/services/copilotMessagesClient.d.ts +23 -0
  128. package/dist/esm/components/bik-copilot/services/copilotMessagesClient.js +78 -0
  129. package/dist/esm/components/bik-copilot/services/copilotMessagesClient.js.map +1 -0
  130. package/dist/esm/components/bik-copilot/services/copilotPageSession.d.ts +37 -0
  131. package/dist/esm/components/bik-copilot/services/copilotPageSession.js +35 -0
  132. package/dist/esm/components/bik-copilot/services/copilotPageSession.js.map +1 -0
  133. package/dist/esm/components/bik-copilot/services/copilotSseParser.d.ts +22 -0
  134. package/dist/esm/components/bik-copilot/services/copilotSseParser.js +52 -0
  135. package/dist/esm/components/bik-copilot/services/copilotSseParser.js.map +1 -0
  136. package/dist/esm/components/bik-copilot/services/copilotStreamClient.d.ts +35 -0
  137. package/dist/esm/components/bik-copilot/services/copilotStreamClient.js +110 -0
  138. package/dist/esm/components/bik-copilot/services/copilotStreamClient.js.map +1 -0
  139. package/dist/esm/components/bik-copilot/useCopilotIcebreakers.d.ts +17 -0
  140. package/dist/esm/components/bik-copilot/useCopilotIcebreakers.js +60 -0
  141. package/dist/esm/components/bik-copilot/useCopilotIcebreakers.js.map +1 -0
  142. package/dist/esm/components/bik-copilot/useCopilotStreamChat.d.ts +20 -0
  143. package/dist/esm/components/bik-copilot/useCopilotStreamChat.js +377 -0
  144. package/dist/esm/components/bik-copilot/useCopilotStreamChat.js.map +1 -0
  145. package/dist/esm/components/bik-copilot/useDraggableFloater.d.ts +9 -0
  146. package/dist/esm/components/bik-copilot/useDraggableFloater.js +118 -0
  147. package/dist/esm/components/bik-copilot/useDraggableFloater.js.map +1 -0
  148. package/dist/esm/components/bik-copilot/utils/markdown.d.ts +1 -0
  149. package/dist/esm/components/bik-copilot/utils/markdown.js +48 -0
  150. package/dist/esm/components/bik-copilot/utils/markdown.js.map +1 -0
  151. package/dist/esm/components/bik-copilot/utils/toolCtas.d.ts +6 -0
  152. package/dist/esm/components/bik-copilot/utils/toolCtas.js +27 -0
  153. package/dist/esm/components/bik-copilot/utils/toolCtas.js.map +1 -0
  154. package/dist/esm/components/bik-layout/BikSidebarV2/SidebarV2Styles.d.ts +18 -49
  155. package/dist/esm/components/bik-layout/CommonStyles.d.ts +28 -88
  156. package/dist/esm/components/bik-layout/SidebarStyles.d.ts +7 -17
  157. package/dist/esm/components/button/Button.styled.d.ts +2 -4
  158. package/dist/esm/components/button/themes.d.ts +2 -16
  159. package/dist/esm/components/buttonGroup/ButtonGroupStyle.d.ts +4 -9
  160. package/dist/esm/components/card-selection-modal/CardSelectionModal.styled.d.ts +2 -7
  161. package/dist/esm/components/card-selector/CardSelector.styled.d.ts +3 -8
  162. package/dist/esm/components/carousel-preview/CarouselPreview.style.d.ts +4 -9
  163. package/dist/esm/components/carousel-secondary/CarouselSecondary.style.d.ts +11 -23
  164. package/dist/esm/components/channel-playground/shell/TestingPlayground.style.d.ts +18 -74
  165. package/dist/esm/components/checkBox/CheckBox.styled.d.ts +4 -9
  166. package/dist/esm/components/checkList/CheckList.styled.d.ts +1 -4
  167. package/dist/esm/components/code-block/CodeBlock.styled.d.ts +20 -43
  168. package/dist/esm/components/colourInput/ColourInput.styled.d.ts +2 -7
  169. package/dist/esm/components/connected-app-dialog/ConnectedAppDialog.styled.d.ts +16 -49
  170. package/dist/esm/components/country-code-picker/CountryCodePicker.styled.d.ts +3 -8
  171. package/dist/esm/components/country-code-picker/CountryPicker.styled.d.ts +3 -8
  172. package/dist/esm/components/curtain/Curtain.styled.d.ts +5 -11
  173. package/dist/esm/components/custom-date-time/CustomDateTime.styled.d.ts +1 -4
  174. package/dist/esm/components/dashboard-review-popup/DashboardReviewPopUp.styled.d.ts +2 -7
  175. package/dist/esm/components/dashboard-review-popup/components/FiveStar.styled.d.ts +2 -7
  176. package/dist/esm/components/dashboard-review-popup/components/Form.styled.d.ts +7 -20
  177. package/dist/esm/components/data-source-panel/DataSourcePanel.style.d.ts +4 -13
  178. package/dist/esm/components/datePicker/DatePicker.styled.d.ts +15 -22
  179. package/dist/esm/components/datePicker/DatePickerWrapper.styled.d.ts +4 -8
  180. package/dist/esm/components/discount-modal/DiscountModal.styled.d.ts +6 -17
  181. package/dist/esm/components/discount-modal/DynamicCoupon/DynamicCoupon.styled.d.ts +8 -23
  182. package/dist/esm/components/dropdown/ChipDropdown.d.ts +2 -4
  183. package/dist/esm/components/dropdown/Common.styled.d.ts +6 -15
  184. package/dist/esm/components/dropdown/OpenedDropdown/components/OpennedDropdown.styled.d.ts +5 -12
  185. package/dist/esm/components/dropdown/OpenedDropdown/components/description/Description.styled.d.ts +2 -5
  186. package/dist/esm/components/dropdown/OpenedDropdown/components/menu/FreeFormMenu.styled.d.ts +1 -4
  187. package/dist/esm/components/dropdown/OpenedDropdown/components/menu/MenuList.styled.d.ts +4 -18
  188. package/dist/esm/components/dropdown/OpenedDropdown/components/multiSelect/MultiSelectDropdownBottomBar.styled.d.ts +1 -4
  189. package/dist/esm/components/dropdown-button/DropdownButton.style.d.ts +5 -9
  190. package/dist/esm/components/dual-icon-button/DualIconButton.styled.d.ts +5 -12
  191. package/dist/esm/components/file-uploader/FileUploaderStyle.d.ts +4 -9
  192. package/dist/esm/components/floating-action-button/FloatingActionButton.styles.d.ts +13 -24
  193. package/dist/esm/components/half-doughnut-chart/HalfDoughnutChart.styled.d.ts +10 -29
  194. package/dist/esm/components/icon-button/IconButton.styled.d.ts +2 -4
  195. package/dist/esm/components/input/Input.styled.d.ts +29 -114
  196. package/dist/esm/components/keywords-input/KeywordsInput.styled.d.ts +1 -4
  197. package/dist/esm/components/list-item/ListItem.styled.d.ts +2 -4
  198. package/dist/esm/components/list-item/themes.d.ts +1 -1
  199. package/dist/esm/components/modals/modal.styled.d.ts +7 -16
  200. package/dist/esm/components/multi-level-dropdown/MultiLevelDropdown.styled.d.ts +22 -60
  201. package/dist/esm/components/navigation-hyperlink/NavigationHyperlink.d.ts +1 -3
  202. package/dist/esm/components/pagination/Pagination.styled.d.ts +1 -4
  203. package/dist/esm/components/plans/DurationSelectorStyles.d.ts +1 -4
  204. package/dist/esm/components/plans/SubscriptionPlanSelector.d.ts +2 -6
  205. package/dist/esm/components/plans/SubscriptionPlanStyled.d.ts +4 -9
  206. package/dist/esm/components/postPicker/PostPicker.styled.d.ts +13 -43
  207. package/dist/esm/components/product-picker/ProductPicker.styled.d.ts +2 -7
  208. package/dist/esm/components/product-picker-v2/style.d.ts +25 -82
  209. package/dist/esm/components/progress-bar/ProgressBarComponent.d.ts +2 -5
  210. package/dist/esm/components/radioButton/RadioButton.styled.d.ts +3 -8
  211. package/dist/esm/components/radioList/RadioList.styled.d.ts +1 -4
  212. package/dist/esm/components/shimmer/ShimmerComponent/ShimmerStyled.d.ts +4 -9
  213. package/dist/esm/components/side-modal/SideModal.style.d.ts +12 -25
  214. package/dist/esm/components/spinner/Spinner.d.ts +2 -4
  215. package/dist/esm/components/states/StateComponent.styled.d.ts +9 -20
  216. package/dist/esm/components/stepper/Stepper.styled.d.ts +4 -10
  217. package/dist/esm/components/switch/Switch.d.ts +6 -12
  218. package/dist/esm/components/tabs/Tabs.styles.d.ts +9 -30
  219. package/dist/esm/components/tag/Tag.styled.d.ts +2 -4
  220. package/dist/esm/components/template-context-mapper/Badge/index.d.ts +2 -5
  221. package/dist/esm/components/template-context-mapper/modalElements/EditMediaV2.style.d.ts +5 -14
  222. package/dist/esm/components/template-context-mapper/modalElements/VariableConnector.d.ts +2 -4
  223. package/dist/esm/components/template-context-mapper/modalElements/VariableConnectorsPanel.d.ts +2 -7
  224. package/dist/esm/components/template-context-mapper/styles/TemplateAnalyticsStyles.d.ts +6 -24
  225. package/dist/esm/components/template-context-mapper/utils/TemplateConstants.d.ts +8 -16
  226. package/dist/esm/components/template-preview/EmailTemplatePreview.styled.d.ts +10 -23
  227. package/dist/esm/components/template-preview/RCS/RCSPreview.styled.d.ts +20 -70
  228. package/dist/esm/components/template-preview/SMS/SMSBubble.d.ts +2 -7
  229. package/dist/esm/components/template-preview/SmsTemplatePreview.styled.d.ts +10 -27
  230. package/dist/esm/components/template-preview/TemplatePreview.styled.d.ts +1 -4
  231. package/dist/esm/components/template-preview/WhatsApp/ChatHeader.style.d.ts +5 -16
  232. package/dist/esm/components/template-preview/WhatsApp/ChatUI.style.d.ts +11 -53
  233. package/dist/esm/components/template-preview/WhatsApp/ChatUiV2.d.ts +1 -3
  234. package/dist/esm/components/template-preview/WhatsApp/LimitedTimeOffer/LimitedTimeOffer.index.d.ts +3 -9
  235. package/dist/esm/components/template-preview/webpush/WebpushPreview.styled.d.ts +1 -4
  236. package/dist/esm/components/testimonial-card/TestimonialCard.style.d.ts +11 -30
  237. package/dist/esm/components/thumbnail/Thumbnail.styled.d.ts +2 -4
  238. package/dist/esm/components/toaster/Toaster.styled.d.ts +2 -4
  239. package/dist/esm/components/unsatisfactory-response-list/UnsatisfactoryCountIntentWiseModal.style.d.ts +1 -4
  240. package/dist/esm/components/unsatisfactory-response-list/UnsatisfactoryResponseList.style.d.ts +1 -4
  241. package/dist/esm/components/variable-picker-v3/styles.d.ts +6 -15
  242. package/dist/esm/components/vertical-full-screen-modal/styles.d.ts +6 -15
  243. package/dist/esm/components/whats-new/WhatsNew.styles.d.ts +7 -18
  244. package/dist/esm/editor/BikEditor.styles.d.ts +7 -18
  245. package/dist/esm/editor/extensions/editorDropdown.styles.d.ts +12 -47
  246. package/dist/esm/index.d.ts +1 -0
  247. package/dist/esm/index.js +820 -761
  248. package/dist/esm/index.js.map +1 -1
  249. package/package.json +3 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilotIcebreakersClient.js","sources":["../../../../../src/components/bik-copilot/services/copilotIcebreakersClient.ts"],"sourcesContent":["import {\n\tCopilotIcebreakersResult,\n\tFetchCopilotIcebreakersOptions,\n} from '../model';\n\n/** Default path of the ice-breaker endpoint. */\nexport const COPILOT_ICEBREAKERS_PATH = '/bik-ai/copilot-icebreakers';\n\n/** The `ApiResponse<T>` envelope every non-streaming BIK AI endpoint returns. */\ninterface ApiEnvelope<T> {\n\tsuccess?: boolean;\n\tdata?: T;\n\terrors?: { code?: string; message?: string }[];\n}\n\ninterface IcebreakersPayload {\n\tagent?: string;\n\troute?: string;\n\tpage_name?: string | null;\n\t/** Tolerated in case the endpoint switches to camelCase serialization. */\n\tpageName?: string | null;\n\ticebreakers?: string[];\n}\n\n/**\n * Fetches the suggested opening prompts for a route.\n *\n * A route with no knowledge file behind it returns an empty list, and the\n * backend is explicit that this is a success rather than a failure — so an empty\n * result must render as \"no chips\", never as an error.\n */\nexport const fetchCopilotIcebreakers = async ({\n\tbaseUrl,\n\tendpointPath = COPILOT_ICEBREAKERS_PATH,\n\theaders,\n\tauthToken,\n\tgetAuthToken,\n\tfetchImpl,\n\tagent,\n\troute,\n\tstoreId,\n\tsignal,\n}: FetchCopilotIcebreakersOptions): Promise<CopilotIcebreakersResult> => {\n\tconst url = `${baseUrl.replace(/\\/$/, '')}${endpointPath}`;\n\tconst token = getAuthToken ? await getAuthToken() : authToken;\n\tconst doFetch = fetchImpl ?? fetch;\n\n\tconst response = await doFetch(url, {\n\t\tmethod: 'POST',\n\t\theaders: {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t...(token ? { authorization: token } : {}),\n\t\t\t...headers,\n\t\t},\n\t\tbody: JSON.stringify({\n\t\t\tagent,\n\t\t\troute,\n\t\t\t...(storeId ? { store_id: storeId } : {}),\n\t\t}),\n\t\tsignal,\n\t});\n\n\tif (!response.ok) {\n\t\tconst detail = await response.text().catch(() => '');\n\t\tthrow new Error(\n\t\t\t`Ice-breaker request failed with ${response.status}${\n\t\t\t\tdetail ? `: ${detail}` : ''\n\t\t\t}`,\n\t\t);\n\t}\n\n\tconst envelope = (await response.json()) as ApiEnvelope<IcebreakersPayload>;\n\tif (envelope.success === false) {\n\t\tthrow new Error(\n\t\t\tenvelope.errors?.[0]?.message || 'Could not resolve icebreakers',\n\t\t);\n\t}\n\n\tconst payload = envelope.data ?? {};\n\treturn {\n\t\tagent: payload.agent ?? agent,\n\t\t// The backend returns the *normalized* route it matched, which can differ\n\t\t// from the one requested.\n\t\troute: payload.route ?? route,\n\t\tpageName: payload.page_name ?? payload.pageName ?? undefined,\n\t\ticebreakers: (payload.icebreakers ?? []).filter(\n\t\t\t(text): text is string => typeof text === 'string' && text.trim() !== '',\n\t\t),\n\t};\n};\n"],"names":["COPILOT_ICEBREAKERS_PATH","fetchCopilotIcebreakers","baseUrl","endpointPath","headers","authToken","getAuthToken","fetchImpl","agent","route","storeId","signal","url","token","response","detail","envelope","payload","text"],"mappings":"gFAMO,MAAMA,EAA2B,8BAyB3BC,EAA0B,MAAO,CAC7C,QAAAC,EACA,aAAAC,EAAeH,EACf,QAAAI,EACA,UAAAC,EACA,aAAAC,EACA,UAAAC,EACA,MAAAC,EACA,MAAAC,EACA,QAAAC,EACA,OAAAC,CACD,IAAyE,CACxE,MAAMC,EAAM,GAAGV,EAAQ,QAAQ,MAAO,EAAE,CAAC,GAAGC,CAAY,GAClDU,EAAQP,EAAe,MAAMA,EAAA,EAAiBD,EAG9CS,EAAW,MAFDP,GAAa,OAEEK,EAAK,CACnC,OAAQ,OACR,QAAS,CACR,eAAgB,mBAChB,GAAIC,EAAQ,CAAE,cAAeA,CAAA,EAAU,CAAA,EACvC,GAAGT,CAAA,EAEJ,KAAM,KAAK,UAAU,CACpB,MAAAI,EACA,MAAAC,EACA,GAAIC,EAAU,CAAE,SAAUA,GAAY,CAAA,CAAC,CACvC,EACD,OAAAC,CAAA,CACA,EAED,GAAI,CAACG,EAAS,GAAI,CACjB,MAAMC,EAAS,MAAMD,EAAS,OAAO,MAAM,IAAM,EAAE,EACnD,MAAM,IAAI,MACT,mCAAmCA,EAAS,MAAM,GACjDC,EAAS,KAAKA,CAAM,GAAK,EAC1B,EAAA,CAEF,CAEA,MAAMC,EAAY,MAAMF,EAAS,KAAA,EACjC,GAAIE,EAAS,UAAY,GACxB,MAAM,IAAI,MACTA,EAAS,SAAS,CAAC,GAAG,SAAW,+BAAA,EAInC,MAAMC,EAAUD,EAAS,MAAQ,CAAA,EACjC,MAAO,CACN,MAAOC,EAAQ,OAAST,EAGxB,MAAOS,EAAQ,OAASR,EACxB,SAAUQ,EAAQ,WAAaA,EAAQ,UAAY,OACnD,aAAcA,EAAQ,aAAe,CAAA,GAAI,OACvCC,GAAyB,OAAOA,GAAS,UAAYA,EAAK,SAAW,EAAA,CACvE,CAEF"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h="/bik-ai/copilot-messages",f=20,E=e=>e&&/user|merchant|human|staff/i.test(e)?"user":"assistant",T=e=>{if(typeof e=="number")return Number.isFinite(e)?e:0;if(typeof e=="string"&&e.trim().length>0){const s=Number(e);if(Number.isFinite(s))return s;const t=Date.parse(e);if(Number.isFinite(t))return t}return 0},P=(e,s)=>{const t=e.message_id,a=T(e.createdAt??e.created_at);return{id:t??`copilot-history-${a}-${s}`,role:E(e.owner),content:e.message??"",timestamp:a,...t?{messageId:t}:{}}},b=async({baseUrl:e,endpointPath:s=h,headers:t,authToken:a,getAuthToken:c,fetchImpl:u,storeId:d,sessionId:l,page:m=1,pageSize:p=f,signal:S})=>{const _=new URLSearchParams({store_id:d,session_id:l,page:String(m),page_size:String(p)}),O=`${e.replace(/\/$/,"")}${s}?${_.toString()}`,g=c?await c():a,n=await(u??fetch)(O,{method:"GET",headers:{"Content-Type":"application/json",...g?{authorization:g}:{},...t},signal:S});if(!n.ok){const r=await n.text().catch(()=>"");throw new Error(`Copilot history request failed with ${n.status}${r?`: ${r}`:""}`)}const i=await n.json();if(i.success===!1)throw new Error(i.errors?.[0]?.message||"Could not load the conversation history");const o=i.data??{};return{messages:(o.messages??[]).map(P).filter(r=>r.content.length>0).reverse().sort((r,y)=>r.timestamp-y.timestamp),page:o.page??m,pageSize:o.page_size??o.pageSize??p,hasMore:o.has_more??o.hasMore??!1}};exports.COPILOT_HISTORY_PAGE_SIZE=f;exports.COPILOT_MESSAGES_PATH=h;exports.fetchCopilotMessages=b;
2
+ //# sourceMappingURL=copilotMessagesClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilotMessagesClient.js","sources":["../../../../../src/components/bik-copilot/services/copilotMessagesClient.ts"],"sourcesContent":["import {\n\tCopilotMessage,\n\tCopilotMessagesPage,\n\tCopilotStoredMessageRow,\n\tFetchCopilotMessagesOptions,\n} from '../model';\n\n/** Default path of the stored-history endpoint. */\nexport const COPILOT_MESSAGES_PATH = '/bik-ai/copilot-messages';\n\n/**\n * How many messages one page holds — and, deliberately, the cap on what\n * IndexedDB keeps.\n *\n * The two are the same number on purpose: the local cache holds exactly what\n * page 1 would return, so the first scroll-up can ask for page 2 without an\n * overlap or a gap. Changing one without the other would tear the transcript.\n */\nexport const COPILOT_HISTORY_PAGE_SIZE = 20;\n\n/** The `ApiResponse<T>` envelope every non-streaming BIK AI endpoint returns. */\ninterface ApiEnvelope<T> {\n\tsuccess?: boolean;\n\tdata?: T;\n\terrors?: { code?: string; message?: string }[];\n}\n\ninterface MessagesPayload {\n\tmessages?: CopilotStoredMessageRow[];\n\tpage?: number;\n\tpage_size?: number;\n\tpageSize?: number;\n\thas_more?: boolean;\n\thasMore?: boolean;\n}\n\n/**\n * Maps the backend's `owner` onto the transcript's `role`.\n *\n * Read as a pattern rather than an exact enum member so a new owner the backend\n * adds lands on a sensible side instead of throwing. Anything that is not\n * recognisably the merchant renders as the assistant, because a mislabelled\n * assistant bubble reads better than a merchant one attributed to the AI.\n */\nconst roleOfOwner = (owner: string | undefined): CopilotMessage['role'] => {\n\tif (owner && /user|merchant|human|staff/i.test(owner)) {\n\t\treturn 'user';\n\t}\n\treturn 'assistant';\n};\n\n/**\n * Coerces a row's `created_at` to epoch millis for ordering.\n *\n * The field is declared as millis, but real responses have arrived as numeric\n * strings and ISO timestamps. Reading all three here keeps the transcript\n * ordered instead of silently falling back to the response order — which is\n * newest-first and would render upside down.\n */\nconst toTimestamp = (value: number | string | undefined): number => {\n\tif (typeof value === 'number') {\n\t\treturn Number.isFinite(value) ? value : 0;\n\t}\n\tif (typeof value === 'string' && value.trim().length > 0) {\n\t\tconst asNumber = Number(value);\n\t\tif (Number.isFinite(asNumber)) {\n\t\t\treturn asNumber;\n\t\t}\n\t\tconst asDate = Date.parse(value);\n\t\tif (Number.isFinite(asDate)) {\n\t\t\treturn asDate;\n\t\t}\n\t}\n\treturn 0;\n};\n\nconst toMessage = (\n\trow: CopilotStoredMessageRow,\n\tindex: number,\n): CopilotMessage => {\n\tconst messageId = row.message_id;\n\tconst timestamp = toTimestamp(row.createdAt ?? row.created_at);\n\treturn {\n\t\t// `message_id` is the server's own id, so a row cannot be prepended twice.\n\t\t// The index fallback only matters for a row that arrives without one.\n\t\tid: messageId ?? `copilot-history-${timestamp}-${index}`,\n\t\trole: roleOfOwner(row.owner),\n\t\tcontent: row.message ?? '',\n\t\ttimestamp,\n\t\t...(messageId ? { messageId } : {}),\n\t};\n};\n\n/**\n * Reads one page of a conversation's stored history.\n *\n * Page 1 is the newest `pageSize` messages and page 2 the ones before that, so\n * scrolling up walks the pages forward until `hasMore` goes false. Within a page\n * the messages come back oldest-first regardless of the order the backend used,\n * which is the order a transcript is rendered in.\n *\n * Rows with no text are dropped: a blank bubble is worse than a missing one.\n */\nexport const fetchCopilotMessages = async ({\n\tbaseUrl,\n\tendpointPath = COPILOT_MESSAGES_PATH,\n\theaders,\n\tauthToken,\n\tgetAuthToken,\n\tfetchImpl,\n\tstoreId,\n\tsessionId,\n\tpage = 1,\n\tpageSize = COPILOT_HISTORY_PAGE_SIZE,\n\tsignal,\n}: FetchCopilotMessagesOptions): Promise<CopilotMessagesPage> => {\n\tconst query = new URLSearchParams({\n\t\tstore_id: storeId,\n\t\tsession_id: sessionId,\n\t\tpage: String(page),\n\t\tpage_size: String(pageSize),\n\t});\n\tconst url = `${baseUrl.replace(\n\t\t/\\/$/,\n\t\t'',\n\t)}${endpointPath}?${query.toString()}`;\n\tconst token = getAuthToken ? await getAuthToken() : authToken;\n\tconst doFetch = fetchImpl ?? fetch;\n\n\tconst response = await doFetch(url, {\n\t\tmethod: 'GET',\n\t\theaders: {\n\t\t\t'Content-Type': 'application/json',\n\t\t\t...(token ? { authorization: token } : {}),\n\t\t\t...headers,\n\t\t},\n\t\tsignal,\n\t});\n\n\tif (!response.ok) {\n\t\tconst detail = await response.text().catch(() => '');\n\t\tthrow new Error(\n\t\t\t`Copilot history request failed with ${response.status}${\n\t\t\t\tdetail ? `: ${detail}` : ''\n\t\t\t}`,\n\t\t);\n\t}\n\n\tconst envelope = (await response.json()) as ApiEnvelope<MessagesPayload>;\n\tif (envelope.success === false) {\n\t\tthrow new Error(\n\t\t\tenvelope.errors?.[0]?.message ||\n\t\t\t\t'Could not load the conversation history',\n\t\t);\n\t}\n\n\tconst payload = envelope.data ?? {};\n\tconst messages = (payload.messages ?? [])\n\t\t.map(toMessage)\n\t\t.filter((message) => message.content.length > 0)\n\t\t// Render order is oldest-first. The endpoint serves each page newest-first\n\t\t// (page 1 is the newest page), so the base order is reversed first; the\n\t\t// stable sort then corrects any within-page disorder when the rows carry a\n\t\t// usable timestamp, and is a no-op when they do not — leaving the reversed,\n\t\t// oldest-first order intact instead of echoing the newest-first response.\n\t\t.reverse()\n\t\t.sort((left, right) => left.timestamp - right.timestamp);\n\n\treturn {\n\t\tmessages,\n\t\tpage: payload.page ?? page,\n\t\tpageSize: payload.page_size ?? payload.pageSize ?? pageSize,\n\t\thasMore: payload.has_more ?? payload.hasMore ?? false,\n\t};\n};\n"],"names":["COPILOT_MESSAGES_PATH","COPILOT_HISTORY_PAGE_SIZE","roleOfOwner","owner","toTimestamp","value","asNumber","asDate","toMessage","row","index","messageId","timestamp","fetchCopilotMessages","baseUrl","endpointPath","headers","authToken","getAuthToken","fetchImpl","storeId","sessionId","page","pageSize","signal","query","url","token","response","detail","envelope","payload","message","left","right"],"mappings":"gFAQO,MAAMA,EAAwB,2BAUxBC,EAA4B,GA0BnCC,EAAeC,GAChBA,GAAS,6BAA6B,KAAKA,CAAK,EAC5C,OAED,YAWFC,EAAeC,GAA+C,CACnE,GAAI,OAAOA,GAAU,SACpB,OAAO,OAAO,SAASA,CAAK,EAAIA,EAAQ,EAEzC,GAAI,OAAOA,GAAU,UAAYA,EAAM,KAAA,EAAO,OAAS,EAAG,CACzD,MAAMC,EAAW,OAAOD,CAAK,EAC7B,GAAI,OAAO,SAASC,CAAQ,EAC3B,OAAOA,EAER,MAAMC,EAAS,KAAK,MAAMF,CAAK,EAC/B,GAAI,OAAO,SAASE,CAAM,EACzB,OAAOA,CAET,CACA,MAAO,EACR,EAEMC,EAAY,CACjBC,EACAC,IACoB,CACpB,MAAMC,EAAYF,EAAI,WAChBG,EAAYR,EAAYK,EAAI,WAAaA,EAAI,UAAU,EAC7D,MAAO,CAGN,GAAIE,GAAa,mBAAmBC,CAAS,IAAIF,CAAK,GACtD,KAAMR,EAAYO,EAAI,KAAK,EAC3B,QAASA,EAAI,SAAW,GACxB,UAAAG,EACA,GAAID,EAAY,CAAE,UAAAA,GAAc,CAAA,CAAC,CAEnC,EAYaE,EAAuB,MAAO,CAC1C,QAAAC,EACA,aAAAC,EAAef,EACf,QAAAgB,EACA,UAAAC,EACA,aAAAC,EACA,UAAAC,EACA,QAAAC,EACA,UAAAC,EACA,KAAAC,EAAO,EACP,SAAAC,EAAWtB,EACX,OAAAuB,CACD,IAAiE,CAChE,MAAMC,EAAQ,IAAI,gBAAgB,CACjC,SAAUL,EACV,WAAYC,EACZ,KAAM,OAAOC,CAAI,EACjB,UAAW,OAAOC,CAAQ,CAAA,CAC1B,EACKG,EAAM,GAAGZ,EAAQ,QACtB,MACA,EAAA,CACA,GAAGC,CAAY,IAAIU,EAAM,UAAU,GAC9BE,EAAQT,EAAe,MAAMA,EAAA,EAAiBD,EAG9CW,EAAW,MAFDT,GAAa,OAEEO,EAAK,CACnC,OAAQ,MACR,QAAS,CACR,eAAgB,mBAChB,GAAIC,EAAQ,CAAE,cAAeA,CAAA,EAAU,CAAA,EACvC,GAAGX,CAAA,EAEJ,OAAAQ,CAAA,CACA,EAED,GAAI,CAACI,EAAS,GAAI,CACjB,MAAMC,EAAS,MAAMD,EAAS,OAAO,MAAM,IAAM,EAAE,EACnD,MAAM,IAAI,MACT,uCAAuCA,EAAS,MAAM,GACrDC,EAAS,KAAKA,CAAM,GAAK,EAC1B,EAAA,CAEF,CAEA,MAAMC,EAAY,MAAMF,EAAS,KAAA,EACjC,GAAIE,EAAS,UAAY,GACxB,MAAM,IAAI,MACTA,EAAS,SAAS,CAAC,GAAG,SACrB,yCAAA,EAIH,MAAMC,EAAUD,EAAS,MAAQ,CAAA,EAYjC,MAAO,CACN,UAZiBC,EAAQ,UAAY,CAAA,GACpC,IAAIvB,CAAS,EACb,OAAQwB,GAAYA,EAAQ,QAAQ,OAAS,CAAC,EAM9C,QAAA,EACA,KAAK,CAACC,EAAMC,IAAUD,EAAK,UAAYC,EAAM,SAAS,EAIvD,KAAMH,EAAQ,MAAQT,EACtB,SAAUS,EAAQ,WAAaA,EAAQ,UAAYR,EACnD,QAASQ,EAAQ,UAAYA,EAAQ,SAAW,EAAA,CAElD"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./copilotDb.js"),t=new Map,c=(o,e)=>`${o??""}:${e}`,a=({route:o,storeId:e})=>{const s=c(e,o),n=t.get(s);if(n)return n;const r=i.createCopilotSessionId();return t.set(s,r),r},d=async({route:o,storeId:e})=>{const s=c(e,o),n=t.get(s);if(n)return n;const l=await i.findLatestCopilotSessionId({route:o,storeId:e})??i.createCopilotSessionId();return t.set(s,l),l},p=({route:o,storeId:e})=>{const s=i.createCopilotSessionId();return t.set(c(e,o),s),s},u=()=>{t.clear()};exports.clearCopilotPageSessions=u;exports.getCopilotSessionIdForRoute=a;exports.resetCopilotSessionForRoute=p;exports.resolveCopilotSessionIdForRoute=d;
2
+ //# sourceMappingURL=copilotPageSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilotPageSession.js","sources":["../../../../../src/components/bik-copilot/services/copilotPageSession.ts"],"sourcesContent":["import {\n\tcreateCopilotSessionId,\n\tfindLatestCopilotSessionId,\n} from './copilotDb';\n\n/**\n * Registry of the session ids in play for the current page load.\n *\n * Module-level and in-memory, so **navigating away and back to the same route**\n * keeps the id and the copilot picks the conversation up where it was left.\n * Component state could not do this — the copilot unmounts on the way out.\n *\n * A **refresh** empties the registry, so the id has to be recovered from the\n * stored records instead: see `resolveCopilotSessionIdForRoute`, which reads the\n * route's most recent conversation out of IndexedDB before minting a new one.\n * That is what makes history survive a reload, and it is why the id must not be\n * regenerated per page load any more.\n *\n * The transcripts themselves live in IndexedDB under `{sessionId}:{route}`; this\n * registry only decides which of those keys the copilot reads.\n */\nconst routeSessionIds = new Map<string, string>();\n\n/**\n * Registry key.\n *\n * The store is part of it, and each entry gets its own session id rather than a\n * shared per-page one — otherwise two stores on the same route would resolve to\n * the same `{sessionId}:{route}` record and show each other's conversation.\n */\nconst registryKey = (storeId: string | undefined, route: string) =>\n\t`${storeId ?? ''}:${route}`;\n\n/**\n * The session id for a route in this page load, created on first use and stable\n * for the rest of the page load.\n */\nexport const getCopilotSessionIdForRoute = ({\n\troute,\n\tstoreId,\n}: {\n\troute: string;\n\tstoreId?: string;\n}): string => {\n\tconst key = registryKey(storeId, route);\n\tconst existing = routeSessionIds.get(key);\n\tif (existing) {\n\t\treturn existing;\n\t}\n\tconst sessionId = createCopilotSessionId();\n\trouteSessionIds.set(key, sessionId);\n\treturn sessionId;\n};\n\n/**\n * The session id for a route, resuming the stored conversation when this page\n * load has not seen the route yet.\n *\n * Order matters: the in-memory registry first, so a route already in play keeps\n * its id without a database read; then the most recent stored conversation, which\n * is how a refresh resumes; and only then a new id.\n *\n * Prefer this over `getCopilotSessionIdForRoute` anywhere persistence is on — the\n * synchronous version cannot see the stored records, so it always starts fresh.\n */\nexport const resolveCopilotSessionIdForRoute = async ({\n\troute,\n\tstoreId,\n}: {\n\troute: string;\n\tstoreId?: string;\n}): Promise<string> => {\n\tconst key = registryKey(storeId, route);\n\tconst inPlay = routeSessionIds.get(key);\n\tif (inPlay) {\n\t\treturn inPlay;\n\t}\n\n\tconst stored = await findLatestCopilotSessionId({ route, storeId });\n\tconst sessionId = stored ?? createCopilotSessionId();\n\t// Registered either way, so a second mount in this page load skips the read.\n\trouteSessionIds.set(key, sessionId);\n\treturn sessionId;\n};\n\n/**\n * Starts a new conversation for one route, leaving other routes untouched. The\n * new id sticks for the rest of the page load, so navigating away and back does\n * not resurrect the conversation the user just cleared.\n */\nexport const resetCopilotSessionForRoute = ({\n\troute,\n\tstoreId,\n}: {\n\troute: string;\n\tstoreId?: string;\n}): string => {\n\tconst sessionId = createCopilotSessionId();\n\trouteSessionIds.set(registryKey(storeId, route), sessionId);\n\treturn sessionId;\n};\n\n/**\n * Forgets every session id, as a reload would. Call it on logout or when the\n * signed-in user changes; tests use it to simulate a refresh.\n */\nexport const clearCopilotPageSessions = (): void => {\n\trouteSessionIds.clear();\n};\n"],"names":["routeSessionIds","registryKey","storeId","route","getCopilotSessionIdForRoute","key","existing","sessionId","createCopilotSessionId","resolveCopilotSessionIdForRoute","inPlay","findLatestCopilotSessionId","resetCopilotSessionForRoute","clearCopilotPageSessions"],"mappings":"kHAqBMA,MAAsB,IAStBC,EAAc,CAACC,EAA6BC,IACjD,GAAGD,GAAW,EAAE,IAAIC,CAAK,GAMbC,EAA8B,CAAC,CAC3C,MAAAD,EACA,QAAAD,CACD,IAGc,CACb,MAAMG,EAAMJ,EAAYC,EAASC,CAAK,EAChCG,EAAWN,EAAgB,IAAIK,CAAG,EACxC,GAAIC,EACH,OAAOA,EAER,MAAMC,EAAYC,EAAAA,uBAAA,EAClB,OAAAR,EAAgB,IAAIK,EAAKE,CAAS,EAC3BA,CACR,EAaaE,EAAkC,MAAO,CACrD,MAAAN,EACA,QAAAD,CACD,IAGuB,CACtB,MAAMG,EAAMJ,EAAYC,EAASC,CAAK,EAChCO,EAASV,EAAgB,IAAIK,CAAG,EACtC,GAAIK,EACH,OAAOA,EAIR,MAAMH,EADS,MAAMI,EAAAA,2BAA2B,CAAE,MAAAR,EAAO,QAAAD,EAAS,GACtCM,yBAAA,EAE5B,OAAAR,EAAgB,IAAIK,EAAKE,CAAS,EAC3BA,CACR,EAOaK,EAA8B,CAAC,CAC3C,MAAAT,EACA,QAAAD,CACD,IAGc,CACb,MAAMK,EAAYC,EAAAA,uBAAA,EAClB,OAAAR,EAAgB,IAAIC,EAAYC,EAASC,CAAK,EAAGI,CAAS,EACnDA,CACR,EAMaM,EAA2B,IAAY,CACnDb,EAAgB,MAAA,CACjB"}
@@ -0,0 +1,7 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class a{buffer="";push(n){this.buffer+=n;const t=[];let e=this.findBoundary();for(;e;){const r=this.buffer.slice(0,e.index);this.buffer=this.buffer.slice(e.index+e.length);const i=l(r);i!==null&&t.push(i),e=this.findBoundary()}return t}flush(){const n=this.buffer;this.buffer="";const t=l(n);return t===null?[]:[t]}findBoundary(){const n=this.buffer.indexOf(`
2
+
3
+ `),t=this.buffer.indexOf(`\r
4
+ \r
5
+ `);return t!==-1&&(n===-1||t<n)?{index:t,length:4}:n!==-1?{index:n,length:2}:null}}const l=s=>{const n=s.split(/\r?\n/).filter(e=>e.startsWith("data:")).map(e=>{const r=e.slice(5);return r.startsWith(" ")?r.slice(1):r});if(n.length===0)return null;const t=n.join(`
6
+ `).trim();return t.length===0?null:t};exports.CopilotSseParser=a;
7
+ //# sourceMappingURL=copilotSseParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilotSseParser.js","sources":["../../../../../src/components/bik-copilot/services/copilotSseParser.ts"],"sourcesContent":["/**\n * Incremental parser for the SSE frames emitted by `/bik-ai/copilot-bikchatbot`.\n *\n * The endpoint writes `data: {json}\\n\\n` frames and never sets an `event:` name\n * — the discriminator lives in the JSON payload's `type`. A chunk off the\n * network can split a frame anywhere, so the parser keeps a buffer between\n * calls and only yields frames it has seen terminated.\n */\nexport class CopilotSseParser {\n\tprivate buffer = '';\n\n\t/**\n\t * Feeds one network chunk in and returns every complete `data:` payload it\n\t * completed, as raw strings.\n\t */\n\tpush(chunk: string): string[] {\n\t\tthis.buffer += chunk;\n\t\tconst payloads: string[] = [];\n\n\t\t// Frames are separated by a blank line. \\r\\n\\r\\n is tolerated because\n\t\t// proxies rewrite line endings.\n\t\tlet boundary = this.findBoundary();\n\t\twhile (boundary) {\n\t\t\tconst frame = this.buffer.slice(0, boundary.index);\n\t\t\tthis.buffer = this.buffer.slice(boundary.index + boundary.length);\n\t\t\tconst payload = extractDataPayload(frame);\n\t\t\tif (payload !== null) {\n\t\t\t\tpayloads.push(payload);\n\t\t\t}\n\t\t\tboundary = this.findBoundary();\n\t\t}\n\n\t\treturn payloads;\n\t}\n\n\t/**\n\t * Returns any trailing frame left in the buffer when the stream ends without\n\t * a final blank line, then empties the buffer.\n\t */\n\tflush(): string[] {\n\t\tconst remaining = this.buffer;\n\t\tthis.buffer = '';\n\t\tconst payload = extractDataPayload(remaining);\n\t\treturn payload === null ? [] : [payload];\n\t}\n\n\tprivate findBoundary(): { index: number; length: number } | null {\n\t\tconst lf = this.buffer.indexOf('\\n\\n');\n\t\tconst crlf = this.buffer.indexOf('\\r\\n\\r\\n');\n\t\tif (crlf !== -1 && (lf === -1 || crlf < lf)) {\n\t\t\treturn { index: crlf, length: 4 };\n\t\t}\n\t\tif (lf !== -1) {\n\t\t\treturn { index: lf, length: 2 };\n\t\t}\n\t\treturn null;\n\t}\n}\n\n/**\n * Pulls the payload out of one SSE frame, joining multi-line `data:` fields the\n * way the SSE spec requires. Returns `null` for comment-only or empty frames.\n */\nconst extractDataPayload = (frame: string): string | null => {\n\tconst dataLines = frame\n\t\t.split(/\\r?\\n/)\n\t\t.filter((line) => line.startsWith('data:'))\n\t\t.map((line) => {\n\t\t\tconst value = line.slice('data:'.length);\n\t\t\t// A single leading space after the colon is part of the framing.\n\t\t\treturn value.startsWith(' ') ? value.slice(1) : value;\n\t\t});\n\n\tif (dataLines.length === 0) {\n\t\treturn null;\n\t}\n\tconst payload = dataLines.join('\\n').trim();\n\treturn payload.length === 0 ? null : payload;\n};\n"],"names":["CopilotSseParser","chunk","payloads","boundary","frame","payload","extractDataPayload","remaining","lf","crlf","dataLines","line","value"],"mappings":"gFAQO,MAAMA,CAAiB,CACrB,OAAS,GAMjB,KAAKC,EAAyB,CAC7B,KAAK,QAAUA,EACf,MAAMC,EAAqB,CAAA,EAI3B,IAAIC,EAAW,KAAK,aAAA,EACpB,KAAOA,GAAU,CAChB,MAAMC,EAAQ,KAAK,OAAO,MAAM,EAAGD,EAAS,KAAK,EACjD,KAAK,OAAS,KAAK,OAAO,MAAMA,EAAS,MAAQA,EAAS,MAAM,EAChE,MAAME,EAAUC,EAAmBF,CAAK,EACpCC,IAAY,MACfH,EAAS,KAAKG,CAAO,EAEtBF,EAAW,KAAK,aAAA,CACjB,CAEA,OAAOD,CACR,CAMA,OAAkB,CACjB,MAAMK,EAAY,KAAK,OACvB,KAAK,OAAS,GACd,MAAMF,EAAUC,EAAmBC,CAAS,EAC5C,OAAOF,IAAY,KAAO,CAAA,EAAK,CAACA,CAAO,CACxC,CAEQ,cAAyD,CAChE,MAAMG,EAAK,KAAK,OAAO,QAAQ;AAAA;AAAA,CAAM,EAC/BC,EAAO,KAAK,OAAO,QAAQ;AAAA;AAAA,CAAU,EAC3C,OAAIA,IAAS,KAAOD,IAAO,IAAMC,EAAOD,GAChC,CAAE,MAAOC,EAAM,OAAQ,CAAA,EAE3BD,IAAO,GACH,CAAE,MAAOA,EAAI,OAAQ,CAAA,EAEtB,IACR,CACD,CAMA,MAAMF,EAAsBF,GAAiC,CAC5D,MAAMM,EAAYN,EAChB,MAAM,OAAO,EACb,OAAQO,GAASA,EAAK,WAAW,OAAO,CAAC,EACzC,IAAKA,GAAS,CACd,MAAMC,EAAQD,EAAK,MAAM,CAAc,EAEvC,OAAOC,EAAM,WAAW,GAAG,EAAIA,EAAM,MAAM,CAAC,EAAIA,CACjD,CAAC,EAEF,GAAIF,EAAU,SAAW,EACxB,OAAO,KAER,MAAML,EAAUK,EAAU,KAAK;AAAA,CAAI,EAAE,KAAA,EACrC,OAAOL,EAAQ,SAAW,EAAI,KAAOA,CACtC"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("./copilotSseParser.js"),m="/bik-ai/copilot-chatbot",I=t=>({agent:t.agent,store_id:t.storeId,session_id:t.sessionId,route:t.route,user_query:t.userPrompt,...t.previousResponseId?{previous_response_id:t.previousResponseId}:{},...t.systemPrompt?{system_prompt:t.systemPrompt}:{}}),v=t=>{const{content:o}=t,s=typeof t.responseId=="string"?t.responseId:void 0;if(typeof o=="string")return{text:o,...s?{responseId:s}:{}};if(!o||typeof o!="object")return{text:"",...s?{responseId:s}:{}};const e=o,i=Array.isArray(e.followUps)?e.followUps.filter(r=>typeof r=="string"&&r.trim().length>0):void 0,l=Array.isArray(e.toolResults)?e.toolResults.filter(r=>!!r&&typeof r=="object"&&typeof r.tool=="string"):void 0,f=typeof e.reply=="string"?e.reply:typeof e.message=="string"?e.message:"",n=typeof e.lastResponseId=="string"?e.lastResponseId:s;return{text:f,...n?{responseId:n}:{},...i&&i.length>0?{followUps:i}:{},...l&&l.length>0?{toolResults:l}:{}}},P=t=>{try{const o=JSON.parse(t);if(typeof o!="object"||o===null)return null;const s=o;return s.type?s:null}catch{return null}},E=({baseUrl:t,endpointPath:o=m,headers:s,authToken:e,getAuthToken:i,fetchImpl:l,...f},n)=>{const r=new AbortController;return(async()=>{const d=`${t.replace(/\/$/,"")}${o}`,g=i?await i():e,y=await(l??fetch)(d,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...g?{authorization:g}:{},...s},body:JSON.stringify(I(f)),signal:r.signal});if(!y.ok){const a=await y.text().catch(()=>"");throw new Error(`Copilot request failed with ${y.status}${a?`: ${a}`:""}`)}if(!y.body)throw new Error("Copilot response carried no stream body");const C=y.body.getReader(),h=new w.CopilotSseParser;let u;const b=a=>{a.forEach(p=>{const c=P(p);c&&n.onEvent(c)})};for(;;){const{done:a,value:p}=await C.read();if(a)break;if(p===void 0)continue;let c;typeof p=="string"?c=p:(u=u??new TextDecoder,c=u.decode(p,{stream:!0})),b(h.push(c))}b(h.flush())})().then(()=>n.onComplete?.()).catch(d=>{if(r.signal.aborted){n.onAbort?.();return}n.onError?.(d instanceof Error?d:new Error(String(d)))}),()=>r.abort()};exports.COPILOT_ENDPOINT_PATH=m;exports.readCopilotEventContent=v;exports.streamCopilotChat=E;
2
+ //# sourceMappingURL=copilotStreamClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copilotStreamClient.js","sources":["../../../../../src/components/bik-copilot/services/copilotStreamClient.ts"],"sourcesContent":["import {\n\tCopilotAnswerPayload,\n\tCopilotStreamEvent,\n\tCopilotStreamHandlers,\n\tCopilotStreamRequest,\n\tCopilotToolResult,\n\tStreamCopilotChatOptions,\n} from '../model';\nimport { CopilotSseParser } from './copilotSseParser';\n\n/** Default path of the streaming copilot endpoint (`/bik-ai/copilot-chatbot`). */\nexport const COPILOT_ENDPOINT_PATH = '/bik-ai/copilot-chatbot';\n\nconst buildRequestBody = (request: CopilotStreamRequest) => ({\n\tagent: request.agent,\n\tstore_id: request.storeId,\n\tsession_id: request.sessionId,\n\troute: request.route,\n\t// The backend field is `user_query` (not `user_prompt`).\n\tuser_query: request.userPrompt,\n\t// Omitted on the first turn; from the second turn on it is the previous TEXT\n\t// event's `lastResponseId`, which is how OpenAI keeps the thread's context.\n\t...(request.previousResponseId\n\t\t? { previous_response_id: request.previousResponseId }\n\t\t: {}),\n\t// Overrides the assistant's server-side system prompt when present.\n\t...(request.systemPrompt ? { system_prompt: request.systemPrompt } : {}),\n});\n\n/**\n * Reads an event's `content`. `STREAM`/`ERROR` carry a bare string; `TEXT` wraps\n * `{ reply, pod, lastResponseId, toolResults }`.\n *\n * `text` prefers `reply`, falling back to the legacy `message`. `responseId`\n * (from `lastResponseId`) threads the next turn. Anything unrecognised reads as\n * empty text rather than throwing, so a shape the backend adds later cannot\n * break a turn that is otherwise fine.\n */\nexport const readCopilotEventContent = (\n\tevent: CopilotStreamEvent,\n): {\n\ttext: string;\n\tresponseId?: string;\n\tfollowUps?: string[];\n\ttoolResults?: CopilotToolResult[];\n} => {\n\tconst { content } = event;\n\t// Real backend puts the id inside the TEXT payload as `lastResponseId`; a\n\t// top-level `responseId` is read as a fallback so either shape threads.\n\tconst eventResponseId =\n\t\ttypeof event.responseId === 'string' ? event.responseId : undefined;\n\n\tif (typeof content === 'string') {\n\t\treturn {\n\t\t\ttext: content,\n\t\t\t...(eventResponseId ? { responseId: eventResponseId } : {}),\n\t\t};\n\t}\n\tif (!content || typeof content !== 'object') {\n\t\treturn {\n\t\t\ttext: '',\n\t\t\t...(eventResponseId ? { responseId: eventResponseId } : {}),\n\t\t};\n\t}\n\n\tconst payload = content as CopilotAnswerPayload;\n\n\tconst followUps = Array.isArray(payload.followUps)\n\t\t? payload.followUps.filter(\n\t\t\t\t(followUp): followUp is string =>\n\t\t\t\t\ttypeof followUp === 'string' && followUp.trim().length > 0,\n\t\t )\n\t\t: undefined;\n\n\t// Tool outputs (e.g. the support-portal link) ride on the TEXT payload as\n\t// well as their own TOOL_RESULT event, so the final message keeps them.\n\tconst toolResults = Array.isArray(payload.toolResults)\n\t\t? payload.toolResults.filter(\n\t\t\t\t(toolResult): toolResult is CopilotToolResult =>\n\t\t\t\t\t!!toolResult &&\n\t\t\t\t\ttypeof toolResult === 'object' &&\n\t\t\t\t\ttypeof (toolResult as CopilotToolResult).tool === 'string',\n\t\t )\n\t\t: undefined;\n\n\tconst text =\n\t\ttypeof payload.reply === 'string'\n\t\t\t? payload.reply\n\t\t\t: typeof payload.message === 'string'\n\t\t\t? payload.message\n\t\t\t: '';\n\n\tconst responseId =\n\t\ttypeof payload.lastResponseId === 'string'\n\t\t\t? payload.lastResponseId\n\t\t\t: eventResponseId;\n\n\treturn {\n\t\ttext,\n\t\t...(responseId ? { responseId } : {}),\n\t\t...(followUps && followUps.length > 0 ? { followUps } : {}),\n\t\t...(toolResults && toolResults.length > 0 ? { toolResults } : {}),\n\t};\n};\n\nconst parseEvent = (payload: string): CopilotStreamEvent | null => {\n\ttry {\n\t\tconst parsed = JSON.parse(payload) as unknown;\n\t\tif (typeof parsed !== 'object' || parsed === null) {\n\t\t\treturn null;\n\t\t}\n\t\tconst event = parsed as CopilotStreamEvent;\n\t\treturn event.type ? event : null;\n\t} catch {\n\t\t// A frame that is not JSON is not something this endpoint emits; dropping\n\t\t// it is better than tearing down a stream that is otherwise fine.\n\t\treturn null;\n\t}\n};\n\n/**\n * Opens one streaming copilot turn and drives the handlers until the server\n * closes the stream.\n *\n * The endpoint's `STOP` never reaches the client as a frame — the server breaks\n * out of its generator, which ends the HTTP stream. So \"the reader is done\" is\n * what completion means here, and `onComplete` fires from there.\n *\n * `TEXT` carries the **whole** message, so it is authoritative: a caller should\n * replace the text accumulated from `STREAM` chunks with it rather than append.\n * When a turn fails halfway the server still sends `TEXT` with the partial\n * answer but **without** `responseId` — that intentionally drops the thread, so\n * the next turn must start fresh.\n *\n * @returns a function that aborts the in-flight stream.\n */\nexport const streamCopilotChat = (\n\t{\n\t\tbaseUrl,\n\t\tendpointPath = COPILOT_ENDPOINT_PATH,\n\t\theaders,\n\t\tauthToken,\n\t\tgetAuthToken,\n\t\tfetchImpl,\n\t\t...request\n\t}: StreamCopilotChatOptions,\n\thandlers: CopilotStreamHandlers,\n): (() => void) => {\n\tconst abortController = new AbortController();\n\n\tconst run = async () => {\n\t\tconst url = `${baseUrl.replace(/\\/$/, '')}${endpointPath}`;\n\t\tconst token = getAuthToken ? await getAuthToken() : authToken;\n\t\tconst doFetch = fetchImpl ?? fetch;\n\n\t\tconst response = await doFetch(url, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\tAccept: 'text/event-stream',\n\t\t\t\t...(token ? { authorization: token } : {}),\n\t\t\t\t...headers,\n\t\t\t},\n\t\t\tbody: JSON.stringify(buildRequestBody(request)),\n\t\t\tsignal: abortController.signal,\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst detail = await response.text().catch(() => '');\n\t\t\tthrow new Error(\n\t\t\t\t`Copilot request failed with ${response.status}${\n\t\t\t\t\tdetail ? `: ${detail}` : ''\n\t\t\t\t}`,\n\t\t\t);\n\t\t}\n\t\tif (!response.body) {\n\t\t\tthrow new Error('Copilot response carried no stream body');\n\t\t}\n\n\t\tconst reader = response.body.getReader();\n\t\tconst parser = new CopilotSseParser();\n\t\tlet decoder: TextDecoder | undefined;\n\n\t\tconst dispatch = (payloads: string[]) => {\n\t\t\tpayloads.forEach((payload) => {\n\t\t\t\tconst event = parseEvent(payload);\n\t\t\t\tif (event) {\n\t\t\t\t\thandlers.onEvent(event);\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t// eslint-disable-next-line no-constant-condition\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (value === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Tests feed strings; the network feeds bytes.\n\t\t\tlet chunk: string;\n\t\t\tif (typeof value === 'string') {\n\t\t\t\tchunk = value;\n\t\t\t} else {\n\t\t\t\tdecoder = decoder ?? new TextDecoder();\n\t\t\t\tchunk = decoder.decode(value, { stream: true });\n\t\t\t}\n\t\t\tdispatch(parser.push(chunk));\n\t\t}\n\n\t\tdispatch(parser.flush());\n\t};\n\n\trun()\n\t\t.then(() => handlers.onComplete?.())\n\t\t.catch((error: unknown) => {\n\t\t\tif (abortController.signal.aborted) {\n\t\t\t\thandlers.onAbort?.();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\thandlers.onError?.(\n\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t);\n\t\t});\n\n\treturn () => abortController.abort();\n};\n"],"names":["COPILOT_ENDPOINT_PATH","buildRequestBody","request","readCopilotEventContent","event","content","eventResponseId","payload","followUps","followUp","toolResults","toolResult","text","responseId","parseEvent","parsed","streamCopilotChat","baseUrl","endpointPath","headers","authToken","getAuthToken","fetchImpl","handlers","abortController","url","token","response","detail","reader","parser","CopilotSseParser","decoder","dispatch","payloads","done","value","chunk","error"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react"),_=require("./services/copilotIcebreakersClient.js"),f="BIK_ASSISTANT_AGENT",g="campaigns/overview",m=({baseUrl:a,icebreakersPath:n,headers:d,authToken:p,getAuthToken:C,fetchImpl:O,agent:c=f,route:i=g,storeId:u,enabled:l=!0})=>{const[o,k]=t.useState(null),[A,s]=t.useState(!1),[E,T]=t.useState(),[I,L]=t.useState(0),b=t.useRef(null);t.useEffect(()=>{if(!l)return;const e=new AbortController;return b.current?.abort(),b.current=e,s(!0),T(void 0),_.fetchCopilotIcebreakers({baseUrl:a,endpointPath:n,headers:d,authToken:p,getAuthToken:C,fetchImpl:O,agent:c,route:i,storeId:u,signal:e.signal}).then(r=>{e.signal.aborted||(k(r),s(!1))}).catch(r=>{e.signal.aborted||(T(r instanceof Error?r.message:String(r)),s(!1))}),()=>e.abort()},[c,i,u,l,a,n,I]);const S=t.useCallback(()=>L(e=>e+1),[]);return{icebreakers:t.useMemo(()=>(o?.icebreakers??[]).map((e,r)=>({id:`copilot-icebreaker-${r}`,text:e})),[o]),pageName:o?.pageName,matchedRoute:o?.route,isLoading:A,error:E,refresh:S}};exports.DEFAULT_COPILOT_AGENT=f;exports.DEFAULT_COPILOT_ROUTE=g;exports.useCopilotIcebreakers=m;
2
+ //# sourceMappingURL=useCopilotIcebreakers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCopilotIcebreakers.js","sources":["../../../../src/components/bik-copilot/useCopilotIcebreakers.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n\tCopilotIcebreakersResult,\n\tUseCopilotIcebreakersOptions,\n\tUseCopilotIcebreakersResult,\n} from './model';\nimport { CopilotAgent } from './model';\nimport { fetchCopilotIcebreakers } from './services/copilotIcebreakersClient';\n\n/** The assistant persona the endpoints expect. */\nexport const DEFAULT_COPILOT_AGENT: CopilotAgent = 'BIK_ASSISTANT_AGENT';\n\n/**\n * Placeholder route. Replace it with the route the merchant is actually on —\n * the backend resolves both the ice breakers and the turn's page knowledge from\n * it, so a stale value means the copilot answers about the wrong page.\n */\nexport const DEFAULT_COPILOT_ROUTE = 'campaigns/overview';\n\n/**\n * Loads the suggested opening prompts for a route and maps them into the shape\n * the panel's suggestion chips take.\n *\n * Refetches whenever `agent` or `route` changes, so the chips follow the\n * merchant as they navigate, and aborts the in-flight request when they do.\n */\nexport const useCopilotIcebreakers = ({\n\tbaseUrl,\n\ticebreakersPath,\n\theaders,\n\tauthToken,\n\tgetAuthToken,\n\tfetchImpl,\n\tagent = DEFAULT_COPILOT_AGENT,\n\troute = DEFAULT_COPILOT_ROUTE,\n\tstoreId,\n\tenabled = true,\n}: UseCopilotIcebreakersOptions): UseCopilotIcebreakersResult => {\n\tconst [result, setResult] = useState<CopilotIcebreakersResult | null>(null);\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst [error, setError] = useState<string | undefined>();\n\tconst [reloadToken, setReloadToken] = useState(0);\n\n\tconst abortRef = useRef<AbortController | null>(null);\n\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst abortController = new AbortController();\n\t\tabortRef.current?.abort();\n\t\tabortRef.current = abortController;\n\n\t\tsetIsLoading(true);\n\t\tsetError(undefined);\n\n\t\tfetchCopilotIcebreakers({\n\t\t\tbaseUrl,\n\t\t\tendpointPath: icebreakersPath,\n\t\t\theaders,\n\t\t\tauthToken,\n\t\t\tgetAuthToken,\n\t\t\tfetchImpl,\n\t\t\tagent,\n\t\t\troute,\n\t\t\tstoreId,\n\t\t\tsignal: abortController.signal,\n\t\t})\n\t\t\t.then((fetched) => {\n\t\t\t\tif (abortController.signal.aborted) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsetResult(fetched);\n\t\t\t\tsetIsLoading(false);\n\t\t\t})\n\t\t\t.catch((fetchError: unknown) => {\n\t\t\t\tif (abortController.signal.aborted) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsetError(\n\t\t\t\t\tfetchError instanceof Error ? fetchError.message : String(fetchError),\n\t\t\t\t);\n\t\t\t\tsetIsLoading(false);\n\t\t\t});\n\n\t\treturn () => abortController.abort();\n\t\t// The transport options are stable config in practice; re-running on a new\n\t\t// inline `headers` object would refetch on every render.\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [agent, route, storeId, enabled, baseUrl, icebreakersPath, reloadToken]);\n\n\tconst refresh = useCallback(() => setReloadToken((token) => token + 1), []);\n\n\tconst icebreakers = useMemo(\n\t\t() =>\n\t\t\t(result?.icebreakers ?? []).map((text, index) => ({\n\t\t\t\tid: `copilot-icebreaker-${index}`,\n\t\t\t\ttext,\n\t\t\t})),\n\t\t[result],\n\t);\n\n\treturn {\n\t\ticebreakers,\n\t\tpageName: result?.pageName,\n\t\tmatchedRoute: result?.route,\n\t\tisLoading,\n\t\terror,\n\t\trefresh,\n\t};\n};\n"],"names":["DEFAULT_COPILOT_AGENT","DEFAULT_COPILOT_ROUTE","useCopilotIcebreakers","baseUrl","icebreakersPath","headers","authToken","getAuthToken","fetchImpl","agent","route","storeId","enabled","result","setResult","useState","isLoading","setIsLoading","error","setError","reloadToken","setReloadToken","abortRef","useRef","useEffect","abortController","fetchCopilotIcebreakers","fetched","fetchError","refresh","useCallback","token","useMemo","text","index"],"mappings":"6JAUaA,EAAsC,sBAOtCC,EAAwB,qBASxBC,EAAwB,CAAC,CACrC,QAAAC,EACA,gBAAAC,EACA,QAAAC,EACA,UAAAC,EACA,aAAAC,EACA,UAAAC,EACA,MAAAC,EAAQT,EACR,MAAAU,EAAQT,EACR,QAAAU,EACA,QAAAC,EAAU,EACX,IAAiE,CAChE,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAA0C,IAAI,EACpE,CAACC,EAAWC,CAAY,EAAIF,EAAAA,SAAS,EAAK,EAC1C,CAACG,EAAOC,CAAQ,EAAIJ,WAAA,EACpB,CAACK,EAAaC,CAAc,EAAIN,EAAAA,SAAS,CAAC,EAE1CO,EAAWC,EAAAA,OAA+B,IAAI,EAEpDC,EAAAA,UAAU,IAAM,CACf,GAAI,CAACZ,EACJ,OAGD,MAAMa,EAAkB,IAAI,gBAC5B,OAAAH,EAAS,SAAS,MAAA,EAClBA,EAAS,QAAUG,EAEnBR,EAAa,EAAI,EACjBE,EAAS,MAAS,EAElBO,0BAAwB,CACvB,QAAAvB,EACA,aAAcC,EACd,QAAAC,EACA,UAAAC,EACA,aAAAC,EACA,UAAAC,EACA,MAAAC,EACA,MAAAC,EACA,QAAAC,EACA,OAAQc,EAAgB,MAAA,CACxB,EACC,KAAME,GAAY,CACdF,EAAgB,OAAO,UAG3BX,EAAUa,CAAO,EACjBV,EAAa,EAAK,EACnB,CAAC,EACA,MAAOW,GAAwB,CAC3BH,EAAgB,OAAO,UAG3BN,EACCS,aAAsB,MAAQA,EAAW,QAAU,OAAOA,CAAU,CAAA,EAErEX,EAAa,EAAK,EACnB,CAAC,EAEK,IAAMQ,EAAgB,MAAA,CAI9B,EAAG,CAAChB,EAAOC,EAAOC,EAASC,EAAST,EAASC,EAAiBgB,CAAW,CAAC,EAE1E,MAAMS,EAAUC,EAAAA,YAAY,IAAMT,EAAgBU,GAAUA,EAAQ,CAAC,EAAG,EAAE,EAW1E,MAAO,CACN,YAVmBC,EAAAA,QACnB,KACEnB,GAAQ,aAAe,CAAA,GAAI,IAAI,CAACoB,EAAMC,KAAW,CACjD,GAAI,sBAAsBA,CAAK,GAC/B,KAAAD,CAAA,EACC,EACH,CAACpB,CAAM,CAAA,EAKP,SAAUA,GAAQ,SAClB,aAAcA,GAAQ,MACtB,UAAAG,EACA,MAAAE,EACA,QAAAW,CAAA,CAEF"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react"),Ie=require("./copilotRegenerate.js"),F=require("./services/copilotDb.js"),me=require("./services/copilotFeedbackClient.js"),re=require("./services/copilotMessagesClient.js"),z=require("./services/copilotPageSession.js"),U=require("./services/copilotStreamClient.js"),se=require("./useCopilotIcebreakers.js"),ne="Something went wrong. Please try again.",he=({storeId:l,agent:w=se.DEFAULT_COPILOT_AGENT,route:R=se.DEFAULT_COPILOT_ROUTE,messagesPath:X,feedbackPath:Y,user:Z,loadHistory:J=!0,systemPrompt:K,sessionId:g,persist:i=!0,onError:b,onResponseComplete:Q,onSessionIdChange:D,baseUrl:M,endpointPath:V,headers:O,authToken:P,getAuthToken:H,fetchImpl:_})=>{const[G,N]=s.useState([]),[oe,W]=s.useState(g??null),[T,y]=s.useState(!1),[ce,ee]=s.useState(!0),[ue,k]=s.useState(),[ae,le]=s.useState(),[ie,L]=s.useState(!1),[B,p]=s.useState(!1),f=s.useRef([]),$=s.useRef(void 0),I=s.useRef(null),u=s.useRef(null),m=s.useRef(g??null),q=s.useRef(R);q.current=R;const h=s.useRef(1),v=s.useRef(!1),a=s.useCallback(e=>{const t=e(f.current);f.current=t,N(t)},[]),E=s.useCallback(e=>{$.current=e,le(e)},[]),C=s.useCallback(()=>{const e=m.current;!i||!e||F.persistCopilotTurn({route:q.current,sessionId:e,messages:f.current,previousResponseId:$.current,storeId:l,agent:w})},[w,i,l]),x=s.useRef({baseUrl:M,messagesPath:X,feedbackPath:Y,headers:O,authToken:P,getAuthToken:H,fetchImpl:_,storeId:l,loadHistory:J,user:Z});x.current={baseUrl:M,messagesPath:X,feedbackPath:Y,headers:O,authToken:P,getAuthToken:H,fetchImpl:_,storeId:l,loadHistory:J,user:Z};const A=s.useCallback(async e=>{const t=x.current,r=m.current;return!t.loadHistory||!r?null:re.fetchCopilotMessages({baseUrl:t.baseUrl,endpointPath:t.messagesPath,headers:t.headers,authToken:t.authToken,getAuthToken:t.getAuthToken,fetchImpl:t.fetchImpl,storeId:t.storeId,sessionId:r,page:e,pageSize:re.COPILOT_HISTORY_PAGE_SIZE})},[]);s.useEffect(()=>{let e=!1;return(async()=>{u.current?.(),u.current=null,I.current=null,y(!1),k(void 0),ee(!0),p(!1),v.current=!1,L(!1);const r=g??(i?await z.resolveCopilotSessionIdForRoute({route:R,storeId:l}):z.getCopilotSessionIdForRoute({route:R,storeId:l})),n=i?await F.loadCopilotSession(R,r):null;if(!e){if(m.current=r,W(r),f.current=n?.messages??[],N(f.current),E(n?.previousResponseId),ee(!1),D?.(r),f.current.length>0){h.current=2,p(x.current.loadHistory);return}if(!g){h.current=1,p(!1);return}h.current=1;try{const o=await A(1);if(e||!o)return;h.current=2,a(()=>o.messages),p(o.hasMore)}catch{p(!1)}}})(),()=>{e=!0}},[R,l,g,i,E,a,A]);const fe=s.useCallback(()=>{if(v.current||!B)return;v.current=!0,L(!0);const e=h.current;(async()=>{try{const t=await A(e);if(!t){p(!1);return}h.current=e+1,p(t.hasMore),a(r=>{const n=new Set(r.flatMap(c=>c.messageId?[c.id,c.messageId]:[c.id])),o=t.messages.filter(c=>!n.has(c.id));return o.length>0?[...o,...r]:r})}catch(t){b?.(t instanceof Error?t:new Error(String(t)))}finally{v.current=!1,L(!1)}})()},[a,B,b,A]);s.useEffect(()=>{i&&F.pruneCopilotSessions()},[i]),s.useEffect(()=>()=>u.current?.(),[]);const S=s.useCallback(e=>{const t=I.current;I.current=null,t&&a(r=>r.map(n=>{if(n.id!==t)return n;const o={...n,isStreaming:!1};return e?e(o):o}).filter(n=>n.id!==t||n.content.length>0||n.wasInterrupted===!0))},[a]),te=s.useCallback(e=>{const t=I.current;if(e.type==="STREAM"){const r=U.readCopilotEventContent(e).text;if(!t||!r)return;a(n=>n.map(o=>o.id===t?{...o,content:o.content+r,messageId:e.messageId??o.messageId}:o));return}if(e.type==="TEXT"){const{text:r,followUps:n,toolResults:o,responseId:c}=U.readCopilotEventContent(e);S(d=>({...d,content:r,messageId:e.messageId??d.messageId,...n?{followUps:n}:{},...o?{toolResults:o}:{}})),E(c),C(),Q?.({text:r,responseId:c,followUps:n});return}e.type==="ERROR"&&(k(U.readCopilotEventContent(e).text||ne),S(),C())},[a,S,Q,C,E]),j=s.useCallback(e=>{const t=e.trim(),r=m.current;if(!t||!r||T)return;k(void 0);const n=Date.now(),o=`copilot-a-${n}`;I.current=o,a(c=>[...c,{id:`copilot-u-${n}`,role:"user",content:t,timestamp:n},{id:o,role:"assistant",content:"",timestamp:n+1,isStreaming:!0}]),y(!0),C(),u.current=U.streamCopilotChat({baseUrl:M,endpointPath:V,headers:O,authToken:P,getAuthToken:H,fetchImpl:_,storeId:l,agent:w,route:R,userPrompt:t,sessionId:r,previousResponseId:$.current,systemPrompt:K},{onEvent:te,onComplete:()=>{S(),y(!1),u.current=null,C()},onError:c=>{k(c.message||ne),S(),y(!1),u.current=null,C(),b?.(c)},onAbort:()=>{S(),y(!1),u.current=null,C()}})},[a,P,M,V,_,w,S,H,te,O,T,b,R,C,l,K]),de=s.useCallback(()=>{f.current.some(t=>t.role==="assistant"&&t.content.length>0)&&j(Ie.COPILOT_REGENERATE_PROMPT)},[j]),Re=s.useCallback((e,t,r)=>{const n=x.current,o=m.current;if(!o)return;const c=f.current.find(d=>(d.messageId??d.id)===e);me.sendCopilotFeedback({baseUrl:n.baseUrl,endpointPath:n.feedbackPath,headers:n.headers,authToken:n.authToken,getAuthToken:n.getAuthToken,fetchImpl:n.fetchImpl,storeId:n.storeId,sessionId:o,messageId:e,feedback:t,route:q.current,reply:c?.content,user:n.user,reasons:r?.reasons,comment:r?.comment}).catch(d=>{b?.(d instanceof Error?d:new Error(String(d)))})},[b]),pe=s.useCallback(()=>{if(!u.current)return;const e=I.current;e&&a(t=>t.map(r=>r.id===e?{...r,wasInterrupted:!0}:r)),u.current(),u.current=null},[a]),Ce=s.useCallback(()=>{u.current?.(),u.current=null,I.current=null,y(!1),k(void 0),h.current=1,v.current=!1,L(!1),p(!1);const e=q.current,t=m.current,r=g??z.resetCopilotSessionForRoute({route:e,storeId:l});m.current=r,W(r),f.current=[],N([]),E(void 0),i&&t&&F.deleteCopilotSession(e,t),D?.(r)},[D,i,g,E,l]),ge=s.useMemo(()=>T&&!G.some(e=>e.isStreaming&&e.content),[T,G]);return{messages:G,sessionId:oe,previousResponseId:ae,isStreaming:T,isThinking:ge,isRestoring:ce,isLoadingHistory:ie,hasMoreHistory:B,error:ue,sendMessage:j,regenerate:de,submitFeedback:Re,loadOlderMessages:fe,stopStreaming:pe,startNewConversation:Ce}};exports.useCopilotStreamChat=he;
2
+ //# sourceMappingURL=useCopilotStreamChat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCopilotStreamChat.js","sources":["../../../../src/components/bik-copilot/useCopilotStreamChat.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { COPILOT_REGENERATE_PROMPT } from './copilotRegenerate';\nimport {\n\tCopilotFeedbackDetail,\n\tCopilotFeedbackVote,\n\tCopilotMessage,\n\tCopilotStreamEvent,\n\tUseCopilotStreamChatOptions,\n\tUseCopilotStreamChatResult,\n} from './model';\nimport {\n\tdeleteCopilotSession,\n\tloadCopilotSession,\n\tpersistCopilotTurn,\n\tpruneCopilotSessions,\n} from './services/copilotDb';\nimport { sendCopilotFeedback } from './services/copilotFeedbackClient';\nimport {\n\tCOPILOT_HISTORY_PAGE_SIZE,\n\tfetchCopilotMessages,\n} from './services/copilotMessagesClient';\nimport {\n\tgetCopilotSessionIdForRoute,\n\tresetCopilotSessionForRoute,\n\tresolveCopilotSessionIdForRoute,\n} from './services/copilotPageSession';\nimport {\n\treadCopilotEventContent,\n\tstreamCopilotChat,\n} from './services/copilotStreamClient';\nimport {\n\tDEFAULT_COPILOT_AGENT,\n\tDEFAULT_COPILOT_ROUTE,\n} from './useCopilotIcebreakers';\n\nconst GENERIC_ERROR = 'Something went wrong. Please try again.';\n\n/**\n * Runs a merchant copilot conversation against the streaming\n * `/bik-ai/copilot-chatbot` endpoint.\n *\n * Owns three things the endpoint's contract requires:\n *\n * 1. **The session id.** One per route. Navigating away and back to the same\n * route continues that conversation, and so does a refresh: the ids live in\n * memory but are recovered from the stored records, which is what keeps them\n * lined up with the history the backend keys by them (see\n * `copilotPageSession`).\n * 2. **`previousResponseId`.** Absent on the first turn; from then on it is the\n * `responseId` of the last `TEXT` event, which is what makes OpenAI replay the\n * earlier turns server side. A turn that breaks halfway returns no\n * `responseId`, and the backend means that — the next turn starts fresh.\n * 3. **The transcript**, stored in IndexedDB under `{sessionId}:{route}` and\n * written every turn, so leaving the page mid-conversation loses nothing.\n */\nexport const useCopilotStreamChat = ({\n\tstoreId,\n\tagent = DEFAULT_COPILOT_AGENT,\n\troute = DEFAULT_COPILOT_ROUTE,\n\tmessagesPath,\n\tfeedbackPath,\n\tuser,\n\tloadHistory = true,\n\tsystemPrompt,\n\tsessionId: pinnedSessionId,\n\tpersist = true,\n\tonError,\n\tonResponseComplete,\n\tonSessionIdChange,\n\tbaseUrl,\n\tendpointPath,\n\theaders,\n\tauthToken,\n\tgetAuthToken,\n\tfetchImpl,\n}: UseCopilotStreamChatOptions): UseCopilotStreamChatResult => {\n\tconst [messages, setMessages] = useState<CopilotMessage[]>([]);\n\tconst [sessionId, setSessionId] = useState<string | null>(\n\t\tpinnedSessionId ?? null,\n\t);\n\tconst [isStreaming, setIsStreaming] = useState(false);\n\tconst [isRestoring, setIsRestoring] = useState(true);\n\tconst [error, setError] = useState<string | undefined>();\n\tconst [previousResponseId, setPreviousResponseId] = useState<\n\t\tstring | undefined\n\t>();\n\tconst [isLoadingHistory, setIsLoadingHistory] = useState(false);\n\tconst [hasMoreHistory, setHasMoreHistory] = useState(false);\n\n\t// Async stream handlers run long after the render that created them, so the\n\t// live values live in refs and state is only the render mirror.\n\tconst messagesRef = useRef<CopilotMessage[]>([]);\n\tconst previousResponseIdRef = useRef<string | undefined>(undefined);\n\tconst streamingIdRef = useRef<string | null>(null);\n\tconst abortRef = useRef<(() => void) | null>(null);\n\tconst sessionIdRef = useRef<string | null>(pinnedSessionId ?? null);\n\t// The active route, for the async handlers that write the transcript.\n\tconst routeRef = useRef<string>(route);\n\trouteRef.current = route;\n\t// Next page of stored history to ask for. Starts at 2 when the local cache\n\t// already holds page 1's worth, which is the steady state.\n\tconst nextHistoryPageRef = useRef(1);\n\tconst isLoadingHistoryRef = useRef(false);\n\n\tconst applyMessages = useCallback(\n\t\t(updater: (previous: CopilotMessage[]) => CopilotMessage[]) => {\n\t\t\tconst next = updater(messagesRef.current);\n\t\t\tmessagesRef.current = next;\n\t\t\tsetMessages(next);\n\t\t},\n\t\t[],\n\t);\n\n\tconst setThreadResponseId = useCallback((responseId: string | undefined) => {\n\t\tpreviousResponseIdRef.current = responseId;\n\t\tsetPreviousResponseId(responseId);\n\t}, []);\n\n\tconst save = useCallback(() => {\n\t\tconst id = sessionIdRef.current;\n\t\tif (!persist || !id) {\n\t\t\treturn;\n\t\t}\n\t\tvoid persistCopilotTurn({\n\t\t\troute: routeRef.current,\n\t\t\tsessionId: id,\n\t\t\tmessages: messagesRef.current,\n\t\t\tpreviousResponseId: previousResponseIdRef.current,\n\t\t\tstoreId,\n\t\t\tagent,\n\t\t});\n\t}, [agent, persist, storeId]);\n\n\t// Transport config for the async readers below. Held in a ref rather than in\n\t// the effect's deps: a host that passes an inline `headers` object would\n\t// otherwise re-run restore on every render and wipe the transcript.\n\tconst transportRef = useRef({\n\t\tbaseUrl,\n\t\tmessagesPath,\n\t\tfeedbackPath,\n\t\theaders,\n\t\tauthToken,\n\t\tgetAuthToken,\n\t\tfetchImpl,\n\t\tstoreId,\n\t\tloadHistory,\n\t\tuser,\n\t});\n\ttransportRef.current = {\n\t\tbaseUrl,\n\t\tmessagesPath,\n\t\tfeedbackPath,\n\t\theaders,\n\t\tauthToken,\n\t\tgetAuthToken,\n\t\tfetchImpl,\n\t\tstoreId,\n\t\tloadHistory,\n\t\tuser,\n\t};\n\n\tconst readHistoryPage = useCallback(async (page: number) => {\n\t\tconst transport = transportRef.current;\n\t\tconst id = sessionIdRef.current;\n\t\tif (!transport.loadHistory || !id) {\n\t\t\treturn null;\n\t\t}\n\t\treturn fetchCopilotMessages({\n\t\t\tbaseUrl: transport.baseUrl,\n\t\t\tendpointPath: transport.messagesPath,\n\t\t\theaders: transport.headers,\n\t\t\tauthToken: transport.authToken,\n\t\t\tgetAuthToken: transport.getAuthToken,\n\t\t\tfetchImpl: transport.fetchImpl,\n\t\t\tstoreId: transport.storeId,\n\t\t\tsessionId: id,\n\t\t\tpage,\n\t\t\tpageSize: COPILOT_HISTORY_PAGE_SIZE,\n\t\t});\n\t}, []);\n\n\t// Resolve the conversation for this route and read it back from IndexedDB.\n\t// Runs again when `route` changes, because the route is half of a\n\t// conversation's identity — a different page is a different chat.\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\n\t\tconst restore = async () => {\n\t\t\t// Chunks from the previous route's turn must not land in this one.\n\t\t\tabortRef.current?.();\n\t\t\tabortRef.current = null;\n\t\t\tstreamingIdRef.current = null;\n\t\t\tsetIsStreaming(false);\n\t\t\tsetError(undefined);\n\t\t\tsetIsRestoring(true);\n\t\t\tsetHasMoreHistory(false);\n\t\t\tisLoadingHistoryRef.current = false;\n\t\t\tsetIsLoadingHistory(false);\n\n\t\t\tconst id =\n\t\t\t\tpinnedSessionId ??\n\t\t\t\t(persist\n\t\t\t\t\t? await resolveCopilotSessionIdForRoute({ route, storeId })\n\t\t\t\t\t: getCopilotSessionIdForRoute({ route, storeId }));\n\t\t\tconst record = persist ? await loadCopilotSession(route, id) : null;\n\t\t\tif (cancelled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsessionIdRef.current = id;\n\t\t\tsetSessionId(id);\n\t\t\tmessagesRef.current = record?.messages ?? [];\n\t\t\tsetMessages(messagesRef.current);\n\t\t\tsetThreadResponseId(record?.previousResponseId);\n\t\t\tsetIsRestoring(false);\n\t\t\tonSessionIdChange?.(id);\n\n\t\t\t// The cache holds at most one page, so what is on screen already *is*\n\t\t\t// page 1 and the reader's first scroll-up wants page 2.\n\t\t\tif (messagesRef.current.length > 0) {\n\t\t\t\tnextHistoryPageRef.current = 2;\n\t\t\t\tsetHasMoreHistory(transportRef.current.loadHistory);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Nothing cached and nothing to scroll, so page 1 has to be fetched for\n\t\t\t// the history to be reachable at all — but only for an id the host\n\t\t\t// pinned. An id this library resolved came out of the local records, so\n\t\t\t// an empty cache for it means an empty conversation, and a freshly\n\t\t\t// minted one has nothing behind it by definition. Asking anyway would\n\t\t\t// put a pointless request on the start of every new conversation.\n\t\t\tif (!pinnedSessionId) {\n\t\t\t\tnextHistoryPageRef.current = 1;\n\t\t\t\tsetHasMoreHistory(false);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tnextHistoryPageRef.current = 1;\n\t\t\ttry {\n\t\t\t\tconst firstPage = await readHistoryPage(1);\n\t\t\t\tif (cancelled || !firstPage) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tnextHistoryPageRef.current = 2;\n\t\t\t\tapplyMessages(() => firstPage.messages);\n\t\t\t\tsetHasMoreHistory(firstPage.hasMore);\n\t\t\t} catch {\n\t\t\t\t// A session the backend has never heard of is the normal case for a\n\t\t\t\t// host-pinned id on its first use; the empty state covers it.\n\t\t\t\tsetHasMoreHistory(false);\n\t\t\t}\n\t\t};\n\n\t\tvoid restore();\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t\t// onSessionIdChange is event-like: re-running restore because the host\n\t\t// passed a new inline callback would wipe the transcript.\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [\n\t\troute,\n\t\tstoreId,\n\t\tpinnedSessionId,\n\t\tpersist,\n\t\tsetThreadResponseId,\n\t\tapplyMessages,\n\t\treadHistoryPage,\n\t]);\n\n\t/**\n\t * Prepends the page before the oldest message on screen.\n\t *\n\t * Guarded by a ref rather than the state flag because a scroll handler can\n\t * fire many times before React re-renders, and each of those would otherwise\n\t * start its own request for the same page.\n\t */\n\tconst loadOlderMessages = useCallback(() => {\n\t\tif (isLoadingHistoryRef.current || !hasMoreHistory) {\n\t\t\treturn;\n\t\t}\n\t\tisLoadingHistoryRef.current = true;\n\t\tsetIsLoadingHistory(true);\n\n\t\tconst page = nextHistoryPageRef.current;\n\t\tvoid (async () => {\n\t\t\ttry {\n\t\t\t\tconst older = await readHistoryPage(page);\n\t\t\t\tif (!older) {\n\t\t\t\t\tsetHasMoreHistory(false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tnextHistoryPageRef.current = page + 1;\n\t\t\t\tsetHasMoreHistory(older.hasMore);\n\t\t\t\tapplyMessages((previous) => {\n\t\t\t\t\tconst known = new Set(\n\t\t\t\t\t\tprevious.flatMap((message) =>\n\t\t\t\t\t\t\tmessage.messageId\n\t\t\t\t\t\t\t\t? [message.id, message.messageId]\n\t\t\t\t\t\t\t\t: [message.id],\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tconst fresh = older.messages.filter(\n\t\t\t\t\t\t(message) => !known.has(message.id),\n\t\t\t\t\t);\n\t\t\t\t\treturn fresh.length > 0 ? [...fresh, ...previous] : previous;\n\t\t\t\t});\n\t\t\t} catch (historyError) {\n\t\t\t\t// Left silent in the transcript on purpose: failing to reach further\n\t\t\t\t// back is not a failure of the conversation on screen. Another\n\t\t\t\t// scroll-up retries the same page.\n\t\t\t\tonError?.(\n\t\t\t\t\thistoryError instanceof Error\n\t\t\t\t\t\t? historyError\n\t\t\t\t\t\t: new Error(String(historyError)),\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tisLoadingHistoryRef.current = false;\n\t\t\t\tsetIsLoadingHistory(false);\n\t\t\t}\n\t\t})();\n\t}, [applyMessages, hasMoreHistory, onError, readHistoryPage]);\n\n\t// Records pile up one per route per page load otherwise, since every refresh\n\t// writes under a new key.\n\tuseEffect(() => {\n\t\tif (persist) {\n\t\t\tvoid pruneCopilotSessions();\n\t\t}\n\t}, [persist]);\n\n\t// Abort an in-flight turn if the copilot unmounts.\n\tuseEffect(() => () => abortRef.current?.(), []);\n\n\tconst finishStreamingBubble = useCallback(\n\t\t(mutate?: (message: CopilotMessage) => CopilotMessage) => {\n\t\t\tconst streamingId = streamingIdRef.current;\n\t\t\tstreamingIdRef.current = null;\n\t\t\tif (!streamingId) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tapplyMessages((previous) =>\n\t\t\t\tprevious\n\t\t\t\t\t.map((message) => {\n\t\t\t\t\t\tif (message.id !== streamingId) {\n\t\t\t\t\t\t\treturn message;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst settled: CopilotMessage = {\n\t\t\t\t\t\t\t...message,\n\t\t\t\t\t\t\tisStreaming: false,\n\t\t\t\t\t\t};\n\t\t\t\t\t\treturn mutate ? mutate(settled) : settled;\n\t\t\t\t\t})\n\t\t\t\t\t// An assistant bubble that never received text would render as an\n\t\t\t\t\t// empty balloon; the error banner carries the information instead.\n\t\t\t\t\t// A stopped turn keeps its bubble either way — the interrupted note\n\t\t\t\t\t// is the only trace a turn the reader cut short ever happened.\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t(message) =>\n\t\t\t\t\t\t\tmessage.id !== streamingId ||\n\t\t\t\t\t\t\tmessage.content.length > 0 ||\n\t\t\t\t\t\t\tmessage.wasInterrupted === true,\n\t\t\t\t\t),\n\t\t\t);\n\t\t},\n\t\t[applyMessages],\n\t);\n\n\tconst handleEvent = useCallback(\n\t\t(event: CopilotStreamEvent) => {\n\t\t\tconst streamingId = streamingIdRef.current;\n\n\t\t\tif (event.type === 'STREAM') {\n\t\t\t\tconst chunk = readCopilotEventContent(event).text;\n\t\t\t\tif (!streamingId || !chunk) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tapplyMessages((previous) =>\n\t\t\t\t\tprevious.map((message) =>\n\t\t\t\t\t\tmessage.id === streamingId\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t...message,\n\t\t\t\t\t\t\t\t\tcontent: message.content + chunk,\n\t\t\t\t\t\t\t\t\tmessageId: event.messageId ?? message.messageId,\n\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t: message,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (event.type === 'TEXT') {\n\t\t\t\t// TEXT carries the whole message, so it replaces the accumulated\n\t\t\t\t// chunks rather than appending — that keeps the bubble correct even if\n\t\t\t\t// a STREAM frame was dropped or duplicated. `responseId` rides inside\n\t\t\t\t// the content payload (as `lastResponseId`).\n\t\t\t\tconst {\n\t\t\t\t\ttext: fullText,\n\t\t\t\t\tfollowUps,\n\t\t\t\t\ttoolResults,\n\t\t\t\t\tresponseId,\n\t\t\t\t} = readCopilotEventContent(event);\n\t\t\t\tfinishStreamingBubble((message) => ({\n\t\t\t\t\t...message,\n\t\t\t\t\tcontent: fullText,\n\t\t\t\t\tmessageId: event.messageId ?? message.messageId,\n\t\t\t\t\t...(followUps ? { followUps } : {}),\n\t\t\t\t\t// Kept on the message, not just handled in passing, so the\n\t\t\t\t\t// action button is still there after a reload.\n\t\t\t\t\t...(toolResults ? { toolResults } : {}),\n\t\t\t\t}));\n\t\t\t\tsetThreadResponseId(responseId);\n\t\t\t\tsave();\n\t\t\t\tonResponseComplete?.({\n\t\t\t\t\ttext: fullText,\n\t\t\t\t\tresponseId,\n\t\t\t\t\tfollowUps,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (event.type === 'ERROR') {\n\t\t\t\tsetError(readCopilotEventContent(event).text || GENERIC_ERROR);\n\t\t\t\tfinishStreamingBubble();\n\t\t\t\tsave();\n\t\t\t}\n\n\t\t\t// Unknown types (TOOL_STATUS is declared server side but not emitted)\n\t\t\t// are ignored so a new event type cannot break an existing client.\n\t\t},\n\t\t[\n\t\t\tapplyMessages,\n\t\t\tfinishStreamingBubble,\n\t\t\tonResponseComplete,\n\t\t\tsave,\n\t\t\tsetThreadResponseId,\n\t\t],\n\t);\n\n\tconst sendMessage = useCallback(\n\t\t(message: string) => {\n\t\t\tconst userPrompt = message.trim();\n\t\t\tconst id = sessionIdRef.current;\n\t\t\tif (!userPrompt || !id || isStreaming) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetError(undefined);\n\t\t\tconst now = Date.now();\n\t\t\tconst assistantBubbleId = `copilot-a-${now}`;\n\t\t\tstreamingIdRef.current = assistantBubbleId;\n\n\t\t\tapplyMessages((previous) => [\n\t\t\t\t...previous,\n\t\t\t\t{\n\t\t\t\t\tid: `copilot-u-${now}`,\n\t\t\t\t\trole: 'user',\n\t\t\t\t\tcontent: userPrompt,\n\t\t\t\t\ttimestamp: now,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: assistantBubbleId,\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: '',\n\t\t\t\t\ttimestamp: now + 1,\n\t\t\t\t\tisStreaming: true,\n\t\t\t\t},\n\t\t\t]);\n\t\t\tsetIsStreaming(true);\n\t\t\tsave();\n\n\t\t\tabortRef.current = streamCopilotChat(\n\t\t\t\t{\n\t\t\t\t\tbaseUrl,\n\t\t\t\t\tendpointPath,\n\t\t\t\t\theaders,\n\t\t\t\t\tauthToken,\n\t\t\t\t\tgetAuthToken,\n\t\t\t\t\tfetchImpl,\n\t\t\t\t\tstoreId,\n\t\t\t\t\tagent,\n\t\t\t\t\troute,\n\t\t\t\t\tuserPrompt,\n\t\t\t\t\tsessionId: id,\n\t\t\t\t\tpreviousResponseId: previousResponseIdRef.current,\n\t\t\t\t\tsystemPrompt,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tonEvent: handleEvent,\n\t\t\t\t\tonComplete: () => {\n\t\t\t\t\t\t// STOP closes the stream without a frame, so this is where a turn\n\t\t\t\t\t\t// ends. TEXT has usually already settled the bubble.\n\t\t\t\t\t\tfinishStreamingBubble();\n\t\t\t\t\t\tsetIsStreaming(false);\n\t\t\t\t\t\tabortRef.current = null;\n\t\t\t\t\t\tsave();\n\t\t\t\t\t},\n\t\t\t\t\tonError: (streamError) => {\n\t\t\t\t\t\tsetError(streamError.message || GENERIC_ERROR);\n\t\t\t\t\t\tfinishStreamingBubble();\n\t\t\t\t\t\tsetIsStreaming(false);\n\t\t\t\t\t\tabortRef.current = null;\n\t\t\t\t\t\tsave();\n\t\t\t\t\t\tonError?.(streamError);\n\t\t\t\t\t},\n\t\t\t\t\tonAbort: () => {\n\t\t\t\t\t\tfinishStreamingBubble();\n\t\t\t\t\t\tsetIsStreaming(false);\n\t\t\t\t\t\tabortRef.current = null;\n\t\t\t\t\t\tsave();\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\t[\n\t\t\tapplyMessages,\n\t\t\tauthToken,\n\t\t\tbaseUrl,\n\t\t\tendpointPath,\n\t\t\tfetchImpl,\n\t\t\tagent,\n\t\t\tfinishStreamingBubble,\n\t\t\tgetAuthToken,\n\t\t\thandleEvent,\n\t\t\theaders,\n\t\t\tisStreaming,\n\t\t\tonError,\n\t\t\troute,\n\t\t\tsave,\n\t\t\tstoreId,\n\t\t\tsystemPrompt,\n\t\t],\n\t);\n\n\tconst regenerate = useCallback(() => {\n\t\tconst hasReply = messagesRef.current.some(\n\t\t\t(message) => message.role === 'assistant' && message.content.length > 0,\n\t\t);\n\t\tif (!hasReply) {\n\t\t\treturn;\n\t\t}\n\t\tsendMessage(COPILOT_REGENERATE_PROMPT);\n\t}, [sendMessage]);\n\n\t/**\n\t * Records a thumbs-up or thumbs-down on one reply.\n\t *\n\t * Fire-and-forget: a rating is a side note to the conversation, so a failed\n\t * post is reported through `onError` and otherwise ignored -- the thumb stays\n\t * lit either way rather than flickering back on a network hiccup.\n\t *\n\t * The reply's own text and the route ride along, so whoever reads the feedback\n\t * sees what was rated without looking the message up.\n\t */\n\tconst submitFeedback = useCallback(\n\t\t(\n\t\t\tmessageId: string,\n\t\t\tfeedback: CopilotFeedbackVote,\n\t\t\tdetail?: CopilotFeedbackDetail,\n\t\t) => {\n\t\t\tconst transport = transportRef.current;\n\t\t\tconst id = sessionIdRef.current;\n\t\t\tif (!id) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// A live turn's bubble carries only a local id until the final event\n\t\t\t// lands, so match on either and let the backend see whichever it gets.\n\t\t\tconst rated = messagesRef.current.find(\n\t\t\t\t(message) => (message.messageId ?? message.id) === messageId,\n\t\t\t);\n\t\t\tvoid sendCopilotFeedback({\n\t\t\t\tbaseUrl: transport.baseUrl,\n\t\t\t\tendpointPath: transport.feedbackPath,\n\t\t\t\theaders: transport.headers,\n\t\t\t\tauthToken: transport.authToken,\n\t\t\t\tgetAuthToken: transport.getAuthToken,\n\t\t\t\tfetchImpl: transport.fetchImpl,\n\t\t\t\tstoreId: transport.storeId,\n\t\t\t\tsessionId: id,\n\t\t\t\tmessageId,\n\t\t\t\tfeedback,\n\t\t\t\troute: routeRef.current,\n\t\t\t\treply: rated?.content,\n\t\t\t\tuser: transport.user,\n\t\t\t\treasons: detail?.reasons,\n\t\t\t\tcomment: detail?.comment,\n\t\t\t}).catch((feedbackError) => {\n\t\t\t\tonError?.(\n\t\t\t\t\tfeedbackError instanceof Error\n\t\t\t\t\t\t? feedbackError\n\t\t\t\t\t\t: new Error(String(feedbackError)),\n\t\t\t\t);\n\t\t\t});\n\t\t},\n\t\t[onError],\n\t);\n\n\tconst stopStreaming = useCallback(() => {\n\t\tif (!abortRef.current) {\n\t\t\treturn;\n\t\t}\n\t\t// Flagged here rather than in `onAbort`, because an abort that lands between\n\t\t// frames ends the stream through `onComplete` instead. Whichever fires, the\n\t\t// reader stopped this turn, and whatever text had arrived stays.\n\t\tconst streamingId = streamingIdRef.current;\n\t\tif (streamingId) {\n\t\t\tapplyMessages((previous) =>\n\t\t\t\tprevious.map((message) =>\n\t\t\t\t\tmessage.id === streamingId\n\t\t\t\t\t\t? { ...message, wasInterrupted: true }\n\t\t\t\t\t\t: message,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tabortRef.current();\n\t\tabortRef.current = null;\n\t}, [applyMessages]);\n\n\tconst startNewConversation = useCallback(() => {\n\t\tabortRef.current?.();\n\t\tabortRef.current = null;\n\t\tstreamingIdRef.current = null;\n\t\tsetIsStreaming(false);\n\t\tsetError(undefined);\n\t\t// A new conversation has no history behind it; the old session's pages\n\t\t// belong to the old session id.\n\t\tnextHistoryPageRef.current = 1;\n\t\tisLoadingHistoryRef.current = false;\n\t\tsetIsLoadingHistory(false);\n\t\tsetHasMoreHistory(false);\n\n\t\tconst activeRoute = routeRef.current;\n\t\t// The conversation being cleared, so its stored transcript can go with it.\n\t\tconst clearedId = sessionIdRef.current;\n\t\t// A host-pinned id is the host's to change, so only clear its transcript.\n\t\tconst nextId =\n\t\t\tpinnedSessionId ??\n\t\t\tresetCopilotSessionForRoute({ route: activeRoute, storeId });\n\t\tsessionIdRef.current = nextId;\n\t\tsetSessionId(nextId);\n\t\tmessagesRef.current = [];\n\t\tsetMessages([]);\n\t\tsetThreadResponseId(undefined);\n\n\t\t// \"Refresh chat\" wipes the record, not just the screen: the cleared\n\t\t// conversation is deleted from IndexedDB so reopening the tab starts fresh\n\t\t// instead of resuming it. Nothing is written for the new session here — its\n\t\t// first record is stamped when the first turn is sent, which is also what\n\t\t// keeps an untouched refresh from leaving an empty record behind.\n\t\tif (persist && clearedId) {\n\t\t\tvoid deleteCopilotSession(activeRoute, clearedId);\n\t\t}\n\t\tonSessionIdChange?.(nextId);\n\t}, [\n\t\tonSessionIdChange,\n\t\tpersist,\n\t\tpinnedSessionId,\n\t\tsetThreadResponseId,\n\t\tstoreId,\n\t]);\n\n\t// The thinking bubble is only for the wait before the first token; once text\n\t// starts arriving the bubble itself shows progress.\n\tconst isThinking = useMemo(\n\t\t() =>\n\t\t\tisStreaming &&\n\t\t\t!messages.some((message) => message.isStreaming && message.content),\n\t\t[isStreaming, messages],\n\t);\n\n\treturn {\n\t\tmessages,\n\t\tsessionId,\n\t\tpreviousResponseId,\n\t\tisStreaming,\n\t\tisThinking,\n\t\tisRestoring,\n\t\tisLoadingHistory,\n\t\thasMoreHistory,\n\t\terror,\n\t\tsendMessage,\n\t\tregenerate,\n\t\tsubmitFeedback,\n\t\tloadOlderMessages,\n\t\tstopStreaming,\n\t\tstartNewConversation,\n\t};\n};\n"],"names":["GENERIC_ERROR","useCopilotStreamChat","storeId","agent","DEFAULT_COPILOT_AGENT","route","DEFAULT_COPILOT_ROUTE","messagesPath","feedbackPath","user","loadHistory","systemPrompt","pinnedSessionId","persist","onError","onResponseComplete","onSessionIdChange","baseUrl","endpointPath","headers","authToken","getAuthToken","fetchImpl","messages","setMessages","useState","sessionId","setSessionId","isStreaming","setIsStreaming","isRestoring","setIsRestoring","error","setError","previousResponseId","setPreviousResponseId","isLoadingHistory","setIsLoadingHistory","hasMoreHistory","setHasMoreHistory","messagesRef","useRef","previousResponseIdRef","streamingIdRef","abortRef","sessionIdRef","routeRef","nextHistoryPageRef","isLoadingHistoryRef","applyMessages","useCallback","updater","next","setThreadResponseId","responseId","save","id","persistCopilotTurn","transportRef","readHistoryPage","page","transport","fetchCopilotMessages","COPILOT_HISTORY_PAGE_SIZE","useEffect","cancelled","resolveCopilotSessionIdForRoute","getCopilotSessionIdForRoute","record","loadCopilotSession","firstPage","loadOlderMessages","older","previous","known","message","fresh","historyError","pruneCopilotSessions","finishStreamingBubble","mutate","streamingId","settled","handleEvent","event","chunk","readCopilotEventContent","fullText","followUps","toolResults","sendMessage","userPrompt","now","assistantBubbleId","streamCopilotChat","streamError","regenerate","COPILOT_REGENERATE_PROMPT","submitFeedback","messageId","feedback","detail","rated","sendCopilotFeedback","feedbackError","stopStreaming","startNewConversation","activeRoute","clearedId","nextId","resetCopilotSessionForRoute","deleteCopilotSession","isThinking","useMemo"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react"),C=4,u=8,g=()=>typeof window>"u"?{width:0,height:0}:{width:window.innerWidth,height:window.innerHeight},p=(r,a,n)=>{if(!n.width||!n.height)return r;const s=Math.max(u,n.width-a-u),c=Math.max(u,n.height-a-u);return{x:Math.min(Math.max(r.x,u),s),y:Math.min(Math.max(r.y,u),c)}},k=(r,a,n,s)=>{const c=s.width-a-n,h=s.height-a-n;switch(r){case"top-left":return{x:n,y:n};case"top-right":return{x:c,y:n};case"bottom-left":return{x:n,y:h};default:return{x:c,y:h}}},E=({size:r,corner:a,offset:n,enabled:s,snapToEdge:c,initialPosition:h,onPositionChange:b})=>{const[R,X]=o.useState(g),[l,x]=o.useState(()=>{const t=g();return p(h??k(a,r,n,t),r,t)}),[D,y]=o.useState(!1),w=o.useRef(null),m=o.useRef(!1);o.useEffect(()=>{const t=()=>{const e=g();X(e),x(i=>p(i,r,e))};return window.addEventListener("resize",t),()=>window.removeEventListener("resize",t)},[r]);const I=o.useCallback(t=>{m.current=!1,!(!s||t.button!==0)&&(t.currentTarget.setPointerCapture(t.pointerId),w.current={pointerId:t.pointerId,startX:t.clientX,startY:t.clientY,originX:l.x,originY:l.y,moved:!1,latest:l})},[s,l]),M=o.useCallback(t=>{const e=w.current;if(!e||e.pointerId!==t.pointerId)return;const i=t.clientX-e.startX,d=t.clientY-e.startY;if(!e.moved){if(Math.abs(i)<C&&Math.abs(d)<C)return;e.moved=!0,y(!0)}const f=p({x:e.originX+i,y:e.originY+d},r,g());e.latest=f,x(f)},[r]),P=o.useCallback(t=>{const e=w.current;if(!e||e.pointerId!==t.pointerId||(w.current=null,t.currentTarget.hasPointerCapture(t.pointerId)&&t.currentTarget.releasePointerCapture(t.pointerId),!e.moved))return;m.current=!0,y(!1);const i=g(),d=c?p({x:e.latest.x+r/2<i.width/2?n:i.width-r-n,y:e.latest.y},r,i):e.latest;x(d),b?.(d)},[n,b,r,c]),Y=o.useCallback(()=>{const t=m.current;return m.current=!1,t},[]),V=o.useMemo(()=>({onPointerDown:I,onPointerMove:M,onPointerUp:P,onPointerCancel:P}),[P,I,M]);return{position:l,isDragging:D,viewport:R,dragHandlers:V,shouldIgnoreClick:Y}};exports.useDraggableFloater=E;
2
+ //# sourceMappingURL=useDraggableFloater.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDraggableFloater.js","sources":["../../../../src/components/bik-copilot/useDraggableFloater.ts"],"sourcesContent":["import {\n\tPointerEvent as ReactPointerEvent,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport {\n\tCopilotBallPosition,\n\tCopilotCorner,\n\tCopilotViewport,\n\tUseDraggableFloaterOptions,\n\tUseDraggableFloaterResult,\n} from './model';\n\n/** Movement (px) a gesture must cover before it counts as a drag, not a tap. */\nconst DRAG_THRESHOLD_PX = 4;\n\n/** Smallest gap kept between the dragged element and the viewport edges. */\nconst VIEWPORT_MARGIN_PX = 8;\n\nconst getViewport = (): CopilotViewport =>\n\ttypeof window === 'undefined'\n\t\t? { width: 0, height: 0 }\n\t\t: { width: window.innerWidth, height: window.innerHeight };\n\nconst clampToViewport = (\n\tposition: CopilotBallPosition,\n\tsize: number,\n\tviewport: CopilotViewport,\n): CopilotBallPosition => {\n\tif (!viewport.width || !viewport.height) {\n\t\treturn position;\n\t}\n\tconst maxX = Math.max(\n\t\tVIEWPORT_MARGIN_PX,\n\t\tviewport.width - size - VIEWPORT_MARGIN_PX,\n\t);\n\tconst maxY = Math.max(\n\t\tVIEWPORT_MARGIN_PX,\n\t\tviewport.height - size - VIEWPORT_MARGIN_PX,\n\t);\n\treturn {\n\t\tx: Math.min(Math.max(position.x, VIEWPORT_MARGIN_PX), maxX),\n\t\ty: Math.min(Math.max(position.y, VIEWPORT_MARGIN_PX), maxY),\n\t};\n};\n\nconst getCornerPosition = (\n\tcorner: CopilotCorner,\n\tsize: number,\n\toffset: number,\n\tviewport: CopilotViewport,\n): CopilotBallPosition => {\n\tconst rightEdge = viewport.width - size - offset;\n\tconst bottomEdge = viewport.height - size - offset;\n\tswitch (corner) {\n\t\tcase 'top-left':\n\t\t\treturn { x: offset, y: offset };\n\t\tcase 'top-right':\n\t\t\treturn { x: rightEdge, y: offset };\n\t\tcase 'bottom-left':\n\t\t\treturn { x: offset, y: bottomEdge };\n\t\tcase 'bottom-right':\n\t\tdefault:\n\t\t\treturn { x: rightEdge, y: bottomEdge };\n\t}\n};\n\ninterface DragGesture {\n\tpointerId: number;\n\tstartX: number;\n\tstartY: number;\n\toriginX: number;\n\toriginY: number;\n\tmoved: boolean;\n\tlatest: CopilotBallPosition;\n}\n\n/**\n * Drives a fixed-position element the user can drag anywhere in the viewport.\n *\n * The hook owns the element's coordinates, keeps them inside the viewport as the\n * window resizes, and separates a tap from a drag so the same element can both\n * be dragged and clicked.\n */\nexport const useDraggableFloater = ({\n\tsize,\n\tcorner,\n\toffset,\n\tenabled,\n\tsnapToEdge,\n\tinitialPosition,\n\tonPositionChange,\n}: UseDraggableFloaterOptions): UseDraggableFloaterResult => {\n\tconst [viewport, setViewport] = useState<CopilotViewport>(getViewport);\n\tconst [position, setPosition] = useState<CopilotBallPosition>(() => {\n\t\tconst initialViewport = getViewport();\n\t\treturn clampToViewport(\n\t\t\tinitialPosition ??\n\t\t\t\tgetCornerPosition(corner, size, offset, initialViewport),\n\t\t\tsize,\n\t\t\tinitialViewport,\n\t\t);\n\t});\n\tconst [isDragging, setIsDragging] = useState(false);\n\n\tconst gestureRef = useRef<DragGesture | null>(null);\n\tconst ignoreNextClickRef = useRef(false);\n\n\t// Keep the element reachable when the window is resized around it.\n\tuseEffect(() => {\n\t\tconst handleResize = () => {\n\t\t\tconst nextViewport = getViewport();\n\t\t\tsetViewport(nextViewport);\n\t\t\tsetPosition((previous) => clampToViewport(previous, size, nextViewport));\n\t\t};\n\t\twindow.addEventListener('resize', handleResize);\n\t\treturn () => window.removeEventListener('resize', handleResize);\n\t}, [size]);\n\n\tconst handlePointerDown = useCallback(\n\t\t(event: ReactPointerEvent<HTMLElement>) => {\n\t\t\t// A stale flag would otherwise swallow the next legitimate click.\n\t\t\tignoreNextClickRef.current = false;\n\t\t\tif (!enabled || event.button !== 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tevent.currentTarget.setPointerCapture(event.pointerId);\n\t\t\tgestureRef.current = {\n\t\t\t\tpointerId: event.pointerId,\n\t\t\t\tstartX: event.clientX,\n\t\t\t\tstartY: event.clientY,\n\t\t\t\toriginX: position.x,\n\t\t\t\toriginY: position.y,\n\t\t\t\tmoved: false,\n\t\t\t\tlatest: position,\n\t\t\t};\n\t\t},\n\t\t[enabled, position],\n\t);\n\n\tconst handlePointerMove = useCallback(\n\t\t(event: ReactPointerEvent<HTMLElement>) => {\n\t\t\tconst gesture = gestureRef.current;\n\t\t\tif (!gesture || gesture.pointerId !== event.pointerId) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst deltaX = event.clientX - gesture.startX;\n\t\t\tconst deltaY = event.clientY - gesture.startY;\n\n\t\t\tif (!gesture.moved) {\n\t\t\t\tif (\n\t\t\t\t\tMath.abs(deltaX) < DRAG_THRESHOLD_PX &&\n\t\t\t\t\tMath.abs(deltaY) < DRAG_THRESHOLD_PX\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tgesture.moved = true;\n\t\t\t\tsetIsDragging(true);\n\t\t\t}\n\n\t\t\tconst next = clampToViewport(\n\t\t\t\t{ x: gesture.originX + deltaX, y: gesture.originY + deltaY },\n\t\t\t\tsize,\n\t\t\t\tgetViewport(),\n\t\t\t);\n\t\t\tgesture.latest = next;\n\t\t\tsetPosition(next);\n\t\t},\n\t\t[size],\n\t);\n\n\tconst endGesture = useCallback(\n\t\t(event: ReactPointerEvent<HTMLElement>) => {\n\t\t\tconst gesture = gestureRef.current;\n\t\t\tif (!gesture || gesture.pointerId !== event.pointerId) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tgestureRef.current = null;\n\t\t\tif (event.currentTarget.hasPointerCapture(event.pointerId)) {\n\t\t\t\tevent.currentTarget.releasePointerCapture(event.pointerId);\n\t\t\t}\n\t\t\tif (!gesture.moved) {\n\t\t\t\t// A tap: let the click handler run untouched.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tignoreNextClickRef.current = true;\n\t\t\tsetIsDragging(false);\n\n\t\t\tconst currentViewport = getViewport();\n\t\t\tconst settled = snapToEdge\n\t\t\t\t? clampToViewport(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tx:\n\t\t\t\t\t\t\t\tgesture.latest.x + size / 2 < currentViewport.width / 2\n\t\t\t\t\t\t\t\t\t? offset\n\t\t\t\t\t\t\t\t\t: currentViewport.width - size - offset,\n\t\t\t\t\t\t\ty: gesture.latest.y,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsize,\n\t\t\t\t\t\tcurrentViewport,\n\t\t\t\t )\n\t\t\t\t: gesture.latest;\n\n\t\t\tsetPosition(settled);\n\t\t\tonPositionChange?.(settled);\n\t\t},\n\t\t[offset, onPositionChange, size, snapToEdge],\n\t);\n\n\tconst shouldIgnoreClick = useCallback(() => {\n\t\tconst ignore = ignoreNextClickRef.current;\n\t\tignoreNextClickRef.current = false;\n\t\treturn ignore;\n\t}, []);\n\n\tconst dragHandlers = useMemo(\n\t\t() => ({\n\t\t\tonPointerDown: handlePointerDown,\n\t\t\tonPointerMove: handlePointerMove,\n\t\t\tonPointerUp: endGesture,\n\t\t\tonPointerCancel: endGesture,\n\t\t}),\n\t\t[endGesture, handlePointerDown, handlePointerMove],\n\t);\n\n\treturn { position, isDragging, viewport, dragHandlers, shouldIgnoreClick };\n};\n"],"names":["DRAG_THRESHOLD_PX","VIEWPORT_MARGIN_PX","getViewport","clampToViewport","position","size","viewport","maxX","maxY","getCornerPosition","corner","offset","rightEdge","bottomEdge","useDraggableFloater","enabled","snapToEdge","initialPosition","onPositionChange","setViewport","useState","setPosition","initialViewport","isDragging","setIsDragging","gestureRef","useRef","ignoreNextClickRef","useEffect","handleResize","nextViewport","previous","handlePointerDown","useCallback","event","handlePointerMove","gesture","deltaX","deltaY","next","endGesture","currentViewport","settled","shouldIgnoreClick","ignore","dragHandlers","useMemo"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=(p,e)=>`<a href="${p}" target="_blank" rel="noopener noreferrer">${e}</a>`,m=/[.,;:!?)\]]+$/;function u(p){let e=p;e=e.replace(/`([^`]+)`/g,"<code>$1</code>"),e=e.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),e=e.replace(/(^|\s)\*(.+?)\*(?=\s|$)/g,"$1<em>$2</em>"),e=e.replace(/(^|\s)_(.+?)_(?=\s|$)/g,"$1<em>$2</em>");const c=[],r=t=>(c.push(t),`@@INLINE${c.length-1}@@`);return e=e.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g,(t,s,l)=>{const o=/^(https?:|mailto:)/i.test(l)?l:"#";return r(f(o,s))}),e=e.replace(/<code>[\s\S]*?<\/code>/g,t=>r(t)),e=e.replace(/https?:\/\/[^\s<>"']+/g,t=>{const s=t.replace(m,"");return`${f(s,s)}${t.slice(s.length)}`}),e.replace(/@@INLINE(\d+)@@/g,(t,s)=>c[Number(s)])}function N(p){if(!p)return"";let e=p.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");const c=[];e=e.replace(/```([\s\S]*?)```/g,(n,i)=>(c.push(`<pre><code>${i.trim()}</code></pre>`),`@@CODE${c.length-1}@@`));const r=[];let t=null,s=[],l=0;const o=()=>{t&&(r.push(`</${t}>`),t=null)},a=()=>{s.length&&(r.push(s.join("<br/>")),s=[])};for(const n of e.split(`
2
+ `)){const i=/^@@CODE\d+@@$/.test(n.trim()),h=n.match(/^(#{1,4})\s+(.+)$/),d=n.match(/^\s*[-*]\s+(.+)$/),g=n.match(/^\s*\d+\.\s+(.+)$/);if(i)a(),o(),l=0,r.push(n.trim());else if(h){a(),o(),l=0;const $=h[1].length;r.push(`<h${$}>${u(h[2])}</h${$}>`)}else d?(a(),t!=="ul"&&(o(),r.push("<ul>"),t="ul"),r.push(`<li>${u(d[1])}</li>`)):g?(a(),t!=="ol"&&(o(),r.push(l>0?`<ol start="${l+1}">`:"<ol>"),t="ol"),l+=1,r.push(`<li>${u(g[1])}</li>`)):n.trim()===""?(a(),o(),l=0,r.push("<br/>")):(o(),l=0,s.push(u(n)))}return a(),o(),r.join(`
3
+ `).replace(/@@CODE(\d+)@@/g,(n,i)=>c[Number(i)])}exports.renderCopilotMarkdown=N;
4
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sources":["../../../../../src/components/bik-copilot/utils/markdown.ts"],"sourcesContent":["// Markdown-to-HTML converter for copilot assistant messages.\n// Escapes HTML, then supports: headings (#–####), bold/italic, inline `code`,\n// fenced ```code``` blocks, links [t](url), bare http(s) urls, unordered (-, *)\n// and ordered (1.) lists, and line breaks. Output is safe to inject: all text is\n// HTML-escaped first, and link hrefs are restricted to http(s)/mailto.\n//\n// Copilot-local on purpose — the bik-chatbot util is intentionally simpler and\n// shared elsewhere, so richer formatting (lists, links, inline code) lives here.\n\nconst anchor = (href: string, label: string): string =>\n\t`<a href=\"${href}\" target=\"_blank\" rel=\"noopener noreferrer\">${label}</a>`;\n\n/** Punctuation that reads as sentence-ending rather than part of the url. */\nconst TRAILING_PUNCTUATION = /[.,;:!?)\\]]+$/;\n\n/** Inline formatting applied within a single line (already HTML-escaped). */\nfunction applyInline(text: string): string {\n\tlet out = text;\n\t// Inline code first, so ** or _ inside code isn't treated as emphasis.\n\tout = out.replace(/`([^`]+)`/g, '<code>$1</code>');\n\t// Bold, then italic.\n\tout = out.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');\n\tout = out.replace(/(^|\\s)\\*(.+?)\\*(?=\\s|$)/g, '$1<em>$2</em>');\n\tout = out.replace(/(^|\\s)_(.+?)_(?=\\s|$)/g, '$1<em>$2</em>');\n\n\t// Stash the tags produced so far — autolinking below must not reach inside an\n\t// href it just wrote, or a url shown as inline code.\n\tconst stashed: string[] = [];\n\tconst stash = (html: string): string => {\n\t\tstashed.push(html);\n\t\treturn `@@INLINE${stashed.length - 1}@@`;\n\t};\n\n\t// Links [text](url) — only safe schemes, everything else neutralised to #.\n\tout = out.replace(/\\[([^\\]]+)\\]\\(([^)\\s]+)\\)/g, (_m, label, url) => {\n\t\tconst safe = /^(https?:|mailto:)/i.test(url) ? url : '#';\n\t\treturn stash(anchor(safe, label));\n\t});\n\tout = out.replace(/<code>[\\s\\S]*?<\\/code>/g, (code) => stash(code));\n\n\t// Bare urls. The model routinely drops the markdown syntax when it\n\t// paraphrases a link it was given, so a url on its own still has to be\n\t// clickable — otherwise the reader gets text they have to copy by hand.\n\tout = out.replace(/https?:\\/\\/[^\\s<>\"']+/g, (match) => {\n\t\tconst url = match.replace(TRAILING_PUNCTUATION, '');\n\t\treturn `${anchor(url, url)}${match.slice(url.length)}`;\n\t});\n\n\treturn out.replace(\n\t\t/@@INLINE(\\d+)@@/g,\n\t\t(_m, index: string) => stashed[Number(index)],\n\t);\n}\n\nexport function renderCopilotMarkdown(text: string): string {\n\tif (!text) return '';\n\n\t// Escape HTML.\n\tlet escaped = text\n\t\t.replace(/&/g, '&amp;')\n\t\t.replace(/</g, '&lt;')\n\t\t.replace(/>/g, '&gt;');\n\n\t// Pull fenced code blocks out so line/inline rules don't touch them.\n\tconst codeBlocks: string[] = [];\n\tescaped = escaped.replace(/```([\\s\\S]*?)```/g, (_m, body) => {\n\t\tcodeBlocks.push(`<pre><code>${body.trim()}</code></pre>`);\n\t\treturn `@@CODE${codeBlocks.length - 1}@@`;\n\t});\n\n\tconst out: string[] = [];\n\tlet listType: 'ul' | 'ol' | null = null;\n\tlet paragraph: string[] = [];\n\t// Running count of ordered items so numbering continues across a bullet\n\t// block that interrupts a numbered list (e.g. step 4, sub-bullets, step 5).\n\t// Only a real break (blank line, heading, paragraph, code) resets it.\n\tlet orderedCount = 0;\n\n\tconst closeList = () => {\n\t\tif (listType) {\n\t\t\tout.push(`</${listType}>`);\n\t\t\tlistType = null;\n\t\t}\n\t};\n\tconst flushParagraph = () => {\n\t\tif (paragraph.length) {\n\t\t\tout.push(paragraph.join('<br/>'));\n\t\t\tparagraph = [];\n\t\t}\n\t};\n\n\tfor (const line of escaped.split('\\n')) {\n\t\tconst isCodeBlock = /^@@CODE\\d+@@$/.test(line.trim());\n\t\tconst heading = line.match(/^(#{1,4})\\s+(.+)$/);\n\t\tconst unordered = line.match(/^\\s*[-*]\\s+(.+)$/);\n\t\tconst ordered = line.match(/^\\s*\\d+\\.\\s+(.+)$/);\n\n\t\tif (isCodeBlock) {\n\t\t\tflushParagraph();\n\t\t\tcloseList();\n\t\t\torderedCount = 0;\n\t\t\tout.push(line.trim());\n\t\t} else if (heading) {\n\t\t\tflushParagraph();\n\t\t\tcloseList();\n\t\t\torderedCount = 0;\n\t\t\tconst level = heading[1].length;\n\t\t\tout.push(`<h${level}>${applyInline(heading[2])}</h${level}>`);\n\t\t} else if (unordered) {\n\t\t\t// A bullet block may interrupt a numbered list; keep orderedCount so\n\t\t\t// the numbering resumes rather than restarting at 1.\n\t\t\tflushParagraph();\n\t\t\tif (listType !== 'ul') {\n\t\t\t\tcloseList();\n\t\t\t\tout.push('<ul>');\n\t\t\t\tlistType = 'ul';\n\t\t\t}\n\t\t\tout.push(`<li>${applyInline(unordered[1])}</li>`);\n\t\t} else if (ordered) {\n\t\t\tflushParagraph();\n\t\t\tif (listType !== 'ol') {\n\t\t\t\tcloseList();\n\t\t\t\t// Continue numbering when reopening after an interruption.\n\t\t\t\tout.push(\n\t\t\t\t\torderedCount > 0 ? `<ol start=\"${orderedCount + 1}\">` : '<ol>',\n\t\t\t\t);\n\t\t\t\tlistType = 'ol';\n\t\t\t}\n\t\t\torderedCount += 1;\n\t\t\tout.push(`<li>${applyInline(ordered[1])}</li>`);\n\t\t} else if (line.trim() === '') {\n\t\t\t// Blank line ends a paragraph/list and leaves a gap.\n\t\t\tflushParagraph();\n\t\t\tcloseList();\n\t\t\torderedCount = 0;\n\t\t\tout.push('<br/>');\n\t\t} else {\n\t\t\tcloseList();\n\t\t\torderedCount = 0;\n\t\t\tparagraph.push(applyInline(line));\n\t\t}\n\t}\n\tflushParagraph();\n\tcloseList();\n\n\t// Restore fenced code blocks.\n\treturn out\n\t\t.join('\\n')\n\t\t.replace(/@@CODE(\\d+)@@/g, (_m, index) => codeBlocks[Number(index)]);\n}\n"],"names":["anchor","href","label","TRAILING_PUNCTUATION","applyInline","text","out","stashed","stash","html","_m","url","safe","code","match","index","renderCopilotMarkdown","escaped","codeBlocks","body","listType","paragraph","orderedCount","closeList","flushParagraph","line","isCodeBlock","heading","unordered","ordered","level"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c="Open link",a=t=>typeof t=="string"&&/^https?:\/\//i.test(t.trim()),l=t=>{const o=t.cta;return typeof o=="string"&&o.trim().length>0?o.trim():c},u=t=>{if(!Array.isArray(t))return[];const o=[],i=new Set;for(const e of t){const r=e?.data;if(!r||typeof r!="object")continue;const n=r;if(!a(n.url))continue;const s=n.url.trim();i.has(s)||(i.add(s),o.push({label:l(n),url:s,tool:typeof e.tool=="string"?e.tool:""}))}return o};exports.toolResultCtas=u;
2
+ //# sourceMappingURL=toolCtas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolCtas.js","sources":["../../../../../src/components/bik-copilot/utils/toolCtas.ts"],"sourcesContent":["// Turns a reply's structured tool outputs into the buttons rendered under it.\n//\n// Tools that hand the merchant somewhere to go (today: `create_jira_ticket` and\n// its support-portal link) return `{ url, cta, buttonType }` — the same field\n// names the chat stack's CtaButton uses. Anything without a usable http(s) url\n// is skipped, so a tool that returns other data cannot render a dead button.\nimport { CopilotToolCta, CopilotToolResult } from '../model';\n\nconst DEFAULT_LABEL = 'Open link';\n\n/** Only real web links become buttons; anything else is dropped. */\nconst isSafeUrl = (value: unknown): value is string =>\n\ttypeof value === 'string' && /^https?:\\/\\//i.test(value.trim());\n\nconst readLabel = (data: Record<string, unknown>): string => {\n\tconst cta = data['cta'];\n\tif (typeof cta === 'string' && cta.trim().length > 0) {\n\t\treturn cta.trim();\n\t}\n\treturn DEFAULT_LABEL;\n};\n\n/**\n * The CTAs for one reply, in the order the tools ran. Empty when a reply has no\n * tool results or none of them point anywhere.\n */\nexport const toolResultCtas = (\n\ttoolResults: CopilotToolResult[] | undefined,\n): CopilotToolCta[] => {\n\tif (!Array.isArray(toolResults)) {\n\t\treturn [];\n\t}\n\tconst ctas: CopilotToolCta[] = [];\n\tconst seen = new Set<string>();\n\tfor (const result of toolResults) {\n\t\tconst data = result?.data;\n\t\tif (!data || typeof data !== 'object') {\n\t\t\tcontinue;\n\t\t}\n\t\tconst record = data as Record<string, unknown>;\n\t\tif (!isSafeUrl(record['url'])) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst url = (record['url'] as string).trim();\n\t\t// A tool called twice in one turn would otherwise stack identical buttons.\n\t\tif (seen.has(url)) {\n\t\t\tcontinue;\n\t\t}\n\t\tseen.add(url);\n\t\tctas.push({\n\t\t\tlabel: readLabel(record),\n\t\t\turl,\n\t\t\ttool: typeof result.tool === 'string' ? result.tool : '',\n\t\t});\n\t}\n\treturn ctas;\n};\n"],"names":["DEFAULT_LABEL","isSafeUrl","value","readLabel","data","cta","toolResultCtas","toolResults","ctas","seen","result","record","url"],"mappings":"gFAQA,MAAMA,EAAgB,YAGhBC,EAAaC,GAClB,OAAOA,GAAU,UAAY,gBAAgB,KAAKA,EAAM,MAAM,EAEzDC,EAAaC,GAA0C,CAC5D,MAAMC,EAAMD,EAAK,IACjB,OAAI,OAAOC,GAAQ,UAAYA,EAAI,KAAA,EAAO,OAAS,EAC3CA,EAAI,KAAA,EAELL,CACR,EAMaM,EACZC,GACsB,CACtB,GAAI,CAAC,MAAM,QAAQA,CAAW,EAC7B,MAAO,CAAA,EAER,MAAMC,EAAyB,CAAA,EACzBC,MAAW,IACjB,UAAWC,KAAUH,EAAa,CACjC,MAAMH,EAAOM,GAAQ,KACrB,GAAI,CAACN,GAAQ,OAAOA,GAAS,SAC5B,SAED,MAAMO,EAASP,EACf,GAAI,CAACH,EAAUU,EAAO,GAAM,EAC3B,SAED,MAAMC,EAAOD,EAAO,IAAkB,KAAA,EAElCF,EAAK,IAAIG,CAAG,IAGhBH,EAAK,IAAIG,CAAG,EACZJ,EAAK,KAAK,CACT,MAAOL,EAAUQ,CAAM,EACvB,IAAAC,EACA,KAAM,OAAOF,EAAO,MAAS,SAAWA,EAAO,KAAO,EAAA,CACtD,EACF,CACA,OAAOF,CACR"}