@designcrowd/library.brand-page 6.0.5 → 6.0.6-ast-bugs

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 (395) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-DhzvKlTS.js → CreatedOnBrandCrowd-de-de-SHCspMwS.js} +3 -3
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-DKH4lmNV.js → CreatedOnBrandCrowd-en-us-C6lITAAT.js} +3 -3
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-RloPCLuV.js → CreatedOnBrandCrowd-es-es-Uh69c4vZ.js} +3 -3
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-Cu9e2H0K.js → CreatedOnBrandCrowd-fr-ca-Bb0rp7BV.js} +3 -3
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-Cu9e2H0K.js → CreatedOnBrandCrowd-fr-fr-Bb0rp7BV.js} +3 -3
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-CiCnjxBZ.js → CreatedOnBrandCrowd-pt-br-DsrQHcjs.js} +3 -3
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-CiCnjxBZ.js → CreatedOnBrandCrowd-pt-pt-DsrQHcjs.js} +3 -3
  8. package/lib/src/{CreatedOnDcom-de-de-CwlnedFV.js → CreatedOnDcom-de-de-BshZYzSp.js} +3 -3
  9. package/lib/src/{CreatedOnDcom-en-us-DFHex61v.js → CreatedOnDcom-en-us-CLu8mKUW.js} +3 -3
  10. package/lib/src/{CreatedOnDcom-es-es-BTxH6I4V.js → CreatedOnDcom-es-es-BZYhkONd.js} +3 -3
  11. package/lib/src/{CreatedOnDcom-fr-ca-BVw0KYxu.js → CreatedOnDcom-fr-ca-CIaBEp_9.js} +3 -3
  12. package/lib/src/{CreatedOnDcom-fr-fr-DaqNz1Er.js → CreatedOnDcom-fr-fr-dyF7hioJ.js} +3 -3
  13. package/lib/src/{CreatedOnDcom-pt-br-B4KsMI8W.js → CreatedOnDcom-pt-br-CUHjk2du.js} +3 -3
  14. package/lib/src/{CreatedOnDcom-pt-pt-CWoHEtOZ.js → CreatedOnDcom-pt-pt-CWDvQidv.js} +3 -3
  15. package/lib/src/brand-page/clients/brand-page.client.d.ts +9 -9
  16. package/lib/src/brand-page/components/banner-section/BannerSection.mixin.d.ts +103 -0
  17. package/lib/src/brand-page/components/banner-section/BannerSection.mixin.js +178 -0
  18. package/lib/src/brand-page/components/image-gallery/masonry/MasonryGallery.mixin.d.ts +1 -2
  19. package/lib/src/brand-page/components/navigation/hamburger/HamburgerNavigation.mixin.d.ts +4 -2
  20. package/lib/src/brand-page/components/navigation/hamburger/HamburgerNavigation.mixin.js +1 -0
  21. package/lib/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.d.ts +4 -2
  22. package/lib/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.js +11 -5
  23. package/lib/src/brand-page/components/page/Page.mixin.d.ts +1 -1
  24. package/lib/src/brand-page/components/page/PageComponent.mixin.d.ts +1 -1
  25. package/lib/src/brand-page/components/payment/Payment.mixin.d.ts +3 -3
  26. package/lib/src/brand-page/components/payment/__fixtures__/request-payment.d.ts +13 -13
  27. package/lib/src/brand-page/components/payment/__fixtures__/support-me.d.ts +13 -13
  28. package/lib/src/brand-page/constants/sections/footer-display.constants.js +1 -1
  29. package/lib/src/brand-page/models/index.d.ts +2 -13
  30. package/lib/src/brand-page/models/index.js +3 -0
  31. package/lib/src/brand-page/models/payment.model.d.ts +1 -1
  32. package/lib/src/brand-page/utils/personalisation.util.js +72 -14
  33. package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +21 -19
  34. package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.js +1 -0
  35. package/lib/src/brand-page-maker/components/admin-background-settings/AdminBackgroundSettings.mixin.d.ts +16 -10
  36. package/lib/src/brand-page-maker/components/admin-background-settings/ShapePositionSlider.mixin.d.ts +1 -1
  37. package/lib/src/brand-page-maker/components/admin-logo-settings/AdminLogoSettings.mixin.d.ts +3 -3
  38. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +181 -170
  39. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +3 -0
  40. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.js +1 -0
  41. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.mixin.d.ts +12 -12
  42. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.stories.js +2 -2
  43. package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-payment.js +0 -7
  44. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +148 -149
  45. package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.d.ts +21 -21
  46. package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.js +1 -1
  47. package/lib/src/brand-page-maker/components/color-picker/components/ColorModeSelect.mixin.d.ts +4 -2
  48. package/lib/src/brand-page-maker/components/color-picker/components/ColorModeSelect.mixin.js +1 -0
  49. package/lib/src/brand-page-maker/components/color-picker/components/GradientColorSlider.mixin.d.ts +4 -2
  50. package/lib/src/brand-page-maker/components/color-picker/components/GradientColorSlider.mixin.js +1 -0
  51. package/lib/src/brand-page-maker/components/color-picker/components/GradientColorSliderHandler.mixin.d.ts +5 -2
  52. package/lib/src/brand-page-maker/components/color-picker/components/GradientColorSliderHandler.mixin.js +1 -0
  53. package/lib/src/brand-page-maker/components/color-picker/components/GradientTypeSelector.mixin.d.ts +4 -2
  54. package/lib/src/brand-page-maker/components/color-picker/components/GradientTypeSelector.mixin.js +1 -0
  55. package/lib/src/brand-page-maker/components/device/Device.mixin.d.ts +4 -2
  56. package/lib/src/brand-page-maker/components/device/Device.mixin.js +1 -0
  57. package/lib/src/brand-page-maker/components/navigation/Navigation.mixin.d.ts +4 -2
  58. package/lib/src/brand-page-maker/components/navigation/Navigation.mixin.js +1 -0
  59. package/lib/src/brand-page-maker/components/preview/Preview.mixin.d.ts +3 -3
  60. package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.d.ts +11 -11
  61. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +27 -25
  62. package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.js +1 -0
  63. package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +27 -27
  64. package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.js +1 -1
  65. package/lib/src/brand-page-maker/components/seo-settings/UseExistingDomainModal.mixin.d.ts +17 -12
  66. package/lib/src/brand-page-maker/components/social-share/SocialShare.mixin.d.ts +12 -12
  67. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +30 -32
  68. package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.js +16 -5
  69. package/lib/src/brand-page-maker/components/upgrade-to-premium-button/UpgradeToPremiumButton.mixin.d.ts +11 -11
  70. package/lib/src/brand-page-maker/composables/ai-chat/types.d.ts +3 -0
  71. package/lib/src/brand-page-maker/composables/ai-chat/ui-actions.d.ts +29 -0
  72. package/lib/src/brand-page-maker/composables/ai-chat/ui-actions.js +32 -0
  73. package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +204 -177
  74. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +1 -1
  75. package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +6 -6
  76. package/lib/src/brand-page-maker/composables/useEventTracker.d.ts +3 -2
  77. package/lib/src/brand-page-maker/composables/useEventTracker.js +1 -0
  78. package/lib/src/brand-page-maker/constants/config-settings-constant.d.ts +6 -6
  79. package/lib/src/brand-page-maker/constants/config-settings-constant.js +3 -3
  80. package/lib/src/brand-page-maker/convertors/text-image-display-style.convertor.d.ts +1 -1
  81. package/lib/src/brand-page-maker/convertors/text-image-display-style.convertor.js +1 -1
  82. package/lib/src/brand-page-maker/models/content-settings.d.ts +1 -1
  83. package/lib/src/brand-page-maker/models/navigation-style-configs.js +1 -1
  84. package/lib/src/brand-page-maker/routing/brand-page-maker-router.d.ts +1 -2
  85. package/lib/src/brand-page-maker/stores/ai-checkpoint/ai-checkpoint-store.d.ts +366 -378
  86. package/lib/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.d.ts +5 -4
  87. package/lib/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.js +8 -5
  88. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.d.ts +3 -1
  89. package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +7 -3
  90. package/lib/src/brand-page-maker/stores/history/history-store.d.ts +15 -15
  91. package/lib/src/brand-page-maker/stores/ui/ui-store.d.ts +6 -0
  92. package/lib/src/brand-page-maker/stores/ui/ui-store.js +8 -0
  93. package/lib/src/brand-page-maker/utils/content-settings.util.js +1 -1
  94. package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +1 -1
  95. package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +4 -4
  96. package/lib/src/clients/ai-assistant-client.d.ts +7 -0
  97. package/lib/src/clients/brand-page-client.d.ts +16 -15
  98. package/lib/src/clients/design-template-client.d.ts +3 -0
  99. package/lib/src/clients/media-client.d.ts +2 -2
  100. package/lib/src/clients/models.d.ts +2 -0
  101. package/lib/src/composables/useSnapshot.js +18 -18
  102. package/lib/src/css/library.brand-page-brandCrowd.min.css +371 -344
  103. package/lib/src/css/library.brand-page-brandPage.min.css +649 -344
  104. package/lib/src/css/library.brand-page-designCom.min.css +371 -344
  105. package/lib/src/css/library.brand-page-preview.min.css +627 -344
  106. package/lib/src/index.d.ts +4 -0
  107. package/lib/src/index.mjs +107 -104
  108. package/lib/src/{lib-BPI8E2Ui.js → lib-COw-Rz05.js} +37005 -33761
  109. package/lib/src/lib.js +10 -0
  110. package/lib/src/metadata-builder/builders/footer-builder.js +105 -62
  111. package/lib/src/metadata-builder/builders/section-builders/image-gallery-builder.js +68 -57
  112. package/lib/src/metadata-builder/builders/section-builders/images-section-builder.js +93 -58
  113. package/lib/src/metadata-builder/builders/section-builders/shapes-section-builder.js +99 -66
  114. package/lib/src/metadata-builder/builders/section-builders/social-links-builder.js +17 -57
  115. package/lib/src/metadata-builder/builders/section-builders/testimonial-section-builder.js +85 -51
  116. package/lib/src/metadata-builder/builders/section-builders/text-section-builder.js +74 -49
  117. package/lib/src/metadata-builder/builders/section-field-utils.d.ts +7 -0
  118. package/lib/src/metadata-builder/builders/section-field-utils.js +1 -1
  119. package/lib/src/metadata-builder/builders/shape-color-utils.js +1 -1
  120. package/lib/src/metadata-builder/parsers/ai-toolcall-parser.d.ts +7 -16
  121. package/lib/src/metadata-builder/parsers/section-tool-arguments.d.ts +48 -66
  122. package/lib/src/plugins/google-maps-plugin/google-maps-plugin.d.ts +1 -1
  123. package/lib/src/plugins/google-maps-plugin/google-maps-plugin.js +8 -8
  124. package/lib/src/shared/background-settings/components/background-shapes/BackgroundShapeSettings.mixin.d.ts +13 -13
  125. package/lib/src/shared/background-settings/store/background-settings-store.d.ts +3 -3
  126. package/lib/src/shared/color-picker/components/ColorPicker.mixin.d.ts +4 -2
  127. package/lib/src/shared/color-picker/components/ColorPicker.mixin.js +2 -2
  128. package/lib/src/shared/color-picker/components/ColorPickerSwatch.mixin.d.ts +4 -2
  129. package/lib/src/shared/color-picker/components/ColorPickerSwatch.mixin.js +1 -0
  130. package/lib/src/shared/confirm-modal/ConfirmModal.mixin.d.ts +5 -2
  131. package/lib/src/shared/confirm-modal/ConfirmModal.mixin.js +1 -0
  132. package/lib/src/shared/content-settings/components/GenericTextInput.mixin.d.ts +0 -1
  133. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +131 -129
  134. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js +2 -1
  135. package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +111 -110
  136. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +84 -81
  137. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.js +5 -0
  138. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +117 -109
  139. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.js +1 -14
  140. package/lib/src/shared/content-settings/components/email-field/EmailField.mixin.d.ts +0 -1
  141. package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.d.ts +72 -70
  142. package/lib/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.js +4 -3
  143. package/lib/src/shared/content-settings/components/form-fields-field/FormFieldsField.mixin.d.ts +4 -4
  144. package/lib/src/shared/content-settings/components/icon-library/IconLibrary.mixin.d.ts +3 -1
  145. package/lib/src/shared/content-settings/components/icon-library/IconLibrary.mixin.js +1 -0
  146. package/lib/src/shared/content-settings/components/images-field/ImagesField.mixin.d.ts +2 -2
  147. package/lib/src/shared/content-settings/components/items-field/ItemsField.mixin.d.ts +4 -3
  148. package/lib/src/shared/content-settings/components/items-field/ItemsField.mixin.js +1 -1
  149. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +40 -40
  150. package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigOptionField.mixin.d.ts +5 -6
  151. package/lib/src/shared/content-settings/components/shape-field/ShapeField.mixin.d.ts +0 -1
  152. package/lib/src/shared/content-settings/components/slider-field/SliderField.mixin.d.ts +2 -2
  153. package/lib/src/shared/content-settings/components/tel-field/TelField.mixin.d.ts +0 -1
  154. package/lib/src/shared/content-settings/components/testimonial-items-field/TestimonialItemsField.mixin.d.ts +1 -2
  155. package/lib/src/shared/content-settings/components/text-field/TextField.mixin.d.ts +0 -1
  156. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.d.ts +1 -2
  157. package/lib/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.js +1 -1
  158. package/lib/src/shared/content-settings/components/text-style-field/TextStyleField.mixin.d.ts +28 -28
  159. package/lib/src/shared/content-settings/components/textarea-field/TextareaField.mixin.d.ts +0 -1
  160. package/lib/src/shared/content-settings/components/toggle-field/ToggleField.mixin.d.ts +2 -2
  161. package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.d.ts +0 -1
  162. package/lib/src/shared/content-settings/components/youtube-video-field/YoutubeVideoField.mixin.d.ts +0 -1
  163. package/lib/src/shared/content-settings/store/content-settings-store.d.ts +39 -39
  164. package/lib/src/shared/content-settings/utils.js +0 -1
  165. package/lib/src/shared/font-family-selector/FontFamilySelector.mixin.d.ts +6 -4
  166. package/lib/src/shared/font-family-selector/FontFamilySelector.mixin.js +1 -0
  167. package/lib/src/shared/image-gallery-style-settings/ImageGalleryStyleSettings.mixin.d.ts +4 -2
  168. package/lib/src/shared/image-gallery-style-settings/ImageGalleryStyleSettings.mixin.js +1 -0
  169. package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +29 -21
  170. package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.js +1 -1
  171. package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +50 -51
  172. package/lib/src/shared/logo-settings/components/LogoSettingsHeader.mixin.d.ts +6 -4
  173. package/lib/src/shared/logo-settings/components/LogoSettingsHeader.mixin.js +1 -0
  174. package/lib/src/shared/logo-settings/store/editable-logo-store.js +1 -1
  175. package/lib/src/shared/logo-settings/store/logo-settings-store.d.ts +1 -1
  176. package/lib/src/shared/logo-versions/LogoVersions.mixin.d.ts +13 -5
  177. package/lib/src/shared/logo-versions/LogoVersions.mixin.js +1 -0
  178. package/lib/src/shared/models.d.ts +2 -0
  179. package/lib/src/shared/my-designs/MyDesigns.mixin.d.ts +14 -6
  180. package/lib/src/shared/my-designs/MyDesigns.mixin.js +1 -0
  181. package/lib/src/shared/my-uploads/MyMedia.mixin.d.ts +14 -5
  182. package/lib/src/shared/my-uploads/MyMedia.mixin.js +1 -0
  183. package/lib/src/shared/my-uploads/MyUploads.mixin.d.ts +14 -5
  184. package/lib/src/shared/my-uploads/MyUploads.mixin.js +1 -0
  185. package/lib/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.mixin.d.ts +5 -3
  186. package/lib/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.mixin.js +1 -0
  187. package/lib/src/shared/navigation-style-settings/store/index.d.ts +2 -2
  188. package/lib/src/shared/page-navigation/store/page-navigation-store.d.ts +2 -2
  189. package/lib/src/shared/page-settings/components/new-page-modal/NewPageModal.mixin.d.ts +27 -28
  190. package/lib/src/shared/page-settings/components/new-page-modal/NewPageModal.mixin.js +0 -2
  191. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +188 -179
  192. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +181 -177
  193. package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.js +1 -1
  194. package/lib/src/shared/page-settings/store/page-settings-store.d.ts +9 -9
  195. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +39 -39
  196. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.js +0 -1
  197. package/lib/src/shared/side-bar/components/SideBar.mixin.d.ts +18 -18
  198. package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +6 -6
  199. package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +66 -60
  200. package/lib/src/shared/style-settings/store/style-settings-store.d.ts +1 -1
  201. package/lib/src/shared/style-settings/store/style-settings-store.js +1 -1
  202. package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.d.ts +20 -450
  203. package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.js +2 -2
  204. package/lib/src/shared/template-settings/models.d.ts +1 -0
  205. package/lib/src/shared/template-settings/store/template-settings-store.d.ts +4 -0
  206. package/lib/src/shared/template-settings/store/template-settings-store.js +79 -11
  207. package/lib/src/shared/unsplash-library/UnsplashLibrary.mixin.d.ts +9 -4
  208. package/lib/src/utils/build-asset-manifest.d.ts +4 -0
  209. package/lib/src/utils/build-asset-manifest.js +8 -0
  210. package/lib/src/utils/minify-brand-page-metadata.d.ts +0 -2
  211. package/lib/src/utils/minify-brand-page-metadata.js +2 -17
  212. package/package.json +60 -56
  213. package/src/brand-page/components/about-section/AboutSection.vue.test.ts +7 -5
  214. package/src/brand-page/components/banner-section/BannerSection.mixin.ts +210 -0
  215. package/src/brand-page/components/banner-section/BannerSection.vue +5 -1
  216. package/src/brand-page/components/brand-page-footer/BrandPageFooter.vue +1 -1
  217. package/src/brand-page/components/image/Image.mixin.ts +1 -1
  218. package/src/brand-page/components/image/Image.test.ts +1 -1
  219. package/src/brand-page/components/image-gallery/masonry/MasonryGallery.mixin.ts +1 -2
  220. package/src/brand-page/components/images-section/ImagesSection.vue +0 -1
  221. package/src/brand-page/components/logo/LogoRender.vue +188 -188
  222. package/src/brand-page/components/navigation/hamburger/HamburgerNavigation.mixin.ts +1 -0
  223. package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.mixin.ts +25 -8
  224. package/src/brand-page/components/page-footer/PageFooter.vue +1 -0
  225. package/src/brand-page/components/page-header/HeaderLayout.vue +12 -6
  226. package/src/brand-page/components/page-header/PageHeader.vue +1 -0
  227. package/src/brand-page/components/shapes-section/ShapesSection.vue +1 -1
  228. package/src/brand-page/components/shop/CartModal.vue +1 -3
  229. package/src/brand-page/components/shop/FeaturedDisplay.vue +2 -2
  230. package/src/brand-page/components/shop/PaymentModal.vue +1 -5
  231. package/src/brand-page/components/shop/ProductDetailModal.vue +1 -1
  232. package/src/brand-page/components/shop/Shop.vue +1 -5
  233. package/src/brand-page/components/shop/TextDisplay.vue +1 -1
  234. package/src/brand-page/components/shop/ThumbnailDisplay.vue +2 -2
  235. package/src/brand-page/components/testimonial-section/TestimonialSection.vue +3 -3
  236. package/src/brand-page/components/text-wrapper/TextWrapper.vue +3 -1
  237. package/src/brand-page/constants/sections/footer-display.constants.ts +1 -1
  238. package/src/brand-page/models/index.ts +4 -12
  239. package/src/brand-page/models/payment.model.ts +2 -1
  240. package/src/brand-page/models/shop.model.ts +0 -2
  241. package/src/brand-page/models/user-personalisation.model.ts +1 -2
  242. package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +3 -0
  243. package/src/brand-page/utils/__snapshots__/migration2.util.test.ts.snap +1 -0
  244. package/src/brand-page/utils/__snapshots__/model.util.test.ts.snap +2 -0
  245. package/src/brand-page/utils/migration/migration-01_1.ts +1 -1
  246. package/src/brand-page/utils/migration/migration-02.ts +0 -1
  247. package/src/brand-page/utils/migration/migration-03.ts +0 -1
  248. package/src/brand-page/utils/migration/migration-04.ts +0 -1
  249. package/src/brand-page/utils/migration/migration-05.ts +1 -5
  250. package/src/brand-page/utils/migration/migration-05_2.ts +1 -1
  251. package/src/brand-page/utils/migration/migration-08.test.ts +1 -1
  252. package/src/brand-page/utils/personalisation.util.test.ts +35 -0
  253. package/src/brand-page/utils/personalisation.util.ts +119 -23
  254. package/src/brand-page/view-models.ts +38 -56
  255. package/src/brand-page-maker/assessors/banner-section-description-visibility.assessor.ts +6 -6
  256. package/src/brand-page-maker/assessors/color-replacement-icon-visibility.assessor.ts +2 -2
  257. package/src/brand-page-maker/assessors/color-replacement-profile-visibility.assessor.ts +2 -2
  258. package/src/brand-page-maker/assessors/color-replacement-visibility.assessor.ts +2 -2
  259. package/src/brand-page-maker/assessors/contact-form-visibility.assessor.ts +14 -14
  260. package/src/brand-page-maker/components/action-bar/ActionBar.mixin.ts +1 -0
  261. package/src/brand-page-maker/components/ai-text-edit/AiActionButtons.vue +27 -12
  262. package/src/brand-page-maker/components/ai-text-edit/AiChatbox.vue +3 -2
  263. package/src/brand-page-maker/components/ai-text-edit/TextBubble.vue +8 -7
  264. package/src/brand-page-maker/components/ai-website-builder/AiWebsiteBuilder.vue +21 -1
  265. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +5 -1
  266. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.ts +1 -0
  267. package/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.stories.ts +2 -5
  268. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +0 -5
  269. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-payment.ts +0 -8
  270. package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-site-template.examples.ts +0 -2
  271. package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.vue +1 -0
  272. package/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.ts +1 -1
  273. package/src/brand-page-maker/components/color-palette/BpColorPalette.vue +1 -2
  274. package/src/brand-page-maker/components/color-picker/components/ColorModeSelect.mixin.ts +1 -0
  275. package/src/brand-page-maker/components/color-picker/components/GradientColorSlider.mixin.ts +1 -0
  276. package/src/brand-page-maker/components/color-picker/components/GradientColorSliderHandler.mixin.ts +1 -0
  277. package/src/brand-page-maker/components/color-picker/components/GradientTypeSelector.mixin.ts +1 -0
  278. package/src/brand-page-maker/components/device/Device.mixin.ts +1 -0
  279. package/src/brand-page-maker/components/navigation/Navigation.mixin.ts +1 -0
  280. package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +3 -1
  281. package/src/brand-page-maker/components/sensitive-content/SensitiveContent.vue +1 -4
  282. package/src/brand-page-maker/components/seo-settings/DeleteDomainModal.vue +1 -1
  283. package/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.ts +1 -0
  284. package/src/brand-page-maker/components/seo-settings/SeoPageSettings.vue +1 -1
  285. package/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.ts +0 -1
  286. package/src/brand-page-maker/components/seo-settings/UrlSettings.vue +0 -1
  287. package/src/brand-page-maker/components/seo-settings/UseExistingDomainModal.vue +1 -5
  288. package/src/brand-page-maker/components/shop/AddOrEditProductContainer.vue +1 -1
  289. package/src/brand-page-maker/components/shop/ReplaceImageSettingsForShop.vue +1 -1
  290. package/src/brand-page-maker/components/social-share/SocialShare.vue +1 -1
  291. package/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.ts +22 -8
  292. package/src/brand-page-maker/components/template-preview/TemplatePreview.vue +5 -10
  293. package/src/brand-page-maker/components/template-preview/TemplatePreviewAiBadge.vue +12 -0
  294. package/src/brand-page-maker/components/video-play/VideoPlayButton.vue +1 -1
  295. package/src/brand-page-maker/composables/ai-chat/types.ts +6 -0
  296. package/src/brand-page-maker/composables/ai-chat/ui-actions.test.ts +80 -0
  297. package/src/brand-page-maker/composables/ai-chat/ui-actions.ts +58 -0
  298. package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +308 -262
  299. package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +6 -6
  300. package/src/brand-page-maker/composables/useEventTracker.ts +1 -0
  301. package/src/brand-page-maker/constants/config-settings-constant.ts +5 -5
  302. package/src/brand-page-maker/convertors/text-image-display-style.convertor.ts +1 -1
  303. package/src/brand-page-maker/models/button-styles-config.ts +4 -2
  304. package/src/brand-page-maker/models/content-settings-configs.ts +4 -2
  305. package/src/brand-page-maker/models/navigation-style-configs.ts +5 -6
  306. package/src/brand-page-maker/stores/admin-logo-settings/admin-logo-settings-store.ts +0 -1
  307. package/src/brand-page-maker/stores/brandpage-container/brand-page-container-store.ts +8 -5
  308. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.test.ts +1 -3
  309. package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +12 -4
  310. package/src/brand-page-maker/stores/ui/ui-store.ts +16 -0
  311. package/src/brand-page-maker/utils/content-settings.util.ts +1 -1
  312. package/src/brand-page-maker/utils/rich-text-editor.util.ts +4 -4
  313. package/src/clients/ai-assistant-client.ts +7 -0
  314. package/src/clients/design-template-client.ts +3 -0
  315. package/src/clients/models.ts +2 -0
  316. package/src/composables/useSnapshot.ts +19 -22
  317. package/src/lib.ts +12 -0
  318. package/src/metadata-builder/builders/footer-builder.test.ts +130 -229
  319. package/src/metadata-builder/builders/footer-builder.ts +155 -90
  320. package/src/metadata-builder/builders/section-builders/image-gallery-builder.ts +88 -62
  321. package/src/metadata-builder/builders/section-builders/images-section-builder.ts +129 -66
  322. package/src/metadata-builder/builders/section-builders/shapes-section-builder.ts +160 -105
  323. package/src/metadata-builder/builders/section-builders/social-links-builder.ts +20 -65
  324. package/src/metadata-builder/builders/section-builders/testimonial-section-builder.ts +146 -83
  325. package/src/metadata-builder/builders/section-builders/text-section-builder.ts +122 -70
  326. package/src/metadata-builder/builders/section-field-utils.ts +1 -1
  327. package/src/metadata-builder/builders/shape-color-utils.ts +2 -2
  328. package/src/metadata-builder/parsers/ai-toolcall-parser.ts +7 -16
  329. package/src/metadata-builder/parsers/section-tool-arguments.ts +48 -66
  330. package/src/plugins/google-maps-plugin/google-maps-plugin.ts +8 -8
  331. package/src/shared/background-settings/components/BackgroundSettings.vue +1 -1
  332. package/src/shared/background-settings/components/background-color/BackgroundColorSettings.vue +1 -1
  333. package/src/shared/color-picker/components/ColorPicker.mixin.ts +2 -7
  334. package/src/shared/color-picker/components/ColorPickerSwatch.mixin.ts +1 -0
  335. package/src/shared/common/NumberInput.vue +1 -0
  336. package/src/shared/common/SideBarSettingsHeader.vue +2 -2
  337. package/src/shared/confirm-modal/ConfirmModal.mixin.ts +1 -0
  338. package/src/shared/content-settings/components/booking-url-field/BookingUrlField.vue +1 -0
  339. package/src/shared/content-settings/components/button-configuration-field/ButtonConfigurationField.vue +1 -0
  340. package/src/shared/content-settings/components/color-field/ColorField.vue +3 -10
  341. package/src/shared/content-settings/components/content-settings/ContentSettings.mixin.ts +1 -1
  342. package/src/shared/content-settings/components/content-settings/ContentSettingsLockedButton.vue +1 -0
  343. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.ts +5 -0
  344. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.ts +1 -14
  345. package/src/shared/content-settings/components/focused-content-item-settings/FocusedContentItemSettings.mixin.ts +4 -6
  346. package/src/shared/content-settings/components/icon-library/IconLibrary.mixin.ts +1 -0
  347. package/src/shared/content-settings/components/items-field/ItemsField.mixin.ts +1 -1
  348. package/src/shared/content-settings/components/logo-selection-field/LogoSelectionField.vue +1 -1
  349. package/src/shared/content-settings/components/logo-size-field/LogoSizeSliderField.vue +1 -1
  350. package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.vue +1 -1
  351. package/src/shared/content-settings/components/personalisation-role-field/PersonalisationRoleField.vue +4 -4
  352. package/src/shared/content-settings/components/text-image-field/TextImageField.vue +2 -8
  353. package/src/shared/content-settings/components/text-items-field/TextItemsField.mixin.ts +1 -1
  354. package/src/shared/content-settings/models.ts +3 -2
  355. package/src/shared/content-settings/utils.ts +0 -1
  356. package/src/shared/dropzone-image-uploader/components/DropzoneImageUploader.vue +1 -0
  357. package/src/shared/ecommerce-settings/store/cart-store.test.ts +1 -1
  358. package/src/shared/font-family-selector/FontFamilySelector.mixin.ts +1 -0
  359. package/src/shared/image-gallery-style-settings/ImageGalleryStyleSettings.mixin.ts +1 -0
  360. package/src/shared/logo-settings/components/EditLogoSettings.mixin.ts +1 -1
  361. package/src/shared/logo-settings/components/LogoSettings.mixin.ts +0 -1
  362. package/src/shared/logo-settings/components/LogoSettingsHeader.mixin.ts +1 -0
  363. package/src/shared/logo-settings/components/LogoStyleSettingsWithState.vue +2 -2
  364. package/src/shared/logo-settings/components/LogoTemplateSearch.vue +1 -1
  365. package/src/shared/logo-settings/store/editable-logo-store.ts +1 -1
  366. package/src/shared/logo-settings/store/logo-settings-store.test.ts +4 -4
  367. package/src/shared/logo-versions/LogoVersions.mixin.ts +1 -0
  368. package/src/shared/models.ts +6 -0
  369. package/src/shared/my-designs/MyDesigns.mixin.ts +1 -0
  370. package/src/shared/my-uploads/MyMedia.mixin.ts +1 -0
  371. package/src/shared/my-uploads/MyMediaSelectionItem.vue +2 -1
  372. package/src/shared/my-uploads/MyUploads.mixin.ts +1 -0
  373. package/src/shared/my-uploads/models.ts +1 -2
  374. package/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.mixin.ts +1 -0
  375. package/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.vue +1 -1
  376. package/src/shared/page-settings/components/new-page-modal/NewPageModal.mixin.ts +0 -3
  377. package/src/shared/page-settings/components/page-settings/NestedDraggable.vue +1 -1
  378. package/src/shared/page-settings/components/page-settings/PageSettings.vue +1 -2
  379. package/src/shared/page-settings/components/page-settings-section-styles/HeaderDisplayStyle.vue +1 -1
  380. package/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.ts +1 -1
  381. package/src/shared/page-settings/store/page-settings-store.test.ts +4 -8
  382. package/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.ts +0 -1
  383. package/src/shared/shape-library/ShapeLibrary.vue +2 -2
  384. package/src/shared/style-settings/store/style-settings-store.ts +1 -1
  385. package/src/shared/template-settings/components/TemplatesSettings.mixin.ts +2 -2
  386. package/src/shared/template-settings/models.ts +1 -0
  387. package/src/shared/template-settings/store/template-settings-store.ts +105 -18
  388. package/src/shared/unsplash-library/UnsplashLibrary.vue +2 -6
  389. package/src/shared/video-library/VideoLibrary.vue +1 -1
  390. package/src/utils/build-asset-manifest.ts +12 -0
  391. package/src/utils/minify-brand-page-metadata.ts +7 -27
  392. package/lib/src/metadata-builder/builders/item-id-utils.d.ts +0 -54
  393. package/lib/src/metadata-builder/builders/item-id-utils.js +0 -96
  394. package/src/metadata-builder/builders/item-id-utils.test.ts +0 -184
  395. package/src/metadata-builder/builders/item-id-utils.ts +0 -117
@@ -1,5 +1,7 @@
1
1
  import type { ComputedRef, Ref } from 'vue';
2
2
  import { type PlanItem } from '../../../clients/websocket-gateway-client';
3
+ import type { AgentAction } from './ui-actions';
4
+ export type { AgentAction };
3
5
  export interface BaseThreadMessage {
4
6
  id: string;
5
7
  role: 'user' | 'agent';
@@ -14,6 +16,7 @@ export interface TextThreadMessage extends BaseThreadMessage {
14
16
  initialMessage?: string;
15
17
  planItems?: PlanItem[];
16
18
  completedItemIds?: string[];
19
+ actions?: AgentAction[];
17
20
  }
18
21
  export interface ImageThreadMessage extends BaseThreadMessage {
19
22
  type: 'image';
@@ -0,0 +1,29 @@
1
+ import type { AiAssistantToolCall } from '../../../clients/ai-assistant-client';
2
+ export declare const UI_ACTIONS: {
3
+ readonly UPGRADE: "upgrade";
4
+ };
5
+ export declare const AI_CHAT_UI_ACTIONS: {
6
+ readonly upgrade: {
7
+ readonly label: "Upgrade";
8
+ readonly icon: "upgrade-alt";
9
+ };
10
+ };
11
+ export type AgentActionType = keyof typeof AI_CHAT_UI_ACTIONS;
12
+ export type AgentAction = {
13
+ type: AgentActionType;
14
+ label: string;
15
+ icon?: string;
16
+ };
17
+ /**
18
+ * Split server tool calls into page mutations and UI-action CTAs.
19
+ *
20
+ * Mutations are executed by the metadata-builder and answered with tool results;
21
+ * UI actions (e.g. the Upgrade button) are rendered only. UI actions MUST stay out
22
+ * of `mutationToolCalls`: they are never executed and never get a tool result, so
23
+ * leaking one into the mutation set would leave an unresolved tool call and break
24
+ * the next LLM turn on the same thread.
25
+ */
26
+ export declare function partitionAiToolCalls(toolCalls: AiAssistantToolCall[]): {
27
+ mutationToolCalls: AiAssistantToolCall[];
28
+ actions: AgentAction[];
29
+ };
@@ -0,0 +1,32 @@
1
+ // Action identities — must match the tool names emitted by the AI pipeline.
2
+ export const UI_ACTIONS = {
3
+ UPGRADE: 'upgrade',
4
+ };
5
+ export const AI_CHAT_UI_ACTIONS = {
6
+ [UI_ACTIONS.UPGRADE]: { label: 'Upgrade', icon: 'upgrade-alt' },
7
+ };
8
+ // `hasOwnProperty` (not `in`) so inherited Object keys like "constructor" are never
9
+ // mistaken for a UI action.
10
+ const isUiActionFn = (fn) => !!fn && Object.prototype.hasOwnProperty.call(AI_CHAT_UI_ACTIONS, fn);
11
+ /**
12
+ * Split server tool calls into page mutations and UI-action CTAs.
13
+ *
14
+ * Mutations are executed by the metadata-builder and answered with tool results;
15
+ * UI actions (e.g. the Upgrade button) are rendered only. UI actions MUST stay out
16
+ * of `mutationToolCalls`: they are never executed and never get a tool result, so
17
+ * leaking one into the mutation set would leave an unresolved tool call and break
18
+ * the next LLM turn on the same thread.
19
+ */
20
+ export function partitionAiToolCalls(toolCalls) {
21
+ const mutationToolCalls = [];
22
+ const actions = [];
23
+ for (const tc of toolCalls) {
24
+ if (isUiActionFn(tc.function)) {
25
+ actions.push({ type: tc.function, ...AI_CHAT_UI_ACTIONS[tc.function] });
26
+ }
27
+ else {
28
+ mutationToolCalls.push(tc);
29
+ }
30
+ }
31
+ return { mutationToolCalls, actions };
32
+ }
@@ -1,12 +1,12 @@
1
- import { ref, computed, watch, nextTick, onUnmounted } from 'vue';
1
+ import { ref, computed, watch, nextTick } from 'vue';
2
2
  import { getInstance as getAiAssistantClient, AI_ASSISTANT_AGENT_TYPES, } from '../../../clients/ai-assistant-client';
3
3
  import { FabricRenderClient } from '../../../clients/fabric-render-client';
4
4
  import { parseLogoThemeToCssStyles } from '../../../brand-page/utils/style.util';
5
5
  import { AI_ASSISTANT_TOOL_NAMES } from '../../../metadata-builder/parsers/ai-toolcall-parser';
6
6
  import { WebSocketGatewayClient, } from '../../../clients/websocket-gateway-client';
7
7
  import { minifyBrandPageMetadata } from '../../../utils/minify-brand-page-metadata';
8
- import { ensureBrandPageItemIds } from '../../../metadata-builder/builders/item-id-utils';
9
8
  import { buildAssetManifest } from '../../../utils/build-asset-manifest';
9
+ import cloneDeep from 'lodash.clonedeep';
10
10
  import { usePageNavigationStore } from '../../../shared/page-navigation/store/page-navigation-store';
11
11
  import { navigateToPageByPageId } from '../../routing';
12
12
  import { useSnapshotStore, useAiWebsiteBuilderThreadStore, useAiCheckpointStore, useBrandPageContainerStore, useUiStore, } from '../../stores';
@@ -19,6 +19,7 @@ import { pickErrorMessage, pickWsErrorMessage, buildSubmitErrorReport, } from '.
19
19
  import raygunUtil from '../../../brand-page/utils/raygun.util';
20
20
  import { useEventTracker, AI_CTA_LOCATIONS } from '../useEventTracker';
21
21
  import { Logger } from '../../../metadata-builder/logger';
22
+ import { partitionAiToolCalls } from './ui-actions';
22
23
  const BUILD_TIMEOUT_MS = 600000;
23
24
  const aiLogger = new Logger();
24
25
  let activeBuildWsClient = null;
@@ -178,10 +179,6 @@ export function useAiWebsiteBuilderChat() {
178
179
  };
179
180
  const buildMessagePayload = async (userPrompt) => {
180
181
  const brandPageData = brandPageMakerStore.brandPageData;
181
- // BP-5603: stamp stable uuid ids onto every nested item BEFORE minifying,
182
- // so the id the AI is shown (and returns as `item_id`) is the exact id the
183
- // executor matches when applying tool calls to this same live model.
184
- ensureBrandPageItemIds(brandPageData);
185
182
  const headerLogoDraftToken = brandPageData.pageHeaderDesktop?.logoImage?.logoDraftToken ??
186
183
  uiStore.logoDraftToken;
187
184
  const [assets, logoContext] = await Promise.all([
@@ -192,6 +189,7 @@ export function useAiWebsiteBuilderChat() {
192
189
  const currentPageId = pageNavigationStore.activePageId;
193
190
  const websiteContext = {
194
191
  metadata: minifyBrandPageMetadata(brandPageData, assets),
192
+ metadataFull: cloneDeep(brandPageData),
195
193
  ...(assets.length > 0 && { assets }),
196
194
  websiteTemplateToken: containerStore.designTemplateToken,
197
195
  ...(containerStore.designDraftToken && {
@@ -375,6 +373,7 @@ export function useAiWebsiteBuilderChat() {
375
373
  let settled = false;
376
374
  let retryCount = 0;
377
375
  let lastAiMessage = null;
376
+ let lastActions;
378
377
  let handler = null;
379
378
  // Vacant-slot queue scoped to this build session. Persists across
380
379
  // retry rounds so a failed CREATE returns to its planned slot via
@@ -394,190 +393,206 @@ export function useAiWebsiteBuilderChat() {
394
393
  finishBuild();
395
394
  reject(new Error('Build timeout'));
396
395
  }, BUILD_TIMEOUT_MS);
397
- handler = (msg) => {
396
+ // Transition the build to "done" exactly once (idempotent). Returns
397
+ // false when already settled, so callers can early-return.
398
+ const markDone = () => {
398
399
  if (settled)
399
- return;
400
+ return false;
401
+ settled = true;
402
+ clearTimeout(timeout);
403
+ finishBuild();
404
+ return true;
405
+ };
406
+ // The single terminal path. Every resolve goes through here, so "where
407
+ // does this Promise settle?" has one answer.
408
+ const settle = (result) => {
409
+ if (markDone())
410
+ resolve(result);
411
+ };
412
+ // Streaming progress frames mutate the in-flight typing bubble and never
413
+ // settle the build. Returns true when `msg` was a progress frame.
414
+ const applyProgressUpdate = (msg) => {
415
+ if (msg.type === 'chat_started' && msg.message) {
416
+ withTypingMessage((m) => {
417
+ m.initialMessage = msg.message;
418
+ });
419
+ return true;
420
+ }
421
+ if (msg.type === 'plan_announced' && msg.items) {
422
+ withTypingMessage((m) => {
423
+ if (!m.planItems)
424
+ m.planItems = msg.items;
425
+ });
426
+ return true;
427
+ }
428
+ if (msg.type === 'item_complete' && msg.itemId) {
429
+ const itemId = msg.itemId;
430
+ withTypingMessage((m) => {
431
+ if (!m.completedItemIds?.includes(itemId)) {
432
+ m.completedItemIds = [...(m.completedItemIds ?? []), itemId];
433
+ }
434
+ });
435
+ return true;
436
+ }
437
+ return false;
438
+ };
439
+ // Apply one round of build tool calls: settle on completion/failure, or
440
+ // bump retryCount so the handler processes the next round's frame.
441
+ const processServerResponse = async (aiResponse) => {
442
+ const toolCalls = aiResponse.toolCalls ?? [];
400
443
  try {
401
- if (msg.buildId !== aiThreadStore.buildId)
402
- return;
403
- if (isStopped.value) {
404
- settled = true;
405
- clearTimeout(timeout);
406
- finishBuild();
407
- resolve({ text: null });
408
- return;
409
- }
410
- if (msg.type === 'chat_started' && msg.message) {
411
- withTypingMessage((m) => {
412
- m.initialMessage = msg.message;
444
+ // No tool calls = build cycle complete (success, max retries, or no retryable sections).
445
+ if (toolCalls.length === 0) {
446
+ // Defence-in-depth: empty toolCalls AND empty message is a
447
+ // degenerate response (graph reached END producing nothing). Never
448
+ // show "Your website has been updated" — it hides real failures.
449
+ const hasMeaningfulMessage = Boolean(aiResponse.message || lastAiMessage);
450
+ if (!hasMeaningfulMessage) {
451
+ raygunUtil.safeSendRaygunError(new Error('AI build server_response had empty toolCalls and empty message'), {
452
+ tags: [
453
+ 'feature:ai-website-builder',
454
+ 'failure:degenerate_server_response',
455
+ ],
456
+ customData: {
457
+ build_id: aiThreadStore.buildId ?? null,
458
+ thread_id: aiThreadStore.threadId ?? null,
459
+ },
460
+ });
461
+ settle({
462
+ text: 'Something went wrong while updating your website. Please try again.',
463
+ isError: true,
464
+ });
465
+ return;
466
+ }
467
+ // Mark settled BEFORE the await so concurrent frames are ignored.
468
+ if (!markDone())
469
+ return;
470
+ await snapshotStore.refreshSnapshotAsync();
471
+ resolve({
472
+ text: aiResponse.message || lastAiMessage || '',
473
+ actions: lastActions,
413
474
  });
414
475
  return;
415
476
  }
416
- if (msg.type === 'plan_announced' && msg.items) {
417
- withTypingMessage((m) => {
418
- if (!m.planItems)
419
- m.planItems = msg.items;
477
+ // Tool calls present — apply locally and submit results back.
478
+ const { toolResults, aiMessage } = await applyToolCallsAsync(aiResponse, userMessageId, vacantSlots);
479
+ lastAiMessage = aiMessage;
480
+ // Submit all tool results (success + failure) so the AI pipeline
481
+ // persists ToolMessages matching every tool_call in the conversation.
482
+ const failedResults = toolResults.filter((tr) => tr.success !== 'success');
483
+ aiLogger.log('tool submission for results', {
484
+ total: toolResults.length,
485
+ failed: failedResults.length,
486
+ failedResults,
487
+ retryCount,
488
+ });
489
+ const submitResult = await client.submitToolResultsBuildAsync(aiThreadStore.threadId, {
490
+ toolCalls: toolResults,
491
+ agentType: AI_ASSISTANT_AGENT_TYPES.WEBSITE_BUILDER,
492
+ connectionId,
493
+ retryCount,
494
+ userPlan,
495
+ });
496
+ if (failedResults.length === 0) {
497
+ settle({
498
+ text: aiMessage || 'Your website has been updated.',
499
+ actions: lastActions,
420
500
  });
421
501
  return;
422
502
  }
423
- if (msg.type === 'item_complete' && msg.itemId) {
424
- const itemId = msg.itemId;
425
- withTypingMessage((m) => {
426
- if (!m.completedItemIds?.includes(itemId)) {
427
- m.completedItemIds = [
428
- ...(m.completedItemIds ?? []),
429
- itemId,
430
- ];
431
- }
432
- });
503
+ // Failed sections will retry: refresh buildId so the handler matches
504
+ // the next round's frames, and count the round.
505
+ if (submitResult.buildId) {
506
+ aiThreadStore.buildId = submitResult.buildId;
507
+ }
508
+ retryCount += 1;
509
+ }
510
+ catch (err) {
511
+ aiLogger.log('server_response apply error', { err });
512
+ // Client-side apply failure (metadata builder, tool-call parser,
513
+ // missing field, etc.) — the server thinks the build succeeded but we
514
+ // couldn't materialise the changes. Surface it and report to Raygun
515
+ // (the server didn't see this failure).
516
+ raygunUtil.safeSendRaygunError(err instanceof Error
517
+ ? err
518
+ : new Error('AI apply failed: non-Error thrown'), {
519
+ tags: [
520
+ 'feature:ai-website-builder',
521
+ 'failure:apply_error',
522
+ 'stage:client_apply',
523
+ ],
524
+ customData: {
525
+ thread_id: aiThreadStore.threadId ?? null,
526
+ build_id: aiThreadStore.buildId ?? null,
527
+ },
528
+ });
529
+ settle({
530
+ text: "I couldn't apply those changes to your website. Please try again.",
531
+ isError: true,
532
+ });
533
+ }
534
+ };
535
+ const handleBuildError = (msg) => {
536
+ if (!markDone())
537
+ return;
538
+ // Backend already reports the underlying pipeline failure to Raygun
539
+ // (with full traceback). We report the frontend's RECEIPT of the error
540
+ // frame as a separate signal — distinct tag/grouping — for triangulation:
541
+ // both sides → normal crash; frontend only → backend Raygun outage;
542
+ // backend only → WS frame didn't reach client.
543
+ const wsMsg = msg;
544
+ raygunUtil.safeSendRaygunError(new Error(`AI build ${wsMsg.type}: ${wsMsg.code ?? wsMsg.error ?? 'unknown'}`), {
545
+ tags: [
546
+ 'feature:ai-website-builder',
547
+ 'failure:websocket_error_received',
548
+ `frame_type:${wsMsg.type}`,
549
+ ],
550
+ customData: {
551
+ code: wsMsg.code ?? null,
552
+ message: wsMsg.message ?? null,
553
+ error: wsMsg.error ?? null,
554
+ build_id: wsMsg.buildId ?? null,
555
+ thread_id: aiThreadStore.threadId ?? null,
556
+ },
557
+ });
558
+ resolve({ text: pickWsErrorMessage(msg), isError: true });
559
+ };
560
+ // Single dispatch point: ignore stale/already-settled frames, then route
561
+ // by frame kind. Progress frames update the bubble; server_response and
562
+ // error frames are the only ones that can settle the build.
563
+ handler = (msg) => {
564
+ if (settled)
565
+ return;
566
+ try {
567
+ if (msg.buildId !== aiThreadStore.buildId)
568
+ return;
569
+ if (isStopped.value) {
570
+ settle({ text: null });
433
571
  return;
434
572
  }
573
+ if (applyProgressUpdate(msg))
574
+ return;
435
575
  if (msg.type === 'server_response') {
436
- const toolCalls = (msg.toolCalls ||
437
- []);
438
- const aiResponse = {
576
+ // CTA buttons (e.g. Upgrade) ride in toolCalls but are presentation,
577
+ // not page edits. Split them out so only real mutations reach the
578
+ // metadata-builder and the tool-result submission — a UI action must
579
+ // never be answered with a tool result (it isn't in the agent's
580
+ // conversation), or the next turn on the thread fails.
581
+ const { mutationToolCalls, actions } = partitionAiToolCalls((msg.toolCalls || []));
582
+ if (actions.length)
583
+ lastActions = actions;
584
+ void processServerResponse({
439
585
  threadId: aiThreadStore.threadId || '',
440
- toolCalls,
586
+ toolCalls: mutationToolCalls,
441
587
  message: msg.message || null,
442
588
  type: 'tool_calls',
443
589
  totalPaidToolCalls: 0,
444
590
  timestamp: Date.now(),
445
- };
446
- (async () => {
447
- try {
448
- // No tool calls = build cycle complete (success, max retries, or no retryable sections)
449
- if (toolCalls.length === 0) {
450
- // Defence-in-depth: a server_response with no toolCalls AND
451
- // no message text is a degenerate response — it means the
452
- // backend graph reached END without producing anything
453
- // actionable. The server-side fix in stream_with_push now
454
- // converts this to a build_error frame, but if a future
455
- // regression slips through we must NOT show "Your website
456
- // has been updated" — that hides real failures from users
457
- // and from monitoring.
458
- const hasMeaningfulMessage = Boolean(aiResponse.message || lastAiMessage);
459
- if (!hasMeaningfulMessage) {
460
- raygunUtil.safeSendRaygunError(new Error('AI build server_response had empty toolCalls and empty message'), {
461
- tags: [
462
- 'feature:ai-website-builder',
463
- 'failure:degenerate_server_response',
464
- ],
465
- customData: {
466
- build_id: aiThreadStore.buildId ?? null,
467
- thread_id: aiThreadStore.threadId ?? null,
468
- },
469
- });
470
- settled = true;
471
- clearTimeout(timeout);
472
- finishBuild();
473
- resolve({
474
- text: 'Something went wrong while updating your website. Please try again.',
475
- isError: true,
476
- });
477
- return;
478
- }
479
- settled = true;
480
- clearTimeout(timeout);
481
- finishBuild();
482
- resolve({
483
- text: aiResponse.message || lastAiMessage || '',
484
- });
485
- return;
486
- }
487
- // Tool calls present — apply locally and submit results back
488
- const { toolResults, aiMessage } = await applyToolCallsAsync(aiResponse, userMessageId, vacantSlots);
489
- lastAiMessage = aiMessage;
490
- // Submit all tool results (success + failure) so the AI pipeline
491
- // persists ToolMessages matching every tool_call in the conversation.
492
- const failedResults = toolResults.filter((tr) => tr.success !== 'success');
493
- aiLogger.log('tool submission for results', {
494
- total: toolResults.length,
495
- failed: failedResults.length,
496
- failedResults,
497
- retryCount,
498
- });
499
- const submitResult = await client.submitToolResultsBuildAsync(aiThreadStore.threadId, {
500
- toolCalls: toolResults,
501
- agentType: AI_ASSISTANT_AGENT_TYPES.WEBSITE_BUILDER,
502
- connectionId,
503
- retryCount,
504
- userPlan,
505
- });
506
- if (failedResults.length === 0) {
507
- settled = true;
508
- clearTimeout(timeout);
509
- finishBuild();
510
- resolve({
511
- text: aiMessage || 'Your website has been updated.',
512
- });
513
- return;
514
- }
515
- // Update buildId so the handler matches subsequent WS messages
516
- if (submitResult.buildId) {
517
- aiThreadStore.buildId = submitResult.buildId;
518
- }
519
- // eslint-disable-next-line no-plusplus
520
- retryCount++;
521
- }
522
- catch (err) {
523
- aiLogger.log('server_response apply error', { err });
524
- // Client-side apply failure (metadata builder, tool-call parser,
525
- // missing field, etc.) — server thinks the build succeeded but we
526
- // couldn't materialise the changes. Mark the chat bubble as an
527
- // error so the user sees the real outcome, and report to Raygun
528
- // so the failure is visible in monitoring (the server didn't see it).
529
- raygunUtil.safeSendRaygunError(err instanceof Error
530
- ? err
531
- : new Error('AI apply failed: non-Error thrown'), {
532
- tags: [
533
- 'feature:ai-website-builder',
534
- 'failure:apply_error',
535
- 'stage:client_apply',
536
- ],
537
- customData: {
538
- thread_id: aiThreadStore.threadId ?? null,
539
- build_id: aiThreadStore.buildId ?? null,
540
- },
541
- });
542
- settled = true;
543
- clearTimeout(timeout);
544
- finishBuild();
545
- resolve({
546
- text: "I couldn't apply those changes to your website. Please try again.",
547
- isError: true,
548
- });
549
- }
550
- })();
591
+ });
551
592
  return;
552
593
  }
553
594
  if (msg.type === 'server_error' || msg.type === 'build_error') {
554
- settled = true;
555
- clearTimeout(timeout);
556
- finishBuild();
557
- // Backend already reports the underlying pipeline failure to
558
- // Raygun via its structured handler (stage:run_build /
559
- // stage:section_builder / etc. with full Python traceback).
560
- // We report the frontend's RECEIPT of the error frame as a
561
- // separate signal — distinct tag, distinct grouping. This
562
- // gives triangulation: both sides have entry → normal crash;
563
- // frontend only → backend Raygun outage; backend only → WS
564
- // frame didn't reach client (different bug shape).
565
- const wsMsg = msg;
566
- raygunUtil.safeSendRaygunError(new Error(`AI build ${wsMsg.type}: ${wsMsg.code ?? wsMsg.error ?? 'unknown'}`), {
567
- tags: [
568
- 'feature:ai-website-builder',
569
- 'failure:websocket_error_received',
570
- `frame_type:${wsMsg.type}`,
571
- ],
572
- customData: {
573
- code: wsMsg.code ?? null,
574
- message: wsMsg.message ?? null,
575
- error: wsMsg.error ?? null,
576
- build_id: wsMsg.buildId ?? null,
577
- thread_id: aiThreadStore.threadId ?? null,
578
- },
579
- });
580
- resolve({ text: pickWsErrorMessage(msg), isError: true });
595
+ handleBuildError(msg);
581
596
  return;
582
597
  }
583
598
  }
@@ -586,12 +601,10 @@ export function useAiWebsiteBuilderChat() {
586
601
  err,
587
602
  type: msg.type,
588
603
  });
589
- if (!settled) {
590
- settled = true;
591
- clearTimeout(timeout);
592
- finishBuild();
593
- resolve({ text: 'An error occurred during the build.' });
594
- }
604
+ settle({
605
+ text: 'An error occurred during the build.',
606
+ isError: true,
607
+ });
595
608
  }
596
609
  };
597
610
  wsClient.onMessage(handler);
@@ -677,6 +690,15 @@ export function useAiWebsiteBuilderChat() {
677
690
  if (result.isError) {
678
691
  threadItems.value[messageIndex].isError = true;
679
692
  }
693
+ // Attach agent-driven actions (e.g. upgrade CTA) only on successful
694
+ // (non-error) responses. Suppressed for premium users client-side as
695
+ // a defence-in-depth guard (server also vetoes via eligibility logic).
696
+ if (!result.isError &&
697
+ result.actions?.length &&
698
+ !userStore.hasPremiumSubscription) {
699
+ threadItems.value[messageIndex].actions =
700
+ result.actions;
701
+ }
680
702
  }
681
703
  else {
682
704
  threadItems.value[messageIndex].text =
@@ -763,6 +785,11 @@ export function useAiWebsiteBuilderChat() {
763
785
  planItems: msg.planItems ?? [],
764
786
  completedItemIds: msg.completedItemIds ?? [],
765
787
  }),
788
+ ...(msg.type === 'text' &&
789
+ !msg.isTyping &&
790
+ msg.actions?.length && {
791
+ actions: msg.actions,
792
+ }),
766
793
  },
767
794
  };
768
795
  });
@@ -71,7 +71,7 @@ export declare const useRichTextEditor: (model: ModelRef<any>, props: {
71
71
  textItemIndex: number;
72
72
  item: TextItem;
73
73
  contentType: string;
74
- }, emit: (event: 'focus' | 'blur' | 'update:modelValue', ...args: any[]) => void, fontSettings: {
74
+ }, emit: (event: "focus" | "blur" | "update:modelValue", ...args: any[]) => void, fontSettings: {
75
75
  selectedTextStyle: string;
76
76
  selectedFont: string;
77
77
  selectedFontSize: string;
@@ -368,13 +368,13 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
368
368
  fontSettings.selectedFontSizePx = Math.ceil(parseFloat(emToPx(globalStyles?.fontSize ?? '2.25em')));
369
369
  fontSettings.selectedTextColor = hasLogoColorVar(globalStyles.color ?? '')
370
370
  ? '#000000'
371
- : globalStyles?.color ?? '#000000';
371
+ : (globalStyles?.color ?? '#000000');
372
372
  fontSettings.selectedBackgroundColor = hasLogoColorVar(globalStyles?.backgroundColor ?? '')
373
373
  ? 'transparent'
374
- : globalStyles?.backgroundColor ?? 'transparent';
374
+ : (globalStyles?.backgroundColor ?? 'transparent');
375
375
  lineHeight.value = globalStyles?.lineHeight?.includes('em')
376
376
  ? emToPx(globalStyles?.lineHeight ?? '1em')
377
- : globalStyles?.lineHeight ?? '1';
377
+ : (globalStyles?.lineHeight ?? '1');
378
378
  letterSpacing.value = letterSpacingValueConvertor.convert(globalStyles ?? {});
379
379
  if (props.styles?.textAlign &&
380
380
  currentAlignment?.textAlign !== props.styles.textAlign) {
@@ -388,13 +388,13 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
388
388
  fontSettings.selectedFontSizePx = Math.ceil(parseFloat(emToPx(props.styles?.fontSize ?? '2.25em')));
389
389
  fontSettings.selectedTextColor = hasLogoColorVar(props.styles?.color ?? '#000000')
390
390
  ? '#000000'
391
- : props.styles?.color ?? '#000000';
391
+ : (props.styles?.color ?? '#000000');
392
392
  fontSettings.selectedBackgroundColor = hasLogoColorVar(props.styles?.backgroundColor ?? '')
393
393
  ? 'transparent'
394
- : props.styles?.backgroundColor ?? 'transparent';
394
+ : (props.styles?.backgroundColor ?? 'transparent');
395
395
  lineHeight.value = props.styles?.lineHeight?.includes('em')
396
396
  ? emToPx(props.styles?.lineHeight ?? '1em')
397
- : props.styles?.lineHeight ?? '1';
397
+ : (props.styles?.lineHeight ?? '1');
398
398
  letterSpacing.value = letterSpacingValueConvertor.convert(props.styles ?? {});
399
399
  if (props.styles?.textAlign &&
400
400
  currentAlignment?.textAlign !== props.styles.textAlign) {
@@ -85,6 +85,7 @@ export declare const UPGRADE_CTA_LOCATIONS: {
85
85
  };
86
86
  export declare const AI_CTA_LOCATIONS: {
87
87
  AI_BUILDER_TAB: string;
88
+ AI_BUILDER_CHAT_UPSELL: string;
88
89
  };
89
90
  export declare const TRIGGER_TYPE: {
90
91
  AUTOMATIC: string;
@@ -129,12 +130,12 @@ declare const useEventTracker: () => {
129
130
  }) => void;
130
131
  sendSaveContactEvent: () => void;
131
132
  sendStartForFreeEvent: () => void;
132
- sendFooterLinkClickEvent: (linkType: 'watermark_logo' | 'create_your_website') => void;
133
+ sendFooterLinkClickEvent: (linkType: "watermark_logo" | "create_your_website") => void;
133
134
  sendGettyVideoAddEvent: () => void;
134
135
  sendGettyVideoReplaceEvent: () => void;
135
136
  sendGettyVideoRemoveEvent: () => void;
136
137
  sendExperimentStartedEvent: (abTestKey: string, abTestValue: string) => void;
137
- setGlobalEventProps: (props: Omit<BpGlobalEventProps, 'template_category'>) => void;
138
+ setGlobalEventProps: (props: Omit<BpGlobalEventProps, "template_category">) => void;
138
139
  setCustomGlobalEventProps: (props: any) => void;
139
140
  setUpsellBridgeState: (props: BpUpsellEventProps) => void;
140
141
  setDomainUpsellBridgeState: (props: BpUpsellEventProps) => void;
@@ -66,6 +66,7 @@ export const UPGRADE_CTA_LOCATIONS = {
66
66
  };
67
67
  export const AI_CTA_LOCATIONS = {
68
68
  AI_BUILDER_TAB: 'ai_builder_tab',
69
+ AI_BUILDER_CHAT_UPSELL: 'ai_builder_chat_upsell',
69
70
  };
70
71
  export const TRIGGER_TYPE = {
71
72
  AUTOMATIC: 'automatic',