@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
@@ -0,0 +1,84 @@
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 "../shared/index.js";
5
+ import { readLegacyProviderPresets } from "./legacyProviders.js";
6
+ import { sdkNameFromModel } from "../shared/modelId.js";
7
+ const inputSchema = z.object({
8
+ presets: z.array(z.object({
9
+ id: z.string().min(1),
10
+ name: z.string().min(1),
11
+ sdkName: z.string().min(1),
12
+ apiKey: z.string().nullish()
13
+ }))
14
+ });
15
+ class ConnectionsHandlerImpl {
16
+ constructor(encryption, masker){
17
+ this.encryption = encryption;
18
+ this.masker = masker;
19
+ this.name = "connections";
20
+ this.inputSchema = inputSchema;
21
+ }
22
+ mapFromStorage(persisted, all) {
23
+ if (persisted && "object" == typeof persisted) {
24
+ const data = persisted;
25
+ return {
26
+ presets: (data.presets ?? []).map((p)=>({
27
+ id: p.id,
28
+ name: p.name,
29
+ sdkName: p.sdkName,
30
+ apiKeyMasked: p.apiKeyMasked ?? "",
31
+ apiKeyEncrypted: p.apiKeyEncrypted ?? ""
32
+ }))
33
+ };
34
+ }
35
+ return {
36
+ presets: readLegacyProviderPresets(all).map((p)=>({
37
+ id: p.id,
38
+ name: p.name,
39
+ sdkName: sdkNameFromModel(p.model),
40
+ apiKeyMasked: p.apiKeyMasked ?? "",
41
+ apiKeyEncrypted: p.apiKeyEncrypted ?? ""
42
+ }))
43
+ };
44
+ }
45
+ async mapToStorage(internal, existing) {
46
+ const input = internal;
47
+ const existingPresets = existing?.presets ?? [];
48
+ const presets = await Promise.all(input.presets.map(async (preset)=>{
49
+ const existingMatch = existingPresets.find((ep)=>ep.id === preset.id);
50
+ let apiKeyEncrypted;
51
+ let apiKeyMasked;
52
+ if (preset.apiKey && preset.apiKey !== existingMatch?.apiKeyMasked) {
53
+ apiKeyEncrypted = await this.encryption.encrypt(preset.apiKey);
54
+ apiKeyMasked = this.masker.mask(preset.apiKey, [
55
+ 8,
56
+ 4
57
+ ]);
58
+ } else {
59
+ apiKeyEncrypted = existingMatch?.apiKeyEncrypted ?? "";
60
+ apiKeyMasked = existingMatch?.apiKeyMasked ?? "";
61
+ }
62
+ return {
63
+ id: preset.id,
64
+ name: preset.name,
65
+ sdkName: preset.sdkName,
66
+ apiKeyEncrypted,
67
+ apiKeyMasked
68
+ };
69
+ }));
70
+ return {
71
+ presets
72
+ };
73
+ }
74
+ }
75
+ const ConnectionsHandler = AiPowerUpsSettingsGroupHandler.createImplementation({
76
+ implementation: ConnectionsHandlerImpl,
77
+ dependencies: [
78
+ Encryption,
79
+ Masker
80
+ ]
81
+ });
82
+ export default ConnectionsHandler;
83
+
84
+ //# sourceMappingURL=ConnectionsHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/Connections/ConnectionsHandler.js","sources":["../../../../src/api/features/Connections/ConnectionsHandler.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { Encryption } from \"@webiny/api-core/features/encryption/index.js\";\nimport { Masker } from \"@webiny/api-core/features/masker/index.js\";\nimport { AiPowerUpsSettingsGroupHandler } from \"~/api/features/shared/index.js\";\nimport { readLegacyProviderPresets } from \"./legacyProviders.js\";\nimport { sdkNameFromModel } from \"~/api/features/shared/modelId.js\";\nimport type {\n ConnectionsSettings,\n PersistedAiConnectionPreset,\n PersistedConnections\n} from \"./types.js\";\n\nconst inputSchema = z.object({\n presets: z.array(\n z.object({\n id: z.string().min(1),\n name: z.string().min(1),\n sdkName: z.string().min(1),\n apiKey: z.string().nullish()\n })\n )\n});\n\nclass ConnectionsHandlerImpl implements AiPowerUpsSettingsGroupHandler.Interface {\n readonly name = \"connections\";\n readonly inputSchema = inputSchema;\n\n constructor(\n private encryption: Encryption.Interface,\n private masker: Masker.Interface\n ) {}\n\n mapFromStorage(persisted: unknown, all?: Record<string, unknown>): ConnectionsSettings {\n if (persisted && typeof persisted === \"object\") {\n const data = persisted as PersistedConnections;\n return {\n presets: (data.presets ?? []).map(p => ({\n id: p.id,\n name: p.name,\n sdkName: p.sdkName,\n apiKeyMasked: p.apiKeyMasked ?? \"\",\n apiKeyEncrypted: p.apiKeyEncrypted ?? \"\"\n }))\n };\n }\n\n /*\n * No `connections` section yet, so derive one from the legacy `providers` presets. The keys\n * are already encrypted in storage, which is why this can be a pure read: nothing has to be\n * re-encrypted, and nothing is written back until the next save.\n *\n * Dropping the model here is safe. `ModelRoles` reads the same legacy section and lifts\n * the first preset's model into the `standard` role, which is the only model the old code\n * ever used.\n */\n return {\n presets: readLegacyProviderPresets(all).map(p => ({\n id: p.id,\n name: p.name,\n sdkName: sdkNameFromModel(p.model),\n apiKeyMasked: p.apiKeyMasked ?? \"\",\n apiKeyEncrypted: p.apiKeyEncrypted ?? \"\"\n }))\n };\n }\n\n async mapToStorage(internal: unknown, existing: unknown | null): Promise<PersistedConnections> {\n const input = internal as ConnectionsSettings;\n const existingPresets = (existing as ConnectionsSettings | null)?.presets ?? [];\n\n const presets: PersistedAiConnectionPreset[] = await Promise.all(\n input.presets.map(async preset => {\n const existingMatch = existingPresets.find(ep => ep.id === preset.id);\n\n let apiKeyEncrypted: string;\n let apiKeyMasked: string;\n\n if (!preset.apiKey || preset.apiKey === existingMatch?.apiKeyMasked) {\n // The form sends back the mask when the key was left alone. Carry it forward.\n apiKeyEncrypted = existingMatch?.apiKeyEncrypted ?? \"\";\n apiKeyMasked = existingMatch?.apiKeyMasked ?? \"\";\n } else {\n apiKeyEncrypted = await this.encryption.encrypt(preset.apiKey);\n apiKeyMasked = this.masker.mask(preset.apiKey, [8, 4]);\n }\n\n return {\n id: preset.id,\n name: preset.name,\n sdkName: preset.sdkName,\n apiKeyEncrypted,\n apiKeyMasked\n };\n })\n );\n\n return { presets };\n }\n}\n\nexport default AiPowerUpsSettingsGroupHandler.createImplementation({\n implementation: ConnectionsHandlerImpl,\n dependencies: [Encryption, Masker]\n});\n"],"names":["inputSchema","z","ConnectionsHandlerImpl","encryption","masker","persisted","all","data","p","readLegacyProviderPresets","sdkNameFromModel","internal","existing","input","existingPresets","presets","Promise","preset","existingMatch","ep","apiKeyEncrypted","apiKeyMasked","AiPowerUpsSettingsGroupHandler","Encryption","Masker"],"mappings":";;;;;;AAYA,MAAMA,cAAcC,EAAE,MAAM,CAAC;IACzB,SAASA,EAAE,KAAK,CACZA,EAAE,MAAM,CAAC;QACL,IAAIA,EAAE,MAAM,GAAG,GAAG,CAAC;QACnB,MAAMA,EAAE,MAAM,GAAG,GAAG,CAAC;QACrB,SAASA,EAAE,MAAM,GAAG,GAAG,CAAC;QACxB,QAAQA,EAAE,MAAM,GAAG,OAAO;IAC9B;AAER;AAEA,MAAMC;IAIF,YACYC,UAAgC,EAChCC,MAAwB,CAClC;aAFUD,UAAU,GAAVA;aACAC,MAAM,GAANA;aALH,IAAI,GAAG;aACP,WAAW,GAAGJ;IAKpB;IAEH,eAAeK,SAAkB,EAAEC,GAA6B,EAAuB;QACnF,IAAID,aAAa,AAAqB,YAArB,OAAOA,WAAwB;YAC5C,MAAME,OAAOF;YACb,OAAO;gBACH,SAAUE,AAAAA,CAAAA,KAAK,OAAO,IAAI,EAAC,EAAG,GAAG,CAACC,CAAAA,IAAM;wBACpC,IAAIA,EAAE,EAAE;wBACR,MAAMA,EAAE,IAAI;wBACZ,SAASA,EAAE,OAAO;wBAClB,cAAcA,EAAE,YAAY,IAAI;wBAChC,iBAAiBA,EAAE,eAAe,IAAI;oBAC1C;YACJ;QACJ;QAWA,OAAO;YACH,SAASC,0BAA0BH,KAAK,GAAG,CAACE,CAAAA,IAAM;oBAC9C,IAAIA,EAAE,EAAE;oBACR,MAAMA,EAAE,IAAI;oBACZ,SAASE,iBAAiBF,EAAE,KAAK;oBACjC,cAAcA,EAAE,YAAY,IAAI;oBAChC,iBAAiBA,EAAE,eAAe,IAAI;gBAC1C;QACJ;IACJ;IAEA,MAAM,aAAaG,QAAiB,EAAEC,QAAwB,EAAiC;QAC3F,MAAMC,QAAQF;QACd,MAAMG,kBAAmBF,UAAyC,WAAW,EAAE;QAE/E,MAAMG,UAAyC,MAAMC,QAAQ,GAAG,CAC5DH,MAAM,OAAO,CAAC,GAAG,CAAC,OAAMI;YACpB,MAAMC,gBAAgBJ,gBAAgB,IAAI,CAACK,CAAAA,KAAMA,GAAG,EAAE,KAAKF,OAAO,EAAE;YAEpE,IAAIG;YACJ,IAAIC;YAEJ,IAAI,AAACJ,OAAO,MAAM,IAAIA,OAAO,MAAM,KAAKC,eAAe,cAIhD;gBACHE,kBAAkB,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAACH,OAAO,MAAM;gBAC7DI,eAAe,IAAI,CAAC,MAAM,CAAC,IAAI,CAACJ,OAAO,MAAM,EAAE;oBAAC;oBAAG;iBAAE;YACzD,OAPqE;gBAEjEG,kBAAkBF,eAAe,mBAAmB;gBACpDG,eAAeH,eAAe,gBAAgB;YAClD;YAKA,OAAO;gBACH,IAAID,OAAO,EAAE;gBACb,MAAMA,OAAO,IAAI;gBACjB,SAASA,OAAO,OAAO;gBACvBG;gBACAC;YACJ;QACJ;QAGJ,OAAO;YAAEN;QAAQ;IACrB;AACJ;AAEA,2BAAeO,+BAA+B,oBAAoB,CAAC;IAC/D,gBAAgBpB;IAChB,cAAc;QAACqB;QAAYC;KAAO;AACtC"}
@@ -0,0 +1,4 @@
1
+ export declare const ConnectionsFeature: {
2
+ name: string;
3
+ register(container: import("@webiny/di").Container): void;
4
+ };
@@ -0,0 +1,13 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import ConnectionsHandler from "./ConnectionsHandler.js";
3
+ import ConnectionsGraphQLMapper from "./ConnectionsGraphQLMapper.js";
4
+ const ConnectionsFeature = createFeature({
5
+ name: "AiPowerUpsConnections",
6
+ register (container) {
7
+ container.register(ConnectionsHandler);
8
+ container.register(ConnectionsGraphQLMapper);
9
+ }
10
+ });
11
+ export { ConnectionsFeature };
12
+
13
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/Connections/feature.js","sources":["../../../../src/api/features/Connections/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport ConnectionsHandler from \"./ConnectionsHandler.js\";\nimport ConnectionsGraphQLMapper from \"./ConnectionsGraphQLMapper.js\";\n\nexport const ConnectionsFeature = createFeature({\n name: \"AiPowerUpsConnections\",\n register(container) {\n container.register(ConnectionsHandler);\n container.register(ConnectionsGraphQLMapper);\n }\n});\n"],"names":["ConnectionsFeature","createFeature","container","ConnectionsHandler","ConnectionsGraphQLMapper"],"mappings":";;;AAIO,MAAMA,qBAAqBC,cAAc;IAC5C,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;QACnBD,UAAU,QAAQ,CAACE;IACvB;AACJ"}
@@ -0,0 +1,2 @@
1
+ export type { AiConnectionPreset, ConnectionsSettings } from "./types.js";
2
+ export { ConnectionsFeature } from "./feature.js";
@@ -0,0 +1 @@
1
+ export { ConnectionsFeature } from "./feature.js";
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Reading the settings section `connections` replaces.
3
+ *
4
+ * `providers` bundled a credential with a single model. Nothing writes it any more, but an upgraded
5
+ * project still has one and has never saved since, so both `Connections` and `ModelRoles` derive
6
+ * their first value from it. That makes this the one piece of code allowed to reach into a section
7
+ * nobody owns.
8
+ *
9
+ * It lives in its own module, and not with the connection types, because it is the only part of
10
+ * this feature with an expiry date: when the legacy section is finally dropped, this file and its
11
+ * two callers go with it.
12
+ */
13
+ /** Shape of a preset in the legacy `providers` section. */
14
+ export interface LegacyProviderPreset {
15
+ id: string;
16
+ name: string;
17
+ model?: string;
18
+ apiKeyEncrypted?: string;
19
+ apiKeyMasked?: string;
20
+ }
21
+ /**
22
+ * Deliberately defensive. This parses a blob written by an older version against no schema, so
23
+ * every level is checked rather than asserted: a project that never had `providers` and one that
24
+ * has a malformed one both read as "nothing to migrate" instead of throwing on read.
25
+ */
26
+ export declare const readLegacyProviderPresets: (all: Record<string, unknown> | undefined) => LegacyProviderPreset[];
@@ -0,0 +1,9 @@
1
+ const readLegacyProviderPresets = (all)=>{
2
+ const providers = all?.["providers"];
3
+ if (!providers || "object" != typeof providers) return [];
4
+ const presets = providers.presets;
5
+ return Array.isArray(presets) ? presets : [];
6
+ };
7
+ export { readLegacyProviderPresets };
8
+
9
+ //# sourceMappingURL=legacyProviders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/Connections/legacyProviders.js","sources":["../../../../src/api/features/Connections/legacyProviders.ts"],"sourcesContent":["/**\n * Reading the settings section `connections` replaces.\n *\n * `providers` bundled a credential with a single model. Nothing writes it any more, but an upgraded\n * project still has one and has never saved since, so both `Connections` and `ModelRoles` derive\n * their first value from it. That makes this the one piece of code allowed to reach into a section\n * nobody owns.\n *\n * It lives in its own module, and not with the connection types, because it is the only part of\n * this feature with an expiry date: when the legacy section is finally dropped, this file and its\n * two callers go with it.\n */\n\n/** Shape of a preset in the legacy `providers` section. */\nexport interface LegacyProviderPreset {\n id: string;\n name: string;\n model?: string;\n apiKeyEncrypted?: string;\n apiKeyMasked?: string;\n}\n\n/**\n * Deliberately defensive. This parses a blob written by an older version against no schema, so\n * every level is checked rather than asserted: a project that never had `providers` and one that\n * has a malformed one both read as \"nothing to migrate\" instead of throwing on read.\n */\nexport const readLegacyProviderPresets = (\n all: Record<string, unknown> | undefined\n): LegacyProviderPreset[] => {\n const providers = all?.[\"providers\"];\n if (!providers || typeof providers !== \"object\") {\n return [];\n }\n\n const presets = (providers as { presets?: unknown }).presets;\n return Array.isArray(presets) ? (presets as LegacyProviderPreset[]) : [];\n};\n"],"names":["readLegacyProviderPresets","all","providers","presets","Array"],"mappings":"AA2BO,MAAMA,4BAA4B,CACrCC;IAEA,MAAMC,YAAYD,KAAK,CAAC,YAAY;IACpC,IAAI,CAACC,aAAa,AAAqB,YAArB,OAAOA,WACrB,OAAO,EAAE;IAGb,MAAMC,UAAWD,UAAoC,OAAO;IAC5D,OAAOE,MAAM,OAAO,CAACD,WAAYA,UAAqC,EAAE;AAC5E"}
@@ -0,0 +1,36 @@
1
+ import type { IAiPowerUpsSettings } from "../../../api/types.js";
2
+ /**
3
+ * A connection is one credential for one vendor. It carries no model.
4
+ *
5
+ * The section it replaces (`providers`) bundled a key with a single model, so a project that wanted
6
+ * two Anthropic models had to paste the same key twice and keep both copies in sync. Splitting the
7
+ * two means the key is entered once and every model that vendor offers is then selectable.
8
+ */
9
+ export interface AiConnectionPreset {
10
+ id: string;
11
+ name: string;
12
+ /** AI SDK namespace, e.g. "anthropic" or "openai". Matches `AiSdkFactory.id`. */
13
+ sdkName: string;
14
+ /** Plaintext. Only ever set on the way in from the admin form, never persisted. */
15
+ apiKey?: string;
16
+ apiKeyMasked: string;
17
+ apiKeyEncrypted: string;
18
+ }
19
+ declare module "~/api/types.js" {
20
+ interface IAiPowerUpsSettings {
21
+ connections: {
22
+ presets: AiConnectionPreset[];
23
+ };
24
+ }
25
+ }
26
+ export type ConnectionsSettings = IAiPowerUpsSettings["connections"];
27
+ export interface PersistedAiConnectionPreset {
28
+ id: string;
29
+ name: string;
30
+ sdkName: string;
31
+ apiKeyEncrypted: string;
32
+ apiKeyMasked: string;
33
+ }
34
+ export interface PersistedConnections {
35
+ presets: PersistedAiConnectionPreset[];
36
+ }
File without changes
@@ -15,7 +15,7 @@ class GetSettingsRepositoryImpl {
15
15
  const storeResult = await this.keyValueStore.get(AI_POWER_UPS_SETTINGS);
16
16
  const raw = storeResult.isOk() && storeResult.value ? storeResult.value : {};
17
17
  const result = {};
18
- for (const handler of this.handlers)result[handler.name] = handler.mapFromStorage(raw[handler.name]);
18
+ for (const handler of this.handlers)result[handler.name] = handler.mapFromStorage(raw[handler.name], raw);
19
19
  for (const key of Object.keys(raw))if (!(key in result)) result[key] = raw[key];
20
20
  const mapped = result;
21
21
  this.cache.set(raw, mapped);
@@ -1 +1 @@
1
- {"version":3,"file":"api/features/GetSettings/GetSettingsRepository.js","sources":["../../../../src/api/features/GetSettings/GetSettingsRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { KeyValueStore } from \"@webiny/api-core/features/keyValueStore/index.js\";\nimport {\n AiPowerUpsSettingsGroupHandler,\n AiPowerUpsSettingsCache\n} from \"~/api/features/shared/index.js\";\nimport { GetSettingsRepository } from \"./abstractions.js\";\nimport type { IAiPowerUpsSettings } from \"~/api/types.js\";\nimport { AI_POWER_UPS_SETTINGS } from \"~/api/constants.js\";\n\nclass GetSettingsRepositoryImpl implements GetSettingsRepository.Interface {\n constructor(\n private keyValueStore: KeyValueStore.Interface,\n private handlers: AiPowerUpsSettingsGroupHandler.Interface[],\n private cache: AiPowerUpsSettingsCache.Interface\n ) {}\n\n async get(): Promise<Result<IAiPowerUpsSettings>> {\n const cached = this.cache.get();\n if (cached) {\n return Result.ok(cached.mapped);\n }\n\n const storeResult =\n await this.keyValueStore.get<Record<string, unknown>>(AI_POWER_UPS_SETTINGS);\n\n const raw: Record<string, unknown> =\n storeResult.isOk() && storeResult.value ? storeResult.value : {};\n\n const result: Record<string, unknown> = {};\n\n for (const handler of this.handlers) {\n result[handler.name] = handler.mapFromStorage(raw[handler.name]);\n }\n\n for (const key of Object.keys(raw)) {\n if (!(key in result)) {\n result[key] = raw[key];\n }\n }\n\n const mapped = result as unknown as IAiPowerUpsSettings;\n this.cache.set(raw, mapped);\n\n return Result.ok(mapped);\n }\n}\n\nexport const GetSettingsRepositoryImplementation = GetSettingsRepository.createImplementation({\n implementation: GetSettingsRepositoryImpl,\n dependencies: [\n KeyValueStore,\n [AiPowerUpsSettingsGroupHandler, { multiple: true }],\n AiPowerUpsSettingsCache\n ]\n});\n"],"names":["GetSettingsRepositoryImpl","keyValueStore","handlers","cache","cached","Result","storeResult","AI_POWER_UPS_SETTINGS","raw","result","handler","key","Object","mapped","GetSettingsRepositoryImplementation","GetSettingsRepository","KeyValueStore","AiPowerUpsSettingsGroupHandler","AiPowerUpsSettingsCache"],"mappings":";;;;;AAUA,MAAMA;IACF,YACYC,aAAsC,EACtCC,QAAoD,EACpDC,KAAwC,CAClD;aAHUF,aAAa,GAAbA;aACAC,QAAQ,GAARA;aACAC,KAAK,GAALA;IACT;IAEH,MAAM,MAA4C;QAC9C,MAAMC,SAAS,IAAI,CAAC,KAAK,CAAC,GAAG;QAC7B,IAAIA,QACA,OAAOC,OAAO,EAAE,CAACD,OAAO,MAAM;QAGlC,MAAME,cACF,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAA0BC;QAE1D,MAAMC,MACFF,YAAY,IAAI,MAAMA,YAAY,KAAK,GAAGA,YAAY,KAAK,GAAG,CAAC;QAEnE,MAAMG,SAAkC,CAAC;QAEzC,KAAK,MAAMC,WAAW,IAAI,CAAC,QAAQ,CAC/BD,MAAM,CAACC,QAAQ,IAAI,CAAC,GAAGA,QAAQ,cAAc,CAACF,GAAG,CAACE,QAAQ,IAAI,CAAC;QAGnE,KAAK,MAAMC,OAAOC,OAAO,IAAI,CAACJ,KAC1B,IAAI,CAAEG,CAAAA,OAAOF,MAAK,GACdA,MAAM,CAACE,IAAI,GAAGH,GAAG,CAACG,IAAI;QAI9B,MAAME,SAASJ;QACf,IAAI,CAAC,KAAK,CAAC,GAAG,CAACD,KAAKK;QAEpB,OAAOR,OAAO,EAAE,CAACQ;IACrB;AACJ;AAEO,MAAMC,sCAAsCC,sBAAsB,oBAAoB,CAAC;IAC1F,gBAAgBf;IAChB,cAAc;QACVgB;QACA;YAACC;YAAgC;gBAAE,UAAU;YAAK;SAAE;QACpDC;KACH;AACL"}
1
+ {"version":3,"file":"api/features/GetSettings/GetSettingsRepository.js","sources":["../../../../src/api/features/GetSettings/GetSettingsRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { KeyValueStore } from \"@webiny/api-core/features/keyValueStore/index.js\";\nimport {\n AiPowerUpsSettingsGroupHandler,\n AiPowerUpsSettingsCache\n} from \"~/api/features/shared/index.js\";\nimport { GetSettingsRepository } from \"./abstractions.js\";\nimport type { IAiPowerUpsSettings } from \"~/api/types.js\";\nimport { AI_POWER_UPS_SETTINGS } from \"~/api/constants.js\";\n\nclass GetSettingsRepositoryImpl implements GetSettingsRepository.Interface {\n constructor(\n private keyValueStore: KeyValueStore.Interface,\n private handlers: AiPowerUpsSettingsGroupHandler.Interface[],\n private cache: AiPowerUpsSettingsCache.Interface\n ) {}\n\n async get(): Promise<Result<IAiPowerUpsSettings>> {\n const cached = this.cache.get();\n if (cached) {\n return Result.ok(cached.mapped);\n }\n\n const storeResult =\n await this.keyValueStore.get<Record<string, unknown>>(AI_POWER_UPS_SETTINGS);\n\n const raw: Record<string, unknown> =\n storeResult.isOk() && storeResult.value ? storeResult.value : {};\n\n const result: Record<string, unknown> = {};\n\n for (const handler of this.handlers) {\n result[handler.name] = handler.mapFromStorage(raw[handler.name], raw);\n }\n\n for (const key of Object.keys(raw)) {\n if (!(key in result)) {\n result[key] = raw[key];\n }\n }\n\n const mapped = result as unknown as IAiPowerUpsSettings;\n this.cache.set(raw, mapped);\n\n return Result.ok(mapped);\n }\n}\n\nexport const GetSettingsRepositoryImplementation = GetSettingsRepository.createImplementation({\n implementation: GetSettingsRepositoryImpl,\n dependencies: [\n KeyValueStore,\n [AiPowerUpsSettingsGroupHandler, { multiple: true }],\n AiPowerUpsSettingsCache\n ]\n});\n"],"names":["GetSettingsRepositoryImpl","keyValueStore","handlers","cache","cached","Result","storeResult","AI_POWER_UPS_SETTINGS","raw","result","handler","key","Object","mapped","GetSettingsRepositoryImplementation","GetSettingsRepository","KeyValueStore","AiPowerUpsSettingsGroupHandler","AiPowerUpsSettingsCache"],"mappings":";;;;;AAUA,MAAMA;IACF,YACYC,aAAsC,EACtCC,QAAoD,EACpDC,KAAwC,CAClD;aAHUF,aAAa,GAAbA;aACAC,QAAQ,GAARA;aACAC,KAAK,GAALA;IACT;IAEH,MAAM,MAA4C;QAC9C,MAAMC,SAAS,IAAI,CAAC,KAAK,CAAC,GAAG;QAC7B,IAAIA,QACA,OAAOC,OAAO,EAAE,CAACD,OAAO,MAAM;QAGlC,MAAME,cACF,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAA0BC;QAE1D,MAAMC,MACFF,YAAY,IAAI,MAAMA,YAAY,KAAK,GAAGA,YAAY,KAAK,GAAG,CAAC;QAEnE,MAAMG,SAAkC,CAAC;QAEzC,KAAK,MAAMC,WAAW,IAAI,CAAC,QAAQ,CAC/BD,MAAM,CAACC,QAAQ,IAAI,CAAC,GAAGA,QAAQ,cAAc,CAACF,GAAG,CAACE,QAAQ,IAAI,CAAC,EAAEF;QAGrE,KAAK,MAAMG,OAAOC,OAAO,IAAI,CAACJ,KAC1B,IAAI,CAAEG,CAAAA,OAAOF,MAAK,GACdA,MAAM,CAACE,IAAI,GAAGH,GAAG,CAACG,IAAI;QAI9B,MAAME,SAASJ;QACf,IAAI,CAAC,KAAK,CAAC,GAAG,CAACD,KAAKK;QAEpB,OAAOR,OAAO,EAAE,CAACQ;IACrB;AACJ;AAEO,MAAMC,sCAAsCC,sBAAsB,oBAAoB,CAAC;IAC1F,gBAAgBf;IAChB,cAAc;QACVgB;QACA;YAACC;YAAgC;gBAAE,UAAU;YAAK;SAAE;QACpDC;KACH;AACL"}
@@ -0,0 +1,15 @@
1
+ import { z } from "zod";
2
+ import { AiPowerUpsSettingsGroupHandler } from "../../../api/features/shared/index.js";
3
+ import type { AiModelRoleAssignments, ModelRolesSettings, PersistedModelRoles } from "./types.js";
4
+ declare class ModelRolesHandlerImpl implements AiPowerUpsSettingsGroupHandler.Interface {
5
+ readonly name = "modelRoles";
6
+ readonly inputSchema: z.ZodObject<{
7
+ roles: z.ZodType<AiModelRoleAssignments>;
8
+ }, z.core.$strip>;
9
+ mapFromStorage(persisted: unknown, all?: Record<string, unknown>): ModelRolesSettings;
10
+ mapToStorage(internal: unknown): Promise<PersistedModelRoles>;
11
+ }
12
+ declare const _default: typeof ModelRolesHandlerImpl & {
13
+ __abstraction: import("@webiny/di").Abstraction<import("../shared/abstractions.js").IAiPowerUpsSettingsGroupHandler>;
14
+ };
15
+ export default _default;
@@ -0,0 +1,68 @@
1
+ import { z } from "zod";
2
+ import { AiPowerUpsSettingsGroupHandler } from "../shared/index.js";
3
+ import { readLegacyProviderPresets } from "../Connections/legacyProviders.js";
4
+ import { AI_MODEL_ROLE_IDS } from "./roles.js";
5
+ import { emptyAssignment } from "./types.js";
6
+ const formString = z.string().nullish();
7
+ const assignmentSchema = z.object({
8
+ connectionId: formString,
9
+ model: formString
10
+ });
11
+ const inputSchema = z.object({
12
+ roles: z.object(Object.fromEntries(AI_MODEL_ROLE_IDS.map((id)=>[
13
+ id,
14
+ assignmentSchema
15
+ ])))
16
+ });
17
+ class ModelRolesHandlerImpl {
18
+ mapFromStorage(persisted, all) {
19
+ const stored = persisted ?? {};
20
+ const roles = Object.fromEntries(AI_MODEL_ROLE_IDS.map((id)=>{
21
+ const assignment = stored.roles?.[id];
22
+ return [
23
+ id,
24
+ {
25
+ connectionId: assignment?.connectionId ?? "",
26
+ model: assignment?.model ?? ""
27
+ }
28
+ ];
29
+ }));
30
+ if (roles.standard.model) return {
31
+ roles
32
+ };
33
+ const legacy = readLegacyProviderPresets(all)[0];
34
+ if (legacy?.model) roles.standard = {
35
+ connectionId: legacy.id,
36
+ model: legacy.model
37
+ };
38
+ return {
39
+ roles
40
+ };
41
+ }
42
+ async mapToStorage(internal) {
43
+ const input = internal;
44
+ return {
45
+ roles: Object.fromEntries(AI_MODEL_ROLE_IDS.map((id)=>{
46
+ const assignment = input.roles?.[id] ?? emptyAssignment();
47
+ return [
48
+ id,
49
+ {
50
+ connectionId: assignment.connectionId ?? "",
51
+ model: assignment.model ?? ""
52
+ }
53
+ ];
54
+ }))
55
+ };
56
+ }
57
+ constructor(){
58
+ this.name = "modelRoles";
59
+ this.inputSchema = inputSchema;
60
+ }
61
+ }
62
+ const ModelRolesHandler = AiPowerUpsSettingsGroupHandler.createImplementation({
63
+ implementation: ModelRolesHandlerImpl,
64
+ dependencies: []
65
+ });
66
+ export default ModelRolesHandler;
67
+
68
+ //# sourceMappingURL=ModelRolesHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/ModelRoles/ModelRolesHandler.js","sources":["../../../../src/api/features/ModelRoles/ModelRolesHandler.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { AiPowerUpsSettingsGroupHandler } from \"~/api/features/shared/index.js\";\nimport { readLegacyProviderPresets } from \"~/api/features/Connections/legacyProviders.js\";\nimport { AI_MODEL_ROLE_IDS } from \"./roles.js\";\nimport { emptyAssignment } from \"./types.js\";\nimport type { AiModelRoleAssignments, ModelRolesSettings, PersistedModelRoles } from \"./types.js\";\n\n/*\n * The admin form sends `null`, not `\"\"`, for a field nobody has touched, and an unfilled role is\n * the normal state of two of the three. `nullish` keeps an untouched role from failing validation;\n * `mapToStorage` is what normalises it to `\"\"`.\n */\nconst formString = z.string().nullish();\n\nconst assignmentSchema = z.object({\n connectionId: formString,\n model: formString\n});\n\nconst inputSchema = z.object({\n roles: z.object(\n Object.fromEntries(AI_MODEL_ROLE_IDS.map(id => [id, assignmentSchema]))\n ) as unknown as z.ZodType<AiModelRoleAssignments>\n});\n\nclass ModelRolesHandlerImpl implements AiPowerUpsSettingsGroupHandler.Interface {\n readonly name = \"modelRoles\";\n readonly inputSchema = inputSchema;\n\n mapFromStorage(persisted: unknown, all?: Record<string, unknown>): ModelRolesSettings {\n const stored = (persisted ?? {}) as PersistedModelRoles;\n const roles = Object.fromEntries(\n AI_MODEL_ROLE_IDS.map(id => {\n const assignment = stored.roles?.[id];\n return [\n id,\n {\n connectionId: assignment?.connectionId ?? \"\",\n model: assignment?.model ?? \"\"\n }\n ];\n })\n ) as AiModelRoleAssignments;\n\n if (roles.standard.model) {\n return { roles };\n }\n\n /*\n * Nothing has filled `standard` yet, so seed it from the legacy `providers` section. Every\n * AI feature used to read `providers.presets[0]` and nothing else, so lifting exactly that\n * preset into `standard` reproduces the old behaviour for a project that upgrades without\n * touching the settings screen.\n *\n * `fast` and `vision` stay empty on purpose. Both fall back to `standard` at resolve time,\n * so an untouched project keeps working, and the settings screen shows the fallback rather\n * than pretending someone chose it.\n */\n const legacy = readLegacyProviderPresets(all)[0];\n\n if (legacy?.model) {\n roles.standard = { connectionId: legacy.id, model: legacy.model };\n }\n\n return { roles };\n }\n\n async mapToStorage(internal: unknown): Promise<PersistedModelRoles> {\n const input = internal as ModelRolesSettings;\n\n return {\n roles: Object.fromEntries(\n AI_MODEL_ROLE_IDS.map(id => {\n const assignment = input.roles?.[id] ?? emptyAssignment();\n return [\n id,\n {\n connectionId: assignment.connectionId ?? \"\",\n model: assignment.model ?? \"\"\n }\n ];\n })\n )\n };\n }\n}\n\nexport default AiPowerUpsSettingsGroupHandler.createImplementation({\n implementation: ModelRolesHandlerImpl,\n dependencies: []\n});\n"],"names":["formString","z","assignmentSchema","inputSchema","Object","AI_MODEL_ROLE_IDS","id","ModelRolesHandlerImpl","persisted","all","stored","roles","assignment","legacy","readLegacyProviderPresets","internal","input","emptyAssignment","AiPowerUpsSettingsGroupHandler"],"mappings":";;;;;AAYA,MAAMA,aAAaC,EAAE,MAAM,GAAG,OAAO;AAErC,MAAMC,mBAAmBD,EAAE,MAAM,CAAC;IAC9B,cAAcD;IACd,OAAOA;AACX;AAEA,MAAMG,cAAcF,EAAE,MAAM,CAAC;IACzB,OAAOA,EAAE,MAAM,CACXG,OAAO,WAAW,CAACC,kBAAkB,GAAG,CAACC,CAAAA,KAAM;YAACA;YAAIJ;SAAiB;AAE7E;AAEA,MAAMK;IAIF,eAAeC,SAAkB,EAAEC,GAA6B,EAAsB;QAClF,MAAMC,SAAUF,aAAa,CAAC;QAC9B,MAAMG,QAAQP,OAAO,WAAW,CAC5BC,kBAAkB,GAAG,CAACC,CAAAA;YAClB,MAAMM,aAAaF,OAAO,KAAK,EAAE,CAACJ,GAAG;YACrC,OAAO;gBACHA;gBACA;oBACI,cAAcM,YAAY,gBAAgB;oBAC1C,OAAOA,YAAY,SAAS;gBAChC;aACH;QACL;QAGJ,IAAID,MAAM,QAAQ,CAAC,KAAK,EACpB,OAAO;YAAEA;QAAM;QAanB,MAAME,SAASC,0BAA0BL,IAAI,CAAC,EAAE;QAEhD,IAAII,QAAQ,OACRF,MAAM,QAAQ,GAAG;YAAE,cAAcE,OAAO,EAAE;YAAE,OAAOA,OAAO,KAAK;QAAC;QAGpE,OAAO;YAAEF;QAAM;IACnB;IAEA,MAAM,aAAaI,QAAiB,EAAgC;QAChE,MAAMC,QAAQD;QAEd,OAAO;YACH,OAAOX,OAAO,WAAW,CACrBC,kBAAkB,GAAG,CAACC,CAAAA;gBAClB,MAAMM,aAAaI,MAAM,KAAK,EAAE,CAACV,GAAG,IAAIW;gBACxC,OAAO;oBACHX;oBACA;wBACI,cAAcM,WAAW,YAAY,IAAI;wBACzC,OAAOA,WAAW,KAAK,IAAI;oBAC/B;iBACH;YACL;QAER;IACJ;;aA1DS,IAAI,GAAG;aACP,WAAW,GAAGT;;AA0D3B;AAEA,0BAAee,+BAA+B,oBAAoB,CAAC;IAC/D,gBAAgBX;IAChB,cAAc,EAAE;AACpB"}
@@ -0,0 +1,4 @@
1
+ export declare const ModelRolesFeature: {
2
+ name: string;
3
+ register(container: import("@webiny/di").Container): void;
4
+ };
@@ -0,0 +1,11 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import ModelRolesHandler from "./ModelRolesHandler.js";
3
+ const ModelRolesFeature = createFeature({
4
+ name: "AiPowerUpsModelRoles",
5
+ register (container) {
6
+ container.register(ModelRolesHandler);
7
+ }
8
+ });
9
+ export { ModelRolesFeature };
10
+
11
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/ModelRoles/feature.js","sources":["../../../../src/api/features/ModelRoles/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport ModelRolesHandler from \"./ModelRolesHandler.js\";\n\nexport const ModelRolesFeature = createFeature({\n name: \"AiPowerUpsModelRoles\",\n register(container) {\n container.register(ModelRolesHandler);\n }\n});\n"],"names":["ModelRolesFeature","createFeature","container","ModelRolesHandler"],"mappings":";;AAGO,MAAMA,oBAAoBC,cAAc;IAC3C,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}
@@ -0,0 +1,4 @@
1
+ export { AI_MODEL_ROLE_IDS, isAiModelRoleId } from "./roles.js";
2
+ export type { AiModelRoleId } from "./roles.js";
3
+ export type { AiModelRoleAssignment, AiModelRoleAssignments, ModelRolesSettings } from "./types.js";
4
+ export { ModelRolesFeature } from "./feature.js";
@@ -0,0 +1,2 @@
1
+ export { AI_MODEL_ROLE_IDS, isAiModelRoleId } from "./roles.js";
2
+ export { ModelRolesFeature } from "./feature.js";
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Model roles are the indirection between an AI feature and a concrete model.
3
+ *
4
+ * A feature never names a model. It names a role, and the project decides which model fills that
5
+ * role. That keeps the settings screen small (one select per role, not one per feature) while still
6
+ * letting a project run cheap work on a cheap model.
7
+ *
8
+ * The set is deliberately fixed and closed. A project that needs a different model for one specific
9
+ * feature overrides that feature under Capabilities instead of inventing a role.
10
+ *
11
+ * Labels and descriptions are not here on purpose: they are UI text, and they live next to the
12
+ * settings form in `~/admin/presentation/modelRoles.js`.
13
+ */
14
+ export declare const AI_MODEL_ROLE_IDS: readonly ["fast", "standard", "vision"];
15
+ export type AiModelRoleId = (typeof AI_MODEL_ROLE_IDS)[number];
16
+ export declare const isAiModelRoleId: (value: unknown) => value is AiModelRoleId;
@@ -0,0 +1,9 @@
1
+ const AI_MODEL_ROLE_IDS = [
2
+ "fast",
3
+ "standard",
4
+ "vision"
5
+ ];
6
+ const isAiModelRoleId = (value)=>"string" == typeof value && AI_MODEL_ROLE_IDS.includes(value);
7
+ export { AI_MODEL_ROLE_IDS, isAiModelRoleId };
8
+
9
+ //# sourceMappingURL=roles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/ModelRoles/roles.js","sources":["../../../../src/api/features/ModelRoles/roles.ts"],"sourcesContent":["/**\n * Model roles are the indirection between an AI feature and a concrete model.\n *\n * A feature never names a model. It names a role, and the project decides which model fills that\n * role. That keeps the settings screen small (one select per role, not one per feature) while still\n * letting a project run cheap work on a cheap model.\n *\n * The set is deliberately fixed and closed. A project that needs a different model for one specific\n * feature overrides that feature under Capabilities instead of inventing a role.\n *\n * Labels and descriptions are not here on purpose: they are UI text, and they live next to the\n * settings form in `~/admin/presentation/modelRoles.js`.\n */\nexport const AI_MODEL_ROLE_IDS = [\"fast\", \"standard\", \"vision\"] as const;\n\nexport type AiModelRoleId = (typeof AI_MODEL_ROLE_IDS)[number];\n\nexport const isAiModelRoleId = (value: unknown): value is AiModelRoleId =>\n typeof value === \"string\" && (AI_MODEL_ROLE_IDS as readonly string[]).includes(value);\n"],"names":["AI_MODEL_ROLE_IDS","isAiModelRoleId","value"],"mappings":"AAaO,MAAMA,oBAAoB;IAAC;IAAQ;IAAY;CAAS;AAIxD,MAAMC,kBAAkB,CAACC,QAC5B,AAAiB,YAAjB,OAAOA,SAAuBF,kBAAwC,QAAQ,CAACE"}
@@ -0,0 +1,21 @@
1
+ import type { IAiPowerUpsSettings } from "../../../api/types.js";
2
+ import type { AiModelRoleId } from "./roles.js";
3
+ export interface AiModelRoleAssignment {
4
+ /** Empty string means the role is unfilled. */
5
+ connectionId: string;
6
+ /** Fully qualified, e.g. `"anthropic/claude-sonnet-4-5"`. Empty string means unfilled. */
7
+ model: string;
8
+ }
9
+ export type AiModelRoleAssignments = Record<AiModelRoleId, AiModelRoleAssignment>;
10
+ declare module "~/api/types.js" {
11
+ interface IAiPowerUpsSettings {
12
+ modelRoles: {
13
+ roles: AiModelRoleAssignments;
14
+ };
15
+ }
16
+ }
17
+ export type ModelRolesSettings = IAiPowerUpsSettings["modelRoles"];
18
+ export interface PersistedModelRoles {
19
+ roles?: Partial<Record<string, Partial<AiModelRoleAssignment>>>;
20
+ }
21
+ export declare const emptyAssignment: () => AiModelRoleAssignment;
@@ -0,0 +1,7 @@
1
+ const emptyAssignment = ()=>({
2
+ connectionId: "",
3
+ model: ""
4
+ });
5
+ export { emptyAssignment };
6
+
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api/features/ModelRoles/types.js","sources":["../../../../src/api/features/ModelRoles/types.ts"],"sourcesContent":["import type { IAiPowerUpsSettings } from \"~/api/types.js\";\nimport type { AiModelRoleId } from \"./roles.js\";\n\nexport interface AiModelRoleAssignment {\n /** Empty string means the role is unfilled. */\n connectionId: string;\n /** Fully qualified, e.g. `\"anthropic/claude-sonnet-4-5\"`. Empty string means unfilled. */\n model: string;\n}\n\nexport type AiModelRoleAssignments = Record<AiModelRoleId, AiModelRoleAssignment>;\n\ndeclare module \"~/api/types.js\" {\n interface IAiPowerUpsSettings {\n modelRoles: {\n roles: AiModelRoleAssignments;\n };\n }\n}\n\nexport type ModelRolesSettings = IAiPowerUpsSettings[\"modelRoles\"];\n\nexport interface PersistedModelRoles {\n roles?: Partial<Record<string, Partial<AiModelRoleAssignment>>>;\n}\n\nexport const emptyAssignment = (): AiModelRoleAssignment => ({ connectionId: \"\", model: \"\" });\n"],"names":["emptyAssignment"],"mappings":"AA0BO,MAAMA,kBAAkB,IAA8B;QAAE,cAAc;QAAI,OAAO;IAAG"}
@@ -19,7 +19,7 @@ class UpdateSettingsRepositoryImpl {
19
19
  raw = storeResult.isOk() && storeResult.value ? storeResult.value : {};
20
20
  }
21
21
  const existingInternal = {};
22
- for (const handler of this.handlers)existingInternal[handler.name] = handler.mapFromStorage(raw[handler.name]);
22
+ for (const handler of this.handlers)existingInternal[handler.name] = handler.mapFromStorage(raw[handler.name], raw);
23
23
  const newSettings = input;
24
24
  const invalidFields = {};
25
25
  for (const handler of this.handlers){
@@ -46,7 +46,7 @@ class UpdateSettingsRepositoryImpl {
46
46
  const writeResult = await this.keyValueStore.set(AI_POWER_UPS_SETTINGS, persisted);
47
47
  if (writeResult.isFail()) return Result.fail(new Error(String(writeResult.error)));
48
48
  const result = {};
49
- for (const handler of this.handlers)result[handler.name] = handler.mapFromStorage(persisted[handler.name]);
49
+ for (const handler of this.handlers)result[handler.name] = handler.mapFromStorage(persisted[handler.name], persisted);
50
50
  for (const key of Object.keys(persisted))if (!(key in result)) result[key] = persisted[key];
51
51
  const mapped = result;
52
52
  this.cache.set(persisted, mapped);
@@ -1 +1 @@
1
- {"version":3,"file":"api/features/UpdateSettings/UpdateSettingsRepository.js","sources":["../../../../src/api/features/UpdateSettings/UpdateSettingsRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { KeyValueStore } from \"@webiny/api-core/features/keyValueStore/index.js\";\nimport type { OutputErrors } from \"@webiny/utils/createZodError.js\";\nimport {\n AiPowerUpsSettingsGroupHandler,\n AiPowerUpsSettingsCache\n} from \"~/api/features/shared/index.js\";\nimport { UpdateSettingsRepository } from \"./abstractions.js\";\nimport { SettingsValidationError } from \"./errors.js\";\nimport type { IAiPowerUpsSettings } from \"~/api/types.js\";\nimport { AI_POWER_UPS_SETTINGS } from \"~/api/constants.js\";\n\nclass UpdateSettingsRepositoryImpl implements UpdateSettingsRepository.Interface {\n constructor(\n private keyValueStore: KeyValueStore.Interface,\n private handlers: AiPowerUpsSettingsGroupHandler.Interface[],\n private cache: AiPowerUpsSettingsCache.Interface\n ) {}\n\n async execute(input: IAiPowerUpsSettings): Promise<Result<IAiPowerUpsSettings, Error>> {\n const cached = this.cache.get();\n let raw: Record<string, unknown>;\n\n if (cached) {\n raw = cached.raw;\n } else {\n const storeResult =\n await this.keyValueStore.get<Record<string, unknown>>(AI_POWER_UPS_SETTINGS);\n raw = storeResult.isOk() && storeResult.value ? storeResult.value : {};\n }\n\n const existingInternal: Record<string, unknown> = {};\n for (const handler of this.handlers) {\n existingInternal[handler.name] = handler.mapFromStorage(raw[handler.name]);\n }\n\n const newSettings = input as unknown as Record<string, unknown>;\n const invalidFields: OutputErrors = {};\n\n for (const handler of this.handlers) {\n const parseResult = await handler.inputSchema.safeParseAsync(newSettings[handler.name]);\n if (!parseResult.success) {\n for (const issue of parseResult.error.issues) {\n const fieldPath = [handler.name, ...issue.path.map(String)].join(\".\");\n invalidFields[fieldPath] = {\n code: issue.code,\n message: issue.message,\n data: { path: issue.path }\n };\n }\n }\n }\n\n if (Object.keys(invalidFields).length > 0) {\n return Result.fail(new SettingsValidationError(invalidFields));\n }\n\n const persisted: Record<string, unknown> = { ...raw };\n for (const handler of this.handlers) {\n persisted[handler.name] = await handler.mapToStorage(\n newSettings[handler.name],\n existingInternal[handler.name]\n );\n }\n\n const writeResult = await this.keyValueStore.set(AI_POWER_UPS_SETTINGS, persisted);\n if (writeResult.isFail()) {\n return Result.fail(new Error(String(writeResult.error)));\n }\n\n const result: Record<string, unknown> = {};\n for (const handler of this.handlers) {\n result[handler.name] = handler.mapFromStorage(persisted[handler.name]);\n }\n\n for (const key of Object.keys(persisted)) {\n if (!(key in result)) {\n result[key] = persisted[key];\n }\n }\n\n const mapped = result as unknown as IAiPowerUpsSettings;\n this.cache.set(persisted, mapped);\n\n return Result.ok(mapped);\n }\n}\n\nexport const UpdateSettingsRepositoryImplementation = UpdateSettingsRepository.createImplementation(\n {\n implementation: UpdateSettingsRepositoryImpl,\n dependencies: [\n KeyValueStore,\n [AiPowerUpsSettingsGroupHandler, { multiple: true }],\n AiPowerUpsSettingsCache\n ]\n }\n);\n"],"names":["UpdateSettingsRepositoryImpl","keyValueStore","handlers","cache","input","cached","raw","storeResult","AI_POWER_UPS_SETTINGS","existingInternal","handler","newSettings","invalidFields","parseResult","issue","fieldPath","String","Object","Result","SettingsValidationError","persisted","writeResult","Error","result","key","mapped","UpdateSettingsRepositoryImplementation","UpdateSettingsRepository","KeyValueStore","AiPowerUpsSettingsGroupHandler","AiPowerUpsSettingsCache"],"mappings":";;;;;;AAYA,MAAMA;IACF,YACYC,aAAsC,EACtCC,QAAoD,EACpDC,KAAwC,CAClD;aAHUF,aAAa,GAAbA;aACAC,QAAQ,GAARA;aACAC,KAAK,GAALA;IACT;IAEH,MAAM,QAAQC,KAA0B,EAA+C;QACnF,MAAMC,SAAS,IAAI,CAAC,KAAK,CAAC,GAAG;QAC7B,IAAIC;QAEJ,IAAID,QACAC,MAAMD,OAAO,GAAG;aACb;YACH,MAAME,cACF,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAA0BC;YAC1DF,MAAMC,YAAY,IAAI,MAAMA,YAAY,KAAK,GAAGA,YAAY,KAAK,GAAG,CAAC;QACzE;QAEA,MAAME,mBAA4C,CAAC;QACnD,KAAK,MAAMC,WAAW,IAAI,CAAC,QAAQ,CAC/BD,gBAAgB,CAACC,QAAQ,IAAI,CAAC,GAAGA,QAAQ,cAAc,CAACJ,GAAG,CAACI,QAAQ,IAAI,CAAC;QAG7E,MAAMC,cAAcP;QACpB,MAAMQ,gBAA8B,CAAC;QAErC,KAAK,MAAMF,WAAW,IAAI,CAAC,QAAQ,CAAE;YACjC,MAAMG,cAAc,MAAMH,QAAQ,WAAW,CAAC,cAAc,CAACC,WAAW,CAACD,QAAQ,IAAI,CAAC;YACtF,IAAI,CAACG,YAAY,OAAO,EACpB,KAAK,MAAMC,SAASD,YAAY,KAAK,CAAC,MAAM,CAAE;gBAC1C,MAAME,YAAY;oBAACL,QAAQ,IAAI;uBAAKI,MAAM,IAAI,CAAC,GAAG,CAACE;iBAAQ,CAAC,IAAI,CAAC;gBACjEJ,aAAa,CAACG,UAAU,GAAG;oBACvB,MAAMD,MAAM,IAAI;oBAChB,SAASA,MAAM,OAAO;oBACtB,MAAM;wBAAE,MAAMA,MAAM,IAAI;oBAAC;gBAC7B;YACJ;QAER;QAEA,IAAIG,OAAO,IAAI,CAACL,eAAe,MAAM,GAAG,GACpC,OAAOM,OAAO,IAAI,CAAC,IAAIC,wBAAwBP;QAGnD,MAAMQ,YAAqC;YAAE,GAAGd,GAAG;QAAC;QACpD,KAAK,MAAMI,WAAW,IAAI,CAAC,QAAQ,CAC/BU,SAAS,CAACV,QAAQ,IAAI,CAAC,GAAG,MAAMA,QAAQ,YAAY,CAChDC,WAAW,CAACD,QAAQ,IAAI,CAAC,EACzBD,gBAAgB,CAACC,QAAQ,IAAI,CAAC;QAItC,MAAMW,cAAc,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAACb,uBAAuBY;QACxE,IAAIC,YAAY,MAAM,IAClB,OAAOH,OAAO,IAAI,CAAC,IAAII,MAAMN,OAAOK,YAAY,KAAK;QAGzD,MAAME,SAAkC,CAAC;QACzC,KAAK,MAAMb,WAAW,IAAI,CAAC,QAAQ,CAC/Ba,MAAM,CAACb,QAAQ,IAAI,CAAC,GAAGA,QAAQ,cAAc,CAACU,SAAS,CAACV,QAAQ,IAAI,CAAC;QAGzE,KAAK,MAAMc,OAAOP,OAAO,IAAI,CAACG,WAC1B,IAAI,CAAEI,CAAAA,OAAOD,MAAK,GACdA,MAAM,CAACC,IAAI,GAAGJ,SAAS,CAACI,IAAI;QAIpC,MAAMC,SAASF;QACf,IAAI,CAAC,KAAK,CAAC,GAAG,CAACH,WAAWK;QAE1B,OAAOP,OAAO,EAAE,CAACO;IACrB;AACJ;AAEO,MAAMC,yCAAyCC,yBAAyB,oBAAoB,CAC/F;IACI,gBAAgB3B;IAChB,cAAc;QACV4B;QACA;YAACC;YAAgC;gBAAE,UAAU;YAAK;SAAE;QACpDC;KACH;AACL"}
1
+ {"version":3,"file":"api/features/UpdateSettings/UpdateSettingsRepository.js","sources":["../../../../src/api/features/UpdateSettings/UpdateSettingsRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { KeyValueStore } from \"@webiny/api-core/features/keyValueStore/index.js\";\nimport type { OutputErrors } from \"@webiny/utils/createZodError.js\";\nimport {\n AiPowerUpsSettingsGroupHandler,\n AiPowerUpsSettingsCache\n} from \"~/api/features/shared/index.js\";\nimport { UpdateSettingsRepository } from \"./abstractions.js\";\nimport { SettingsValidationError } from \"./errors.js\";\nimport type { IAiPowerUpsSettings } from \"~/api/types.js\";\nimport { AI_POWER_UPS_SETTINGS } from \"~/api/constants.js\";\n\nclass UpdateSettingsRepositoryImpl implements UpdateSettingsRepository.Interface {\n constructor(\n private keyValueStore: KeyValueStore.Interface,\n private handlers: AiPowerUpsSettingsGroupHandler.Interface[],\n private cache: AiPowerUpsSettingsCache.Interface\n ) {}\n\n async execute(input: IAiPowerUpsSettings): Promise<Result<IAiPowerUpsSettings, Error>> {\n const cached = this.cache.get();\n let raw: Record<string, unknown>;\n\n if (cached) {\n raw = cached.raw;\n } else {\n const storeResult =\n await this.keyValueStore.get<Record<string, unknown>>(AI_POWER_UPS_SETTINGS);\n raw = storeResult.isOk() && storeResult.value ? storeResult.value : {};\n }\n\n const existingInternal: Record<string, unknown> = {};\n for (const handler of this.handlers) {\n /*\n * `raw` matters here as much as it does on read. `connections` derives itself from the\n * legacy `providers` section until it has one of its own, and this is what\n * `mapToStorage` diffs against to carry forward an encrypted key the form only ever saw\n * as a mask. Without it, the first save after an upgrade compares against an empty list\n * and silently drops every stored key.\n */\n existingInternal[handler.name] = handler.mapFromStorage(raw[handler.name], raw);\n }\n\n const newSettings = input as unknown as Record<string, unknown>;\n const invalidFields: OutputErrors = {};\n\n for (const handler of this.handlers) {\n const parseResult = await handler.inputSchema.safeParseAsync(newSettings[handler.name]);\n if (!parseResult.success) {\n for (const issue of parseResult.error.issues) {\n const fieldPath = [handler.name, ...issue.path.map(String)].join(\".\");\n invalidFields[fieldPath] = {\n code: issue.code,\n message: issue.message,\n data: { path: issue.path }\n };\n }\n }\n }\n\n if (Object.keys(invalidFields).length > 0) {\n return Result.fail(new SettingsValidationError(invalidFields));\n }\n\n const persisted: Record<string, unknown> = { ...raw };\n for (const handler of this.handlers) {\n persisted[handler.name] = await handler.mapToStorage(\n newSettings[handler.name],\n existingInternal[handler.name]\n );\n }\n\n const writeResult = await this.keyValueStore.set(AI_POWER_UPS_SETTINGS, persisted);\n if (writeResult.isFail()) {\n return Result.fail(new Error(String(writeResult.error)));\n }\n\n const result: Record<string, unknown> = {};\n for (const handler of this.handlers) {\n result[handler.name] = handler.mapFromStorage(persisted[handler.name], persisted);\n }\n\n for (const key of Object.keys(persisted)) {\n if (!(key in result)) {\n result[key] = persisted[key];\n }\n }\n\n const mapped = result as unknown as IAiPowerUpsSettings;\n this.cache.set(persisted, mapped);\n\n return Result.ok(mapped);\n }\n}\n\nexport const UpdateSettingsRepositoryImplementation = UpdateSettingsRepository.createImplementation(\n {\n implementation: UpdateSettingsRepositoryImpl,\n dependencies: [\n KeyValueStore,\n [AiPowerUpsSettingsGroupHandler, { multiple: true }],\n AiPowerUpsSettingsCache\n ]\n }\n);\n"],"names":["UpdateSettingsRepositoryImpl","keyValueStore","handlers","cache","input","cached","raw","storeResult","AI_POWER_UPS_SETTINGS","existingInternal","handler","newSettings","invalidFields","parseResult","issue","fieldPath","String","Object","Result","SettingsValidationError","persisted","writeResult","Error","result","key","mapped","UpdateSettingsRepositoryImplementation","UpdateSettingsRepository","KeyValueStore","AiPowerUpsSettingsGroupHandler","AiPowerUpsSettingsCache"],"mappings":";;;;;;AAYA,MAAMA;IACF,YACYC,aAAsC,EACtCC,QAAoD,EACpDC,KAAwC,CAClD;aAHUF,aAAa,GAAbA;aACAC,QAAQ,GAARA;aACAC,KAAK,GAALA;IACT;IAEH,MAAM,QAAQC,KAA0B,EAA+C;QACnF,MAAMC,SAAS,IAAI,CAAC,KAAK,CAAC,GAAG;QAC7B,IAAIC;QAEJ,IAAID,QACAC,MAAMD,OAAO,GAAG;aACb;YACH,MAAME,cACF,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAA0BC;YAC1DF,MAAMC,YAAY,IAAI,MAAMA,YAAY,KAAK,GAAGA,YAAY,KAAK,GAAG,CAAC;QACzE;QAEA,MAAME,mBAA4C,CAAC;QACnD,KAAK,MAAMC,WAAW,IAAI,CAAC,QAAQ,CAQ/BD,gBAAgB,CAACC,QAAQ,IAAI,CAAC,GAAGA,QAAQ,cAAc,CAACJ,GAAG,CAACI,QAAQ,IAAI,CAAC,EAAEJ;QAG/E,MAAMK,cAAcP;QACpB,MAAMQ,gBAA8B,CAAC;QAErC,KAAK,MAAMF,WAAW,IAAI,CAAC,QAAQ,CAAE;YACjC,MAAMG,cAAc,MAAMH,QAAQ,WAAW,CAAC,cAAc,CAACC,WAAW,CAACD,QAAQ,IAAI,CAAC;YACtF,IAAI,CAACG,YAAY,OAAO,EACpB,KAAK,MAAMC,SAASD,YAAY,KAAK,CAAC,MAAM,CAAE;gBAC1C,MAAME,YAAY;oBAACL,QAAQ,IAAI;uBAAKI,MAAM,IAAI,CAAC,GAAG,CAACE;iBAAQ,CAAC,IAAI,CAAC;gBACjEJ,aAAa,CAACG,UAAU,GAAG;oBACvB,MAAMD,MAAM,IAAI;oBAChB,SAASA,MAAM,OAAO;oBACtB,MAAM;wBAAE,MAAMA,MAAM,IAAI;oBAAC;gBAC7B;YACJ;QAER;QAEA,IAAIG,OAAO,IAAI,CAACL,eAAe,MAAM,GAAG,GACpC,OAAOM,OAAO,IAAI,CAAC,IAAIC,wBAAwBP;QAGnD,MAAMQ,YAAqC;YAAE,GAAGd,GAAG;QAAC;QACpD,KAAK,MAAMI,WAAW,IAAI,CAAC,QAAQ,CAC/BU,SAAS,CAACV,QAAQ,IAAI,CAAC,GAAG,MAAMA,QAAQ,YAAY,CAChDC,WAAW,CAACD,QAAQ,IAAI,CAAC,EACzBD,gBAAgB,CAACC,QAAQ,IAAI,CAAC;QAItC,MAAMW,cAAc,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAACb,uBAAuBY;QACxE,IAAIC,YAAY,MAAM,IAClB,OAAOH,OAAO,IAAI,CAAC,IAAII,MAAMN,OAAOK,YAAY,KAAK;QAGzD,MAAME,SAAkC,CAAC;QACzC,KAAK,MAAMb,WAAW,IAAI,CAAC,QAAQ,CAC/Ba,MAAM,CAACb,QAAQ,IAAI,CAAC,GAAGA,QAAQ,cAAc,CAACU,SAAS,CAACV,QAAQ,IAAI,CAAC,EAAEU;QAG3E,KAAK,MAAMI,OAAOP,OAAO,IAAI,CAACG,WAC1B,IAAI,CAAEI,CAAAA,OAAOD,MAAK,GACdA,MAAM,CAACC,IAAI,GAAGJ,SAAS,CAACI,IAAI;QAIpC,MAAMC,SAASF;QACf,IAAI,CAAC,KAAK,CAAC,GAAG,CAACH,WAAWK;QAE1B,OAAOP,OAAO,EAAE,CAACO;IACrB;AACJ;AAEO,MAAMC,yCAAyCC,yBAAyB,oBAAoB,CAC/F;IACI,gBAAgB3B;IAChB,cAAc;QACV4B;QACA;YAACC;YAAgC;gBAAE,UAAU;YAAK;SAAE;QACpDC;KACH;AACL"}
@@ -1,20 +1,18 @@
1
1
  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
- 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
- import { GetSettingsUseCase } from "../../../api/features/GetSettings/index.js";
5
+ import { ResolveAiCapabilityUseCase } from "../../../api/features/Capabilities/index.js";
7
6
  import { AiPromptContextBuilder } from "../../../api/features/AiPromptContext/index.js";
8
7
  import { WbGeneratePageContentUseCase } from "./abstractions.js";
9
8
  import type { WbGeneratePageContentParams, GeneratePageContentResult } from "./abstractions.js";
10
9
  declare class WbGeneratePageContentUseCaseImpl implements WbGeneratePageContentUseCase.Interface {
11
10
  private promptContextBuilder;
12
- private getSettings;
11
+ private resolveCapability;
13
12
  private ai;
14
13
  private aiSdkTools;
15
- private encryption;
16
14
  private listTags;
17
- constructor(promptContextBuilder: AiPromptContextBuilder.Interface, getSettings: GetSettingsUseCase.Interface, ai: Ai.Interface, aiSdkTools: AiSdkTools.Interface, encryption: Encryption.Interface, listTags: ListTagsUseCase.Interface);
15
+ constructor(promptContextBuilder: AiPromptContextBuilder.Interface, resolveCapability: ResolveAiCapabilityUseCase.Interface, ai: Ai.Interface, aiSdkTools: AiSdkTools.Interface, listTags: ListTagsUseCase.Interface);
18
16
  execute(params: WbGeneratePageContentParams): Promise<Result<GeneratePageContentResult, Error>>;
19
17
  }
20
18
  export declare const WbGeneratePageContentUseCaseImplementation: typeof WbGeneratePageContentUseCaseImpl & {
@@ -1,9 +1,9 @@
1
1
  import { stepCountIs } from "ai";
2
2
  import { Result } from "@webiny/feature/api";
3
3
  import { Ai, AiSdkTools } 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
- import { GetSettingsUseCase } from "../GetSettings/index.js";
5
+ import { ResolveAiCapabilityUseCase, withAdditionalInstructions } from "../Capabilities/index.js";
6
+ import { WB_GENERATE_PAGE_CAPABILITY } from "./capability.js";
7
7
  import { AiPromptContextBuilder, formatAdditionalFilesContext } from "../AiPromptContext/index.js";
8
8
  import { createReadProjectFileTool } from "../AiPromptContext/ReadProjectFileTool.js";
9
9
  import { WbGeneratePageContentUseCase } from "./abstractions.js";
@@ -11,21 +11,17 @@ import { buildDomainPrompt } from "./buildPrompt.js";
11
11
  import { LlmJsonResponse } from "./LlmJsonResponse.js";
12
12
  import { ComponentFilter } from "./ComponentFilter.js";
13
13
  class WbGeneratePageContentUseCaseImpl {
14
- constructor(promptContextBuilder, getSettings, ai, aiSdkTools, encryption, listTags){
14
+ constructor(promptContextBuilder, resolveCapability, ai, aiSdkTools, listTags){
15
15
  this.promptContextBuilder = promptContextBuilder;
16
- this.getSettings = getSettings;
16
+ this.resolveCapability = resolveCapability;
17
17
  this.ai = ai;
18
18
  this.aiSdkTools = aiSdkTools;
19
- this.encryption = encryption;
20
19
  this.listTags = listTags;
21
20
  }
22
21
  async execute(params) {
23
- const settingsResult = await this.getSettings.execute();
24
- if (settingsResult.isFail()) return Result.fail(new Error("Failed to load AI PowerUps settings."));
25
- const settings = settingsResult.value;
26
- const firstProvider = settings.providers.presets[0];
27
- if (!firstProvider) return Result.fail(new Error("No AI provider configured. Add a provider in AI Power Ups settings."));
28
- const apiKey = await this.encryption.decrypt(firstProvider.apiKeyEncrypted);
22
+ const resolved = await this.resolveCapability.execute(WB_GENERATE_PAGE_CAPABILITY);
23
+ if (resolved.isFail()) return Result.fail(resolved.error);
24
+ const capability = resolved.value;
29
25
  const sdkTools = this.aiSdkTools.getToolSet();
30
26
  const context = await this.promptContextBuilder.execute({
31
27
  projectId: params.projectId,
@@ -46,7 +42,7 @@ class WbGeneratePageContentUseCaseImpl {
46
42
  });
47
43
  const imageTags = tagsResult.isOk() ? tagsResult.value.map((t)=>t.tag) : [];
48
44
  const components = params.components;
49
- const systemText = buildDomainPrompt(components, params.tools, imageTags) + context.toString();
45
+ const systemText = withAdditionalInstructions(capability, buildDomainPrompt(components, params.tools, imageTags) + context.toString());
50
46
  const system = {
51
47
  role: "system",
52
48
  content: systemText,
@@ -60,11 +56,8 @@ class WbGeneratePageContentUseCaseImpl {
60
56
  };
61
57
  try {
62
58
  const aiResult = await this.ai.generateText({
63
- model: firstProvider.model,
64
- connection: {
65
- sdkName: firstProvider.model.split("/")[0],
66
- apiKey
67
- },
59
+ model: capability.model,
60
+ connection: capability.connection,
68
61
  system,
69
62
  toolChoice: "auto",
70
63
  prompt: params.prompt + formatAdditionalFilesContext(context.additionalFiles),
@@ -109,10 +102,9 @@ const WbGeneratePageContentUseCaseImplementation = WbGeneratePageContentUseCase.
109
102
  implementation: WbGeneratePageContentUseCaseImpl,
110
103
  dependencies: [
111
104
  AiPromptContextBuilder,
112
- GetSettingsUseCase,
105
+ ResolveAiCapabilityUseCase,
113
106
  Ai,
114
107
  AiSdkTools,
115
- Encryption,
116
108
  ListTagsUseCase
117
109
  ]
118
110
  });