@webiny/ai-powerups 6.6.0-alpha.0 → 6.6.0-alpha.1

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 (195) hide show
  1. package/AiPowerups.js +2 -2
  2. package/AiPowerups.js.map +1 -1
  3. package/admin/Extension.js +10 -2
  4. package/admin/Extension.js.map +1 -1
  5. package/admin/features/compareEntryRevisions/CompareEntryRevisionsGateway.d.ts +12 -0
  6. package/admin/features/compareEntryRevisions/CompareEntryRevisionsGateway.js +46 -0
  7. package/admin/features/compareEntryRevisions/CompareEntryRevisionsGateway.js.map +1 -0
  8. package/admin/features/compareEntryRevisions/CompareEntryRevisionsRepository.d.ts +11 -0
  9. package/admin/features/compareEntryRevisions/CompareEntryRevisionsRepository.js +18 -0
  10. package/admin/features/compareEntryRevisions/CompareEntryRevisionsRepository.js.map +1 -0
  11. package/admin/features/compareEntryRevisions/CompareEntryRevisionsUseCase.d.ts +11 -0
  12. package/admin/features/compareEntryRevisions/CompareEntryRevisionsUseCase.js +18 -0
  13. package/admin/features/compareEntryRevisions/CompareEntryRevisionsUseCase.js.map +1 -0
  14. package/admin/features/compareEntryRevisions/abstractions.d.ts +32 -0
  15. package/admin/features/compareEntryRevisions/abstractions.js +7 -0
  16. package/admin/features/compareEntryRevisions/abstractions.js.map +1 -0
  17. package/admin/features/compareEntryRevisions/feature.d.ts +1 -0
  18. package/admin/features/compareEntryRevisions/feature.js +15 -0
  19. package/admin/features/compareEntryRevisions/feature.js.map +1 -0
  20. package/admin/features/compareEntryRevisions/index.d.ts +2 -0
  21. package/admin/features/compareEntryRevisions/index.js +2 -0
  22. package/admin/features/feature.js +2 -0
  23. package/admin/features/feature.js.map +1 -1
  24. package/admin/features/generateEntryContent/GenerateEntryContentGateway.js +2 -0
  25. package/admin/features/generateEntryContent/GenerateEntryContentGateway.js.map +1 -1
  26. package/admin/features/generateEntryContent/abstractions.d.ts +1 -0
  27. package/admin/features/generateEntryContent/abstractions.js.map +1 -1
  28. package/admin/features/generatePageContent/GeneratePageContentGateway.js +2 -0
  29. package/admin/features/generatePageContent/GeneratePageContentGateway.js.map +1 -1
  30. package/admin/features/generatePageContent/abstractions.d.ts +1 -0
  31. package/admin/features/generatePageContent/abstractions.js.map +1 -1
  32. package/admin/presentation/AiPowerUpsSettings/AiPowerUpsSettingsPage.d.ts +2 -2
  33. package/admin/presentation/AiPromptFormFactory/AiPromptFormFactory.d.ts +20 -0
  34. package/admin/presentation/AiPromptFormFactory/AiPromptFormFactory.js +108 -0
  35. package/admin/presentation/AiPromptFormFactory/AiPromptFormFactory.js.map +1 -0
  36. package/admin/presentation/AiPromptFormFactory/abstractions.d.ts +14 -0
  37. package/admin/presentation/AiPromptFormFactory/abstractions.js +5 -0
  38. package/admin/presentation/AiPromptFormFactory/abstractions.js.map +1 -0
  39. package/admin/presentation/AiPromptFormFactory/feature.d.ts +1 -0
  40. package/admin/presentation/AiPromptFormFactory/feature.js +11 -0
  41. package/admin/presentation/AiPromptFormFactory/feature.js.map +1 -0
  42. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsDialog.d.ts +9 -0
  43. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsDialog.js +118 -0
  44. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsDialog.js.map +1 -0
  45. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsDrawer.d.ts +9 -0
  46. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsDrawer.js +72 -0
  47. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsDrawer.js.map +1 -0
  48. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsMenuItem.d.ts +4 -0
  49. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsMenuItem.js +21 -0
  50. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsMenuItem.js.map +1 -0
  51. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsOverlays.d.ts +2 -0
  52. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsOverlays.js +17 -0
  53. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsOverlays.js.map +1 -0
  54. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsPresenter.d.ts +25 -0
  55. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsPresenter.js +90 -0
  56. package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsPresenter.js.map +1 -0
  57. package/admin/presentation/CmsCompareEntryRevisions/Extension.d.ts +2 -0
  58. package/admin/presentation/CmsCompareEntryRevisions/Extension.js +16 -0
  59. package/admin/presentation/CmsCompareEntryRevisions/Extension.js.map +1 -0
  60. package/admin/presentation/CmsCompareEntryRevisions/abstractions.d.ts +29 -0
  61. package/admin/presentation/CmsCompareEntryRevisions/abstractions.js +5 -0
  62. package/admin/presentation/CmsCompareEntryRevisions/abstractions.js.map +1 -0
  63. package/admin/presentation/CmsCompareEntryRevisions/feature.d.ts +3 -0
  64. package/admin/presentation/CmsCompareEntryRevisions/feature.js +17 -0
  65. package/admin/presentation/CmsCompareEntryRevisions/feature.js.map +1 -0
  66. package/admin/presentation/CmsContentGeneration/CmsGenerateContentButton.d.ts +2 -2
  67. package/admin/presentation/CmsContentGeneration/CmsGenerateContentDialog.d.ts +2 -2
  68. package/admin/presentation/CmsContentGeneration/CmsGenerateContentPresenter.d.ts +4 -12
  69. package/admin/presentation/CmsContentGeneration/CmsGenerateContentPresenter.js +12 -94
  70. package/admin/presentation/CmsContentGeneration/CmsGenerateContentPresenter.js.map +1 -1
  71. package/admin/presentation/CmsContentGeneration/Extension.d.ts +1 -1
  72. package/admin/presentation/CmsContentGeneration/Extension.js +9 -5
  73. package/admin/presentation/CmsContentGeneration/Extension.js.map +1 -1
  74. package/admin/presentation/CmsEntryWizard/CmsEntryWizard.d.ts +4 -0
  75. package/admin/presentation/CmsEntryWizard/CmsEntryWizard.js +113 -0
  76. package/admin/presentation/CmsEntryWizard/CmsEntryWizard.js.map +1 -0
  77. package/admin/presentation/CmsEntryWizard/CmsEntryWizardGate.d.ts +4 -0
  78. package/admin/presentation/CmsEntryWizard/CmsEntryWizardGate.js +19 -0
  79. package/admin/presentation/CmsEntryWizard/CmsEntryWizardGate.js.map +1 -0
  80. package/admin/presentation/CmsEntryWizard/Extension.d.ts +2 -0
  81. package/admin/presentation/CmsEntryWizard/Extension.js +10 -0
  82. package/admin/presentation/CmsEntryWizard/Extension.js.map +1 -0
  83. package/admin/presentation/ProvidersSettings.js +1 -1
  84. package/admin/presentation/ProvidersSettings.js.map +1 -1
  85. package/admin/presentation/WbContentGeneration/GenerateContentDialog.d.ts +2 -2
  86. package/admin/presentation/WbContentGeneration/GenerateContentDialog.js +2 -2
  87. package/admin/presentation/WbContentGeneration/GenerateContentDialog.js.map +1 -1
  88. package/admin/presentation/WbContentGeneration/GenerateContentPresenter.d.ts +4 -12
  89. package/admin/presentation/WbContentGeneration/GenerateContentPresenter.js +12 -94
  90. package/admin/presentation/WbContentGeneration/GenerateContentPresenter.js.map +1 -1
  91. package/api/Extension.js +8 -0
  92. package/api/Extension.js.map +1 -1
  93. package/api/features/AiChatProvider/PowerUpsAiChatProvider.d.ts +24 -0
  94. package/api/features/AiChatProvider/PowerUpsAiChatProvider.js +31 -0
  95. package/api/features/AiChatProvider/PowerUpsAiChatProvider.js.map +1 -0
  96. package/api/features/AiChatProvider/feature.d.ts +9 -0
  97. package/api/features/AiChatProvider/feature.js +11 -0
  98. package/api/features/AiChatProvider/feature.js.map +1 -0
  99. package/api/features/AiChatProvider/index.d.ts +2 -0
  100. package/api/features/AiChatProvider/index.js +2 -0
  101. package/api/features/AiImageEnrichment/AiImageEnrichmentAfterCreateHandler.d.ts +1 -3
  102. package/api/features/AiImageEnrichment/AiImageEnrichmentAfterCreateHandler.js +2 -6
  103. package/api/features/AiImageEnrichment/AiImageEnrichmentAfterCreateHandler.js.map +1 -1
  104. package/api/features/AiImageEnrichment/AiImageEnrichmentStreamRoute.d.ts +36 -0
  105. package/api/features/AiImageEnrichment/AiImageEnrichmentStreamRoute.js +85 -0
  106. package/api/features/AiImageEnrichment/AiImageEnrichmentStreamRoute.js.map +1 -0
  107. package/api/features/AiImageEnrichment/AiImageEnrichmentTask.d.ts +10 -16
  108. package/api/features/AiImageEnrichment/AiImageEnrichmentTask.js +27 -102
  109. package/api/features/AiImageEnrichment/AiImageEnrichmentTask.js.map +1 -1
  110. package/api/features/AiImageEnrichment/ApplyImageEnrichmentUseCase.d.ts +18 -0
  111. package/api/features/AiImageEnrichment/ApplyImageEnrichmentUseCase.js +50 -0
  112. package/api/features/AiImageEnrichment/ApplyImageEnrichmentUseCase.js.map +1 -0
  113. package/api/features/AiImageEnrichment/PrepareImageEnrichmentUseCase.d.ts +19 -0
  114. package/api/features/AiImageEnrichment/PrepareImageEnrichmentUseCase.js +49 -0
  115. package/api/features/AiImageEnrichment/PrepareImageEnrichmentUseCase.js.map +1 -0
  116. package/api/features/AiImageEnrichment/abstractions.d.ts +60 -0
  117. package/api/features/AiImageEnrichment/abstractions.js +12 -0
  118. package/api/features/AiImageEnrichment/abstractions.js.map +1 -0
  119. package/api/features/AiImageEnrichment/buildEnrichmentAiRequest.d.ts +12 -0
  120. package/api/features/AiImageEnrichment/buildEnrichmentAiRequest.js +30 -0
  121. package/api/features/AiImageEnrichment/buildEnrichmentAiRequest.js.map +1 -0
  122. package/api/features/AiImageEnrichment/errors.d.ts +26 -0
  123. package/api/features/AiImageEnrichment/errors.js +28 -0
  124. package/api/features/AiImageEnrichment/errors.js.map +1 -0
  125. package/api/features/AiImageEnrichment/feature.js +9 -0
  126. package/api/features/AiImageEnrichment/feature.js.map +1 -1
  127. package/api/features/AiImageEnrichment/imageEnrichmentErrorStatusCode.d.ts +6 -0
  128. package/api/features/AiImageEnrichment/imageEnrichmentErrorStatusCode.js +9 -0
  129. package/api/features/AiImageEnrichment/imageEnrichmentErrorStatusCode.js.map +1 -0
  130. package/api/features/AiImageEnrichment/readEnrichmentPartial.d.ts +8 -0
  131. package/api/features/AiImageEnrichment/readEnrichmentPartial.js +16 -0
  132. package/api/features/AiImageEnrichment/readEnrichmentPartial.js.map +1 -0
  133. package/api/features/AiImageEnrichment/streamEvents.d.ts +36 -0
  134. package/api/features/AiImageEnrichment/streamEvents.js +0 -0
  135. package/api/features/AiPromptContext/AiPromptContextBuilder.d.ts +8 -1
  136. package/api/features/AiPromptContext/AiPromptContextBuilder.js +46 -2
  137. package/api/features/AiPromptContext/AiPromptContextBuilder.js.map +1 -1
  138. package/api/features/AiPromptContext/abstractions.d.ts +3 -0
  139. package/api/features/AiPromptContext/abstractions.js +9 -1
  140. package/api/features/AiPromptContext/abstractions.js.map +1 -1
  141. package/api/features/AiPromptContext/index.d.ts +1 -1
  142. package/api/features/AiPromptContext/index.js +1 -1
  143. package/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.d.ts +22 -0
  144. package/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.js +136 -0
  145. package/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.js.map +1 -0
  146. package/api/features/CmsCompareEntryRevisions/abstractions.d.ts +18 -0
  147. package/api/features/CmsCompareEntryRevisions/abstractions.js +5 -0
  148. package/api/features/CmsCompareEntryRevisions/abstractions.js.map +1 -0
  149. package/api/features/CmsCompareEntryRevisions/feature.d.ts +4 -0
  150. package/api/features/CmsCompareEntryRevisions/feature.js +11 -0
  151. package/api/features/CmsCompareEntryRevisions/feature.js.map +1 -0
  152. package/api/features/CmsCompareEntryRevisions/index.d.ts +2 -0
  153. package/api/features/CmsCompareEntryRevisions/index.js +2 -0
  154. package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentTask.d.ts +1 -0
  155. package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentTask.js +20 -10
  156. package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentTask.js.map +1 -1
  157. package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.d.ts +1 -1
  158. package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.js +5 -5
  159. package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.js.map +1 -1
  160. package/api/features/CmsGenerateEntryContent/abstractions.d.ts +10 -3
  161. package/api/features/CmsGenerateEntryContent/abstractions.js.map +1 -1
  162. package/api/features/GetSettings/index.d.ts +1 -0
  163. package/api/features/GetSettings/index.js +1 -0
  164. package/api/features/Providers/types.d.ts +2 -2
  165. package/api/features/WbGeneratePageContent/WbGeneratePageContentTask.d.ts +1 -0
  166. package/api/features/WbGeneratePageContent/WbGeneratePageContentTask.js +19 -9
  167. package/api/features/WbGeneratePageContent/WbGeneratePageContentTask.js.map +1 -1
  168. package/api/features/WbGeneratePageContent/WbGeneratePageContentUseCase.js +4 -3
  169. package/api/features/WbGeneratePageContent/WbGeneratePageContentUseCase.js.map +1 -1
  170. package/api/features/WbGeneratePageContent/abstractions.d.ts +1 -0
  171. package/api/features/WbGeneratePageContent/abstractions.js.map +1 -1
  172. package/api/features/WbTranslatePage/LexicalParser.d.ts +10 -0
  173. package/api/features/WbTranslatePage/LexicalParser.js +37 -0
  174. package/api/features/WbTranslatePage/LexicalParser.js.map +1 -0
  175. package/api/features/WbTranslatePage/WbTranslatePageDecorator.d.ts +27 -0
  176. package/api/features/WbTranslatePage/WbTranslatePageDecorator.js +134 -0
  177. package/api/features/WbTranslatePage/WbTranslatePageDecorator.js.map +1 -0
  178. package/api/features/WbTranslatePage/abstractions/LexicalParser.d.ts +7 -0
  179. package/api/features/WbTranslatePage/abstractions/LexicalParser.js +5 -0
  180. package/api/features/WbTranslatePage/abstractions/LexicalParser.js.map +1 -0
  181. package/api/features/WbTranslatePage/feature.d.ts +4 -0
  182. package/api/features/WbTranslatePage/feature.js +13 -0
  183. package/api/features/WbTranslatePage/feature.js.map +1 -0
  184. package/api/features/WbTranslatePage/index.d.ts +2 -0
  185. package/api/features/WbTranslatePage/index.js +2 -0
  186. package/api/graphql/BaseGraphQLSchema.js +11 -4
  187. package/api/graphql/BaseGraphQLSchema.js.map +1 -1
  188. package/api/graphql/CmsCompareEntryRevisionsSchema.d.ts +8 -0
  189. package/api/graphql/CmsCompareEntryRevisionsSchema.js +68 -0
  190. package/api/graphql/CmsCompareEntryRevisionsSchema.js.map +1 -0
  191. package/exports/admin/ai-powerups.d.ts +1 -0
  192. package/exports/admin/ai-powerups.js +1 -0
  193. package/exports/api/ai-powerups.d.ts +2 -0
  194. package/exports/api/ai-powerups.js +2 -0
  195. package/package.json +32 -25
@@ -1 +1 @@
1
- {"version":3,"file":"admin/presentation/WbContentGeneration/GenerateContentDialog.js","sources":["../../../../src/admin/presentation/WbContentGeneration/GenerateContentDialog.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef } from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport { useDialog, FormView } from \"@webiny/app-admin\";\nimport { Dialog, OverlayLoader, useToast } from \"@webiny/admin-ui\";\nimport { useFeature } from \"@webiny/app\";\nimport type { IncomingGenericData } from \"@webiny/app-websockets\";\nimport { useWebsockets } from \"@webiny/app-websockets\";\nimport { useSelectFromEditor } from \"@webiny/app-website-builder/BaseEditor/hooks/useSelectFromEditor.js\";\nimport { useCreateElement } from \"@webiny/app-website-builder/BaseEditor/hooks/useCreateElement.js\";\nimport { GenerateContentFeature } from \"./feature.js\";\nimport { decompressGzipBase64 } from \"./decompressGzipBase64.js\";\nimport type { CreateElementParams } from \"./abstractions.js\";\n\nfunction formatElapsed(totalSeconds: number): string {\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return `${minutes}:${seconds.toString().padStart(2, \"0\")}`;\n}\n\nexport const GENERATE_CONTENT_DIALOG = \"generate-content\";\n\nexport const WS_ACTION_CONTENT = \"aiPowerUps.generatePageContent.content\";\nexport const WS_ACTION_ERROR = \"aiPowerUps.generatePageContent.error\";\n\nexport interface GeneratePageContentMessage extends IncomingGenericData {\n action: typeof WS_ACTION_CONTENT;\n data: {\n compression: \"gzip\";\n value: string;\n };\n}\n\nexport interface GeneratePageContentErrorMessage extends IncomingGenericData {\n action: typeof WS_ACTION_ERROR;\n data: {\n message: string;\n };\n}\n\nexport const GenerateContentDialog = observer(() => {\n const { closeDialog } = useDialog();\n const { presenter } = useFeature(GenerateContentFeature);\n const vm = presenter.vm;\n const wasSubmitting = useRef(false);\n const websockets = useWebsockets();\n const toast = useToast();\n\n const components = useSelectFromEditor(state => state.components);\n const { createElement } = useCreateElement();\n\n const createElements = useCallback(\n async (elements: CreateElementParams[]) => {\n for (const el of elements) {\n await createElement(el);\n }\n },\n [createElement]\n );\n\n useEffect(() => {\n const aiComponents = Object.values(components)\n .filter(c => c.useInAiContentGeneration !== false)\n .map(c => {\n return {\n name: c.name,\n label: c.label,\n aiContext: c.aiContext,\n inputs: c.inputs.map(input => ({\n type: input.type,\n name: input.name,\n label: input.label,\n description: input.description\n }))\n };\n });\n presenter.init(aiComponents, createElements);\n }, [components, createElements]);\n\n useEffect(() => {\n const contentSubscription = websockets.onMessage<GeneratePageContentMessage>(\n WS_ACTION_CONTENT,\n async message => {\n const responseText = await decompressGzipBase64(message.data.value);\n try {\n await presenter.processAiResponse(responseText);\n } catch (e) {\n console.error(\"Failed to process AI response\", { responseText });\n console.error(e);\n toast.showWarningToast({\n title: \"Failed to process AI response\",\n description: \"Open the console for more details.\"\n });\n presenter.cancelPrompt();\n }\n }\n );\n\n const errorSubscription = websockets.onMessage<GeneratePageContentErrorMessage>(\n WS_ACTION_ERROR,\n async message => {\n toast.showWarningToast({\n title: \"Failed to generate content\",\n description: message.data.message\n });\n presenter.cancelPrompt();\n }\n );\n\n return () => {\n contentSubscription.off();\n errorSubscription.off();\n };\n }, []);\n\n useEffect(() => {\n if (wasSubmitting.current && !vm.submitting && !vm.timedOut) {\n closeDialog();\n }\n wasSubmitting.current = vm.submitting;\n }, [vm.submitting]);\n\n useEffect(() => {\n if (vm.timedOut) {\n toast.showWarningToast({\n title: \"Request timed out\",\n description: \"The AI generation took too long. Please try again.\"\n });\n }\n }, [vm.timedOut]);\n\n const handleSubmit = async () => {\n await presenter.submit();\n };\n\n return (\n <Dialog\n open={true}\n onClose={closeDialog}\n title=\"Generate Content\"\n size={\"lg\"}\n actions={\n <>\n <Dialog.CancelAction onClick={closeDialog} text=\"Cancel\" />\n <Dialog.ConfirmAction\n onClick={handleSubmit}\n text=\"Generate\"\n disabled={vm.loading || vm.submitting}\n />\n </>\n }\n >\n {vm.loading ? <OverlayLoader text={\"Loading...\"} /> : null}\n {vm.submitting ? (\n <OverlayLoader\n className={\"bg-neutral-base/90\"}\n text={\n <>\n <div>Generating content... {formatElapsed(vm.elapsedSeconds)}</div>\n <div className=\"text-sm text-neutral-muted pt-xs\">\n Content generation can take a few minutes, depending on the model\n you&apos;re using.\n </div>\n </>\n }\n />\n ) : null}\n {vm.processing ? <OverlayLoader text={\"Processing content...\"} /> : null}\n {vm.form ? <FormView name=\"GenerateContent\" form={vm.form} /> : null}\n </Dialog>\n );\n});\n"],"names":["formatElapsed","totalSeconds","minutes","Math","seconds","GENERATE_CONTENT_DIALOG","WS_ACTION_CONTENT","WS_ACTION_ERROR","GenerateContentDialog","observer","closeDialog","useDialog","presenter","useFeature","GenerateContentFeature","vm","wasSubmitting","useRef","websockets","useWebsockets","toast","useToast","components","useSelectFromEditor","state","createElement","useCreateElement","createElements","useCallback","elements","el","useEffect","aiComponents","Object","c","input","contentSubscription","message","responseText","decompressGzipBase64","e","console","errorSubscription","handleSubmit","Dialog","OverlayLoader","FormView"],"mappings":";;;;;;;;;;AAaA,SAASA,cAAcC,YAAoB;IACvC,MAAMC,UAAUC,KAAK,KAAK,CAACF,eAAe;IAC1C,MAAMG,UAAUH,eAAe;IAC/B,OAAO,GAAGC,QAAQ,CAAC,EAAEE,QAAQ,QAAQ,GAAG,QAAQ,CAAC,GAAG,MAAM;AAC9D;AAEO,MAAMC,0BAA0B;AAEhC,MAAMC,oBAAoB;AAC1B,MAAMC,kBAAkB;AAiBxB,MAAMC,wBAAwBC,SAAS;IAC1C,MAAM,EAAEC,WAAW,EAAE,GAAGC;IACxB,MAAM,EAAEC,SAAS,EAAE,GAAGC,WAAWC;IACjC,MAAMC,KAAKH,UAAU,EAAE;IACvB,MAAMI,gBAAgBC,OAAO;IAC7B,MAAMC,aAAaC;IACnB,MAAMC,QAAQC;IAEd,MAAMC,aAAaC,oBAAoBC,CAAAA,QAASA,MAAM,UAAU;IAChE,MAAM,EAAEC,aAAa,EAAE,GAAGC;IAE1B,MAAMC,iBAAiBC,YACnB,OAAOC;QACH,KAAK,MAAMC,MAAMD,SACb,MAAMJ,cAAcK;IAE5B,GACA;QAACL;KAAc;IAGnBM,UAAU;QACN,MAAMC,eAAeC,OAAO,MAAM,CAACX,YAC9B,MAAM,CAACY,CAAAA,IAAKA,AAA+B,UAA/BA,EAAE,wBAAwB,EACtC,GAAG,CAACA,CAAAA,IACM;gBACH,MAAMA,EAAE,IAAI;gBACZ,OAAOA,EAAE,KAAK;gBACd,WAAWA,EAAE,SAAS;gBACtB,QAAQA,EAAE,MAAM,CAAC,GAAG,CAACC,CAAAA,QAAU;wBAC3B,MAAMA,MAAM,IAAI;wBAChB,MAAMA,MAAM,IAAI;wBAChB,OAAOA,MAAM,KAAK;wBAClB,aAAaA,MAAM,WAAW;oBAClC;YACJ;QAERvB,UAAU,IAAI,CAACoB,cAAcL;IACjC,GAAG;QAACL;QAAYK;KAAe;IAE/BI,UAAU;QACN,MAAMK,sBAAsBlB,WAAW,SAAS,CAC5CZ,mBACA,OAAM+B;YACF,MAAMC,eAAe,MAAMC,qBAAqBF,QAAQ,IAAI,CAAC,KAAK;YAClE,IAAI;gBACA,MAAMzB,UAAU,iBAAiB,CAAC0B;YACtC,EAAE,OAAOE,GAAG;gBACRC,QAAQ,KAAK,CAAC,iCAAiC;oBAAEH;gBAAa;gBAC9DG,QAAQ,KAAK,CAACD;gBACdpB,MAAM,gBAAgB,CAAC;oBACnB,OAAO;oBACP,aAAa;gBACjB;gBACAR,UAAU,YAAY;YAC1B;QACJ;QAGJ,MAAM8B,oBAAoBxB,WAAW,SAAS,CAC1CX,iBACA,OAAM8B;YACFjB,MAAM,gBAAgB,CAAC;gBACnB,OAAO;gBACP,aAAaiB,QAAQ,IAAI,CAAC,OAAO;YACrC;YACAzB,UAAU,YAAY;QAC1B;QAGJ,OAAO;YACHwB,oBAAoB,GAAG;YACvBM,kBAAkB,GAAG;QACzB;IACJ,GAAG,EAAE;IAELX,UAAU;QACN,IAAIf,cAAc,OAAO,IAAI,CAACD,GAAG,UAAU,IAAI,CAACA,GAAG,QAAQ,EACvDL;QAEJM,cAAc,OAAO,GAAGD,GAAG,UAAU;IACzC,GAAG;QAACA,GAAG,UAAU;KAAC;IAElBgB,UAAU;QACN,IAAIhB,GAAG,QAAQ,EACXK,MAAM,gBAAgB,CAAC;YACnB,OAAO;YACP,aAAa;QACjB;IAER,GAAG;QAACL,GAAG,QAAQ;KAAC;IAEhB,MAAM4B,eAAe;QACjB,MAAM/B,UAAU,MAAM;IAC1B;IAEA,OAAO,WAAP,GACI,oBAACgC,QAAMA;QACH,MAAM;QACN,SAASlC;QACT,OAAM;QACN,MAAM;QACN,uBACI,wDACI,oBAACkC,OAAO,YAAY;YAAC,SAASlC;YAAa,MAAK;0BAChD,oBAACkC,OAAO,aAAa;YACjB,SAASD;YACT,MAAK;YACL,UAAU5B,GAAG,OAAO,IAAIA,GAAG,UAAU;;OAKhDA,GAAG,OAAO,GAAG,WAAH,GAAG,oBAAC8B,eAAaA;QAAC,MAAM;SAAmB,MACrD9B,GAAG,UAAU,GAAG,WAAH,GACV,oBAAC8B,eAAaA;QACV,WAAW;QACX,oBACI,wDACI,oBAAC,aAAI,0BAAuB7C,cAAce,GAAG,cAAc,kBAC3D,oBAAC;YAAI,WAAU;WAAmC;SAO9D,MACHA,GAAG,UAAU,GAAG,WAAH,GAAG,oBAAC8B,eAAaA;QAAC,MAAM;SAA8B,MACnE9B,GAAG,IAAI,GAAG,WAAH,GAAG,oBAAC+B,UAAQA;QAAC,MAAK;QAAkB,MAAM/B,GAAG,IAAI;SAAO;AAG5E"}
1
+ {"version":3,"file":"admin/presentation/WbContentGeneration/GenerateContentDialog.js","sources":["../../../../src/admin/presentation/WbContentGeneration/GenerateContentDialog.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef } from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport { useDialog, FormView } from \"@webiny/app-admin\";\nimport { BetaBadge } from \"@webiny/admin-ui\";\nimport { Dialog, OverlayLoader, useToast } from \"@webiny/admin-ui\";\nimport { useFeature } from \"@webiny/app\";\nimport type { IncomingGenericData } from \"@webiny/app-websockets\";\nimport { useWebsockets } from \"@webiny/app-websockets\";\nimport { useSelectFromEditor } from \"@webiny/app-website-builder/BaseEditor/hooks/useSelectFromEditor.js\";\nimport { useCreateElement } from \"@webiny/app-website-builder/BaseEditor/hooks/useCreateElement.js\";\nimport { GenerateContentFeature } from \"./feature.js\";\nimport { decompressGzipBase64 } from \"./decompressGzipBase64.js\";\nimport type { CreateElementParams } from \"./abstractions.js\";\n\nfunction formatElapsed(totalSeconds: number): string {\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return `${minutes}:${seconds.toString().padStart(2, \"0\")}`;\n}\n\nexport const GENERATE_CONTENT_DIALOG = \"generate-content\";\n\nexport const WS_ACTION_CONTENT = \"aiPowerUps.generatePageContent.content\";\nexport const WS_ACTION_ERROR = \"aiPowerUps.generatePageContent.error\";\n\nexport interface GeneratePageContentMessage extends IncomingGenericData {\n action: typeof WS_ACTION_CONTENT;\n data: {\n compression: \"gzip\";\n value: string;\n };\n}\n\nexport interface GeneratePageContentErrorMessage extends IncomingGenericData {\n action: typeof WS_ACTION_ERROR;\n data: {\n message: string;\n };\n}\n\nexport const GenerateContentDialog = observer(() => {\n const { closeDialog } = useDialog();\n const { presenter } = useFeature(GenerateContentFeature);\n const vm = presenter.vm;\n const wasSubmitting = useRef(false);\n const websockets = useWebsockets();\n const toast = useToast();\n\n const components = useSelectFromEditor(state => state.components);\n const { createElement } = useCreateElement();\n\n const createElements = useCallback(\n async (elements: CreateElementParams[]) => {\n for (const el of elements) {\n await createElement(el);\n }\n },\n [createElement]\n );\n\n useEffect(() => {\n const aiComponents = Object.values(components)\n .filter(c => c.useInAiContentGeneration !== false)\n .map(c => {\n return {\n name: c.name,\n label: c.label,\n aiContext: c.aiContext,\n inputs: c.inputs.map(input => ({\n type: input.type,\n name: input.name,\n label: input.label,\n description: input.description\n }))\n };\n });\n presenter.init(aiComponents, createElements);\n }, [components, createElements]);\n\n useEffect(() => {\n const contentSubscription = websockets.onMessage<GeneratePageContentMessage>(\n WS_ACTION_CONTENT,\n async message => {\n const responseText = await decompressGzipBase64(message.data.value);\n try {\n await presenter.processAiResponse(responseText);\n } catch (e) {\n console.error(\"Failed to process AI response\", { responseText });\n console.error(e);\n toast.showWarningToast({\n title: \"Failed to process AI response\",\n description: \"Open the console for more details.\"\n });\n presenter.cancelPrompt();\n }\n }\n );\n\n const errorSubscription = websockets.onMessage<GeneratePageContentErrorMessage>(\n WS_ACTION_ERROR,\n async message => {\n toast.showWarningToast({\n title: \"Failed to generate content\",\n description: message.data.message\n });\n presenter.cancelPrompt();\n }\n );\n\n return () => {\n contentSubscription.off();\n errorSubscription.off();\n };\n }, []);\n\n useEffect(() => {\n if (wasSubmitting.current && !vm.submitting && !vm.timedOut) {\n closeDialog();\n }\n wasSubmitting.current = vm.submitting;\n }, [vm.submitting]);\n\n useEffect(() => {\n if (vm.timedOut) {\n toast.showWarningToast({\n title: \"Request timed out\",\n description: \"The AI generation took too long. Please try again.\"\n });\n }\n }, [vm.timedOut]);\n\n const handleSubmit = async () => {\n await presenter.submit();\n };\n\n return (\n <Dialog\n open={true}\n onClose={closeDialog}\n title={\n <>\n Generate Content <BetaBadge />\n </>\n }\n size={\"lg\"}\n actions={\n <>\n <Dialog.CancelAction onClick={closeDialog} text=\"Cancel\" />\n <Dialog.ConfirmAction\n onClick={handleSubmit}\n text=\"Generate\"\n disabled={vm.loading || vm.submitting}\n />\n </>\n }\n >\n {vm.loading ? <OverlayLoader text={\"Loading...\"} /> : null}\n {vm.submitting ? (\n <OverlayLoader\n className={\"bg-neutral-base/90\"}\n text={\n <>\n <div>Generating content... {formatElapsed(vm.elapsedSeconds)}</div>\n <div className=\"text-sm text-neutral-muted pt-xs\">\n Content generation can take a few minutes, depending on the model\n you&apos;re using.\n </div>\n </>\n }\n />\n ) : null}\n {vm.processing ? <OverlayLoader text={\"Processing content...\"} /> : null}\n {vm.form ? <FormView name=\"GenerateContent\" form={vm.form} /> : null}\n </Dialog>\n );\n});\n"],"names":["formatElapsed","totalSeconds","minutes","Math","seconds","GENERATE_CONTENT_DIALOG","WS_ACTION_CONTENT","WS_ACTION_ERROR","GenerateContentDialog","observer","closeDialog","useDialog","presenter","useFeature","GenerateContentFeature","vm","wasSubmitting","useRef","websockets","useWebsockets","toast","useToast","components","useSelectFromEditor","state","createElement","useCreateElement","createElements","useCallback","elements","el","useEffect","aiComponents","Object","c","input","contentSubscription","message","responseText","decompressGzipBase64","e","console","errorSubscription","handleSubmit","Dialog","BetaBadge","OverlayLoader","FormView"],"mappings":"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"}
@@ -1,13 +1,12 @@
1
- import { FormModelFactory, ToolRegistry, ToolPipelineRunner } from "@webiny/app-admin";
1
+ import { ToolRegistry, ToolPipelineRunner } from "@webiny/app-admin";
2
2
  import { GenerateContentPresenter, type CreateElementsFn } from "./abstractions.js";
3
3
  import { GeneratePageContentUseCase } from "../../../admin/features/generatePageContent/index.js";
4
- import { GetSettingsUseCase } from "../../../admin/features/settings/getSettings/abstractions.js";
4
+ import { AiPromptFormFactory } from "../../../admin/presentation/AiPromptFormFactory/abstractions.js";
5
5
  declare class GenerateContentPresenterImpl implements GenerateContentPresenter.Interface {
6
6
  private toolRegistry;
7
7
  private pipelineRunner;
8
8
  private generatePageContent;
9
- private formModelFactory;
10
- private getSettings;
9
+ private formFactory;
11
10
  private _loading;
12
11
  private _submitting;
13
12
  private _processing;
@@ -15,11 +14,10 @@ declare class GenerateContentPresenterImpl implements GenerateContentPresenter.I
15
14
  private _components;
16
15
  private _createElements;
17
16
  private _form;
18
- private _settings;
19
17
  private _timeoutId;
20
18
  private _intervalId;
21
19
  private _elapsedSeconds;
22
- constructor(toolRegistry: ToolRegistry.Interface, pipelineRunner: ToolPipelineRunner.Interface, generatePageContent: GeneratePageContentUseCase.Interface, formModelFactory: FormModelFactory.Interface, getSettings: GetSettingsUseCase.Interface);
20
+ constructor(toolRegistry: ToolRegistry.Interface, pipelineRunner: ToolPipelineRunner.Interface, generatePageContent: GeneratePageContentUseCase.Interface, formFactory: AiPromptFormFactory.Interface);
23
21
  get vm(): GenerateContentPresenter.ViewModel;
24
22
  init(components: Record<string, any>[], createElements: CreateElementsFn): Promise<void>;
25
23
  submit(): Promise<void>;
@@ -28,12 +26,6 @@ declare class GenerateContentPresenterImpl implements GenerateContentPresenter.I
28
26
  private startTimeout;
29
27
  private clearTimeout;
30
28
  private clearInterval;
31
- private buildForm;
32
- private getSelectedProject;
33
- private getProjectFileOptions;
34
- private computeExcludedFileIds;
35
- private getProjectOptions;
36
- private getPersonaOptions;
37
29
  }
38
30
  export declare const GenerateContentPresenterRegistration: typeof GenerateContentPresenterImpl & {
39
31
  __abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").IGenerateContentPresenter>;
@@ -1,18 +1,17 @@
1
1
  import { computed, makeAutoObservable, runInAction, toJS } from "mobx";
2
2
  import { z } from "zod";
3
3
  import pick from "lodash/pick.js";
4
- import { FormModelFactory, ToolPipelineRunner, ToolRegistry } from "@webiny/app-admin";
4
+ import { ToolPipelineRunner, ToolRegistry } from "@webiny/app-admin";
5
5
  import { GenerateContentPresenter } from "./abstractions.js";
6
6
  import { GeneratePageContentUseCase } from "../../features/generatePageContent/index.js";
7
- import { GetSettingsUseCase } from "../../features/settings/getSettings/abstractions.js";
7
+ import { AiPromptFormFactory } from "../AiPromptFormFactory/abstractions.js";
8
8
  const SUBMIT_TIMEOUT_MS = 300000;
9
9
  class GenerateContentPresenterImpl {
10
- constructor(toolRegistry, pipelineRunner, generatePageContent, formModelFactory, getSettings){
10
+ constructor(toolRegistry, pipelineRunner, generatePageContent, formFactory){
11
11
  this.toolRegistry = toolRegistry;
12
12
  this.pipelineRunner = pipelineRunner;
13
13
  this.generatePageContent = generatePageContent;
14
- this.formModelFactory = formModelFactory;
15
- this.getSettings = getSettings;
14
+ this.formFactory = formFactory;
16
15
  this._loading = false;
17
16
  this._submitting = false;
18
17
  this._processing = false;
@@ -20,7 +19,6 @@ class GenerateContentPresenterImpl {
20
19
  this._components = [];
21
20
  this._createElements = ()=>{};
22
21
  this._form = null;
23
- this._settings = null;
24
22
  this._timeoutId = null;
25
23
  this._intervalId = null;
26
24
  this._elapsedSeconds = 0;
@@ -43,18 +41,9 @@ class GenerateContentPresenterImpl {
43
41
  async init(components, createElements) {
44
42
  this._components = components;
45
43
  this._createElements = createElements;
46
- this._loading = true;
47
- try {
48
- const settings = await this.getSettings.execute();
49
- runInAction(()=>{
50
- this._settings = settings;
51
- this._form = this.buildForm();
52
- });
53
- } finally{
54
- runInAction(()=>{
55
- this._loading = false;
56
- });
57
- }
44
+ this._form = this.formFactory.createForm({
45
+ promptDescription: "Describe the page content you want to generate."
46
+ });
58
47
  }
59
48
  async submit() {
60
49
  if (!this._form) return;
@@ -78,7 +67,8 @@ class GenerateContentPresenterImpl {
78
67
  "type"
79
68
  ])
80
69
  }));
81
- const excludedFileIds = this.computeExcludedFileIds(data.project, data.includedFiles);
70
+ const excludedFileIds = this.formFactory.computeExcludedFileIds(this._form);
71
+ const additionalFileIds = data.additionalFiles?.map((f)=>f.id) ?? null;
82
72
  await this.generatePageContent.execute({
83
73
  prompt: data.prompt,
84
74
  components: toJS(this._components),
@@ -86,7 +76,8 @@ class GenerateContentPresenterImpl {
86
76
  projectId: data.project || null,
87
77
  excludedFileIds,
88
78
  readerPersonaId: data.readerPersona || null,
89
- writerPersonaId: data.writerPersona || null
79
+ writerPersonaId: data.writerPersona || null,
80
+ additionalFileIds
90
81
  });
91
82
  } catch {
92
83
  this.clearTimeout();
@@ -155,78 +146,6 @@ class GenerateContentPresenterImpl {
155
146
  this._intervalId = null;
156
147
  }
157
148
  }
158
- buildForm() {
159
- return this.formModelFactory.create({
160
- fields: (fields)=>({
161
- project: fields.text().label("Project").description("Select a predefined context to attach.").options(()=>this.getProjectOptions()).afterChange((value, { form })=>{
162
- const projectId = value;
163
- const project = projectId ? this._settings?.projects?.presets?.find((p)=>p.id === projectId) : void 0;
164
- if (project?.defaultReaderPersonaId) form.field("readerPersona").setValue(project.defaultReaderPersonaId);
165
- if (project?.defaultWriterPersonaId) form.field("writerPersona").setValue(project.defaultWriterPersonaId);
166
- const fileIds = (project?.files ?? []).map((f)=>f.id);
167
- form.field("includedFiles").setValue(fileIds);
168
- }),
169
- includedFiles: fields.text().label("Files included").description("Uncheck files to exclude them from this generation only.").options(()=>this.getProjectFileOptions()).renderer("checkboxes").list().hiddenWhen(({ form })=>{
170
- const projectId = form.field("project").as("text").getValue();
171
- if (!projectId) return true;
172
- const project = this._settings?.projects?.presets?.find((p)=>p.id === projectId);
173
- return !project?.files || 0 === project.files.length;
174
- }),
175
- readerPersona: fields.text().label("Reader Persona").description("Select the target audience for the generated content.").options(()=>this.getPersonaOptions("reader")),
176
- writerPersona: fields.text().label("Writer Persona").description("Select the writing style for the generated content.").options(()=>this.getPersonaOptions("writer")),
177
- prompt: fields.text().label("Prompt").description("Describe the page content you want to generate.").required("Prompt is required").renderer("textarea", {
178
- rows: 6
179
- })
180
- }),
181
- layout: (layout)=>[
182
- layout.row("project"),
183
- layout.row("includedFiles"),
184
- layout.row("readerPersona"),
185
- layout.row("writerPersona"),
186
- layout.row("prompt")
187
- ]
188
- });
189
- }
190
- getSelectedProject() {
191
- if (!this._form || !this._settings) return;
192
- const projectId = this._form.field("project").getValue();
193
- if (!projectId) return;
194
- return this._settings.projects?.presets?.find((p)=>p.id === projectId);
195
- }
196
- getProjectFileOptions() {
197
- const project = this.getSelectedProject();
198
- const files = project?.files;
199
- if (!files || 0 === files.length) return [];
200
- return files.map((f)=>({
201
- label: f.name,
202
- value: f.id
203
- }));
204
- }
205
- computeExcludedFileIds(projectId, includedFiles) {
206
- if (!projectId) return null;
207
- const project = this._settings?.projects?.presets?.find((p)=>p.id === projectId);
208
- const allFileIds = (project?.files ?? []).map((f)=>f.id);
209
- if (0 === allFileIds.length) return null;
210
- const included = new Set(includedFiles ?? []);
211
- const excluded = allFileIds.filter((id)=>!included.has(id));
212
- return excluded.length > 0 ? excluded : null;
213
- }
214
- getProjectOptions() {
215
- const presets = this._settings?.projects?.presets;
216
- if (!presets || 0 === presets.length) return [];
217
- return presets.map((preset)=>({
218
- label: preset.name,
219
- value: preset.id
220
- }));
221
- }
222
- getPersonaOptions(type) {
223
- const presets = "reader" === type ? this._settings?.readerPersonas?.presets : this._settings?.writerPersonas?.presets;
224
- if (!presets || 0 === presets.length) return [];
225
- return presets.map((preset)=>({
226
- label: preset.name,
227
- value: preset.id
228
- }));
229
- }
230
149
  }
231
150
  const GenerateContentPresenterRegistration = GenerateContentPresenter.createImplementation({
232
151
  implementation: GenerateContentPresenterImpl,
@@ -234,8 +153,7 @@ const GenerateContentPresenterRegistration = GenerateContentPresenter.createImpl
234
153
  ToolRegistry,
235
154
  ToolPipelineRunner,
236
155
  GeneratePageContentUseCase,
237
- FormModelFactory,
238
- GetSettingsUseCase
156
+ AiPromptFormFactory
239
157
  ]
240
158
  });
241
159
  export { GenerateContentPresenterRegistration };
@@ -1 +1 @@
1
- {"version":3,"file":"admin/presentation/WbContentGeneration/GenerateContentPresenter.js","sources":["../../../../src/admin/presentation/WbContentGeneration/GenerateContentPresenter.ts"],"sourcesContent":["import { makeAutoObservable, computed, toJS, runInAction } from \"mobx\";\nimport { z } from \"zod\";\nimport pick from \"lodash/pick.js\";\nimport { FormModelFactory, FormModel, ToolRegistry, ToolPipelineRunner } from \"@webiny/app-admin\";\nimport { GenerateContentPresenter, type CreateElementsFn } from \"./abstractions.js\";\nimport { GeneratePageContentUseCase } from \"~/admin/features/generatePageContent/index.js\";\nimport { GetSettingsUseCase } from \"~/admin/features/settings/getSettings/abstractions.js\";\nimport type { IAiPowerUpsSettings } from \"~/admin/features/settings/shared/abstractions.js\";\n\nconst SUBMIT_TIMEOUT_MS = 300_000;\n\nclass GenerateContentPresenterImpl implements GenerateContentPresenter.Interface {\n private _loading = false;\n private _submitting = false;\n private _processing = false;\n private _timedOut = false;\n private _components: Record<string, any>[] = [];\n private _createElements: CreateElementsFn = () => {};\n private _form: FormModel.Interface | null = null;\n private _settings: IAiPowerUpsSettings | null = null;\n private _timeoutId: ReturnType<typeof setTimeout> | null = null;\n private _intervalId: ReturnType<typeof setInterval> | null = null;\n private _elapsedSeconds = 0;\n\n constructor(\n private toolRegistry: ToolRegistry.Interface,\n private pipelineRunner: ToolPipelineRunner.Interface,\n private generatePageContent: GeneratePageContentUseCase.Interface,\n private formModelFactory: FormModelFactory.Interface,\n private getSettings: GetSettingsUseCase.Interface\n ) {\n makeAutoObservable(this, { vm: computed }, { autoBind: true });\n }\n\n get vm(): GenerateContentPresenter.ViewModel {\n return {\n form: this._form ? this._form.vm : null,\n loading: this._loading,\n submitting: this._submitting,\n processing: this._processing,\n timedOut: this._timedOut,\n elapsedSeconds: this._elapsedSeconds\n };\n }\n\n async init(components: Record<string, any>[], createElements: CreateElementsFn): Promise<void> {\n this._components = components;\n this._createElements = createElements;\n\n this._loading = true;\n\n try {\n const settings = await this.getSettings.execute();\n runInAction(() => {\n this._settings = settings;\n this._form = this.buildForm();\n });\n } finally {\n runInAction(() => {\n this._loading = false;\n });\n }\n }\n\n async submit(): Promise<void> {\n if (!this._form) {\n return;\n }\n\n const data = await this._form.submit<{\n prompt: string;\n project?: string;\n includedFiles?: string[];\n readerPersona?: string;\n writerPersona?: string;\n }>();\n\n if (!data) {\n return;\n }\n\n runInAction(() => {\n this._submitting = true;\n this._timedOut = false;\n });\n\n this.startTimeout();\n\n try {\n const tools = this.toolRegistry.getTools().map(tool => ({\n name: tool.name,\n description: tool.description,\n inputSchema: pick(z.toJSONSchema(tool.inputSchema), [\"properties\", \"type\"]),\n outputSchema: pick(z.toJSONSchema(tool.outputSchema), [\"properties\", \"type\"])\n }));\n\n const excludedFileIds = this.computeExcludedFileIds(data.project, data.includedFiles);\n\n await this.generatePageContent.execute({\n prompt: data.prompt,\n components: toJS(this._components),\n tools,\n projectId: data.project || null,\n excludedFileIds,\n readerPersonaId: data.readerPersona || null,\n writerPersonaId: data.writerPersona || null\n });\n } catch {\n this.clearTimeout();\n runInAction(() => {\n this._submitting = false;\n });\n }\n }\n\n async processAiResponse(responseText: string): Promise<void> {\n this.clearTimeout();\n runInAction(() => {\n this._processing = true;\n this._submitting = false;\n });\n\n try {\n const aiResponseJson = JSON.parse(responseText);\n const resolved = await this.pipelineRunner.resolve(aiResponseJson);\n const items = Array.isArray(resolved) ? resolved : [resolved];\n\n await this._createElements(\n items.map((element: { component: string; inputs: Record<string, unknown> }) => ({\n componentName: element.component,\n parentId: \"root\",\n slot: \"children\",\n bindings: { inputs: element.inputs }\n }))\n );\n } finally {\n runInAction(() => {\n this._processing = false;\n });\n }\n }\n\n cancelPrompt(): void {\n this.clearTimeout();\n this._processing = false;\n this._submitting = false;\n }\n\n private startTimeout(): void {\n this.clearTimeout();\n this._elapsedSeconds = 0;\n this._intervalId = setInterval(() => {\n runInAction(() => {\n this._elapsedSeconds++;\n });\n }, 1000);\n this._timeoutId = setTimeout(() => {\n runInAction(() => {\n this._submitting = false;\n this._timedOut = true;\n });\n this.clearInterval();\n }, SUBMIT_TIMEOUT_MS);\n }\n\n private clearTimeout(): void {\n if (this._timeoutId !== null) {\n clearTimeout(this._timeoutId);\n this._timeoutId = null;\n }\n this.clearInterval();\n }\n\n private clearInterval(): void {\n if (this._intervalId !== null) {\n clearInterval(this._intervalId);\n this._intervalId = null;\n }\n }\n\n private buildForm() {\n return this.formModelFactory.create({\n fields: fields => ({\n project: fields\n .text()\n .label(\"Project\")\n .description(\"Select a predefined context to attach.\")\n .options(() => this.getProjectOptions())\n .afterChange((value, { form }) => {\n const projectId = value as string | undefined;\n const project = projectId\n ? this._settings?.projects?.presets?.find(p => p.id === projectId)\n : undefined;\n\n if (project?.defaultReaderPersonaId) {\n form.field(\"readerPersona\").setValue(project.defaultReaderPersonaId);\n }\n if (project?.defaultWriterPersonaId) {\n form.field(\"writerPersona\").setValue(project.defaultWriterPersonaId);\n }\n\n const fileIds = (project?.files ?? []).map(f => f.id);\n form.field(\"includedFiles\").setValue(fileIds);\n }),\n includedFiles: fields\n .text()\n .label(\"Files included\")\n .description(\"Uncheck files to exclude them from this generation only.\")\n .options(() => this.getProjectFileOptions())\n .renderer(\"checkboxes\")\n .list()\n .hiddenWhen(({ form }) => {\n const projectId = form.field(\"project\").as(\"text\").getValue();\n if (!projectId) {\n return true;\n }\n const project = this._settings?.projects?.presets?.find(\n p => p.id === projectId\n );\n return !project?.files || project.files.length === 0;\n }),\n readerPersona: fields\n .text()\n .label(\"Reader Persona\")\n .description(\"Select the target audience for the generated content.\")\n .options(() => this.getPersonaOptions(\"reader\")),\n writerPersona: fields\n .text()\n .label(\"Writer Persona\")\n .description(\"Select the writing style for the generated content.\")\n .options(() => this.getPersonaOptions(\"writer\")),\n prompt: fields\n .text()\n .label(\"Prompt\")\n .description(\"Describe the page content you want to generate.\")\n .required(\"Prompt is required\")\n .renderer(\"textarea\", { rows: 6 })\n }),\n layout: layout => [\n layout.row(\"project\"),\n layout.row(\"includedFiles\"),\n layout.row(\"readerPersona\"),\n layout.row(\"writerPersona\"),\n layout.row(\"prompt\")\n ]\n });\n }\n\n private getSelectedProject() {\n if (!this._form || !this._settings) {\n return undefined;\n }\n const projectId = this._form.field(\"project\").getValue<string>();\n if (!projectId) {\n return undefined;\n }\n return this._settings.projects?.presets?.find(p => p.id === projectId);\n }\n\n private getProjectFileOptions() {\n const project = this.getSelectedProject();\n const files = project?.files;\n if (!files || files.length === 0) {\n return [];\n }\n return files.map(f => ({\n label: f.name,\n value: f.id\n }));\n }\n\n private computeExcludedFileIds(projectId?: string, includedFiles?: string[]): string[] | null {\n if (!projectId) {\n return null;\n }\n const project = this._settings?.projects?.presets?.find(p => p.id === projectId);\n const allFileIds = (project?.files ?? []).map(f => f.id);\n if (allFileIds.length === 0) {\n return null;\n }\n const included = new Set(includedFiles ?? []);\n const excluded = allFileIds.filter(id => !included.has(id));\n return excluded.length > 0 ? excluded : null;\n }\n\n private getProjectOptions() {\n const presets = this._settings?.projects?.presets;\n if (!presets || presets.length === 0) {\n return [];\n }\n return presets.map(preset => ({\n label: preset.name,\n value: preset.id\n }));\n }\n\n private getPersonaOptions(type: \"reader\" | \"writer\") {\n const presets =\n type === \"reader\"\n ? this._settings?.readerPersonas?.presets\n : this._settings?.writerPersonas?.presets;\n\n if (!presets || presets.length === 0) {\n return [];\n }\n\n return presets.map(preset => ({\n label: preset.name,\n value: preset.id\n }));\n }\n}\n\nexport const GenerateContentPresenterRegistration = GenerateContentPresenter.createImplementation({\n implementation: GenerateContentPresenterImpl,\n dependencies: [\n ToolRegistry,\n ToolPipelineRunner,\n GeneratePageContentUseCase,\n FormModelFactory,\n GetSettingsUseCase\n ]\n});\n"],"names":["SUBMIT_TIMEOUT_MS","GenerateContentPresenterImpl","toolRegistry","pipelineRunner","generatePageContent","formModelFactory","getSettings","makeAutoObservable","computed","components","createElements","settings","runInAction","data","tools","tool","pick","z","excludedFileIds","toJS","responseText","aiResponseJson","JSON","resolved","items","Array","element","setInterval","setTimeout","clearTimeout","clearInterval","fields","value","form","projectId","project","p","undefined","fileIds","f","layout","files","includedFiles","allFileIds","included","Set","excluded","id","presets","preset","type","GenerateContentPresenterRegistration","GenerateContentPresenter","ToolRegistry","ToolPipelineRunner","GeneratePageContentUseCase","FormModelFactory","GetSettingsUseCase"],"mappings":"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"}
1
+ {"version":3,"file":"admin/presentation/WbContentGeneration/GenerateContentPresenter.js","sources":["../../../../src/admin/presentation/WbContentGeneration/GenerateContentPresenter.ts"],"sourcesContent":["import { makeAutoObservable, computed, toJS, runInAction } from \"mobx\";\nimport { z } from \"zod\";\nimport pick from \"lodash/pick.js\";\nimport { ToolRegistry, ToolPipelineRunner } from \"@webiny/app-admin\";\nimport type { FormModel } from \"@webiny/app-admin\";\nimport type { FileValue } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { GenerateContentPresenter, type CreateElementsFn } from \"./abstractions.js\";\nimport { GeneratePageContentUseCase } from \"~/admin/features/generatePageContent/index.js\";\nimport { AiPromptFormFactory } from \"~/admin/presentation/AiPromptFormFactory/abstractions.js\";\n\nconst SUBMIT_TIMEOUT_MS = 300_000;\n\nclass GenerateContentPresenterImpl implements GenerateContentPresenter.Interface {\n private _loading = false;\n private _submitting = false;\n private _processing = false;\n private _timedOut = false;\n private _components: Record<string, any>[] = [];\n private _createElements: CreateElementsFn = () => {};\n private _form: FormModel.Interface | null = null;\n private _timeoutId: ReturnType<typeof setTimeout> | null = null;\n private _intervalId: ReturnType<typeof setInterval> | null = null;\n private _elapsedSeconds = 0;\n\n constructor(\n private toolRegistry: ToolRegistry.Interface,\n private pipelineRunner: ToolPipelineRunner.Interface,\n private generatePageContent: GeneratePageContentUseCase.Interface,\n private formFactory: AiPromptFormFactory.Interface\n ) {\n makeAutoObservable(this, { vm: computed }, { autoBind: true });\n }\n\n get vm(): GenerateContentPresenter.ViewModel {\n return {\n form: this._form ? this._form.vm : null,\n loading: this._loading,\n submitting: this._submitting,\n processing: this._processing,\n timedOut: this._timedOut,\n elapsedSeconds: this._elapsedSeconds\n };\n }\n\n async init(components: Record<string, any>[], createElements: CreateElementsFn): Promise<void> {\n this._components = components;\n this._createElements = createElements;\n\n this._form = this.formFactory.createForm({\n promptDescription: \"Describe the page content you want to generate.\"\n });\n }\n\n async submit(): Promise<void> {\n if (!this._form) {\n return;\n }\n\n const data = await this._form.submit<{\n prompt: string;\n project?: string;\n includedFiles?: string[];\n readerPersona?: string;\n writerPersona?: string;\n additionalFiles?: FileValue[];\n }>();\n\n if (!data) {\n return;\n }\n\n runInAction(() => {\n this._submitting = true;\n this._timedOut = false;\n });\n\n this.startTimeout();\n\n try {\n const tools = this.toolRegistry.getTools().map(tool => ({\n name: tool.name,\n description: tool.description,\n inputSchema: pick(z.toJSONSchema(tool.inputSchema), [\"properties\", \"type\"]),\n outputSchema: pick(z.toJSONSchema(tool.outputSchema), [\"properties\", \"type\"])\n }));\n\n const excludedFileIds = this.formFactory.computeExcludedFileIds(this._form);\n const additionalFileIds = data.additionalFiles?.map(f => f.id) ?? null;\n\n await this.generatePageContent.execute({\n prompt: data.prompt,\n components: toJS(this._components),\n tools,\n projectId: data.project || null,\n excludedFileIds,\n readerPersonaId: data.readerPersona || null,\n writerPersonaId: data.writerPersona || null,\n additionalFileIds\n });\n } catch {\n this.clearTimeout();\n runInAction(() => {\n this._submitting = false;\n });\n }\n }\n\n async processAiResponse(responseText: string): Promise<void> {\n this.clearTimeout();\n runInAction(() => {\n this._processing = true;\n this._submitting = false;\n });\n\n try {\n const aiResponseJson = JSON.parse(responseText);\n const resolved = await this.pipelineRunner.resolve(aiResponseJson);\n const items = Array.isArray(resolved) ? resolved : [resolved];\n\n await this._createElements(\n items.map((element: { component: string; inputs: Record<string, unknown> }) => ({\n componentName: element.component,\n parentId: \"root\",\n slot: \"children\",\n bindings: { inputs: element.inputs }\n }))\n );\n } finally {\n runInAction(() => {\n this._processing = false;\n });\n }\n }\n\n cancelPrompt(): void {\n this.clearTimeout();\n this._processing = false;\n this._submitting = false;\n }\n\n private startTimeout(): void {\n this.clearTimeout();\n this._elapsedSeconds = 0;\n this._intervalId = setInterval(() => {\n runInAction(() => {\n this._elapsedSeconds++;\n });\n }, 1000);\n this._timeoutId = setTimeout(() => {\n runInAction(() => {\n this._submitting = false;\n this._timedOut = true;\n });\n this.clearInterval();\n }, SUBMIT_TIMEOUT_MS);\n }\n\n private clearTimeout(): void {\n if (this._timeoutId !== null) {\n clearTimeout(this._timeoutId);\n this._timeoutId = null;\n }\n this.clearInterval();\n }\n\n private clearInterval(): void {\n if (this._intervalId !== null) {\n clearInterval(this._intervalId);\n this._intervalId = null;\n }\n }\n}\n\nexport const GenerateContentPresenterRegistration = GenerateContentPresenter.createImplementation({\n implementation: GenerateContentPresenterImpl,\n dependencies: [\n ToolRegistry,\n ToolPipelineRunner,\n GeneratePageContentUseCase,\n AiPromptFormFactory\n ]\n});\n"],"names":["SUBMIT_TIMEOUT_MS","GenerateContentPresenterImpl","toolRegistry","pipelineRunner","generatePageContent","formFactory","makeAutoObservable","computed","components","createElements","data","runInAction","tools","tool","pick","z","excludedFileIds","additionalFileIds","f","toJS","responseText","aiResponseJson","JSON","resolved","items","Array","element","setInterval","setTimeout","clearTimeout","clearInterval","GenerateContentPresenterRegistration","GenerateContentPresenter","ToolRegistry","ToolPipelineRunner","GeneratePageContentUseCase","AiPromptFormFactory"],"mappings":"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"}
package/api/Extension.js CHANGED
@@ -14,6 +14,10 @@ import { AiImageEnrichmentFeature } from "./features/AiImageEnrichment/feature.j
14
14
  import { ExtractFrontmatterFeature } from "./features/ExtractFrontmatter/feature.js";
15
15
  import { CmsGenerateEntryContentFeature } from "./features/CmsGenerateEntryContent/feature.js";
16
16
  import { CmsResolveImageToolFeature } from "./features/CmsResolveImageTool/feature.js";
17
+ import { AiChatProviderFeature } from "./features/AiChatProvider/index.js";
18
+ import { CmsCompareEntryRevisionsFeature } from "./features/CmsCompareEntryRevisions/feature.js";
19
+ import { WbTranslatePageFeature } from "./features/WbTranslatePage/feature.js";
20
+ import { CmsCompareEntryRevisionsSchema } from "./graphql/CmsCompareEntryRevisionsSchema.js";
17
21
  const Extension = createFeature({
18
22
  name: "AiPowerUps",
19
23
  register (container) {
@@ -28,10 +32,14 @@ const Extension = createFeature({
28
32
  WbGeneratePageContentFeature.register(container);
29
33
  CmsGenerateEntryContentFeature.register(container);
30
34
  CmsResolveImageToolFeature.register(container);
35
+ AiChatProviderFeature.register(container);
31
36
  ExtractFrontmatterFeature.register(container);
32
37
  AiImageEnrichmentFeature.register(container);
38
+ CmsCompareEntryRevisionsFeature.register(container);
39
+ WbTranslatePageFeature.register(container);
33
40
  container.register(AiPowerUpsSettingsGraphQLMapper).inSingletonScope();
34
41
  container.register(BaseGraphQLSchema);
42
+ container.register(CmsCompareEntryRevisionsSchema);
35
43
  }
36
44
  });
37
45
  export { Extension };
@@ -1 +1 @@
1
- {"version":3,"file":"api/Extension.js","sources":["../../src/api/Extension.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { BaseGraphQLSchema } from \"./graphql/BaseGraphQLSchema.js\";\nimport AiPowerUpsSettingsGraphQLMapperImpl from \"./graphql/AiPowerUpsSettingsGraphQLMapper.js\";\nimport { AiPowerUpsSettingsCache } from \"./features/shared/SettingsCache.js\";\nimport { GetSettingsFeature } from \"./features/GetSettings/feature.js\";\nimport { UpdateSettingsFeature } from \"./features/UpdateSettings/feature.js\";\nimport { WbGeneratePageContentFeature } from \"./features/WbGeneratePageContent/feature.js\";\nimport { ProvidersFeature } from \"./features/Providers/feature.js\";\nimport { ReaderPersonasFeature } from \"./features/ReaderPersonas/feature.js\";\nimport { WriterPersonasFeature } from \"./features/WriterPersonas/feature.js\";\nimport { ProjectsFeature } from \"./features/Projects/feature.js\";\nimport { AiPromptContextFeature } from \"./features/AiPromptContext/feature.js\";\nimport { AiImageEnrichmentFeature } from \"./features/AiImageEnrichment/feature.js\";\nimport { ExtractFrontmatterFeature } from \"./features/ExtractFrontmatter/feature.js\";\nimport { CmsGenerateEntryContentFeature } from \"./features/CmsGenerateEntryContent/feature.js\";\nimport { CmsResolveImageToolFeature } from \"./features/CmsResolveImageTool/feature.js\";\n\nexport const Extension = createFeature({\n name: \"AiPowerUps\",\n register(container) {\n container.register(AiPowerUpsSettingsCache).inSingletonScope();\n\n GetSettingsFeature.register(container);\n UpdateSettingsFeature.register(container);\n ProvidersFeature.register(container);\n ReaderPersonasFeature.register(container);\n WriterPersonasFeature.register(container);\n ProjectsFeature.register(container);\n AiPromptContextFeature.register(container);\n WbGeneratePageContentFeature.register(container);\n CmsGenerateEntryContentFeature.register(container);\n CmsResolveImageToolFeature.register(container);\n ExtractFrontmatterFeature.register(container);\n\n // Registered unconditionally. The WCP license gate lives inside the feature's\n // FileAfterCreate handler (trigger-time), because the license isn't loaded yet during this\n // register() phase — a register-time canUse* check reads NullLicense and is always false.\n AiImageEnrichmentFeature.register(container);\n\n container.register(AiPowerUpsSettingsGraphQLMapperImpl).inSingletonScope();\n container.register(BaseGraphQLSchema);\n }\n});\n"],"names":["Extension","createFeature","container","AiPowerUpsSettingsCache","GetSettingsFeature","UpdateSettingsFeature","ProvidersFeature","ReaderPersonasFeature","WriterPersonasFeature","ProjectsFeature","AiPromptContextFeature","WbGeneratePageContentFeature","CmsGenerateEntryContentFeature","CmsResolveImageToolFeature","ExtractFrontmatterFeature","AiImageEnrichmentFeature","AiPowerUpsSettingsGraphQLMapperImpl","BaseGraphQLSchema"],"mappings":";;;;;;;;;;;;;;;;AAiBO,MAAMA,YAAYC,cAAc;IACnC,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC,yBAAyB,gBAAgB;QAE5DC,mBAAmB,QAAQ,CAACF;QAC5BG,sBAAsB,QAAQ,CAACH;QAC/BI,iBAAiB,QAAQ,CAACJ;QAC1BK,sBAAsB,QAAQ,CAACL;QAC/BM,sBAAsB,QAAQ,CAACN;QAC/BO,gBAAgB,QAAQ,CAACP;QACzBQ,uBAAuB,QAAQ,CAACR;QAChCS,6BAA6B,QAAQ,CAACT;QACtCU,+BAA+B,QAAQ,CAACV;QACxCW,2BAA2B,QAAQ,CAACX;QACpCY,0BAA0B,QAAQ,CAACZ;QAKnCa,yBAAyB,QAAQ,CAACb;QAElCA,UAAU,QAAQ,CAACc,iCAAqC,gBAAgB;QACxEd,UAAU,QAAQ,CAACe;IACvB;AACJ"}
1
+ {"version":3,"file":"api/Extension.js","sources":["../../src/api/Extension.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { BaseGraphQLSchema } from \"./graphql/BaseGraphQLSchema.js\";\nimport AiPowerUpsSettingsGraphQLMapperImpl from \"./graphql/AiPowerUpsSettingsGraphQLMapper.js\";\nimport { AiPowerUpsSettingsCache } from \"./features/shared/SettingsCache.js\";\nimport { GetSettingsFeature } from \"./features/GetSettings/feature.js\";\nimport { UpdateSettingsFeature } from \"./features/UpdateSettings/feature.js\";\nimport { WbGeneratePageContentFeature } from \"./features/WbGeneratePageContent/feature.js\";\nimport { ProvidersFeature } from \"./features/Providers/feature.js\";\nimport { ReaderPersonasFeature } from \"./features/ReaderPersonas/feature.js\";\nimport { WriterPersonasFeature } from \"./features/WriterPersonas/feature.js\";\nimport { ProjectsFeature } from \"./features/Projects/feature.js\";\nimport { AiPromptContextFeature } from \"./features/AiPromptContext/feature.js\";\nimport { AiImageEnrichmentFeature } from \"./features/AiImageEnrichment/feature.js\";\nimport { ExtractFrontmatterFeature } from \"./features/ExtractFrontmatter/feature.js\";\nimport { CmsGenerateEntryContentFeature } from \"./features/CmsGenerateEntryContent/feature.js\";\nimport { CmsResolveImageToolFeature } from \"./features/CmsResolveImageTool/feature.js\";\nimport { AiChatProviderFeature } from \"./features/AiChatProvider/index.js\";\nimport { CmsCompareEntryRevisionsFeature } from \"./features/CmsCompareEntryRevisions/feature.js\";\nimport { WbTranslatePageFeature } from \"./features/WbTranslatePage/feature.js\";\nimport { CmsCompareEntryRevisionsSchema } from \"./graphql/CmsCompareEntryRevisionsSchema.js\";\n\nexport const Extension = createFeature({\n name: \"AiPowerUps\",\n register(container) {\n container.register(AiPowerUpsSettingsCache).inSingletonScope();\n\n GetSettingsFeature.register(container);\n UpdateSettingsFeature.register(container);\n ProvidersFeature.register(container);\n ReaderPersonasFeature.register(container);\n WriterPersonasFeature.register(container);\n ProjectsFeature.register(container);\n AiPromptContextFeature.register(container);\n WbGeneratePageContentFeature.register(container);\n CmsGenerateEntryContentFeature.register(container);\n CmsResolveImageToolFeature.register(container);\n AiChatProviderFeature.register(container);\n ExtractFrontmatterFeature.register(container);\n\n // Registered unconditionally. The WCP license gate lives inside the feature's\n // FileAfterCreate handler (trigger-time), because the license isn't loaded yet during this\n // register() phase — a register-time canUse* check reads NullLicense and is always false.\n AiImageEnrichmentFeature.register(container);\n\n CmsCompareEntryRevisionsFeature.register(container);\n WbTranslatePageFeature.register(container);\n\n container.register(AiPowerUpsSettingsGraphQLMapperImpl).inSingletonScope();\n container.register(BaseGraphQLSchema);\n container.register(CmsCompareEntryRevisionsSchema);\n }\n});\n"],"names":["Extension","createFeature","container","AiPowerUpsSettingsCache","GetSettingsFeature","UpdateSettingsFeature","ProvidersFeature","ReaderPersonasFeature","WriterPersonasFeature","ProjectsFeature","AiPromptContextFeature","WbGeneratePageContentFeature","CmsGenerateEntryContentFeature","CmsResolveImageToolFeature","AiChatProviderFeature","ExtractFrontmatterFeature","AiImageEnrichmentFeature","CmsCompareEntryRevisionsFeature","WbTranslatePageFeature","AiPowerUpsSettingsGraphQLMapperImpl","BaseGraphQLSchema","CmsCompareEntryRevisionsSchema"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqBO,MAAMA,YAAYC,cAAc;IACnC,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC,yBAAyB,gBAAgB;QAE5DC,mBAAmB,QAAQ,CAACF;QAC5BG,sBAAsB,QAAQ,CAACH;QAC/BI,iBAAiB,QAAQ,CAACJ;QAC1BK,sBAAsB,QAAQ,CAACL;QAC/BM,sBAAsB,QAAQ,CAACN;QAC/BO,gBAAgB,QAAQ,CAACP;QACzBQ,uBAAuB,QAAQ,CAACR;QAChCS,6BAA6B,QAAQ,CAACT;QACtCU,+BAA+B,QAAQ,CAACV;QACxCW,2BAA2B,QAAQ,CAACX;QACpCY,sBAAsB,QAAQ,CAACZ;QAC/Ba,0BAA0B,QAAQ,CAACb;QAKnCc,yBAAyB,QAAQ,CAACd;QAElCe,gCAAgC,QAAQ,CAACf;QACzCgB,uBAAuB,QAAQ,CAAChB;QAEhCA,UAAU,QAAQ,CAACiB,iCAAqC,gBAAgB;QACxEjB,UAAU,QAAQ,CAACkB;QACnBlB,UAAU,QAAQ,CAACmB;IACvB;AACJ"}
@@ -0,0 +1,24 @@
1
+ import { AiChatProvider as Abstraction } from "@webiny/ai-chat/api/index.js";
2
+ import type { IAiChatProviderResolution } from "@webiny/ai-chat/api/index.js";
3
+ import { Encryption } from "@webiny/api-core/features/encryption/index.js";
4
+ import { GetSettingsUseCase } from "../../../api/features/GetSettings/index.js";
5
+ /**
6
+ * Runs the assistant on the provider configured in AI Power-Ups settings.
7
+ *
8
+ * Overrides the environment-variable default so the model and its key are managed where every other
9
+ * AI feature in the project already manages them — in the admin UI, per tenant, with the key
10
+ * encrypted at rest. Same source `CmsGenerateEntryContent` and `CmsCompareEntryRevisions` read.
11
+ *
12
+ * Uses the FIRST configured provider, matching the other AI Power-Ups use cases. Picking per-feature
13
+ * providers is a settings design question, not something to invent here.
14
+ */
15
+ declare class PowerUpsAiChatProviderImpl implements Abstraction.Interface {
16
+ private readonly getSettings;
17
+ private readonly encryption;
18
+ constructor(getSettings: GetSettingsUseCase.Interface, encryption: Encryption.Interface);
19
+ resolve(): Promise<IAiChatProviderResolution>;
20
+ }
21
+ export declare const PowerUpsAiChatProvider: typeof PowerUpsAiChatProviderImpl & {
22
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/ai-chat/api/abstractions").IAiChatProvider>;
23
+ };
24
+ export {};
@@ -0,0 +1,31 @@
1
+ import { AiChatProvider } from "@webiny/ai-chat/api/index.js";
2
+ import { Encryption } from "@webiny/api-core/features/encryption/index.js";
3
+ import { GetSettingsUseCase } from "../GetSettings/index.js";
4
+ class PowerUpsAiChatProviderImpl {
5
+ constructor(getSettings, encryption){
6
+ this.getSettings = getSettings;
7
+ this.encryption = encryption;
8
+ }
9
+ async resolve() {
10
+ const settingsResult = await this.getSettings.execute();
11
+ if (settingsResult.isFail()) throw new Error("Failed to load AI Power Ups settings.");
12
+ const provider = settingsResult.value.providers.presets[0];
13
+ if (!provider) throw new Error("No AI provider configured. Add one under Settings → AI Power-Ups → Providers.");
14
+ if (!provider.model) throw new Error(`The AI provider "${provider.name}" has no model selected. Pick one under Settings → AI Power-Ups → Providers.`);
15
+ if (!provider.apiKeyEncrypted) throw new Error(`The AI provider "${provider.name}" has no API key. Add one under Settings → AI Power-Ups → Providers.`);
16
+ return {
17
+ model: provider.model,
18
+ apiKey: await this.encryption.decrypt(provider.apiKeyEncrypted)
19
+ };
20
+ }
21
+ }
22
+ const PowerUpsAiChatProvider = AiChatProvider.createImplementation({
23
+ implementation: PowerUpsAiChatProviderImpl,
24
+ dependencies: [
25
+ GetSettingsUseCase,
26
+ Encryption
27
+ ]
28
+ });
29
+ export { PowerUpsAiChatProvider };
30
+
31
+ //# sourceMappingURL=PowerUpsAiChatProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/AiChatProvider/PowerUpsAiChatProvider.js","sources":["../../../../src/api/features/AiChatProvider/PowerUpsAiChatProvider.ts"],"sourcesContent":["import { AiChatProvider as Abstraction } from \"@webiny/ai-chat/api/index.js\";\nimport type { IAiChatProviderResolution } from \"@webiny/ai-chat/api/index.js\";\nimport { Encryption } from \"@webiny/api-core/features/encryption/index.js\";\nimport { GetSettingsUseCase } from \"~/api/features/GetSettings/index.js\";\n\n/**\n * Runs the assistant on the provider configured in AI Power-Ups settings.\n *\n * Overrides the environment-variable default so the model and its key are managed where every other\n * AI feature in the project already manages them — in the admin UI, per tenant, with the key\n * encrypted at rest. Same source `CmsGenerateEntryContent` and `CmsCompareEntryRevisions` read.\n *\n * Uses the FIRST configured provider, matching the other AI Power-Ups use cases. Picking per-feature\n * providers is a settings design question, not something to invent here.\n */\nclass PowerUpsAiChatProviderImpl implements Abstraction.Interface {\n constructor(\n private readonly getSettings: GetSettingsUseCase.Interface,\n private readonly encryption: Encryption.Interface\n ) {}\n\n async resolve(): Promise<IAiChatProviderResolution> {\n const settingsResult = await this.getSettings.execute();\n\n if (settingsResult.isFail()) {\n throw new Error(\"Failed to load AI Power Ups settings.\");\n }\n\n const provider = settingsResult.value.providers.presets[0];\n\n if (!provider) {\n throw new Error(\n \"No AI provider configured. Add one under Settings → AI Power-Ups → Providers.\"\n );\n }\n\n if (!provider.model) {\n throw new Error(\n `The AI provider \"${provider.name}\" has no model selected. Pick one under Settings → AI Power-Ups → Providers.`\n );\n }\n\n /*\n * A row can exist before a key is entered. Erroring here is deliberate: falling back to an\n * environment variable when a provider IS configured is what made the previous behaviour so\n * hard to reason about — the settings screen said one thing and the request used another.\n */\n if (!provider.apiKeyEncrypted) {\n throw new Error(\n `The AI provider \"${provider.name}\" has no API key. Add one under Settings → AI Power-Ups → Providers.`\n );\n }\n\n return {\n model: provider.model,\n apiKey: await this.encryption.decrypt(provider.apiKeyEncrypted)\n };\n }\n}\n\nexport const PowerUpsAiChatProvider = Abstraction.createImplementation({\n implementation: PowerUpsAiChatProviderImpl,\n dependencies: [GetSettingsUseCase, Encryption]\n});\n"],"names":["PowerUpsAiChatProviderImpl","getSettings","encryption","settingsResult","Error","provider","PowerUpsAiChatProvider","Abstraction","GetSettingsUseCase","Encryption"],"mappings":";;;AAeA,MAAMA;IACF,YACqBC,WAAyC,EACzCC,UAAgC,CACnD;aAFmBD,WAAW,GAAXA;aACAC,UAAU,GAAVA;IAClB;IAEH,MAAM,UAA8C;QAChD,MAAMC,iBAAiB,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO;QAErD,IAAIA,eAAe,MAAM,IACrB,MAAM,IAAIC,MAAM;QAGpB,MAAMC,WAAWF,eAAe,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE;QAE1D,IAAI,CAACE,UACD,MAAM,IAAID,MACN;QAIR,IAAI,CAACC,SAAS,KAAK,EACf,MAAM,IAAID,MACN,CAAC,iBAAiB,EAAEC,SAAS,IAAI,CAAC,4EAA4E,CAAC;QASvH,IAAI,CAACA,SAAS,eAAe,EACzB,MAAM,IAAID,MACN,CAAC,iBAAiB,EAAEC,SAAS,IAAI,CAAC,oEAAoE,CAAC;QAI/G,OAAO;YACH,OAAOA,SAAS,KAAK;YACrB,QAAQ,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAACA,SAAS,eAAe;QAClE;IACJ;AACJ;AAEO,MAAMC,yBAAyBC,eAAAA,oBAAgC,CAAC;IACnE,gBAAgBP;IAChB,cAAc;QAACQ;QAAoBC;KAAW;AAClD"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Points the admin AI assistant at the providers configured in AI Power-Ups.
3
+ *
4
+ * Registered after `AiChatFeature`'s environment default so this one wins.
5
+ */
6
+ export declare const AiChatProviderFeature: {
7
+ name: string;
8
+ register(container: import("@webiny/di").Container): void;
9
+ };
@@ -0,0 +1,11 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { PowerUpsAiChatProvider } from "./PowerUpsAiChatProvider.js";
3
+ const AiChatProviderFeature = createFeature({
4
+ name: "AiPowerUps/AiChatProvider",
5
+ register (container) {
6
+ container.register(PowerUpsAiChatProvider);
7
+ }
8
+ });
9
+ export { AiChatProviderFeature };
10
+
11
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/AiChatProvider/feature.js","sources":["../../../../src/api/features/AiChatProvider/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { PowerUpsAiChatProvider } from \"./PowerUpsAiChatProvider.js\";\n\n/**\n * Points the admin AI assistant at the providers configured in AI Power-Ups.\n *\n * Registered after `AiChatFeature`'s environment default so this one wins.\n */\nexport const AiChatProviderFeature = createFeature({\n name: \"AiPowerUps/AiChatProvider\",\n register(container) {\n container.register(PowerUpsAiChatProvider);\n }\n});\n"],"names":["AiChatProviderFeature","createFeature","container","PowerUpsAiChatProvider"],"mappings":";;AAQO,MAAMA,wBAAwBC,cAAc;IAC/C,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}
@@ -0,0 +1,2 @@
1
+ export { AiChatProviderFeature } from "./feature.js";
2
+ export { PowerUpsAiChatProvider } from "./PowerUpsAiChatProvider.js";
@@ -0,0 +1,2 @@
1
+ export { AiChatProviderFeature } from "./feature.js";
2
+ export { PowerUpsAiChatProvider } from "./PowerUpsAiChatProvider.js";
@@ -1,10 +1,8 @@
1
1
  import { FileAfterCreateEventHandler } from "@webiny/api-file-manager/features/file/CreateFile/events.js";
2
2
  import { TaskService } from "@webiny/api-core/features/task/TaskService/index.js";
3
- import { WcpContext } from "@webiny/api-core/features/wcp/WcpContext/index.js";
4
3
  declare class AiImageEnrichmentAfterCreateHandlerImpl implements FileAfterCreateEventHandler.Interface {
5
4
  private taskService;
6
- private wcp;
7
- constructor(taskService: TaskService.Interface, wcp: WcpContext.Interface);
5
+ constructor(taskService: TaskService.Interface);
8
6
  handle(event: FileAfterCreateEventHandler.Event): Promise<void>;
9
7
  }
10
8
  export declare const AiImageEnrichmentAfterCreateHandler: typeof AiImageEnrichmentAfterCreateHandlerImpl & {
@@ -1,16 +1,13 @@
1
1
  import { FileAfterCreateEventHandler } from "@webiny/api-file-manager/features/file/CreateFile/events.js";
2
2
  import { TaskService } from "@webiny/api-core/features/task/TaskService/index.js";
3
- import { WcpContext } from "@webiny/api-core/features/wcp/WcpContext/index.js";
4
3
  import { AI_IMAGE_ENRICHMENT_TASK_ID } from "./AiImageEnrichmentTask.js";
5
4
  class AiImageEnrichmentAfterCreateHandlerImpl {
6
- constructor(taskService, wcp){
5
+ constructor(taskService){
7
6
  this.taskService = taskService;
8
- this.wcp = wcp;
9
7
  }
10
8
  async handle(event) {
11
9
  const { file } = event.payload;
12
10
  if (!file.type.startsWith("image/")) return;
13
- if (!this.wcp.canUseAiImageEnrichment()) return;
14
11
  await this.taskService.trigger({
15
12
  definition: AI_IMAGE_ENRICHMENT_TASK_ID,
16
13
  input: {
@@ -22,8 +19,7 @@ class AiImageEnrichmentAfterCreateHandlerImpl {
22
19
  const AiImageEnrichmentAfterCreateHandler = FileAfterCreateEventHandler.createImplementation({
23
20
  implementation: AiImageEnrichmentAfterCreateHandlerImpl,
24
21
  dependencies: [
25
- TaskService,
26
- WcpContext
22
+ TaskService
27
23
  ]
28
24
  });
29
25
  export { AiImageEnrichmentAfterCreateHandler };
@@ -1 +1 @@
1
- {"version":3,"file":"api/features/AiImageEnrichment/AiImageEnrichmentAfterCreateHandler.js","sources":["../../../../src/api/features/AiImageEnrichment/AiImageEnrichmentAfterCreateHandler.ts"],"sourcesContent":["import { FileAfterCreateEventHandler } from \"@webiny/api-file-manager/features/file/CreateFile/events.js\";\nimport { TaskService } from \"@webiny/api-core/features/task/TaskService/index.js\";\nimport { WcpContext } from \"@webiny/api-core/features/wcp/WcpContext/index.js\";\nimport type { IAiImageEnrichmentTaskInput } from \"./AiImageEnrichmentTask.js\";\nimport { AI_IMAGE_ENRICHMENT_TASK_ID } from \"./AiImageEnrichmentTask.js\";\n\nclass AiImageEnrichmentAfterCreateHandlerImpl implements FileAfterCreateEventHandler.Interface {\n constructor(\n private taskService: TaskService.Interface,\n private wcp: WcpContext.Interface\n ) {}\n\n async handle(event: FileAfterCreateEventHandler.Event): Promise<void> {\n const { file } = event.payload;\n\n if (!file.type.startsWith(\"image/\")) {\n return;\n }\n\n // Gate at trigger-time, NOT at feature-registration time: the WCP license is loaded per\n // request by WcpLicenseInitializer (a RequestInitializer), which runs AFTER the register()\n // phase. A register-time check reads the placeholder NullLicense (canUse* → false), so the\n // feature would never register. handle() runs during a resolver, once the license is loaded.\n if (!this.wcp.canUseAiImageEnrichment()) {\n return;\n }\n\n await this.taskService.trigger<IAiImageEnrichmentTaskInput>({\n definition: AI_IMAGE_ENRICHMENT_TASK_ID,\n input: {\n fileId: file.id\n }\n });\n }\n}\n\nexport const AiImageEnrichmentAfterCreateHandler = FileAfterCreateEventHandler.createImplementation(\n {\n implementation: AiImageEnrichmentAfterCreateHandlerImpl,\n dependencies: [TaskService, WcpContext]\n }\n);\n"],"names":["AiImageEnrichmentAfterCreateHandlerImpl","taskService","wcp","event","file","AI_IMAGE_ENRICHMENT_TASK_ID","AiImageEnrichmentAfterCreateHandler","FileAfterCreateEventHandler","TaskService","WcpContext"],"mappings":";;;;AAMA,MAAMA;IACF,YACYC,WAAkC,EAClCC,GAAyB,CACnC;aAFUD,WAAW,GAAXA;aACAC,GAAG,GAAHA;IACT;IAEH,MAAM,OAAOC,KAAwC,EAAiB;QAClE,MAAM,EAAEC,IAAI,EAAE,GAAGD,MAAM,OAAO;QAE9B,IAAI,CAACC,KAAK,IAAI,CAAC,UAAU,CAAC,WACtB;QAOJ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,uBAAuB,IACjC;QAGJ,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAA8B;YACxD,YAAYC;YACZ,OAAO;gBACH,QAAQD,KAAK,EAAE;YACnB;QACJ;IACJ;AACJ;AAEO,MAAME,sCAAsCC,4BAA4B,oBAAoB,CAC/F;IACI,gBAAgBP;IAChB,cAAc;QAACQ;QAAaC;KAAW;AAC3C"}
1
+ {"version":3,"file":"api/features/AiImageEnrichment/AiImageEnrichmentAfterCreateHandler.js","sources":["../../../../src/api/features/AiImageEnrichment/AiImageEnrichmentAfterCreateHandler.ts"],"sourcesContent":["import { FileAfterCreateEventHandler } from \"@webiny/api-file-manager/features/file/CreateFile/events.js\";\nimport { TaskService } from \"@webiny/api-core/features/task/TaskService/index.js\";\nimport type { IAiImageEnrichmentTaskInput } from \"./AiImageEnrichmentTask.js\";\nimport { AI_IMAGE_ENRICHMENT_TASK_ID } from \"./AiImageEnrichmentTask.js\";\n\nclass AiImageEnrichmentAfterCreateHandlerImpl implements FileAfterCreateEventHandler.Interface {\n constructor(private taskService: TaskService.Interface) {}\n\n async handle(event: FileAfterCreateEventHandler.Event): Promise<void> {\n const { file } = event.payload;\n\n if (!file.type.startsWith(\"image/\")) {\n return;\n }\n\n await this.taskService.trigger<IAiImageEnrichmentTaskInput>({\n definition: AI_IMAGE_ENRICHMENT_TASK_ID,\n input: {\n fileId: file.id\n }\n });\n }\n}\n\nexport const AiImageEnrichmentAfterCreateHandler = FileAfterCreateEventHandler.createImplementation(\n {\n implementation: AiImageEnrichmentAfterCreateHandlerImpl,\n dependencies: [TaskService]\n }\n);\n"],"names":["AiImageEnrichmentAfterCreateHandlerImpl","taskService","event","file","AI_IMAGE_ENRICHMENT_TASK_ID","AiImageEnrichmentAfterCreateHandler","FileAfterCreateEventHandler","TaskService"],"mappings":";;;AAKA,MAAMA;IACF,YAAoBC,WAAkC,CAAE;aAApCA,WAAW,GAAXA;IAAqC;IAEzD,MAAM,OAAOC,KAAwC,EAAiB;QAClE,MAAM,EAAEC,IAAI,EAAE,GAAGD,MAAM,OAAO;QAE9B,IAAI,CAACC,KAAK,IAAI,CAAC,UAAU,CAAC,WACtB;QAGJ,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAA8B;YACxD,YAAYC;YACZ,OAAO;gBACH,QAAQD,KAAK,EAAE;YACnB;QACJ;IACJ;AACJ;AAEO,MAAME,sCAAsCC,4BAA4B,oBAAoB,CAC/F;IACI,gBAAgBN;IAChB,cAAc;QAACO;KAAY;AAC/B"}
@@ -0,0 +1,36 @@
1
+ import { HttpRouteDefinition, HttpRouteHandler } from "@webiny/event-handler-core";
2
+ import type { IHttpRequest, IHttpResponseBuilder } from "@webiny/event-handler-core";
3
+ import { Ai } from "@webiny/api-core/features/ai/index.js";
4
+ import { PrepareImageEnrichmentUseCase } from "./abstractions.js";
5
+ /**
6
+ * Re-runs AI enrichment for a single file, streaming the model's output to the caller as
7
+ * server-sent events. Read-only: the result is a proposal the caller can accept or discard.
8
+ *
9
+ * Preparation (file lookup, image read, provider resolution) happens BEFORE the response opens, so
10
+ * anything knowable up front — missing file, wrong type, no provider — comes back as a real status
11
+ * code. Only the AI call itself streams; once the first byte is out the status is committed to 200
12
+ * and failures can only be reported as an `error` event.
13
+ */
14
+ declare class AiImageEnrichmentStreamRouteImpl implements HttpRouteHandler.Interface {
15
+ private prepare;
16
+ private ai;
17
+ constructor(prepare: PrepareImageEnrichmentUseCase.Interface, ai: Ai.Interface);
18
+ handle(request: IHttpRequest, response: IHttpResponseBuilder): Promise<IHttpResponseBuilder>;
19
+ private enrich;
20
+ }
21
+ export declare const AiImageEnrichmentStreamRoute: typeof AiImageEnrichmentStreamRouteImpl & {
22
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-core").IHttpRoute>;
23
+ };
24
+ declare class AiImageEnrichmentStreamRouteDefinitionImpl implements HttpRouteDefinition.Interface {
25
+ readonly name = "ai-image-enrichment-stream";
26
+ readonly method = "POST";
27
+ readonly path = "/stream/fm/files/:fileId/enrich";
28
+ readonly handler: typeof AiImageEnrichmentStreamRouteImpl & {
29
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-core").IHttpRoute>;
30
+ };
31
+ }
32
+ /** What the router matches on. Zero dependencies, so building it costs nothing. */
33
+ export declare const AiImageEnrichmentStreamRouteDefinition: typeof AiImageEnrichmentStreamRouteDefinitionImpl & {
34
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-core").IHttpRouteDefinition>;
35
+ };
36
+ export {};