@webiny/ai-powerups 6.6.0-alpha.3 → 6.6.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/AiPowerups.d.ts +12 -0
  2. package/AiPowerups.js +1 -2
  3. package/AiPowerups.js.map +1 -1
  4. package/admin/Extension.d.ts +1 -1
  5. package/admin/Extension.js +6 -2
  6. package/admin/Extension.js.map +1 -1
  7. package/admin/domain/modelRoles.d.ts +17 -0
  8. package/admin/domain/modelRoles.js +8 -0
  9. package/admin/domain/modelRoles.js.map +1 -0
  10. package/admin/features/feature.js +2 -0
  11. package/admin/features/feature.js.map +1 -1
  12. package/admin/features/listCapabilities/ListCapabilitiesGateway.d.ts +12 -0
  13. package/admin/features/listCapabilities/ListCapabilitiesGateway.js +34 -0
  14. package/admin/features/listCapabilities/ListCapabilitiesGateway.js.map +1 -0
  15. package/admin/features/listCapabilities/ListCapabilitiesRepository.d.ts +13 -0
  16. package/admin/features/listCapabilities/ListCapabilitiesRepository.js +27 -0
  17. package/admin/features/listCapabilities/ListCapabilitiesRepository.js.map +1 -0
  18. package/admin/features/listCapabilities/ListCapabilitiesUseCase.d.ts +10 -0
  19. package/admin/features/listCapabilities/ListCapabilitiesUseCase.js +18 -0
  20. package/admin/features/listCapabilities/ListCapabilitiesUseCase.js.map +1 -0
  21. package/admin/features/listCapabilities/abstractions.d.ts +28 -0
  22. package/admin/features/listCapabilities/abstractions.js +7 -0
  23. package/admin/features/listCapabilities/abstractions.js.map +1 -0
  24. package/admin/features/listCapabilities/feature.d.ts +3 -0
  25. package/admin/features/listCapabilities/feature.js +21 -0
  26. package/admin/features/listCapabilities/feature.js.map +1 -0
  27. package/admin/features/listCapabilities/index.d.ts +3 -0
  28. package/admin/features/listCapabilities/index.js +2 -0
  29. package/admin/features/settings/shared/abstractions.d.ts +58 -25
  30. package/admin/features/settings/shared/abstractions.js.map +1 -1
  31. package/admin/presentation/AiPowerUpsSettings/AiPowerUpsSettingsPresenter.js +13 -1
  32. package/admin/presentation/AiPowerUpsSettings/AiPowerUpsSettingsPresenter.js.map +1 -1
  33. package/admin/presentation/AiPowerUpsSettings/feature.js +6 -2
  34. package/admin/presentation/AiPowerUpsSettings/feature.js.map +1 -1
  35. package/admin/presentation/AiPowerUpsSettings/hasUsableModel.d.ts +13 -0
  36. package/admin/presentation/AiPowerUpsSettings/hasUsableModel.js +9 -0
  37. package/admin/presentation/AiPowerUpsSettings/hasUsableModel.js.map +1 -0
  38. package/admin/presentation/AiPowerUpsSettings/index.d.ts +1 -0
  39. package/admin/presentation/AiPowerUpsSettings/index.js +1 -0
  40. package/admin/presentation/AiPowerUpsSettings/settingsGroup.d.ts +9 -0
  41. package/admin/presentation/AiPowerUpsSettings/settingsGroup.js.map +1 -1
  42. package/admin/presentation/CapabilitiesSettings.d.ts +39 -0
  43. package/admin/presentation/CapabilitiesSettings.js +104 -0
  44. package/admin/presentation/CapabilitiesSettings.js.map +1 -0
  45. package/admin/presentation/CmsContentGeneration/CmsGenerateContentButton.js +2 -2
  46. package/admin/presentation/CmsContentGeneration/CmsGenerateContentButton.js.map +1 -1
  47. package/admin/presentation/ConnectionsSettings.d.ts +25 -0
  48. package/admin/presentation/ConnectionsSettings.js +52 -0
  49. package/admin/presentation/ConnectionsSettings.js.map +1 -0
  50. package/admin/presentation/ModelRolesSettings.d.ts +29 -0
  51. package/admin/presentation/ModelRolesSettings.js +67 -0
  52. package/admin/presentation/ModelRolesSettings.js.map +1 -0
  53. package/admin/presentation/WbContentGeneration/GenerateContentButton.js +2 -2
  54. package/admin/presentation/WbContentGeneration/GenerateContentButton.js.map +1 -1
  55. package/admin/presentation/modelRoles.d.ts +10 -0
  56. package/admin/presentation/modelRoles.js +23 -0
  57. package/admin/presentation/modelRoles.js.map +1 -0
  58. package/api/Extension.js +10 -2
  59. package/api/Extension.js.map +1 -1
  60. package/api/features/AdminAssistant/AdminAssistantStreamRoute.d.ts +34 -0
  61. package/api/features/AdminAssistant/AdminAssistantStreamRoute.js +42 -0
  62. package/api/features/AdminAssistant/AdminAssistantStreamRoute.js.map +1 -0
  63. package/api/features/AdminAssistant/AdminAssistantUseCase.d.ts +42 -0
  64. package/api/features/AdminAssistant/AdminAssistantUseCase.js +170 -0
  65. package/api/features/AdminAssistant/AdminAssistantUseCase.js.map +1 -0
  66. package/api/features/AdminAssistant/abstractions.d.ts +38 -0
  67. package/api/features/AdminAssistant/abstractions.js +6 -0
  68. package/api/features/AdminAssistant/abstractions.js.map +1 -0
  69. package/api/features/AdminAssistant/approvals.d.ts +29 -0
  70. package/api/features/AdminAssistant/approvals.js +30 -0
  71. package/api/features/AdminAssistant/approvals.js.map +1 -0
  72. package/api/features/AdminAssistant/capability.d.ts +31 -0
  73. package/api/features/AdminAssistant/capability.js +19 -0
  74. package/api/features/AdminAssistant/capability.js.map +1 -0
  75. package/api/features/AdminAssistant/events.d.ts +54 -0
  76. package/api/features/AdminAssistant/events.js +0 -0
  77. package/api/features/AdminAssistant/feature.d.ts +12 -0
  78. package/api/features/AdminAssistant/feature.js +23 -0
  79. package/api/features/AdminAssistant/feature.js.map +1 -0
  80. package/api/features/AdminAssistant/index.d.ts +5 -0
  81. package/api/features/AdminAssistant/index.js +3 -0
  82. package/api/features/AdminAssistant/parseChatBody.d.ts +14 -0
  83. package/api/features/AdminAssistant/parseChatBody.js +33 -0
  84. package/api/features/AdminAssistant/parseChatBody.js.map +1 -0
  85. package/api/features/AdminAssistant/systemPrompt.d.ts +7 -0
  86. package/api/features/AdminAssistant/systemPrompt.js +24 -0
  87. package/api/features/AdminAssistant/systemPrompt.js.map +1 -0
  88. package/api/features/AiImageEnrichment/PrepareImageEnrichmentUseCase.d.ts +3 -5
  89. package/api/features/AiImageEnrichment/PrepareImageEnrichmentUseCase.js +11 -16
  90. package/api/features/AiImageEnrichment/PrepareImageEnrichmentUseCase.js.map +1 -1
  91. package/api/features/AiImageEnrichment/abstractions.d.ts +6 -0
  92. package/api/features/AiImageEnrichment/abstractions.js.map +1 -1
  93. package/api/features/AiImageEnrichment/buildEnrichmentAiRequest.js +2 -2
  94. package/api/features/AiImageEnrichment/buildEnrichmentAiRequest.js.map +1 -1
  95. package/api/features/AiImageEnrichment/capability.d.ts +18 -0
  96. package/api/features/AiImageEnrichment/capability.js +19 -0
  97. package/api/features/AiImageEnrichment/capability.js.map +1 -0
  98. package/api/features/AiImageEnrichment/errors.d.ts +6 -1
  99. package/api/features/AiImageEnrichment/errors.js +2 -2
  100. package/api/features/AiImageEnrichment/errors.js.map +1 -1
  101. package/api/features/AiImageEnrichment/feature.js +2 -0
  102. package/api/features/AiImageEnrichment/feature.js.map +1 -1
  103. package/api/features/Capabilities/CapabilitiesHandler.d.ts +28 -0
  104. package/api/features/Capabilities/CapabilitiesHandler.js +56 -0
  105. package/api/features/Capabilities/CapabilitiesHandler.js.map +1 -0
  106. package/api/features/Capabilities/ListAiCapabilitiesUseCase.d.ts +18 -0
  107. package/api/features/Capabilities/ListAiCapabilitiesUseCase.js +28 -0
  108. package/api/features/Capabilities/ListAiCapabilitiesUseCase.js.map +1 -0
  109. package/api/features/Capabilities/ResolveAiCapabilityUseCase.d.ts +30 -0
  110. package/api/features/Capabilities/ResolveAiCapabilityUseCase.js +88 -0
  111. package/api/features/Capabilities/ResolveAiCapabilityUseCase.js.map +1 -0
  112. package/api/features/Capabilities/abstractions.d.ts +77 -0
  113. package/api/features/Capabilities/abstractions.js +7 -0
  114. package/api/features/Capabilities/abstractions.js.map +1 -0
  115. package/api/features/Capabilities/composeSystemPrompt.d.ts +14 -0
  116. package/api/features/Capabilities/composeSystemPrompt.js +13 -0
  117. package/api/features/Capabilities/composeSystemPrompt.js.map +1 -0
  118. package/api/features/Capabilities/feature.d.ts +4 -0
  119. package/api/features/Capabilities/feature.js +15 -0
  120. package/api/features/Capabilities/feature.js.map +1 -0
  121. package/api/features/Capabilities/index.d.ts +5 -0
  122. package/api/features/Capabilities/index.js +3 -0
  123. package/api/features/Capabilities/types.d.ts +86 -0
  124. package/api/features/Capabilities/types.js +4 -0
  125. package/api/features/Capabilities/types.js.map +1 -0
  126. package/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.d.ts +3 -5
  127. package/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.js +11 -65
  128. package/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.js.map +1 -1
  129. package/api/features/CmsCompareEntryRevisions/capability.d.ts +13 -0
  130. package/api/features/CmsCompareEntryRevisions/capability.js +64 -0
  131. package/api/features/CmsCompareEntryRevisions/capability.js.map +1 -0
  132. package/api/features/CmsCompareEntryRevisions/feature.js +2 -0
  133. package/api/features/CmsCompareEntryRevisions/feature.js.map +1 -1
  134. package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.d.ts +3 -5
  135. package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.js +11 -19
  136. package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.js.map +1 -1
  137. package/api/features/CmsGenerateEntryContent/capability.d.ts +17 -0
  138. package/api/features/CmsGenerateEntryContent/capability.js +17 -0
  139. package/api/features/CmsGenerateEntryContent/capability.js.map +1 -0
  140. package/api/features/CmsGenerateEntryContent/feature.js +2 -0
  141. package/api/features/CmsGenerateEntryContent/feature.js.map +1 -1
  142. package/api/features/Connections/ConnectionsGraphQLMapper.d.ts +20 -0
  143. package/api/features/Connections/ConnectionsGraphQLMapper.js +37 -0
  144. package/api/features/Connections/ConnectionsGraphQLMapper.js.map +1 -0
  145. package/api/features/Connections/ConnectionsHandler.d.ts +25 -0
  146. package/api/features/Connections/ConnectionsHandler.js +84 -0
  147. package/api/features/Connections/ConnectionsHandler.js.map +1 -0
  148. package/api/features/Connections/feature.d.ts +4 -0
  149. package/api/features/Connections/feature.js +13 -0
  150. package/api/features/Connections/feature.js.map +1 -0
  151. package/api/features/Connections/index.d.ts +2 -0
  152. package/api/features/Connections/index.js +1 -0
  153. package/api/features/Connections/legacyProviders.d.ts +26 -0
  154. package/api/features/Connections/legacyProviders.js +9 -0
  155. package/api/features/Connections/legacyProviders.js.map +1 -0
  156. package/api/features/Connections/types.d.ts +36 -0
  157. package/api/features/Connections/types.js +0 -0
  158. package/api/features/GetSettings/GetSettingsRepository.js +1 -1
  159. package/api/features/GetSettings/GetSettingsRepository.js.map +1 -1
  160. package/api/features/ModelRoles/ModelRolesHandler.d.ts +15 -0
  161. package/api/features/ModelRoles/ModelRolesHandler.js +68 -0
  162. package/api/features/ModelRoles/ModelRolesHandler.js.map +1 -0
  163. package/api/features/ModelRoles/feature.d.ts +4 -0
  164. package/api/features/ModelRoles/feature.js +11 -0
  165. package/api/features/ModelRoles/feature.js.map +1 -0
  166. package/api/features/ModelRoles/index.d.ts +4 -0
  167. package/api/features/ModelRoles/index.js +2 -0
  168. package/api/features/ModelRoles/roles.d.ts +16 -0
  169. package/api/features/ModelRoles/roles.js +9 -0
  170. package/api/features/ModelRoles/roles.js.map +1 -0
  171. package/api/features/ModelRoles/types.d.ts +21 -0
  172. package/api/features/ModelRoles/types.js +7 -0
  173. package/api/features/ModelRoles/types.js.map +1 -0
  174. package/api/features/UpdateSettings/UpdateSettingsRepository.js +2 -2
  175. package/api/features/UpdateSettings/UpdateSettingsRepository.js.map +1 -1
  176. package/api/features/WbGeneratePageContent/WbGeneratePageContentUseCase.d.ts +3 -5
  177. package/api/features/WbGeneratePageContent/WbGeneratePageContentUseCase.js +11 -19
  178. package/api/features/WbGeneratePageContent/WbGeneratePageContentUseCase.js.map +1 -1
  179. package/api/features/WbGeneratePageContent/capability.d.ts +16 -0
  180. package/api/features/WbGeneratePageContent/capability.js +17 -0
  181. package/api/features/WbGeneratePageContent/capability.js.map +1 -0
  182. package/api/features/WbGeneratePageContent/feature.js +2 -0
  183. package/api/features/WbGeneratePageContent/feature.js.map +1 -1
  184. package/api/features/WbTranslatePage/WbTranslatePageDecorator.d.ts +5 -5
  185. package/api/features/WbTranslatePage/WbTranslatePageDecorator.js +19 -19
  186. package/api/features/WbTranslatePage/WbTranslatePageDecorator.js.map +1 -1
  187. package/api/features/WbTranslatePage/capability.d.ts +13 -0
  188. package/api/features/WbTranslatePage/capability.js +19 -0
  189. package/api/features/WbTranslatePage/capability.js.map +1 -0
  190. package/api/features/WbTranslatePage/feature.js +2 -0
  191. package/api/features/WbTranslatePage/feature.js.map +1 -1
  192. package/api/features/shared/abstractions.d.ts +6 -1
  193. package/api/features/shared/abstractions.js.map +1 -1
  194. package/api/features/shared/modelId.d.ts +11 -0
  195. package/api/features/shared/modelId.js +4 -0
  196. package/api/features/shared/modelId.js.map +1 -0
  197. package/api/graphql/BaseGraphQLSchema.js +16 -0
  198. package/api/graphql/BaseGraphQLSchema.js.map +1 -1
  199. package/api/types.d.ts +3 -0
  200. package/api/types.js +3 -0
  201. package/exports/api/ai-powerups.d.ts +5 -0
  202. package/exports/api/ai-powerups.js +3 -0
  203. package/package.json +24 -26
  204. package/api/features/AiChatProvider/PowerUpsAiChatProvider.d.ts +0 -24
  205. package/api/features/AiChatProvider/PowerUpsAiChatProvider.js +0 -31
  206. package/api/features/AiChatProvider/PowerUpsAiChatProvider.js.map +0 -1
  207. package/api/features/AiChatProvider/feature.d.ts +0 -9
  208. package/api/features/AiChatProvider/feature.js +0 -11
  209. package/api/features/AiChatProvider/feature.js.map +0 -1
  210. package/api/features/AiChatProvider/index.d.ts +0 -2
  211. package/api/features/AiChatProvider/index.js +0 -2
@@ -1,73 +1,24 @@
1
1
  import { Ai } from "@webiny/api-core/features/ai/index.js";
2
- import { Encryption } from "@webiny/api-core/features/encryption/index.js";
3
2
  import { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
4
3
  import { ModelToAstConverter } from "@webiny/api-headless-cms/features/contentModel/ModelToAstConverter/index.js";
5
4
  import { CmsModelToJsonSchemaConverter } from "@webiny/api-headless-cms/utils/contentModelToJsonSchema/index.js";
6
5
  import { GetRevisionByIdUseCase } from "@webiny/api-headless-cms/features/contentEntry/GetRevisionById/index.js";
7
- import { GetSettingsUseCase } from "../GetSettings/index.js";
6
+ import { ResolveAiCapabilityUseCase, withAdditionalInstructions } from "../Capabilities/index.js";
7
+ import { CMS_COMPARE_ENTRY_REVISIONS_CAPABILITY } from "./capability.js";
8
8
  import { CmsCompareEntryRevisionsUseCase } from "./abstractions.js";
9
- const SYSTEM_PROMPT = `You are a content intelligence assistant specialized in version comparison for headless CMS platforms.
10
-
11
- I will provide:
12
-
13
- 1. The content model JSON Schema that defines the structure of the entry.
14
- 2. Two versions of the content entry values in JSON format: Version A and Version B.
15
-
16
- Your task:
17
-
18
- - Parse both versions according to the JSON Schema.
19
- - Identify all differences between Version A and Version B.
20
- - For each difference, explain:
21
- - The field name (use the human-readable label from the schema description if available)
22
- - The value in Version A
23
- - The value in Version B
24
- - A brief summary of the change (e.g., "Title changed from 'Old' to 'New'")
25
- - If nested fields or objects exist, perform a deep comparison.
26
- - Return the comparison in clean HTML format.
27
-
28
- Output format:
29
-
30
- <div class="comparison-report">
31
- <table class="comparison-table">
32
- <thead>
33
- <tr>
34
- <th>Field</th>
35
- <th>Version A</th>
36
- <th>Version B</th>
37
- <th>Change Summary</th>
38
- </tr>
39
- </thead>
40
- <tbody>
41
- <tr>
42
- <td><strong>title</strong></td>
43
- <td>Launch Plan</td>
44
- <td>Updated Launch Plan</td>
45
- <td>Title changed from 'Launch Plan' to 'Updated Launch Plan'</td>
46
- </tr>
47
- </tbody>
48
- </table>
49
- </div>
50
-
51
- If no differences are found, return: <div class="no-changes"><h3>No differences detected between Version A and Version B.</h3></div>
52
-
53
- Use semantic HTML with appropriate CSS classes for styling. Do not include <style> tags or CSS — only return the HTML structure.
54
- For rich text or complex nested values, show a concise summary rather than raw JSON.`;
55
9
  class CmsCompareEntryRevisionsUseCaseImpl {
56
- constructor(getSettings, ai, encryption, getModel, getRevisionById, modelToAst){
57
- this.getSettings = getSettings;
10
+ constructor(resolveCapability, ai, getModel, getRevisionById, modelToAst){
11
+ this.resolveCapability = resolveCapability;
58
12
  this.ai = ai;
59
- this.encryption = encryption;
60
13
  this.getModel = getModel;
61
14
  this.getRevisionById = getRevisionById;
62
15
  this.modelToAst = modelToAst;
63
16
  }
64
17
  async execute(params) {
65
18
  const { modelId, revisionId1, revisionId2 } = params;
66
- const settingsResult = await this.getSettings.execute();
67
- if (settingsResult.isFail()) throw new Error("Failed to load AI Power Ups settings.");
68
- const settings = settingsResult.value;
69
- const firstProvider = settings.providers.presets[0];
70
- if (!firstProvider) throw new Error("No AI provider configured. Add a provider in AI Power Ups settings.");
19
+ const resolved = await this.resolveCapability.execute(CMS_COMPARE_ENTRY_REVISIONS_CAPABILITY);
20
+ if (resolved.isFail()) throw resolved.error;
21
+ const capability = resolved.value;
71
22
  const modelResult = await this.getModel.execute(modelId);
72
23
  if (modelResult.isFail()) throw new Error(`Content model "${modelId}" not found.`);
73
24
  const model = modelResult.value;
@@ -85,7 +36,6 @@ class CmsCompareEntryRevisionsUseCaseImpl {
85
36
  name: model.name,
86
37
  description: model.description
87
38
  });
88
- const apiKey = await this.encryption.decrypt(firstProvider.apiKeyEncrypted);
89
39
  const userPrompt = `CONTENT MODEL JSON SCHEMA:
90
40
  ${JSON.stringify(entrySchema, null, 2)}
91
41
 
@@ -95,12 +45,9 @@ ${JSON.stringify(revision1.values, null, 2)}
95
45
  VERSION B (Revision #${revision2.version}):
96
46
  ${JSON.stringify(revision2.values, null, 2)}`;
97
47
  const result = await this.ai.generateText({
98
- model: firstProvider.model,
99
- connection: {
100
- sdkName: firstProvider.model.split("/")[0],
101
- apiKey
102
- },
103
- system: SYSTEM_PROMPT,
48
+ model: capability.model,
49
+ connection: capability.connection,
50
+ system: withAdditionalInstructions(capability),
104
51
  prompt: userPrompt,
105
52
  temperature: 0.3
106
53
  });
@@ -123,9 +70,8 @@ ${JSON.stringify(revision2.values, null, 2)}`;
123
70
  const CmsCompareEntryRevisionsUseCaseImplementation = CmsCompareEntryRevisionsUseCase.createImplementation({
124
71
  implementation: CmsCompareEntryRevisionsUseCaseImpl,
125
72
  dependencies: [
126
- GetSettingsUseCase,
73
+ ResolveAiCapabilityUseCase,
127
74
  Ai,
128
- Encryption,
129
75
  GetModelUseCase,
130
76
  GetRevisionByIdUseCase,
131
77
  ModelToAstConverter
@@ -1 +1 @@
1
- {"version":3,"file":"api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.js","sources":["../../../../src/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.ts"],"sourcesContent":["import { Ai } from \"@webiny/api-core/features/ai/index.js\";\nimport { Encryption } from \"@webiny/api-core/features/encryption/index.js\";\nimport { GetModelUseCase } from \"@webiny/api-headless-cms/features/contentModel/GetModel/index.js\";\nimport { ModelToAstConverter } from \"@webiny/api-headless-cms/features/contentModel/ModelToAstConverter/index.js\";\nimport { CmsModelToJsonSchemaConverter } from \"@webiny/api-headless-cms/utils/contentModelToJsonSchema/index.js\";\nimport { GetRevisionByIdUseCase } from \"@webiny/api-headless-cms/features/contentEntry/GetRevisionById/index.js\";\nimport { GetSettingsUseCase } from \"~/api/features/GetSettings/index.js\";\nimport { CmsCompareEntryRevisionsUseCase } from \"./abstractions.js\";\nimport type {\n ICmsCompareEntryRevisionsParams,\n ICmsCompareEntryRevisionsResult\n} from \"./abstractions.js\";\n\nconst SYSTEM_PROMPT = `You are a content intelligence assistant specialized in version comparison for headless CMS platforms.\n\nI will provide:\n\n1. The content model JSON Schema that defines the structure of the entry.\n2. Two versions of the content entry values in JSON format: Version A and Version B.\n\nYour task:\n\n- Parse both versions according to the JSON Schema.\n- Identify all differences between Version A and Version B.\n- For each difference, explain:\n - The field name (use the human-readable label from the schema description if available)\n - The value in Version A\n - The value in Version B\n - A brief summary of the change (e.g., \"Title changed from 'Old' to 'New'\")\n- If nested fields or objects exist, perform a deep comparison.\n- Return the comparison in clean HTML format.\n\nOutput format:\n\n<div class=\"comparison-report\">\n <table class=\"comparison-table\">\n <thead>\n <tr>\n <th>Field</th>\n <th>Version A</th>\n <th>Version B</th>\n <th>Change Summary</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td><strong>title</strong></td>\n <td>Launch Plan</td>\n <td>Updated Launch Plan</td>\n <td>Title changed from 'Launch Plan' to 'Updated Launch Plan'</td>\n </tr>\n </tbody>\n </table>\n</div>\n\nIf no differences are found, return: <div class=\"no-changes\"><h3>No differences detected between Version A and Version B.</h3></div>\n\nUse semantic HTML with appropriate CSS classes for styling. Do not include <style> tags or CSS — only return the HTML structure.\nFor rich text or complex nested values, show a concise summary rather than raw JSON.`;\n\nclass CmsCompareEntryRevisionsUseCaseImpl implements CmsCompareEntryRevisionsUseCase.Interface {\n constructor(\n private getSettings: GetSettingsUseCase.Interface,\n private ai: Ai.Interface,\n private encryption: Encryption.Interface,\n private getModel: GetModelUseCase.Interface,\n private getRevisionById: GetRevisionByIdUseCase.Interface,\n private modelToAst: ModelToAstConverter.Interface\n ) {}\n\n async execute(\n params: ICmsCompareEntryRevisionsParams\n ): Promise<ICmsCompareEntryRevisionsResult> {\n const { modelId, revisionId1, revisionId2 } = params;\n\n const settingsResult = await this.getSettings.execute();\n if (settingsResult.isFail()) {\n throw new Error(\"Failed to load AI Power Ups settings.\");\n }\n\n const settings = settingsResult.value;\n const firstProvider = settings.providers.presets[0];\n\n if (!firstProvider) {\n throw new Error(\"No AI provider configured. Add a provider in AI Power Ups settings.\");\n }\n\n const modelResult = await this.getModel.execute(modelId);\n if (modelResult.isFail()) {\n throw new Error(`Content model \"${modelId}\" not found.`);\n }\n const model = modelResult.value;\n\n const [rev1Result, rev2Result] = await Promise.all([\n this.getRevisionById.execute(model, revisionId1),\n this.getRevisionById.execute(model, revisionId2)\n ]);\n\n if (rev1Result.isFail()) {\n throw new Error(`Revision \"${revisionId1}\" not found.`);\n }\n if (rev2Result.isFail()) {\n throw new Error(`Revision \"${revisionId2}\" not found.`);\n }\n\n const revision1 = rev1Result.value;\n const revision2 = rev2Result.value;\n\n const modelAst = this.modelToAst.toAst(model);\n const jsonSchemaConverter = new CmsModelToJsonSchemaConverter();\n const entrySchema = jsonSchemaConverter.convert(modelAst, {\n name: model.name,\n description: model.description\n });\n\n const apiKey = await this.encryption.decrypt(firstProvider.apiKeyEncrypted);\n\n const userPrompt = `CONTENT MODEL JSON SCHEMA:\n${JSON.stringify(entrySchema, null, 2)}\n\nVERSION A (Revision #${revision1.version}):\n${JSON.stringify(revision1.values, null, 2)}\n\nVERSION B (Revision #${revision2.version}):\n${JSON.stringify(revision2.values, null, 2)}`;\n\n const result = await this.ai.generateText({\n model: firstProvider.model,\n connection: {\n sdkName: firstProvider.model.split(\"/\")[0],\n apiKey\n },\n system: SYSTEM_PROMPT,\n prompt: userPrompt,\n temperature: 0.3\n });\n\n const text = result.text;\n\n const noChangesMatch = text.match(/No differences detected/);\n let summary = \"Content comparison completed\";\n if (noChangesMatch) {\n summary = \"No differences detected between versions\";\n } else {\n const headingMatch = text.match(/<h[2-3][^>]*>([^<]+)<\\/h[2-3]>/);\n const trCount = (text.match(/<tr>/g) || []).length - 1;\n if (headingMatch) {\n summary = headingMatch[1].trim();\n } else if (trCount > 0) {\n summary = `${trCount} field${trCount === 1 ? \"\" : \"s\"} changed`;\n }\n }\n\n return { html: text, summary };\n }\n}\n\nexport const CmsCompareEntryRevisionsUseCaseImplementation =\n CmsCompareEntryRevisionsUseCase.createImplementation({\n implementation: CmsCompareEntryRevisionsUseCaseImpl,\n dependencies: [\n GetSettingsUseCase,\n Ai,\n Encryption,\n GetModelUseCase,\n GetRevisionByIdUseCase,\n ModelToAstConverter\n ]\n });\n"],"names":["SYSTEM_PROMPT","CmsCompareEntryRevisionsUseCaseImpl","getSettings","ai","encryption","getModel","getRevisionById","modelToAst","params","modelId","revisionId1","revisionId2","settingsResult","Error","settings","firstProvider","modelResult","model","rev1Result","rev2Result","Promise","revision1","revision2","modelAst","jsonSchemaConverter","CmsModelToJsonSchemaConverter","entrySchema","apiKey","userPrompt","JSON","result","text","noChangesMatch","summary","headingMatch","trCount","CmsCompareEntryRevisionsUseCaseImplementation","CmsCompareEntryRevisionsUseCase","GetSettingsUseCase","Ai","Encryption","GetModelUseCase","GetRevisionByIdUseCase","ModelToAstConverter"],"mappings":"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"}
1
+ {"version":3,"file":"api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.js","sources":["../../../../src/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.ts"],"sourcesContent":["import { Ai } from \"@webiny/api-core/features/ai/index.js\";\nimport { GetModelUseCase } from \"@webiny/api-headless-cms/features/contentModel/GetModel/index.js\";\nimport { ModelToAstConverter } from \"@webiny/api-headless-cms/features/contentModel/ModelToAstConverter/index.js\";\nimport { CmsModelToJsonSchemaConverter } from \"@webiny/api-headless-cms/utils/contentModelToJsonSchema/index.js\";\nimport { GetRevisionByIdUseCase } from \"@webiny/api-headless-cms/features/contentEntry/GetRevisionById/index.js\";\nimport {\n ResolveAiCapabilityUseCase,\n withAdditionalInstructions\n} from \"~/api/features/Capabilities/index.js\";\nimport { CMS_COMPARE_ENTRY_REVISIONS_CAPABILITY } from \"./capability.js\";\nimport { CmsCompareEntryRevisionsUseCase } from \"./abstractions.js\";\nimport type {\n ICmsCompareEntryRevisionsParams,\n ICmsCompareEntryRevisionsResult\n} from \"./abstractions.js\";\n\nclass CmsCompareEntryRevisionsUseCaseImpl implements CmsCompareEntryRevisionsUseCase.Interface {\n constructor(\n private resolveCapability: ResolveAiCapabilityUseCase.Interface,\n private ai: Ai.Interface,\n private getModel: GetModelUseCase.Interface,\n private getRevisionById: GetRevisionByIdUseCase.Interface,\n private modelToAst: ModelToAstConverter.Interface\n ) {}\n\n async execute(\n params: ICmsCompareEntryRevisionsParams\n ): Promise<ICmsCompareEntryRevisionsResult> {\n const { modelId, revisionId1, revisionId2 } = params;\n\n const resolved = await this.resolveCapability.execute(\n CMS_COMPARE_ENTRY_REVISIONS_CAPABILITY\n );\n if (resolved.isFail()) {\n throw resolved.error;\n }\n\n const capability = resolved.value;\n\n const modelResult = await this.getModel.execute(modelId);\n if (modelResult.isFail()) {\n throw new Error(`Content model \"${modelId}\" not found.`);\n }\n const model = modelResult.value;\n\n const [rev1Result, rev2Result] = await Promise.all([\n this.getRevisionById.execute(model, revisionId1),\n this.getRevisionById.execute(model, revisionId2)\n ]);\n\n if (rev1Result.isFail()) {\n throw new Error(`Revision \"${revisionId1}\" not found.`);\n }\n if (rev2Result.isFail()) {\n throw new Error(`Revision \"${revisionId2}\" not found.`);\n }\n\n const revision1 = rev1Result.value;\n const revision2 = rev2Result.value;\n\n const modelAst = this.modelToAst.toAst(model);\n const jsonSchemaConverter = new CmsModelToJsonSchemaConverter();\n const entrySchema = jsonSchemaConverter.convert(modelAst, {\n name: model.name,\n description: model.description\n });\n\n const userPrompt = `CONTENT MODEL JSON SCHEMA:\n${JSON.stringify(entrySchema, null, 2)}\n\nVERSION A (Revision #${revision1.version}):\n${JSON.stringify(revision1.values, null, 2)}\n\nVERSION B (Revision #${revision2.version}):\n${JSON.stringify(revision2.values, null, 2)}`;\n\n const result = await this.ai.generateText({\n model: capability.model,\n connection: capability.connection,\n system: withAdditionalInstructions(capability),\n prompt: userPrompt,\n temperature: 0.3\n });\n\n const text = result.text;\n\n const noChangesMatch = text.match(/No differences detected/);\n let summary = \"Content comparison completed\";\n if (noChangesMatch) {\n summary = \"No differences detected between versions\";\n } else {\n const headingMatch = text.match(/<h[2-3][^>]*>([^<]+)<\\/h[2-3]>/);\n const trCount = (text.match(/<tr>/g) || []).length - 1;\n if (headingMatch) {\n summary = headingMatch[1].trim();\n } else if (trCount > 0) {\n summary = `${trCount} field${trCount === 1 ? \"\" : \"s\"} changed`;\n }\n }\n\n return { html: text, summary };\n }\n}\n\nexport const CmsCompareEntryRevisionsUseCaseImplementation =\n CmsCompareEntryRevisionsUseCase.createImplementation({\n implementation: CmsCompareEntryRevisionsUseCaseImpl,\n dependencies: [\n ResolveAiCapabilityUseCase,\n Ai,\n GetModelUseCase,\n GetRevisionByIdUseCase,\n ModelToAstConverter\n ]\n });\n"],"names":["CmsCompareEntryRevisionsUseCaseImpl","resolveCapability","ai","getModel","getRevisionById","modelToAst","params","modelId","revisionId1","revisionId2","resolved","CMS_COMPARE_ENTRY_REVISIONS_CAPABILITY","capability","modelResult","Error","model","rev1Result","rev2Result","Promise","revision1","revision2","modelAst","jsonSchemaConverter","CmsModelToJsonSchemaConverter","entrySchema","userPrompt","JSON","result","withAdditionalInstructions","text","noChangesMatch","summary","headingMatch","trCount","CmsCompareEntryRevisionsUseCaseImplementation","CmsCompareEntryRevisionsUseCase","ResolveAiCapabilityUseCase","Ai","GetModelUseCase","GetRevisionByIdUseCase","ModelToAstConverter"],"mappings":";;;;;;;;AAgBA,MAAMA;IACF,YACYC,iBAAuD,EACvDC,EAAgB,EAChBC,QAAmC,EACnCC,eAAiD,EACjDC,UAAyC,CACnD;aALUJ,iBAAiB,GAAjBA;aACAC,EAAE,GAAFA;aACAC,QAAQ,GAARA;aACAC,eAAe,GAAfA;aACAC,UAAU,GAAVA;IACT;IAEH,MAAM,QACFC,MAAuC,EACC;QACxC,MAAM,EAAEC,OAAO,EAAEC,WAAW,EAAEC,WAAW,EAAE,GAAGH;QAE9C,MAAMI,WAAW,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CACjDC;QAEJ,IAAID,SAAS,MAAM,IACf,MAAMA,SAAS,KAAK;QAGxB,MAAME,aAAaF,SAAS,KAAK;QAEjC,MAAMG,cAAc,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAACN;QAChD,IAAIM,YAAY,MAAM,IAClB,MAAM,IAAIC,MAAM,CAAC,eAAe,EAAEP,QAAQ,YAAY,CAAC;QAE3D,MAAMQ,QAAQF,YAAY,KAAK;QAE/B,MAAM,CAACG,YAAYC,WAAW,GAAG,MAAMC,QAAQ,GAAG,CAAC;YAC/C,IAAI,CAAC,eAAe,CAAC,OAAO,CAACH,OAAOP;YACpC,IAAI,CAAC,eAAe,CAAC,OAAO,CAACO,OAAON;SACvC;QAED,IAAIO,WAAW,MAAM,IACjB,MAAM,IAAIF,MAAM,CAAC,UAAU,EAAEN,YAAY,YAAY,CAAC;QAE1D,IAAIS,WAAW,MAAM,IACjB,MAAM,IAAIH,MAAM,CAAC,UAAU,EAAEL,YAAY,YAAY,CAAC;QAG1D,MAAMU,YAAYH,WAAW,KAAK;QAClC,MAAMI,YAAYH,WAAW,KAAK;QAElC,MAAMI,WAAW,IAAI,CAAC,UAAU,CAAC,KAAK,CAACN;QACvC,MAAMO,sBAAsB,IAAIC;QAChC,MAAMC,cAAcF,oBAAoB,OAAO,CAACD,UAAU;YACtD,MAAMN,MAAM,IAAI;YAChB,aAAaA,MAAM,WAAW;QAClC;QAEA,MAAMU,aAAa,CAAC;AAC5B,EAAEC,KAAK,SAAS,CAACF,aAAa,MAAM,GAAG;;qBAElB,EAAEL,UAAU,OAAO,CAAC;AACzC,EAAEO,KAAK,SAAS,CAACP,UAAU,MAAM,EAAE,MAAM,GAAG;;qBAEvB,EAAEC,UAAU,OAAO,CAAC;AACzC,EAAEM,KAAK,SAAS,CAACN,UAAU,MAAM,EAAE,MAAM,IAAI;QAErC,MAAMO,SAAS,MAAM,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC;YACtC,OAAOf,WAAW,KAAK;YACvB,YAAYA,WAAW,UAAU;YACjC,QAAQgB,2BAA2BhB;YACnC,QAAQa;YACR,aAAa;QACjB;QAEA,MAAMI,OAAOF,OAAO,IAAI;QAExB,MAAMG,iBAAiBD,KAAK,KAAK,CAAC;QAClC,IAAIE,UAAU;QACd,IAAID,gBACAC,UAAU;aACP;YACH,MAAMC,eAAeH,KAAK,KAAK,CAAC;YAChC,MAAMI,UAAWJ,AAAAA,CAAAA,KAAK,KAAK,CAAC,YAAY,EAAC,EAAG,MAAM,GAAG;YACrD,IAAIG,cACAD,UAAUC,YAAY,CAAC,EAAE,CAAC,IAAI;iBAC3B,IAAIC,UAAU,GACjBF,UAAU,GAAGE,QAAQ,MAAM,EAAEA,AAAY,MAAZA,UAAgB,KAAK,IAAI,QAAQ,CAAC;QAEvE;QAEA,OAAO;YAAE,MAAMJ;YAAME;QAAQ;IACjC;AACJ;AAEO,MAAMG,gDACTC,gCAAgC,oBAAoB,CAAC;IACjD,gBAAgBnC;IAChB,cAAc;QACVoC;QACAC;QACAC;QACAC;QACAC;KACH;AACL"}
@@ -0,0 +1,13 @@
1
+ import { AiCapability } from "../../../api/features/Capabilities/index.js";
2
+ export declare const CMS_COMPARE_ENTRY_REVISIONS_CAPABILITY = "cms.compareEntryRevisions";
3
+ declare class CmsCompareEntryRevisionsCapabilityImpl implements AiCapability.Interface {
4
+ readonly id = "cms.compareEntryRevisions";
5
+ readonly label = "CMS revision comparison";
6
+ readonly description = "Summarises what changed between two revisions of an entry. Short, structural work that a smaller model handles well.";
7
+ readonly defaultRole: "fast";
8
+ readonly guidance = "You are a content intelligence assistant specialized in version comparison for headless CMS platforms.\n\nI will provide:\n\n1. The content model JSON Schema that defines the structure of the entry.\n2. Two versions of the content entry values in JSON format: Version A and Version B.\n\nYour task:\n\n- Parse both versions according to the JSON Schema.\n- Identify all differences between Version A and Version B.\n- For each difference, explain:\n - The field name (use the human-readable label from the schema description if available)\n - The value in Version A\n - The value in Version B\n - A brief summary of the change (e.g., \"Title changed from 'Old' to 'New'\")\n- If nested fields or objects exist, perform a deep comparison.\n- Return the comparison in clean HTML format.\n\nOutput format:\n\n<div class=\"comparison-report\">\n <table class=\"comparison-table\">\n <thead>\n <tr>\n <th>Field</th>\n <th>Version A</th>\n <th>Version B</th>\n <th>Change Summary</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td><strong>title</strong></td>\n <td>Launch Plan</td>\n <td>Updated Launch Plan</td>\n <td>Title changed from 'Launch Plan' to 'Updated Launch Plan'</td>\n </tr>\n </tbody>\n </table>\n</div>\n\nIf no differences are found, return: <div class=\"no-changes\"><h3>No differences detected between Version A and Version B.</h3></div>\n\nUse semantic HTML with appropriate CSS classes for styling. Do not include <style> tags or CSS \u2014 only return the HTML structure.\nFor rich text or complex nested values, show a concise summary rather than raw JSON.";
9
+ }
10
+ export declare const CmsCompareEntryRevisionsCapability: typeof CmsCompareEntryRevisionsCapabilityImpl & {
11
+ __abstraction: import("@webiny/di").Abstraction<import("~/api/features/Capabilities/index.js").IAiCapability>;
12
+ };
13
+ export {};
@@ -0,0 +1,64 @@
1
+ import { AiCapability } from "../Capabilities/index.js";
2
+ const CMS_COMPARE_ENTRY_REVISIONS_CAPABILITY = "cms.compareEntryRevisions";
3
+ const guidance = `You are a content intelligence assistant specialized in version comparison for headless CMS platforms.
4
+
5
+ I will provide:
6
+
7
+ 1. The content model JSON Schema that defines the structure of the entry.
8
+ 2. Two versions of the content entry values in JSON format: Version A and Version B.
9
+
10
+ Your task:
11
+
12
+ - Parse both versions according to the JSON Schema.
13
+ - Identify all differences between Version A and Version B.
14
+ - For each difference, explain:
15
+ - The field name (use the human-readable label from the schema description if available)
16
+ - The value in Version A
17
+ - The value in Version B
18
+ - A brief summary of the change (e.g., "Title changed from 'Old' to 'New'")
19
+ - If nested fields or objects exist, perform a deep comparison.
20
+ - Return the comparison in clean HTML format.
21
+
22
+ Output format:
23
+
24
+ <div class="comparison-report">
25
+ <table class="comparison-table">
26
+ <thead>
27
+ <tr>
28
+ <th>Field</th>
29
+ <th>Version A</th>
30
+ <th>Version B</th>
31
+ <th>Change Summary</th>
32
+ </tr>
33
+ </thead>
34
+ <tbody>
35
+ <tr>
36
+ <td><strong>title</strong></td>
37
+ <td>Launch Plan</td>
38
+ <td>Updated Launch Plan</td>
39
+ <td>Title changed from 'Launch Plan' to 'Updated Launch Plan'</td>
40
+ </tr>
41
+ </tbody>
42
+ </table>
43
+ </div>
44
+
45
+ If no differences are found, return: <div class="no-changes"><h3>No differences detected between Version A and Version B.</h3></div>
46
+
47
+ Use semantic HTML with appropriate CSS classes for styling. Do not include <style> tags or CSS — only return the HTML structure.
48
+ For rich text or complex nested values, show a concise summary rather than raw JSON.`;
49
+ class CmsCompareEntryRevisionsCapabilityImpl {
50
+ constructor(){
51
+ this.id = CMS_COMPARE_ENTRY_REVISIONS_CAPABILITY;
52
+ this.label = "CMS revision comparison";
53
+ this.description = "Summarises what changed between two revisions of an entry. Short, structural work that a smaller model handles well.";
54
+ this.defaultRole = "fast";
55
+ this.guidance = guidance;
56
+ }
57
+ }
58
+ const CmsCompareEntryRevisionsCapability = AiCapability.createImplementation({
59
+ implementation: CmsCompareEntryRevisionsCapabilityImpl,
60
+ dependencies: []
61
+ });
62
+ export { CMS_COMPARE_ENTRY_REVISIONS_CAPABILITY, CmsCompareEntryRevisionsCapability };
63
+
64
+ //# sourceMappingURL=capability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/CmsCompareEntryRevisions/capability.js","sources":["../../../../src/api/features/CmsCompareEntryRevisions/capability.ts"],"sourcesContent":["import { AiCapability } from \"~/api/features/Capabilities/index.js\";\n\nexport const CMS_COMPARE_ENTRY_REVISIONS_CAPABILITY = \"cms.compareEntryRevisions\";\n\n/**\n * The output contract lives in this prompt: the use case regex-matches the HTML table it specifies\n * to build the summary, down to the literal \"No differences detected\" sentence and a count of\n * `<tr>` tags, and the dialog styles those classes. That is why a project can only append to it.\n */\nconst guidance = `You are a content intelligence assistant specialized in version comparison for headless CMS platforms.\n\nI will provide:\n\n1. The content model JSON Schema that defines the structure of the entry.\n2. Two versions of the content entry values in JSON format: Version A and Version B.\n\nYour task:\n\n- Parse both versions according to the JSON Schema.\n- Identify all differences between Version A and Version B.\n- For each difference, explain:\n - The field name (use the human-readable label from the schema description if available)\n - The value in Version A\n - The value in Version B\n - A brief summary of the change (e.g., \"Title changed from 'Old' to 'New'\")\n- If nested fields or objects exist, perform a deep comparison.\n- Return the comparison in clean HTML format.\n\nOutput format:\n\n<div class=\"comparison-report\">\n <table class=\"comparison-table\">\n <thead>\n <tr>\n <th>Field</th>\n <th>Version A</th>\n <th>Version B</th>\n <th>Change Summary</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td><strong>title</strong></td>\n <td>Launch Plan</td>\n <td>Updated Launch Plan</td>\n <td>Title changed from 'Launch Plan' to 'Updated Launch Plan'</td>\n </tr>\n </tbody>\n </table>\n</div>\n\nIf no differences are found, return: <div class=\"no-changes\"><h3>No differences detected between Version A and Version B.</h3></div>\n\nUse semantic HTML with appropriate CSS classes for styling. Do not include <style> tags or CSS — only return the HTML structure.\nFor rich text or complex nested values, show a concise summary rather than raw JSON.`;\n\nclass CmsCompareEntryRevisionsCapabilityImpl implements AiCapability.Interface {\n readonly id = CMS_COMPARE_ENTRY_REVISIONS_CAPABILITY;\n readonly label = \"CMS revision comparison\";\n readonly description =\n \"Summarises what changed between two revisions of an entry. Short, structural work that a smaller model handles well.\";\n readonly defaultRole = \"fast\" as const;\n readonly guidance = guidance;\n}\n\nexport const CmsCompareEntryRevisionsCapability = AiCapability.createImplementation({\n implementation: CmsCompareEntryRevisionsCapabilityImpl,\n dependencies: []\n});\n"],"names":["CMS_COMPARE_ENTRY_REVISIONS_CAPABILITY","guidance","CmsCompareEntryRevisionsCapabilityImpl","CmsCompareEntryRevisionsCapability","AiCapability"],"mappings":";AAEO,MAAMA,yCAAyC;AAOtD,MAAMC,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oFA6CkE,CAAC;AAErF,MAAMC;;aACO,EAAE,GAAGF;aACL,KAAK,GAAG;aACR,WAAW,GAChB;aACK,WAAW,GAAG;aACd,QAAQ,GAAGC;;AACxB;AAEO,MAAME,qCAAqCC,aAAa,oBAAoB,CAAC;IAChF,gBAAgBF;IAChB,cAAc,EAAE;AACpB"}
@@ -1,8 +1,10 @@
1
1
  import { createFeature } from "@webiny/feature/api";
2
2
  import { CmsCompareEntryRevisionsUseCaseImplementation } from "./CmsCompareEntryRevisionsUseCase.js";
3
+ import { CmsCompareEntryRevisionsCapability } from "./capability.js";
3
4
  const CmsCompareEntryRevisionsFeature = createFeature({
4
5
  name: "AiPowerUps/CmsCompareEntryRevisions",
5
6
  register (container) {
7
+ container.register(CmsCompareEntryRevisionsCapability);
6
8
  container.register(CmsCompareEntryRevisionsUseCaseImplementation);
7
9
  }
8
10
  });
@@ -1 +1 @@
1
- {"version":3,"file":"api/features/CmsCompareEntryRevisions/feature.js","sources":["../../../../src/api/features/CmsCompareEntryRevisions/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { CmsCompareEntryRevisionsUseCaseImplementation } from \"./CmsCompareEntryRevisionsUseCase.js\";\n\nexport const CmsCompareEntryRevisionsFeature = createFeature({\n name: \"AiPowerUps/CmsCompareEntryRevisions\",\n register(container) {\n container.register(CmsCompareEntryRevisionsUseCaseImplementation);\n }\n});\n"],"names":["CmsCompareEntryRevisionsFeature","createFeature","container","CmsCompareEntryRevisionsUseCaseImplementation"],"mappings":";;AAGO,MAAMA,kCAAkCC,cAAc;IACzD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}
1
+ {"version":3,"file":"api/features/CmsCompareEntryRevisions/feature.js","sources":["../../../../src/api/features/CmsCompareEntryRevisions/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { CmsCompareEntryRevisionsUseCaseImplementation } from \"./CmsCompareEntryRevisionsUseCase.js\";\nimport { CmsCompareEntryRevisionsCapability } from \"./capability.js\";\n\nexport const CmsCompareEntryRevisionsFeature = createFeature({\n name: \"AiPowerUps/CmsCompareEntryRevisions\",\n register(container) {\n container.register(CmsCompareEntryRevisionsCapability);\n container.register(CmsCompareEntryRevisionsUseCaseImplementation);\n }\n});\n"],"names":["CmsCompareEntryRevisionsFeature","createFeature","container","CmsCompareEntryRevisionsCapability","CmsCompareEntryRevisionsUseCaseImplementation"],"mappings":";;;AAIO,MAAMA,kCAAkCC,cAAc;IACzD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;QACnBD,UAAU,QAAQ,CAACE;IACvB;AACJ"}
@@ -2,25 +2,23 @@ import { Result } from "@webiny/feature/api";
2
2
  import { Ai } from "@webiny/api-core/features/ai/index.js";
3
3
  import { AiSdkTools } from "@webiny/api-core/features/ai/index.js";
4
4
  import { AiToolPipelineRunner } from "@webiny/api-core/features/ai/index.js";
5
- import { Encryption } from "@webiny/api-core/features/encryption/index.js";
6
5
  import { ListTagsUseCase } from "@webiny/api-file-manager/features/file/ListTags/index.js";
7
6
  import { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
8
7
  import { ModelToAstConverter } from "@webiny/api-headless-cms/features/contentModel/ModelToAstConverter/index.js";
9
- import { GetSettingsUseCase } from "../../../api/features/GetSettings/index.js";
8
+ import { ResolveAiCapabilityUseCase } from "../../../api/features/Capabilities/index.js";
10
9
  import { AiPromptContextBuilder } from "../../../api/features/AiPromptContext/index.js";
11
10
  import { CmsGenerateEntryContentUseCase } from "./abstractions.js";
12
11
  import type { CmsGenerateEntryContentParams, GenerateEntryContentResult } from "./abstractions.js";
13
12
  declare class CmsGenerateEntryContentUseCaseImpl implements CmsGenerateEntryContentUseCase.Interface {
14
13
  private promptContextBuilder;
15
- private getSettings;
14
+ private resolveCapability;
16
15
  private ai;
17
16
  private aiSdkTools;
18
- private encryption;
19
17
  private listTags;
20
18
  private getModel;
21
19
  private modelToAst;
22
20
  private toolPipelineRunner;
23
- constructor(promptContextBuilder: AiPromptContextBuilder.Interface, getSettings: GetSettingsUseCase.Interface, ai: Ai.Interface, aiSdkTools: AiSdkTools.Interface, encryption: Encryption.Interface, listTags: ListTagsUseCase.Interface, getModel: GetModelUseCase.Interface, modelToAst: ModelToAstConverter.Interface, toolPipelineRunner: AiToolPipelineRunner.Interface);
21
+ constructor(promptContextBuilder: AiPromptContextBuilder.Interface, resolveCapability: ResolveAiCapabilityUseCase.Interface, ai: Ai.Interface, aiSdkTools: AiSdkTools.Interface, listTags: ListTagsUseCase.Interface, getModel: GetModelUseCase.Interface, modelToAst: ModelToAstConverter.Interface, toolPipelineRunner: AiToolPipelineRunner.Interface);
24
22
  execute<TValues = Record<string, any>>(params: CmsGenerateEntryContentParams): Promise<Result<GenerateEntryContentResult<TValues>, Error>>;
25
23
  }
26
24
  export declare const CmsGenerateEntryContentUseCaseImplementation: typeof CmsGenerateEntryContentUseCaseImpl & {
@@ -1,12 +1,12 @@
1
1
  import { stepCountIs } from "ai";
2
2
  import { Result } from "@webiny/feature/api";
3
3
  import { Ai, AiSdkTools, AiToolPipelineRunner } from "@webiny/api-core/features/ai/index.js";
4
- import { Encryption } from "@webiny/api-core/features/encryption/index.js";
5
4
  import { ListTagsUseCase } from "@webiny/api-file-manager/features/file/ListTags/index.js";
6
5
  import { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
7
6
  import { ModelToAstConverter } from "@webiny/api-headless-cms/features/contentModel/ModelToAstConverter/index.js";
8
7
  import { CmsModelToJsonSchemaConverter } from "@webiny/api-headless-cms/utils/contentModelToJsonSchema/index.js";
9
- import { GetSettingsUseCase } from "../GetSettings/index.js";
8
+ import { ResolveAiCapabilityUseCase, withAdditionalInstructions } from "../Capabilities/index.js";
9
+ import { CMS_GENERATE_ENTRY_CAPABILITY } from "./capability.js";
10
10
  import { AiPromptContextBuilder, formatAdditionalFilesContext } from "../AiPromptContext/index.js";
11
11
  import { createReadProjectFileTool } from "../AiPromptContext/ReadProjectFileTool.js";
12
12
  import { CmsGenerateEntryContentUseCase } from "./abstractions.js";
@@ -14,23 +14,20 @@ import { buildEntryPrompt } from "./buildPrompt.js";
14
14
  import { LlmJsonResponse } from "../WbGeneratePageContent/LlmJsonResponse.js";
15
15
  import { injectDynamicZoneTypenames } from "./injectDynamicZoneTypenames.js";
16
16
  class CmsGenerateEntryContentUseCaseImpl {
17
- constructor(promptContextBuilder, getSettings, ai, aiSdkTools, encryption, listTags, getModel, modelToAst, toolPipelineRunner){
17
+ constructor(promptContextBuilder, resolveCapability, ai, aiSdkTools, listTags, getModel, modelToAst, toolPipelineRunner){
18
18
  this.promptContextBuilder = promptContextBuilder;
19
- this.getSettings = getSettings;
19
+ this.resolveCapability = resolveCapability;
20
20
  this.ai = ai;
21
21
  this.aiSdkTools = aiSdkTools;
22
- this.encryption = encryption;
23
22
  this.listTags = listTags;
24
23
  this.getModel = getModel;
25
24
  this.modelToAst = modelToAst;
26
25
  this.toolPipelineRunner = toolPipelineRunner;
27
26
  }
28
27
  async execute(params) {
29
- const settingsResult = await this.getSettings.execute();
30
- if (settingsResult.isFail()) return Result.fail(new Error("Failed to load AI PowerUps settings."));
31
- const settings = settingsResult.value;
32
- const firstProvider = settings.providers.presets[0];
33
- if (!firstProvider) return Result.fail(new Error("No AI provider configured. Add a provider in AI Power Ups settings."));
28
+ const resolved = await this.resolveCapability.execute(CMS_GENERATE_ENTRY_CAPABILITY);
29
+ if (resolved.isFail()) return Result.fail(resolved.error);
30
+ const capability = resolved.value;
34
31
  const modelResult = await this.getModel.execute(params.modelId);
35
32
  if (modelResult.isFail()) return Result.fail(new Error(`Content model "${params.modelId}" not found.`));
36
33
  const model = modelResult.value;
@@ -40,7 +37,6 @@ class CmsGenerateEntryContentUseCaseImpl {
40
37
  name: model.name,
41
38
  description: model.description
42
39
  });
43
- const apiKey = await this.encryption.decrypt(firstProvider.apiKeyEncrypted);
44
40
  const sdkTools = this.aiSdkTools.getToolSet();
45
41
  const context = await this.promptContextBuilder.execute({
46
42
  projectId: params.projectId,
@@ -60,7 +56,7 @@ class CmsGenerateEntryContentUseCaseImpl {
60
56
  limit: 100
61
57
  });
62
58
  const imageTags = tagsResult.isOk() ? tagsResult.value.map((t)=>t.tag) : [];
63
- const systemText = buildEntryPrompt(model.name, entrySchema, imageTags) + context.toString();
59
+ const systemText = withAdditionalInstructions(capability, buildEntryPrompt(model.name, entrySchema, imageTags) + context.toString());
64
60
  const system = {
65
61
  role: "system",
66
62
  content: systemText,
@@ -74,11 +70,8 @@ class CmsGenerateEntryContentUseCaseImpl {
74
70
  };
75
71
  try {
76
72
  const aiResult = await this.ai.generateText({
77
- model: firstProvider.model,
78
- connection: {
79
- sdkName: firstProvider.model.split("/")[0],
80
- apiKey
81
- },
73
+ model: capability.model,
74
+ connection: capability.connection,
82
75
  system,
83
76
  toolChoice: "auto",
84
77
  prompt: params.prompt + formatAdditionalFilesContext(context.additionalFiles),
@@ -126,10 +119,9 @@ const CmsGenerateEntryContentUseCaseImplementation = CmsGenerateEntryContentUseC
126
119
  implementation: CmsGenerateEntryContentUseCaseImpl,
127
120
  dependencies: [
128
121
  AiPromptContextBuilder,
129
- GetSettingsUseCase,
122
+ ResolveAiCapabilityUseCase,
130
123
  Ai,
131
124
  AiSdkTools,
132
- Encryption,
133
125
  ListTagsUseCase,
134
126
  GetModelUseCase,
135
127
  ModelToAstConverter,
@@ -1 +1 @@
1
- {"version":3,"file":"api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.js","sources":["../../../../src/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.ts"],"sourcesContent":["import { stepCountIs } from \"ai\";\nimport { Result } from \"@webiny/feature/api\";\nimport { Ai } from \"@webiny/api-core/features/ai/index.js\";\nimport { AiSdkTools } from \"@webiny/api-core/features/ai/index.js\";\nimport { AiToolPipelineRunner } from \"@webiny/api-core/features/ai/index.js\";\nimport { Encryption } from \"@webiny/api-core/features/encryption/index.js\";\nimport { ListTagsUseCase } from \"@webiny/api-file-manager/features/file/ListTags/index.js\";\nimport { GetModelUseCase } from \"@webiny/api-headless-cms/features/contentModel/GetModel/index.js\";\nimport { ModelToAstConverter } from \"@webiny/api-headless-cms/features/contentModel/ModelToAstConverter/index.js\";\nimport { CmsModelToJsonSchemaConverter } from \"@webiny/api-headless-cms/utils/contentModelToJsonSchema/index.js\";\nimport { GetSettingsUseCase } from \"~/api/features/GetSettings/index.js\";\nimport {\n AiPromptContextBuilder,\n formatAdditionalFilesContext\n} from \"~/api/features/AiPromptContext/index.js\";\nimport { createReadProjectFileTool } from \"~/api/features/AiPromptContext/ReadProjectFileTool.js\";\nimport { CmsGenerateEntryContentUseCase } from \"./abstractions.js\";\nimport type {\n CmsGenerateEntryContentParams,\n GenerateEntryContentResult,\n GenerateEntryContentTelemetry\n} from \"./abstractions.js\";\nimport { buildEntryPrompt } from \"./buildPrompt.js\";\nimport { LlmJsonResponse } from \"../WbGeneratePageContent/LlmJsonResponse.js\";\nimport { injectDynamicZoneTypenames } from \"./injectDynamicZoneTypenames.js\";\n\nclass CmsGenerateEntryContentUseCaseImpl implements CmsGenerateEntryContentUseCase.Interface {\n constructor(\n private promptContextBuilder: AiPromptContextBuilder.Interface,\n private getSettings: GetSettingsUseCase.Interface,\n private ai: Ai.Interface,\n private aiSdkTools: AiSdkTools.Interface,\n private encryption: Encryption.Interface,\n private listTags: ListTagsUseCase.Interface,\n private getModel: GetModelUseCase.Interface,\n private modelToAst: ModelToAstConverter.Interface,\n private toolPipelineRunner: AiToolPipelineRunner.Interface\n ) {}\n\n async execute<TValues = Record<string, any>>(\n params: CmsGenerateEntryContentParams\n ): Promise<Result<GenerateEntryContentResult<TValues>, Error>> {\n const settingsResult = await this.getSettings.execute();\n if (settingsResult.isFail()) {\n return Result.fail(new Error(\"Failed to load AI PowerUps settings.\"));\n }\n\n const settings = settingsResult.value;\n const firstProvider = settings.providers.presets[0];\n\n if (!firstProvider) {\n return Result.fail(\n new Error(\"No AI provider configured. Add a provider in AI Power Ups settings.\")\n );\n }\n\n const modelResult = await this.getModel.execute(params.modelId);\n if (modelResult.isFail()) {\n return Result.fail(new Error(`Content model \"${params.modelId}\" not found.`));\n }\n\n const model = modelResult.value;\n const modelAst = this.modelToAst.toAst(model);\n const jsonSchemaConverter = new CmsModelToJsonSchemaConverter();\n const entrySchema = jsonSchemaConverter.convert(modelAst, {\n name: model.name,\n description: model.description\n });\n\n const apiKey = await this.encryption.decrypt(firstProvider.apiKeyEncrypted);\n const sdkTools = this.aiSdkTools.getToolSet();\n\n const context = await this.promptContextBuilder.execute({\n projectId: params.projectId,\n readerPersonaId: params.readerPersonaId,\n writerPersonaId: params.writerPersonaId,\n excludedFileIds: params.excludedFileIds,\n additionalFileIds: params.additionalFileIds\n });\n\n if (context.allProjectFiles.length > 0) {\n const projectFileTool = createReadProjectFileTool(\n context.allProjectFiles,\n context.excludedFileIds\n );\n Object.assign(sdkTools, projectFileTool);\n }\n\n const tagsResult = await this.listTags.execute({\n where: { type_startsWith: \"image/\" },\n limit: 100\n });\n const imageTags = tagsResult.isOk() ? tagsResult.value.map(t => t.tag) : [];\n\n const systemText =\n buildEntryPrompt(model.name, entrySchema, imageTags) + context.toString();\n\n const system = {\n role: \"system\" as const,\n content: systemText,\n providerOptions: {\n anthropic: {\n cacheControl: { type: \"ephemeral\" }\n }\n }\n };\n\n try {\n const aiResult = await this.ai.generateText({\n model: firstProvider.model,\n connection: {\n sdkName: firstProvider.model.split(\"/\")[0],\n apiKey\n },\n system,\n toolChoice: \"auto\",\n prompt: params.prompt + formatAdditionalFilesContext(context.additionalFiles),\n ...(Object.keys(sdkTools).length > 0\n ? { tools: sdkTools, stopWhen: stepCountIs(20) }\n : {})\n });\n\n const text =\n aiResult.text ||\n (aiResult.steps.filter(step => step.text.length > 0).pop()?.text ?? \"\");\n\n const entry = LlmJsonResponse.fromRawText(text).toArray().pop();\n\n let resolved: Record<string, any> | undefined;\n\n if (entry) {\n resolved = (await this.toolPipelineRunner.resolve(entry)) as Record<string, any>;\n await injectDynamicZoneTypenames(resolved, modelAst, model.singularApiName);\n }\n\n const filesRead = new Set<string>();\n let toolCallsMade = 0;\n for (const step of aiResult.steps) {\n for (const call of step.toolCalls) {\n toolCallsMade++;\n if (call.toolName === \"read_project_file\") {\n const input = call.input as { fileId?: string };\n if (input.fileId) {\n filesRead.add(input.fileId);\n }\n }\n }\n }\n\n const telemetry: GenerateEntryContentTelemetry = {\n filesRead: [...filesRead],\n cacheHit: context.cacheHit,\n toolCallsMade,\n totalSteps: aiResult.steps.length,\n toolsAvailable: Object.keys(sdkTools),\n imageTagsInPrompt: imageTags\n };\n\n // Boundary cast: the AI output is dynamic JSON, so this is the one honest point\n // where we hand the resolved values to the caller's chosen `TValues` shape.\n return Result.ok({ values: (resolved ?? {}) as TValues, telemetry });\n } catch (error) {\n return Result.fail(\n new Error(\n `AI generation failed: ${error instanceof Error ? error.message : String(error)}`\n )\n );\n }\n }\n}\n\nexport const CmsGenerateEntryContentUseCaseImplementation =\n CmsGenerateEntryContentUseCase.createImplementation({\n implementation: CmsGenerateEntryContentUseCaseImpl,\n dependencies: [\n AiPromptContextBuilder,\n GetSettingsUseCase,\n Ai,\n AiSdkTools,\n Encryption,\n ListTagsUseCase,\n GetModelUseCase,\n ModelToAstConverter,\n AiToolPipelineRunner\n ]\n });\n"],"names":["CmsGenerateEntryContentUseCaseImpl","promptContextBuilder","getSettings","ai","aiSdkTools","encryption","listTags","getModel","modelToAst","toolPipelineRunner","params","settingsResult","Result","Error","settings","firstProvider","modelResult","model","modelAst","jsonSchemaConverter","CmsModelToJsonSchemaConverter","entrySchema","apiKey","sdkTools","context","projectFileTool","createReadProjectFileTool","Object","tagsResult","imageTags","t","systemText","buildEntryPrompt","system","aiResult","formatAdditionalFilesContext","stepCountIs","text","step","entry","LlmJsonResponse","resolved","injectDynamicZoneTypenames","filesRead","Set","toolCallsMade","call","input","telemetry","error","String","CmsGenerateEntryContentUseCaseImplementation","CmsGenerateEntryContentUseCase","AiPromptContextBuilder","GetSettingsUseCase","Ai","AiSdkTools","Encryption","ListTagsUseCase","GetModelUseCase","ModelToAstConverter","AiToolPipelineRunner"],"mappings":"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"}
1
+ {"version":3,"file":"api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.js","sources":["../../../../src/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.ts"],"sourcesContent":["import { stepCountIs } from \"ai\";\nimport { Result } from \"@webiny/feature/api\";\nimport { Ai } from \"@webiny/api-core/features/ai/index.js\";\nimport { AiSdkTools } from \"@webiny/api-core/features/ai/index.js\";\nimport { AiToolPipelineRunner } from \"@webiny/api-core/features/ai/index.js\";\nimport { ListTagsUseCase } from \"@webiny/api-file-manager/features/file/ListTags/index.js\";\nimport { GetModelUseCase } from \"@webiny/api-headless-cms/features/contentModel/GetModel/index.js\";\nimport { ModelToAstConverter } from \"@webiny/api-headless-cms/features/contentModel/ModelToAstConverter/index.js\";\nimport { CmsModelToJsonSchemaConverter } from \"@webiny/api-headless-cms/utils/contentModelToJsonSchema/index.js\";\nimport {\n ResolveAiCapabilityUseCase,\n withAdditionalInstructions\n} from \"~/api/features/Capabilities/index.js\";\nimport { CMS_GENERATE_ENTRY_CAPABILITY } from \"./capability.js\";\nimport {\n AiPromptContextBuilder,\n formatAdditionalFilesContext\n} from \"~/api/features/AiPromptContext/index.js\";\nimport { createReadProjectFileTool } from \"~/api/features/AiPromptContext/ReadProjectFileTool.js\";\nimport { CmsGenerateEntryContentUseCase } from \"./abstractions.js\";\nimport type {\n CmsGenerateEntryContentParams,\n GenerateEntryContentResult,\n GenerateEntryContentTelemetry\n} from \"./abstractions.js\";\nimport { buildEntryPrompt } from \"./buildPrompt.js\";\nimport { LlmJsonResponse } from \"../WbGeneratePageContent/LlmJsonResponse.js\";\nimport { injectDynamicZoneTypenames } from \"./injectDynamicZoneTypenames.js\";\n\nclass CmsGenerateEntryContentUseCaseImpl implements CmsGenerateEntryContentUseCase.Interface {\n constructor(\n private promptContextBuilder: AiPromptContextBuilder.Interface,\n private resolveCapability: ResolveAiCapabilityUseCase.Interface,\n private ai: Ai.Interface,\n private aiSdkTools: AiSdkTools.Interface,\n private listTags: ListTagsUseCase.Interface,\n private getModel: GetModelUseCase.Interface,\n private modelToAst: ModelToAstConverter.Interface,\n private toolPipelineRunner: AiToolPipelineRunner.Interface\n ) {}\n\n async execute<TValues = Record<string, any>>(\n params: CmsGenerateEntryContentParams\n ): Promise<Result<GenerateEntryContentResult<TValues>, Error>> {\n const resolved = await this.resolveCapability.execute(CMS_GENERATE_ENTRY_CAPABILITY);\n if (resolved.isFail()) {\n return Result.fail(resolved.error);\n }\n\n const capability = resolved.value;\n\n const modelResult = await this.getModel.execute(params.modelId);\n if (modelResult.isFail()) {\n return Result.fail(new Error(`Content model \"${params.modelId}\" not found.`));\n }\n\n const model = modelResult.value;\n const modelAst = this.modelToAst.toAst(model);\n const jsonSchemaConverter = new CmsModelToJsonSchemaConverter();\n const entrySchema = jsonSchemaConverter.convert(modelAst, {\n name: model.name,\n description: model.description\n });\n\n const sdkTools = this.aiSdkTools.getToolSet();\n\n const context = await this.promptContextBuilder.execute({\n projectId: params.projectId,\n readerPersonaId: params.readerPersonaId,\n writerPersonaId: params.writerPersonaId,\n excludedFileIds: params.excludedFileIds,\n additionalFileIds: params.additionalFileIds\n });\n\n if (context.allProjectFiles.length > 0) {\n const projectFileTool = createReadProjectFileTool(\n context.allProjectFiles,\n context.excludedFileIds\n );\n Object.assign(sdkTools, projectFileTool);\n }\n\n const tagsResult = await this.listTags.execute({\n where: { type_startsWith: \"image/\" },\n limit: 100\n });\n const imageTags = tagsResult.isOk() ? tagsResult.value.map(t => t.tag) : [];\n\n const systemText = withAdditionalInstructions(\n capability,\n buildEntryPrompt(model.name, entrySchema, imageTags) + context.toString()\n );\n\n const system = {\n role: \"system\" as const,\n content: systemText,\n providerOptions: {\n anthropic: {\n cacheControl: { type: \"ephemeral\" }\n }\n }\n };\n\n try {\n const aiResult = await this.ai.generateText({\n model: capability.model,\n connection: capability.connection,\n system,\n toolChoice: \"auto\",\n prompt: params.prompt + formatAdditionalFilesContext(context.additionalFiles),\n ...(Object.keys(sdkTools).length > 0\n ? { tools: sdkTools, stopWhen: stepCountIs(20) }\n : {})\n });\n\n const text =\n aiResult.text ||\n (aiResult.steps.filter(step => step.text.length > 0).pop()?.text ?? \"\");\n\n const entry = LlmJsonResponse.fromRawText(text).toArray().pop();\n\n let resolved: Record<string, any> | undefined;\n\n if (entry) {\n resolved = (await this.toolPipelineRunner.resolve(entry)) as Record<string, any>;\n await injectDynamicZoneTypenames(resolved, modelAst, model.singularApiName);\n }\n\n const filesRead = new Set<string>();\n let toolCallsMade = 0;\n for (const step of aiResult.steps) {\n for (const call of step.toolCalls) {\n toolCallsMade++;\n if (call.toolName === \"read_project_file\") {\n const input = call.input as { fileId?: string };\n if (input.fileId) {\n filesRead.add(input.fileId);\n }\n }\n }\n }\n\n const telemetry: GenerateEntryContentTelemetry = {\n filesRead: [...filesRead],\n cacheHit: context.cacheHit,\n toolCallsMade,\n totalSteps: aiResult.steps.length,\n toolsAvailable: Object.keys(sdkTools),\n imageTagsInPrompt: imageTags\n };\n\n // Boundary cast: the AI output is dynamic JSON, so this is the one honest point\n // where we hand the resolved values to the caller's chosen `TValues` shape.\n return Result.ok({ values: (resolved ?? {}) as TValues, telemetry });\n } catch (error) {\n return Result.fail(\n new Error(\n `AI generation failed: ${error instanceof Error ? error.message : String(error)}`\n )\n );\n }\n }\n}\n\nexport const CmsGenerateEntryContentUseCaseImplementation =\n CmsGenerateEntryContentUseCase.createImplementation({\n implementation: CmsGenerateEntryContentUseCaseImpl,\n dependencies: [\n AiPromptContextBuilder,\n ResolveAiCapabilityUseCase,\n Ai,\n AiSdkTools,\n ListTagsUseCase,\n GetModelUseCase,\n ModelToAstConverter,\n AiToolPipelineRunner\n ]\n });\n"],"names":["CmsGenerateEntryContentUseCaseImpl","promptContextBuilder","resolveCapability","ai","aiSdkTools","listTags","getModel","modelToAst","toolPipelineRunner","params","resolved","CMS_GENERATE_ENTRY_CAPABILITY","Result","capability","modelResult","Error","model","modelAst","jsonSchemaConverter","CmsModelToJsonSchemaConverter","entrySchema","sdkTools","context","projectFileTool","createReadProjectFileTool","Object","tagsResult","imageTags","t","systemText","withAdditionalInstructions","buildEntryPrompt","system","aiResult","formatAdditionalFilesContext","stepCountIs","text","step","entry","LlmJsonResponse","injectDynamicZoneTypenames","filesRead","Set","toolCallsMade","call","input","telemetry","error","String","CmsGenerateEntryContentUseCaseImplementation","CmsGenerateEntryContentUseCase","AiPromptContextBuilder","ResolveAiCapabilityUseCase","Ai","AiSdkTools","ListTagsUseCase","GetModelUseCase","ModelToAstConverter","AiToolPipelineRunner"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { AiCapability } from "../../../api/features/Capabilities/index.js";
2
+ export declare const CMS_GENERATE_ENTRY_CAPABILITY = "cms.generateEntry";
3
+ /**
4
+ * No `guidance`: this prompt is rebuilt on every request from the content model's JSON Schema and
5
+ * the File Manager's current image tags, so there is no fixed block a project could replace without
6
+ * dropping the schema the output has to conform to. Additional instructions still apply.
7
+ */
8
+ declare class CmsGenerateEntryCapabilityImpl implements AiCapability.Interface {
9
+ readonly id = "cms.generateEntry";
10
+ readonly label = "CMS entry generation";
11
+ readonly description = "Writes a content entry from a prompt, following the content model's schema and picking images from the File Manager.";
12
+ readonly defaultRole: "standard";
13
+ }
14
+ export declare const CmsGenerateEntryCapability: typeof CmsGenerateEntryCapabilityImpl & {
15
+ __abstraction: import("@webiny/di").Abstraction<import("~/api/features/Capabilities/index.js").IAiCapability>;
16
+ };
17
+ export {};
@@ -0,0 +1,17 @@
1
+ import { AiCapability } from "../Capabilities/index.js";
2
+ const CMS_GENERATE_ENTRY_CAPABILITY = "cms.generateEntry";
3
+ class CmsGenerateEntryCapabilityImpl {
4
+ constructor(){
5
+ this.id = CMS_GENERATE_ENTRY_CAPABILITY;
6
+ this.label = "CMS entry generation";
7
+ this.description = "Writes a content entry from a prompt, following the content model's schema and picking images from the File Manager.";
8
+ this.defaultRole = "standard";
9
+ }
10
+ }
11
+ const CmsGenerateEntryCapability = AiCapability.createImplementation({
12
+ implementation: CmsGenerateEntryCapabilityImpl,
13
+ dependencies: []
14
+ });
15
+ export { CMS_GENERATE_ENTRY_CAPABILITY, CmsGenerateEntryCapability };
16
+
17
+ //# sourceMappingURL=capability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/CmsGenerateEntryContent/capability.js","sources":["../../../../src/api/features/CmsGenerateEntryContent/capability.ts"],"sourcesContent":["import { AiCapability } from \"~/api/features/Capabilities/index.js\";\n\nexport const CMS_GENERATE_ENTRY_CAPABILITY = \"cms.generateEntry\";\n\n/**\n * No `guidance`: this prompt is rebuilt on every request from the content model's JSON Schema and\n * the File Manager's current image tags, so there is no fixed block a project could replace without\n * dropping the schema the output has to conform to. Additional instructions still apply.\n */\nclass CmsGenerateEntryCapabilityImpl implements AiCapability.Interface {\n readonly id = CMS_GENERATE_ENTRY_CAPABILITY;\n readonly label = \"CMS entry generation\";\n readonly description =\n \"Writes a content entry from a prompt, following the content model's schema and picking images from the File Manager.\";\n readonly defaultRole = \"standard\" as const;\n}\n\nexport const CmsGenerateEntryCapability = AiCapability.createImplementation({\n implementation: CmsGenerateEntryCapabilityImpl,\n dependencies: []\n});\n"],"names":["CMS_GENERATE_ENTRY_CAPABILITY","CmsGenerateEntryCapabilityImpl","CmsGenerateEntryCapability","AiCapability"],"mappings":";AAEO,MAAMA,gCAAgC;AAO7C,MAAMC;;aACO,EAAE,GAAGD;aACL,KAAK,GAAG;aACR,WAAW,GAChB;aACK,WAAW,GAAG;;AAC3B;AAEO,MAAME,6BAA6BC,aAAa,oBAAoB,CAAC;IACxE,gBAAgBF;IAChB,cAAc,EAAE;AACpB"}
@@ -1,9 +1,11 @@
1
1
  import { createFeature } from "@webiny/feature/api";
2
2
  import { CmsGenerateEntryContentUseCaseImplementation } from "./CmsGenerateEntryContentUseCase.js";
3
3
  import { CmsGenerateEntryContentTask } from "./CmsGenerateEntryContentTask.js";
4
+ import { CmsGenerateEntryCapability } from "./capability.js";
4
5
  const CmsGenerateEntryContentFeature = createFeature({
5
6
  name: "AiPowerUps/CmsGenerateEntryContent",
6
7
  register (container) {
8
+ container.register(CmsGenerateEntryCapability);
7
9
  container.register(CmsGenerateEntryContentUseCaseImplementation);
8
10
  container.register(CmsGenerateEntryContentTask);
9
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"api/features/CmsGenerateEntryContent/feature.js","sources":["../../../../src/api/features/CmsGenerateEntryContent/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { CmsGenerateEntryContentUseCaseImplementation } from \"./CmsGenerateEntryContentUseCase.js\";\nimport { CmsGenerateEntryContentTask } from \"./CmsGenerateEntryContentTask.js\";\n\nexport const CmsGenerateEntryContentFeature = createFeature({\n name: \"AiPowerUps/CmsGenerateEntryContent\",\n register(container) {\n container.register(CmsGenerateEntryContentUseCaseImplementation);\n container.register(CmsGenerateEntryContentTask);\n }\n});\n"],"names":["CmsGenerateEntryContentFeature","createFeature","container","CmsGenerateEntryContentUseCaseImplementation","CmsGenerateEntryContentTask"],"mappings":";;;AAIO,MAAMA,iCAAiCC,cAAc;IACxD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;QACnBD,UAAU,QAAQ,CAACE;IACvB;AACJ"}
1
+ {"version":3,"file":"api/features/CmsGenerateEntryContent/feature.js","sources":["../../../../src/api/features/CmsGenerateEntryContent/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { CmsGenerateEntryContentUseCaseImplementation } from \"./CmsGenerateEntryContentUseCase.js\";\nimport { CmsGenerateEntryContentTask } from \"./CmsGenerateEntryContentTask.js\";\nimport { CmsGenerateEntryCapability } from \"./capability.js\";\n\nexport const CmsGenerateEntryContentFeature = createFeature({\n name: \"AiPowerUps/CmsGenerateEntryContent\",\n register(container) {\n container.register(CmsGenerateEntryCapability);\n container.register(CmsGenerateEntryContentUseCaseImplementation);\n container.register(CmsGenerateEntryContentTask);\n }\n});\n"],"names":["CmsGenerateEntryContentFeature","createFeature","container","CmsGenerateEntryCapability","CmsGenerateEntryContentUseCaseImplementation","CmsGenerateEntryContentTask"],"mappings":";;;;AAKO,MAAMA,iCAAiCC,cAAc;IACxD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;QACnBD,UAAU,QAAQ,CAACE;QACnBF,UAAU,QAAQ,CAACG;IACvB;AACJ"}
@@ -0,0 +1,20 @@
1
+ import { AiPowerUpsSettingsGroupGraphQLMapper } from "../../../api/features/shared/index.js";
2
+ import type { ConnectionsSettings } from "./types.js";
3
+ interface ApiConnectionPreset {
4
+ id: string;
5
+ name: string;
6
+ sdkName: string;
7
+ apiKey: string | null;
8
+ }
9
+ interface ApiConnections {
10
+ presets: ApiConnectionPreset[];
11
+ }
12
+ declare class ConnectionsGraphQLMapperImpl implements AiPowerUpsSettingsGroupGraphQLMapper.Interface {
13
+ readonly name = "connections";
14
+ toApi(internal: unknown): ApiConnections;
15
+ fromApi(api: unknown): ConnectionsSettings;
16
+ }
17
+ declare const _default: typeof ConnectionsGraphQLMapperImpl & {
18
+ __abstraction: import("@webiny/di").Abstraction<import("../shared/abstractions.js").IAiPowerUpsSettingsGroupGraphQLMapper>;
19
+ };
20
+ export default _default;
@@ -0,0 +1,37 @@
1
+ import { AiPowerUpsSettingsGroupGraphQLMapper } from "../shared/index.js";
2
+ class ConnectionsGraphQLMapperImpl {
3
+ toApi(internal) {
4
+ const data = internal;
5
+ return {
6
+ presets: data.presets.map((p)=>({
7
+ id: p.id,
8
+ name: p.name,
9
+ sdkName: p.sdkName,
10
+ apiKey: p.apiKeyMasked ?? null
11
+ }))
12
+ };
13
+ }
14
+ fromApi(api) {
15
+ const data = api;
16
+ return {
17
+ presets: data.presets.map((p)=>({
18
+ id: p.id,
19
+ name: p.name,
20
+ sdkName: p.sdkName,
21
+ apiKey: p.apiKey,
22
+ apiKeyMasked: "",
23
+ apiKeyEncrypted: ""
24
+ }))
25
+ };
26
+ }
27
+ constructor(){
28
+ this.name = "connections";
29
+ }
30
+ }
31
+ const ConnectionsGraphQLMapper = AiPowerUpsSettingsGroupGraphQLMapper.createImplementation({
32
+ implementation: ConnectionsGraphQLMapperImpl,
33
+ dependencies: []
34
+ });
35
+ export default ConnectionsGraphQLMapper;
36
+
37
+ //# sourceMappingURL=ConnectionsGraphQLMapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/Connections/ConnectionsGraphQLMapper.js","sources":["../../../../src/api/features/Connections/ConnectionsGraphQLMapper.ts"],"sourcesContent":["import { AiPowerUpsSettingsGroupGraphQLMapper } from \"~/api/features/shared/index.js\";\nimport type { ConnectionsSettings } from \"./types.js\";\n\ninterface ApiConnectionPreset {\n id: string;\n name: string;\n sdkName: string;\n apiKey: string | null;\n}\n\ninterface ApiConnections {\n presets: ApiConnectionPreset[];\n}\n\ninterface ApiInputConnectionPreset {\n id: string;\n name: string;\n sdkName: string;\n apiKey?: string;\n}\n\nclass ConnectionsGraphQLMapperImpl implements AiPowerUpsSettingsGroupGraphQLMapper.Interface {\n readonly name = \"connections\";\n\n toApi(internal: unknown): ApiConnections {\n const data = internal as ConnectionsSettings;\n return {\n presets: data.presets.map(p => ({\n id: p.id,\n name: p.name,\n sdkName: p.sdkName,\n // The admin form only ever sees the mask. The plaintext key never leaves the api.\n apiKey: p.apiKeyMasked ?? null\n }))\n };\n }\n\n fromApi(api: unknown): ConnectionsSettings {\n const data = api as { presets: ApiInputConnectionPreset[] };\n return {\n presets: data.presets.map(p => ({\n id: p.id,\n name: p.name,\n sdkName: p.sdkName,\n apiKey: p.apiKey,\n apiKeyMasked: \"\",\n apiKeyEncrypted: \"\"\n }))\n };\n }\n}\n\nexport default AiPowerUpsSettingsGroupGraphQLMapper.createImplementation({\n implementation: ConnectionsGraphQLMapperImpl,\n dependencies: []\n});\n"],"names":["ConnectionsGraphQLMapperImpl","internal","data","p","api","AiPowerUpsSettingsGroupGraphQLMapper"],"mappings":";AAqBA,MAAMA;IAGF,MAAMC,QAAiB,EAAkB;QACrC,MAAMC,OAAOD;QACb,OAAO;YACH,SAASC,KAAK,OAAO,CAAC,GAAG,CAACC,CAAAA,IAAM;oBAC5B,IAAIA,EAAE,EAAE;oBACR,MAAMA,EAAE,IAAI;oBACZ,SAASA,EAAE,OAAO;oBAElB,QAAQA,EAAE,YAAY,IAAI;gBAC9B;QACJ;IACJ;IAEA,QAAQC,GAAY,EAAuB;QACvC,MAAMF,OAAOE;QACb,OAAO;YACH,SAASF,KAAK,OAAO,CAAC,GAAG,CAACC,CAAAA,IAAM;oBAC5B,IAAIA,EAAE,EAAE;oBACR,MAAMA,EAAE,IAAI;oBACZ,SAASA,EAAE,OAAO;oBAClB,QAAQA,EAAE,MAAM;oBAChB,cAAc;oBACd,iBAAiB;gBACrB;QACJ;IACJ;;aA3BS,IAAI,GAAG;;AA4BpB;AAEA,iCAAeE,qCAAqC,oBAAoB,CAAC;IACrE,gBAAgBL;IAChB,cAAc,EAAE;AACpB"}
@@ -0,0 +1,25 @@
1
+ import { z } from "zod";
2
+ import { Encryption } from "@webiny/api-core/features/encryption/index.js";
3
+ import { Masker } from "@webiny/api-core/features/masker/index.js";
4
+ import { AiPowerUpsSettingsGroupHandler } from "../../../api/features/shared/index.js";
5
+ import type { ConnectionsSettings, PersistedConnections } from "./types.js";
6
+ declare class ConnectionsHandlerImpl implements AiPowerUpsSettingsGroupHandler.Interface {
7
+ private encryption;
8
+ private masker;
9
+ readonly name = "connections";
10
+ readonly inputSchema: z.ZodObject<{
11
+ presets: z.ZodArray<z.ZodObject<{
12
+ id: z.ZodString;
13
+ name: z.ZodString;
14
+ sdkName: z.ZodString;
15
+ apiKey: z.ZodOptional<z.ZodNullable<z.ZodString>>;
16
+ }, z.core.$strip>>;
17
+ }, z.core.$strip>;
18
+ constructor(encryption: Encryption.Interface, masker: Masker.Interface);
19
+ mapFromStorage(persisted: unknown, all?: Record<string, unknown>): ConnectionsSettings;
20
+ mapToStorage(internal: unknown, existing: unknown | null): Promise<PersistedConnections>;
21
+ }
22
+ declare const _default: typeof ConnectionsHandlerImpl & {
23
+ __abstraction: import("@webiny/di").Abstraction<import("../shared/abstractions.js").IAiPowerUpsSettingsGroupHandler>;
24
+ };
25
+ export default _default;