@webiny/ai-powerups 6.4.11 → 6.6.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AiPowerups.js +2 -2
- package/AiPowerups.js.map +1 -1
- package/admin/Extension.js +11 -2
- package/admin/Extension.js.map +1 -1
- package/admin/features/compareEntryRevisions/CompareEntryRevisionsGateway.d.ts +12 -0
- package/admin/features/compareEntryRevisions/CompareEntryRevisionsGateway.js +46 -0
- package/admin/features/compareEntryRevisions/CompareEntryRevisionsGateway.js.map +1 -0
- package/admin/features/compareEntryRevisions/CompareEntryRevisionsRepository.d.ts +11 -0
- package/admin/features/compareEntryRevisions/CompareEntryRevisionsRepository.js +18 -0
- package/admin/features/compareEntryRevisions/CompareEntryRevisionsRepository.js.map +1 -0
- package/admin/features/compareEntryRevisions/CompareEntryRevisionsUseCase.d.ts +11 -0
- package/admin/features/compareEntryRevisions/CompareEntryRevisionsUseCase.js +18 -0
- package/admin/features/compareEntryRevisions/CompareEntryRevisionsUseCase.js.map +1 -0
- package/admin/features/compareEntryRevisions/abstractions.d.ts +32 -0
- package/admin/features/compareEntryRevisions/abstractions.js +7 -0
- package/admin/features/compareEntryRevisions/abstractions.js.map +1 -0
- package/admin/features/compareEntryRevisions/feature.d.ts +1 -0
- package/admin/features/compareEntryRevisions/feature.js +15 -0
- package/admin/features/compareEntryRevisions/feature.js.map +1 -0
- package/admin/features/compareEntryRevisions/index.d.ts +2 -0
- package/admin/features/compareEntryRevisions/index.js +2 -0
- package/admin/features/feature.js +2 -0
- package/admin/features/feature.js.map +1 -1
- package/admin/features/generateEntryContent/GenerateEntryContentGateway.d.ts +12 -0
- package/admin/features/generateEntryContent/GenerateEntryContentGateway.js +45 -0
- package/admin/features/generateEntryContent/GenerateEntryContentGateway.js.map +1 -0
- package/admin/features/generateEntryContent/GenerateEntryContentUseCase.d.ts +11 -0
- package/admin/features/generateEntryContent/GenerateEntryContentUseCase.js +18 -0
- package/admin/features/generateEntryContent/GenerateEntryContentUseCase.js.map +1 -0
- package/admin/features/generateEntryContent/abstractions.d.ts +24 -0
- package/admin/features/generateEntryContent/abstractions.js +6 -0
- package/admin/features/generateEntryContent/abstractions.js.map +1 -0
- package/admin/features/generateEntryContent/feature.d.ts +1 -0
- package/admin/features/generateEntryContent/feature.js +13 -0
- package/admin/features/generateEntryContent/feature.js.map +1 -0
- package/admin/features/generateEntryContent/index.d.ts +3 -0
- package/admin/features/generateEntryContent/index.js +2 -0
- package/admin/features/generatePageContent/GeneratePageContentGateway.js +2 -0
- package/admin/features/generatePageContent/GeneratePageContentGateway.js.map +1 -1
- package/admin/features/generatePageContent/abstractions.d.ts +1 -0
- package/admin/features/generatePageContent/abstractions.js.map +1 -1
- package/admin/presentation/AiPowerUpsSettings/AiPowerUpsSettingsPage.d.ts +2 -2
- package/admin/presentation/AiPowerUpsSettings/AiPowerUpsSettingsPage.js +3 -4
- package/admin/presentation/AiPowerUpsSettings/AiPowerUpsSettingsPage.js.map +1 -1
- package/admin/presentation/AiPromptFormFactory/AiPromptFormFactory.d.ts +20 -0
- package/admin/presentation/AiPromptFormFactory/AiPromptFormFactory.js +108 -0
- package/admin/presentation/AiPromptFormFactory/AiPromptFormFactory.js.map +1 -0
- package/admin/presentation/AiPromptFormFactory/abstractions.d.ts +14 -0
- package/admin/presentation/AiPromptFormFactory/abstractions.js +5 -0
- package/admin/presentation/AiPromptFormFactory/abstractions.js.map +1 -0
- package/admin/presentation/AiPromptFormFactory/feature.d.ts +1 -0
- package/admin/presentation/AiPromptFormFactory/feature.js +11 -0
- package/admin/presentation/AiPromptFormFactory/feature.js.map +1 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsDialog.d.ts +9 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsDialog.js +118 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsDialog.js.map +1 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsDrawer.d.ts +9 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsDrawer.js +72 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsDrawer.js.map +1 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsMenuItem.d.ts +4 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsMenuItem.js +21 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsMenuItem.js.map +1 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsOverlays.d.ts +2 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsOverlays.js +17 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsOverlays.js.map +1 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsPresenter.d.ts +25 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsPresenter.js +90 -0
- package/admin/presentation/CmsCompareEntryRevisions/CmsCompareEntryRevisionsPresenter.js.map +1 -0
- package/admin/presentation/CmsCompareEntryRevisions/Extension.d.ts +2 -0
- package/admin/presentation/CmsCompareEntryRevisions/Extension.js +16 -0
- package/admin/presentation/CmsCompareEntryRevisions/Extension.js.map +1 -0
- package/admin/presentation/CmsCompareEntryRevisions/abstractions.d.ts +29 -0
- package/admin/presentation/CmsCompareEntryRevisions/abstractions.js +5 -0
- package/admin/presentation/CmsCompareEntryRevisions/abstractions.js.map +1 -0
- package/admin/presentation/CmsCompareEntryRevisions/feature.d.ts +3 -0
- package/admin/presentation/CmsCompareEntryRevisions/feature.js +17 -0
- package/admin/presentation/CmsCompareEntryRevisions/feature.js.map +1 -0
- package/admin/presentation/CmsContentGeneration/CmsGenerateContentButton.d.ts +4 -0
- package/admin/presentation/CmsContentGeneration/CmsGenerateContentButton.js +27 -0
- package/admin/presentation/CmsContentGeneration/CmsGenerateContentButton.js.map +1 -0
- package/admin/presentation/CmsContentGeneration/CmsGenerateContentDialog.d.ts +5 -0
- package/admin/presentation/CmsContentGeneration/CmsGenerateContentDialog.js +106 -0
- package/admin/presentation/CmsContentGeneration/CmsGenerateContentDialog.js.map +1 -0
- package/admin/presentation/CmsContentGeneration/CmsGenerateContentPresenter.d.ts +29 -0
- package/admin/presentation/CmsContentGeneration/CmsGenerateContentPresenter.js +120 -0
- package/admin/presentation/CmsContentGeneration/CmsGenerateContentPresenter.js.map +1 -0
- package/admin/presentation/CmsContentGeneration/Extension.d.ts +2 -0
- package/admin/presentation/CmsContentGeneration/Extension.js +27 -0
- package/admin/presentation/CmsContentGeneration/Extension.js.map +1 -0
- package/admin/presentation/CmsContentGeneration/abstractions.d.ts +20 -0
- package/admin/presentation/CmsContentGeneration/abstractions.js +5 -0
- package/admin/presentation/CmsContentGeneration/abstractions.js.map +1 -0
- package/admin/presentation/CmsContentGeneration/feature.d.ts +3 -0
- package/admin/presentation/CmsContentGeneration/feature.js +17 -0
- package/admin/presentation/CmsContentGeneration/feature.js.map +1 -0
- package/admin/presentation/CmsEntryWizard/CmsEntryWizard.d.ts +4 -0
- package/admin/presentation/CmsEntryWizard/CmsEntryWizard.js +113 -0
- package/admin/presentation/CmsEntryWizard/CmsEntryWizard.js.map +1 -0
- package/admin/presentation/CmsEntryWizard/CmsEntryWizardGate.d.ts +4 -0
- package/admin/presentation/CmsEntryWizard/CmsEntryWizardGate.js +19 -0
- package/admin/presentation/CmsEntryWizard/CmsEntryWizardGate.js.map +1 -0
- package/admin/presentation/CmsEntryWizard/Extension.d.ts +2 -0
- package/admin/presentation/CmsEntryWizard/Extension.js +10 -0
- package/admin/presentation/CmsEntryWizard/Extension.js.map +1 -0
- package/admin/presentation/ProjectsSettings.js +4 -4
- package/admin/presentation/ProjectsSettings.js.map +1 -1
- package/admin/presentation/ProvidersSettings.js +1 -1
- package/admin/presentation/ProvidersSettings.js.map +1 -1
- package/admin/presentation/WbContentGeneration/GenerateContentDialog.d.ts +2 -2
- package/admin/presentation/WbContentGeneration/GenerateContentDialog.js +2 -2
- package/admin/presentation/WbContentGeneration/GenerateContentDialog.js.map +1 -1
- package/admin/presentation/WbContentGeneration/GenerateContentPresenter.d.ts +4 -12
- package/admin/presentation/WbContentGeneration/GenerateContentPresenter.js +12 -94
- package/admin/presentation/WbContentGeneration/GenerateContentPresenter.js.map +1 -1
- package/api/Extension.js +13 -3
- package/api/Extension.js.map +1 -1
- package/api/features/AiChatProvider/PowerUpsAiChatProvider.d.ts +24 -0
- package/api/features/AiChatProvider/PowerUpsAiChatProvider.js +31 -0
- package/api/features/AiChatProvider/PowerUpsAiChatProvider.js.map +1 -0
- package/api/features/AiChatProvider/feature.d.ts +9 -0
- package/api/features/AiChatProvider/feature.js +11 -0
- package/api/features/AiChatProvider/feature.js.map +1 -0
- package/api/features/AiChatProvider/index.d.ts +2 -0
- package/api/features/AiChatProvider/index.js +2 -0
- package/api/features/AiImageEnrichment/AiImageEnrichmentStreamRoute.d.ts +36 -0
- package/api/features/AiImageEnrichment/AiImageEnrichmentStreamRoute.js +85 -0
- package/api/features/AiImageEnrichment/AiImageEnrichmentStreamRoute.js.map +1 -0
- package/api/features/AiImageEnrichment/AiImageEnrichmentTask.d.ts +10 -14
- package/api/features/AiImageEnrichment/AiImageEnrichmentTask.js +27 -100
- package/api/features/AiImageEnrichment/AiImageEnrichmentTask.js.map +1 -1
- package/api/features/AiImageEnrichment/ApplyImageEnrichmentUseCase.d.ts +18 -0
- package/api/features/AiImageEnrichment/ApplyImageEnrichmentUseCase.js +50 -0
- package/api/features/AiImageEnrichment/ApplyImageEnrichmentUseCase.js.map +1 -0
- package/api/features/AiImageEnrichment/PrepareImageEnrichmentUseCase.d.ts +19 -0
- package/api/features/AiImageEnrichment/PrepareImageEnrichmentUseCase.js +49 -0
- package/api/features/AiImageEnrichment/PrepareImageEnrichmentUseCase.js.map +1 -0
- package/api/features/AiImageEnrichment/abstractions.d.ts +60 -0
- package/api/features/AiImageEnrichment/abstractions.js +12 -0
- package/api/features/AiImageEnrichment/abstractions.js.map +1 -0
- package/api/features/AiImageEnrichment/buildEnrichmentAiRequest.d.ts +12 -0
- package/api/features/AiImageEnrichment/buildEnrichmentAiRequest.js +30 -0
- package/api/features/AiImageEnrichment/buildEnrichmentAiRequest.js.map +1 -0
- package/api/features/AiImageEnrichment/errors.d.ts +26 -0
- package/api/features/AiImageEnrichment/errors.js +28 -0
- package/api/features/AiImageEnrichment/errors.js.map +1 -0
- package/api/features/AiImageEnrichment/feature.js +9 -0
- package/api/features/AiImageEnrichment/feature.js.map +1 -1
- package/api/features/AiImageEnrichment/imageEnrichmentErrorStatusCode.d.ts +6 -0
- package/api/features/AiImageEnrichment/imageEnrichmentErrorStatusCode.js +9 -0
- package/api/features/AiImageEnrichment/imageEnrichmentErrorStatusCode.js.map +1 -0
- package/api/features/AiImageEnrichment/readEnrichmentPartial.d.ts +8 -0
- package/api/features/AiImageEnrichment/readEnrichmentPartial.js +16 -0
- package/api/features/AiImageEnrichment/readEnrichmentPartial.js.map +1 -0
- package/api/features/AiImageEnrichment/streamEvents.d.ts +36 -0
- package/api/features/AiImageEnrichment/streamEvents.js +0 -0
- package/api/features/AiPromptContext/AiPromptContextBuilder.d.ts +8 -1
- package/api/features/AiPromptContext/AiPromptContextBuilder.js +46 -2
- package/api/features/AiPromptContext/AiPromptContextBuilder.js.map +1 -1
- package/api/features/AiPromptContext/abstractions.d.ts +3 -0
- package/api/features/AiPromptContext/abstractions.js +9 -1
- package/api/features/AiPromptContext/abstractions.js.map +1 -1
- package/api/features/AiPromptContext/index.d.ts +1 -1
- package/api/features/AiPromptContext/index.js +1 -1
- package/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.d.ts +22 -0
- package/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.js +136 -0
- package/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.js.map +1 -0
- package/api/features/CmsCompareEntryRevisions/abstractions.d.ts +18 -0
- package/api/features/CmsCompareEntryRevisions/abstractions.js +5 -0
- package/api/features/CmsCompareEntryRevisions/abstractions.js.map +1 -0
- package/api/features/CmsCompareEntryRevisions/feature.d.ts +4 -0
- package/api/features/CmsCompareEntryRevisions/feature.js +11 -0
- package/api/features/CmsCompareEntryRevisions/feature.js.map +1 -0
- package/api/features/CmsCompareEntryRevisions/index.d.ts +2 -0
- package/api/features/CmsCompareEntryRevisions/index.js +2 -0
- package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentTask.d.ts +33 -0
- package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentTask.js +84 -0
- package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentTask.js.map +1 -0
- package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.d.ts +29 -0
- package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.js +141 -0
- package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.js.map +1 -0
- package/api/features/CmsGenerateEntryContent/abstractions.d.ts +36 -0
- package/api/features/CmsGenerateEntryContent/abstractions.js +5 -0
- package/api/features/CmsGenerateEntryContent/abstractions.js.map +1 -0
- package/api/features/CmsGenerateEntryContent/buildPrompt.d.ts +2 -0
- package/api/features/CmsGenerateEntryContent/buildPrompt.js +61 -0
- package/api/features/CmsGenerateEntryContent/buildPrompt.js.map +1 -0
- package/api/features/CmsGenerateEntryContent/feature.d.ts +4 -0
- package/api/features/CmsGenerateEntryContent/feature.js +13 -0
- package/api/features/CmsGenerateEntryContent/feature.js.map +1 -0
- package/api/features/CmsGenerateEntryContent/index.d.ts +1 -0
- package/api/features/CmsGenerateEntryContent/index.js +1 -0
- package/api/features/CmsGenerateEntryContent/injectDynamicZoneTypenames.d.ts +2 -0
- package/api/features/CmsGenerateEntryContent/injectDynamicZoneTypenames.js +30 -0
- package/api/features/CmsGenerateEntryContent/injectDynamicZoneTypenames.js.map +1 -0
- package/api/features/CmsResolveImageTool/CmsResolveImageTool.d.ts +14 -0
- package/api/features/CmsResolveImageTool/CmsResolveImageTool.js +27 -0
- package/api/features/CmsResolveImageTool/CmsResolveImageTool.js.map +1 -0
- package/api/features/CmsResolveImageTool/feature.d.ts +4 -0
- package/api/features/CmsResolveImageTool/feature.js +11 -0
- package/api/features/CmsResolveImageTool/feature.js.map +1 -0
- package/api/features/GetSettings/GetSettingsUseCase.d.ts +1 -1
- package/api/features/GetSettings/index.d.ts +1 -0
- package/api/features/GetSettings/index.js +1 -0
- package/api/features/Providers/ProvidersHandler.d.ts +1 -3
- package/api/features/Providers/ProvidersHandler.js +2 -15
- package/api/features/Providers/ProvidersHandler.js.map +1 -1
- package/api/features/Providers/types.d.ts +2 -2
- package/api/features/WbGeneratePageContent/WbGeneratePageContentTask.d.ts +4 -3
- package/api/features/WbGeneratePageContent/WbGeneratePageContentTask.js +25 -15
- package/api/features/WbGeneratePageContent/WbGeneratePageContentTask.js.map +1 -1
- package/api/features/WbGeneratePageContent/WbGeneratePageContentUseCase.js +4 -3
- package/api/features/WbGeneratePageContent/WbGeneratePageContentUseCase.js.map +1 -1
- package/api/features/WbGeneratePageContent/abstractions.d.ts +1 -0
- package/api/features/WbGeneratePageContent/abstractions.js.map +1 -1
- package/api/features/WbTranslatePage/LexicalParser.d.ts +10 -0
- package/api/features/WbTranslatePage/LexicalParser.js +37 -0
- package/api/features/WbTranslatePage/LexicalParser.js.map +1 -0
- package/api/features/WbTranslatePage/WbTranslatePageDecorator.d.ts +27 -0
- package/api/features/WbTranslatePage/WbTranslatePageDecorator.js +134 -0
- package/api/features/WbTranslatePage/WbTranslatePageDecorator.js.map +1 -0
- package/api/features/WbTranslatePage/abstractions/LexicalParser.d.ts +7 -0
- package/api/features/WbTranslatePage/abstractions/LexicalParser.js +5 -0
- package/api/features/WbTranslatePage/abstractions/LexicalParser.js.map +1 -0
- package/api/features/WbTranslatePage/feature.d.ts +4 -0
- package/api/features/WbTranslatePage/feature.js +13 -0
- package/api/features/WbTranslatePage/feature.js.map +1 -0
- package/api/features/WbTranslatePage/index.d.ts +2 -0
- package/api/features/WbTranslatePage/index.js +2 -0
- package/api/graphql/BaseGraphQLSchema.d.ts +2 -2
- package/api/graphql/BaseGraphQLSchema.js +45 -6
- package/api/graphql/BaseGraphQLSchema.js.map +1 -1
- package/api/graphql/CmsCompareEntryRevisionsSchema.d.ts +8 -0
- package/api/graphql/CmsCompareEntryRevisionsSchema.js +68 -0
- package/api/graphql/CmsCompareEntryRevisionsSchema.js.map +1 -0
- package/exports/admin/ai-powerups.d.ts +1 -0
- package/exports/admin/ai-powerups.js +1 -0
- package/exports/api/ai-powerups.d.ts +2 -0
- package/exports/api/ai-powerups.js +2 -0
- package/package.json +33 -25
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { stepCountIs } from "ai";
|
|
2
|
+
import { Result } from "@webiny/feature/api";
|
|
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
|
+
import { ListTagsUseCase } from "@webiny/api-file-manager/features/file/ListTags/index.js";
|
|
6
|
+
import { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
|
|
7
|
+
import { ModelToAstConverter } from "@webiny/api-headless-cms/features/contentModel/ModelToAstConverter/index.js";
|
|
8
|
+
import { CmsModelToJsonSchemaConverter } from "@webiny/api-headless-cms/utils/contentModelToJsonSchema/index.js";
|
|
9
|
+
import { GetSettingsUseCase } from "../GetSettings/index.js";
|
|
10
|
+
import { AiPromptContextBuilder, formatAdditionalFilesContext } from "../AiPromptContext/index.js";
|
|
11
|
+
import { createReadProjectFileTool } from "../AiPromptContext/ReadProjectFileTool.js";
|
|
12
|
+
import { CmsGenerateEntryContentUseCase } from "./abstractions.js";
|
|
13
|
+
import { buildEntryPrompt } from "./buildPrompt.js";
|
|
14
|
+
import { LlmJsonResponse } from "../WbGeneratePageContent/LlmJsonResponse.js";
|
|
15
|
+
import { injectDynamicZoneTypenames } from "./injectDynamicZoneTypenames.js";
|
|
16
|
+
class CmsGenerateEntryContentUseCaseImpl {
|
|
17
|
+
constructor(promptContextBuilder, getSettings, ai, aiSdkTools, encryption, listTags, getModel, modelToAst, toolPipelineRunner){
|
|
18
|
+
this.promptContextBuilder = promptContextBuilder;
|
|
19
|
+
this.getSettings = getSettings;
|
|
20
|
+
this.ai = ai;
|
|
21
|
+
this.aiSdkTools = aiSdkTools;
|
|
22
|
+
this.encryption = encryption;
|
|
23
|
+
this.listTags = listTags;
|
|
24
|
+
this.getModel = getModel;
|
|
25
|
+
this.modelToAst = modelToAst;
|
|
26
|
+
this.toolPipelineRunner = toolPipelineRunner;
|
|
27
|
+
}
|
|
28
|
+
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."));
|
|
34
|
+
const modelResult = await this.getModel.execute(params.modelId);
|
|
35
|
+
if (modelResult.isFail()) return Result.fail(new Error(`Content model "${params.modelId}" not found.`));
|
|
36
|
+
const model = modelResult.value;
|
|
37
|
+
const modelAst = this.modelToAst.toAst(model);
|
|
38
|
+
const jsonSchemaConverter = new CmsModelToJsonSchemaConverter();
|
|
39
|
+
const entrySchema = jsonSchemaConverter.convert(modelAst, {
|
|
40
|
+
name: model.name,
|
|
41
|
+
description: model.description
|
|
42
|
+
});
|
|
43
|
+
const apiKey = await this.encryption.decrypt(firstProvider.apiKeyEncrypted);
|
|
44
|
+
const sdkTools = this.aiSdkTools.getToolSet();
|
|
45
|
+
const context = await this.promptContextBuilder.execute({
|
|
46
|
+
projectId: params.projectId,
|
|
47
|
+
readerPersonaId: params.readerPersonaId,
|
|
48
|
+
writerPersonaId: params.writerPersonaId,
|
|
49
|
+
excludedFileIds: params.excludedFileIds,
|
|
50
|
+
additionalFileIds: params.additionalFileIds
|
|
51
|
+
});
|
|
52
|
+
if (context.allProjectFiles.length > 0) {
|
|
53
|
+
const projectFileTool = createReadProjectFileTool(context.allProjectFiles, context.excludedFileIds);
|
|
54
|
+
Object.assign(sdkTools, projectFileTool);
|
|
55
|
+
}
|
|
56
|
+
const tagsResult = await this.listTags.execute({
|
|
57
|
+
where: {
|
|
58
|
+
type_startsWith: "image/"
|
|
59
|
+
},
|
|
60
|
+
limit: 100
|
|
61
|
+
});
|
|
62
|
+
const imageTags = tagsResult.isOk() ? tagsResult.value.map((t)=>t.tag) : [];
|
|
63
|
+
const systemText = buildEntryPrompt(model.name, entrySchema, imageTags) + context.toString();
|
|
64
|
+
const system = {
|
|
65
|
+
role: "system",
|
|
66
|
+
content: systemText,
|
|
67
|
+
providerOptions: {
|
|
68
|
+
anthropic: {
|
|
69
|
+
cacheControl: {
|
|
70
|
+
type: "ephemeral"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
try {
|
|
76
|
+
const aiResult = await this.ai.generateText({
|
|
77
|
+
model: firstProvider.model,
|
|
78
|
+
connection: {
|
|
79
|
+
sdkName: firstProvider.model.split("/")[0],
|
|
80
|
+
apiKey
|
|
81
|
+
},
|
|
82
|
+
system,
|
|
83
|
+
toolChoice: "auto",
|
|
84
|
+
prompt: params.prompt + formatAdditionalFilesContext(context.additionalFiles),
|
|
85
|
+
...Object.keys(sdkTools).length > 0 ? {
|
|
86
|
+
tools: sdkTools,
|
|
87
|
+
stopWhen: stepCountIs(20)
|
|
88
|
+
} : {}
|
|
89
|
+
});
|
|
90
|
+
const text = aiResult.text || (aiResult.steps.filter((step)=>step.text.length > 0).pop()?.text ?? "");
|
|
91
|
+
const entry = LlmJsonResponse.fromRawText(text).toArray().pop();
|
|
92
|
+
let resolved;
|
|
93
|
+
if (entry) {
|
|
94
|
+
resolved = await this.toolPipelineRunner.resolve(entry);
|
|
95
|
+
await injectDynamicZoneTypenames(resolved, modelAst, model.singularApiName);
|
|
96
|
+
}
|
|
97
|
+
const filesRead = new Set();
|
|
98
|
+
let toolCallsMade = 0;
|
|
99
|
+
for (const step of aiResult.steps)for (const call of step.toolCalls){
|
|
100
|
+
toolCallsMade++;
|
|
101
|
+
if ("read_project_file" === call.toolName) {
|
|
102
|
+
const input = call.input;
|
|
103
|
+
if (input.fileId) filesRead.add(input.fileId);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const telemetry = {
|
|
107
|
+
filesRead: [
|
|
108
|
+
...filesRead
|
|
109
|
+
],
|
|
110
|
+
cacheHit: context.cacheHit,
|
|
111
|
+
toolCallsMade,
|
|
112
|
+
totalSteps: aiResult.steps.length,
|
|
113
|
+
toolsAvailable: Object.keys(sdkTools),
|
|
114
|
+
imageTagsInPrompt: imageTags
|
|
115
|
+
};
|
|
116
|
+
return Result.ok({
|
|
117
|
+
values: resolved ?? {},
|
|
118
|
+
telemetry
|
|
119
|
+
});
|
|
120
|
+
} catch (error) {
|
|
121
|
+
return Result.fail(new Error(`AI generation failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const CmsGenerateEntryContentUseCaseImplementation = CmsGenerateEntryContentUseCase.createImplementation({
|
|
126
|
+
implementation: CmsGenerateEntryContentUseCaseImpl,
|
|
127
|
+
dependencies: [
|
|
128
|
+
AiPromptContextBuilder,
|
|
129
|
+
GetSettingsUseCase,
|
|
130
|
+
Ai,
|
|
131
|
+
AiSdkTools,
|
|
132
|
+
Encryption,
|
|
133
|
+
ListTagsUseCase,
|
|
134
|
+
GetModelUseCase,
|
|
135
|
+
ModelToAstConverter,
|
|
136
|
+
AiToolPipelineRunner
|
|
137
|
+
]
|
|
138
|
+
});
|
|
139
|
+
export { CmsGenerateEntryContentUseCaseImplementation };
|
|
140
|
+
|
|
141
|
+
//# sourceMappingURL=CmsGenerateEntryContentUseCase.js.map
|
|
@@ -0,0 +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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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Result } from "@webiny/feature/api";
|
|
2
|
+
export interface CmsGenerateEntryContentParams {
|
|
3
|
+
prompt: string;
|
|
4
|
+
modelId: string;
|
|
5
|
+
projectId?: string | null;
|
|
6
|
+
excludedFileIds?: string[] | null;
|
|
7
|
+
readerPersonaId?: string | null;
|
|
8
|
+
writerPersonaId?: string | null;
|
|
9
|
+
additionalFileIds?: string[] | null;
|
|
10
|
+
}
|
|
11
|
+
export interface GenerateEntryContentTelemetry {
|
|
12
|
+
filesRead: string[];
|
|
13
|
+
cacheHit: boolean;
|
|
14
|
+
toolCallsMade: number;
|
|
15
|
+
totalSteps: number;
|
|
16
|
+
toolsAvailable: string[];
|
|
17
|
+
imageTagsInPrompt: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface GenerateEntryContentResult<TValues = Record<string, any>> {
|
|
20
|
+
/**
|
|
21
|
+
* The generated entry values, keyed by fieldId. Callers that consume the result
|
|
22
|
+
* directly (e.g. a bulk action) can read fields straight off this object; transport
|
|
23
|
+
* edges (the background task / websocket stream) serialize it themselves. Pass a type
|
|
24
|
+
* argument to `execute` to shape this (e.g. `execute<{ aiSummary?: string }>`).
|
|
25
|
+
*/
|
|
26
|
+
values: TValues;
|
|
27
|
+
telemetry: GenerateEntryContentTelemetry;
|
|
28
|
+
}
|
|
29
|
+
export interface ICmsGenerateEntryContentUseCase {
|
|
30
|
+
execute<TValues = Record<string, any>>(params: CmsGenerateEntryContentParams): Promise<Result<GenerateEntryContentResult<TValues>, Error>>;
|
|
31
|
+
}
|
|
32
|
+
export declare const CmsGenerateEntryContentUseCase: import("@webiny/di").Abstraction<ICmsGenerateEntryContentUseCase>;
|
|
33
|
+
export declare namespace CmsGenerateEntryContentUseCase {
|
|
34
|
+
type Interface = ICmsGenerateEntryContentUseCase;
|
|
35
|
+
type Params = CmsGenerateEntryContentParams;
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/CmsGenerateEntryContent/abstractions.js","sources":["../../../../src/api/features/CmsGenerateEntryContent/abstractions.ts"],"sourcesContent":["import { createAbstraction, Result } from \"@webiny/feature/api\";\n\nexport interface CmsGenerateEntryContentParams {\n prompt: string;\n modelId: string;\n projectId?: string | null;\n excludedFileIds?: string[] | null;\n readerPersonaId?: string | null;\n writerPersonaId?: string | null;\n additionalFileIds?: string[] | null;\n}\n\nexport interface GenerateEntryContentTelemetry {\n filesRead: string[];\n cacheHit: boolean;\n toolCallsMade: number;\n totalSteps: number;\n toolsAvailable: string[];\n imageTagsInPrompt: string[];\n}\n\nexport interface GenerateEntryContentResult<TValues = Record<string, any>> {\n /**\n * The generated entry values, keyed by fieldId. Callers that consume the result\n * directly (e.g. a bulk action) can read fields straight off this object; transport\n * edges (the background task / websocket stream) serialize it themselves. Pass a type\n * argument to `execute` to shape this (e.g. `execute<{ aiSummary?: string }>`).\n */\n values: TValues;\n telemetry: GenerateEntryContentTelemetry;\n}\n\nexport interface ICmsGenerateEntryContentUseCase {\n execute<TValues = Record<string, any>>(\n params: CmsGenerateEntryContentParams\n ): Promise<Result<GenerateEntryContentResult<TValues>, Error>>;\n}\n\nexport const CmsGenerateEntryContentUseCase = createAbstraction<ICmsGenerateEntryContentUseCase>(\n \"AiPowerUpsCmsGenerateEntryContentUseCase\"\n);\n\nexport namespace CmsGenerateEntryContentUseCase {\n export type Interface = ICmsGenerateEntryContentUseCase;\n export type Params = CmsGenerateEntryContentParams;\n}\n"],"names":["CmsGenerateEntryContentUseCase","createAbstraction"],"mappings":";AAsCO,MAAMA,iCAAiCC,kBAC1C"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
function buildEntryPrompt(modelName, entrySchema, availableImageTags) {
|
|
2
|
+
const tagListing = availableImageTags.length > 0 ? availableImageTags.map((t)=>`\`${t}\``).join(", ") : "(no image tags available in the File Manager — image fields should be left empty or omitted)";
|
|
3
|
+
return `You are a CMS content entry generator. Given a user prompt, generate structured content for a "${modelName}" entry using the JSON Schema below.
|
|
4
|
+
|
|
5
|
+
### Rich Text Content
|
|
6
|
+
|
|
7
|
+
For rich text fields, wrap the value in a tool envelope:
|
|
8
|
+
\`\`\`json
|
|
9
|
+
{ "tool": "textToLexical", "params": { "text": "<html content>" } }
|
|
10
|
+
\`\`\`
|
|
11
|
+
|
|
12
|
+
Write the content as semantic HTML: use <h1>-<h6>, <p>, <strong>, <em>, <ul>, <ol>, <li>, <a>, <blockquote>.
|
|
13
|
+
A single rich text field CAN contain an entire article with all headings, paragraphs, lists, and blockquotes.
|
|
14
|
+
|
|
15
|
+
### Image Selection
|
|
16
|
+
|
|
17
|
+
You MUST call the \`listImagesByTag\` tool BEFORE using any image ID.
|
|
18
|
+
Do NOT invent image IDs. Any ID not returned by \`listImagesByTag\` will fail to resolve.
|
|
19
|
+
|
|
20
|
+
The File Manager currently has images tagged with: ${tagListing}.
|
|
21
|
+
|
|
22
|
+
When a field needs an image:
|
|
23
|
+
1. Pick the tag from the list above that best matches the content topic.
|
|
24
|
+
2. Call \`listImagesByTag\` with that tag.
|
|
25
|
+
3. If results are non-empty, wrap the image reference in a tool envelope:
|
|
26
|
+
\`{ "tool": "cmsResolveImage", "params": { "id": "<image_id_from_search>" } }\`
|
|
27
|
+
4. If results are empty, try one more tag. If still nothing, leave the field empty.
|
|
28
|
+
|
|
29
|
+
### File Fields
|
|
30
|
+
|
|
31
|
+
For file/image fields, always use the \`cmsResolveImage\` tool envelope with an ID obtained from \`listImagesByTag\`:
|
|
32
|
+
\`{ "tool": "cmsResolveImage", "params": { "id": "<file_id>" } }\`
|
|
33
|
+
|
|
34
|
+
### Reference Fields
|
|
35
|
+
|
|
36
|
+
Reference fields expect \`{ "entryId": "<id>", "modelId": "<model>" }\`. If you don't have real entry IDs, leave reference fields empty or use placeholder values.
|
|
37
|
+
|
|
38
|
+
### SEO & Content Best Practices
|
|
39
|
+
|
|
40
|
+
- Use exactly ONE <h1> per rich text field as the main title.
|
|
41
|
+
- Use <h2> for sections, <h3> for subsections. Never skip heading levels.
|
|
42
|
+
- Keep paragraphs short — 2 to 4 sentences.
|
|
43
|
+
- Lead with the most important information first.
|
|
44
|
+
- Incorporate topic keywords naturally without stuffing.
|
|
45
|
+
|
|
46
|
+
### Entry Schema
|
|
47
|
+
|
|
48
|
+
The entry must conform to this JSON Schema:
|
|
49
|
+
|
|
50
|
+
\`\`\`json
|
|
51
|
+
${JSON.stringify(entrySchema, null, 2)}
|
|
52
|
+
\`\`\`
|
|
53
|
+
|
|
54
|
+
You MUST generate the full entry content as JSON after using any tools.
|
|
55
|
+
Tool calls are for gathering information — your final response must always be the complete entry JSON object.
|
|
56
|
+
|
|
57
|
+
IMPORTANT: You MUST return a parsable JSON object conforming to the schema above. No extra text outside the JSON.`;
|
|
58
|
+
}
|
|
59
|
+
export { buildEntryPrompt };
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=buildPrompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/CmsGenerateEntryContent/buildPrompt.js","sources":["../../../../src/api/features/CmsGenerateEntryContent/buildPrompt.ts"],"sourcesContent":["import type { JsonSchema } from \"@webiny/api-headless-cms/utils/contentModelToJsonSchema/types.js\";\n\nexport function buildEntryPrompt(\n modelName: string,\n entrySchema: JsonSchema,\n availableImageTags: string[]\n): string {\n const tagListing =\n availableImageTags.length > 0\n ? availableImageTags.map(t => `\\`${t}\\``).join(\", \")\n : \"(no image tags available in the File Manager — image fields should be left empty or omitted)\";\n\n return `You are a CMS content entry generator. Given a user prompt, generate structured content for a \"${modelName}\" entry using the JSON Schema below.\n\n### Rich Text Content\n\nFor rich text fields, wrap the value in a tool envelope:\n\\`\\`\\`json\n{ \"tool\": \"textToLexical\", \"params\": { \"text\": \"<html content>\" } }\n\\`\\`\\`\n\nWrite the content as semantic HTML: use <h1>-<h6>, <p>, <strong>, <em>, <ul>, <ol>, <li>, <a>, <blockquote>.\nA single rich text field CAN contain an entire article with all headings, paragraphs, lists, and blockquotes.\n\n### Image Selection\n\nYou MUST call the \\`listImagesByTag\\` tool BEFORE using any image ID.\nDo NOT invent image IDs. Any ID not returned by \\`listImagesByTag\\` will fail to resolve.\n\nThe File Manager currently has images tagged with: ${tagListing}.\n\nWhen a field needs an image:\n1. Pick the tag from the list above that best matches the content topic.\n2. Call \\`listImagesByTag\\` with that tag.\n3. If results are non-empty, wrap the image reference in a tool envelope:\n \\`{ \"tool\": \"cmsResolveImage\", \"params\": { \"id\": \"<image_id_from_search>\" } }\\`\n4. If results are empty, try one more tag. If still nothing, leave the field empty.\n\n### File Fields\n\nFor file/image fields, always use the \\`cmsResolveImage\\` tool envelope with an ID obtained from \\`listImagesByTag\\`:\n\\`{ \"tool\": \"cmsResolveImage\", \"params\": { \"id\": \"<file_id>\" } }\\`\n\n### Reference Fields\n\nReference fields expect \\`{ \"entryId\": \"<id>\", \"modelId\": \"<model>\" }\\`. If you don't have real entry IDs, leave reference fields empty or use placeholder values.\n\n### SEO & Content Best Practices\n\n- Use exactly ONE <h1> per rich text field as the main title.\n- Use <h2> for sections, <h3> for subsections. Never skip heading levels.\n- Keep paragraphs short — 2 to 4 sentences.\n- Lead with the most important information first.\n- Incorporate topic keywords naturally without stuffing.\n\n### Entry Schema\n\nThe entry must conform to this JSON Schema:\n\n\\`\\`\\`json\n${JSON.stringify(entrySchema, null, 2)}\n\\`\\`\\`\n\nYou MUST generate the full entry content as JSON after using any tools.\nTool calls are for gathering information — your final response must always be the complete entry JSON object.\n\nIMPORTANT: You MUST return a parsable JSON object conforming to the schema above. No extra text outside the JSON.`;\n}\n"],"names":["buildEntryPrompt","modelName","entrySchema","availableImageTags","tagListing","t","JSON"],"mappings":"AAEO,SAASA,iBACZC,SAAiB,EACjBC,WAAuB,EACvBC,kBAA4B;IAE5B,MAAMC,aACFD,mBAAmB,MAAM,GAAG,IACtBA,mBAAmB,GAAG,CAACE,CAAAA,IAAK,CAAC,EAAE,EAAEA,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,QAC7C;IAEV,OAAO,CAAC,+FAA+F,EAAEJ,UAAU;;;;;;;;;;;;;;;;;mDAiBpE,EAAEG,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BhE,EAAEE,KAAK,SAAS,CAACJ,aAAa,MAAM,GAAG;;;;;;iHAM0E,CAAC;AAClH"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createFeature } from "@webiny/feature/api";
|
|
2
|
+
import { CmsGenerateEntryContentUseCaseImplementation } from "./CmsGenerateEntryContentUseCase.js";
|
|
3
|
+
import { CmsGenerateEntryContentTask } from "./CmsGenerateEntryContentTask.js";
|
|
4
|
+
const CmsGenerateEntryContentFeature = createFeature({
|
|
5
|
+
name: "AiPowerUps/CmsGenerateEntryContent",
|
|
6
|
+
register (container) {
|
|
7
|
+
container.register(CmsGenerateEntryContentUseCaseImplementation);
|
|
8
|
+
container.register(CmsGenerateEntryContentTask);
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
export { CmsGenerateEntryContentFeature };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=feature.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { CmsGenerateEntryContentUseCase } from "./abstractions.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { CmsGenerateEntryContentUseCase } from "./abstractions.js";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ContentEntryTraverser } from "@webiny/api-headless-cms/features/contentEntry/ContentEntryTraverser/ContentEntryTraverser.js";
|
|
2
|
+
import { createTypeName } from "@webiny/api-headless-cms/utils/createTypeName.js";
|
|
3
|
+
async function injectDynamicZoneTypenames(values, modelAst, singularApiName) {
|
|
4
|
+
const traverser = new ContentEntryTraverser(modelAst);
|
|
5
|
+
const graphQLTypeMap = new Map();
|
|
6
|
+
graphQLTypeMap.set("", singularApiName);
|
|
7
|
+
await traverser.traverse(values, async ({ field, value, path })=>{
|
|
8
|
+
if ("dynamicZone" !== field.type || null == value) return;
|
|
9
|
+
const pathParts = path.split(".");
|
|
10
|
+
const parentPrefix = pathParts.slice(0, -1).join(".");
|
|
11
|
+
const enclosingType = graphQLTypeMap.get(parentPrefix) || singularApiName;
|
|
12
|
+
const typeName = `${enclosingType}_${createTypeName(field.fieldId)}`;
|
|
13
|
+
const templates = field.settings?.templates || [];
|
|
14
|
+
const items = field.list && Array.isArray(value) ? value : [
|
|
15
|
+
value
|
|
16
|
+
];
|
|
17
|
+
for(let i = 0; i < items.length; i++){
|
|
18
|
+
const item = items[i];
|
|
19
|
+
if (!item || !item._templateId) continue;
|
|
20
|
+
const template = templates.find((t)=>t.id === item._templateId);
|
|
21
|
+
if (!template) continue;
|
|
22
|
+
item.__typename = `${typeName}_${template.gqlTypeName}`;
|
|
23
|
+
const itemPath = field.list ? `${path}.${i}` : path;
|
|
24
|
+
graphQLTypeMap.set(itemPath, item.__typename);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
export { injectDynamicZoneTypenames };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=injectDynamicZoneTypenames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/CmsGenerateEntryContent/injectDynamicZoneTypenames.js","sources":["../../../../src/api/features/CmsGenerateEntryContent/injectDynamicZoneTypenames.ts"],"sourcesContent":["import type { CmsModelAst } from \"@webiny/api-headless-cms/types\";\nimport { ContentEntryTraverser } from \"@webiny/api-headless-cms/features/contentEntry/ContentEntryTraverser/ContentEntryTraverser.js\";\nimport { createTypeName } from \"@webiny/api-headless-cms/utils/createTypeName.js\";\n\ninterface DynamicZoneTemplate {\n id: string;\n gqlTypeName: string;\n}\n\nexport async function injectDynamicZoneTypenames(\n values: Record<string, any>,\n modelAst: CmsModelAst,\n singularApiName: string\n): Promise<void> {\n const traverser = new ContentEntryTraverser(modelAst);\n\n const graphQLTypeMap = new Map<string, string>();\n graphQLTypeMap.set(\"\", singularApiName);\n\n await traverser.traverse(values, async ({ field, value, path }) => {\n if (field.type !== \"dynamicZone\" || value == null) {\n return;\n }\n\n const pathParts = path.split(\".\");\n const parentPrefix = pathParts.slice(0, -1).join(\".\");\n const enclosingType = graphQLTypeMap.get(parentPrefix) || singularApiName;\n const typeName = `${enclosingType}_${createTypeName(field.fieldId)}`;\n\n const templates: DynamicZoneTemplate[] = field.settings?.templates || [];\n const items: Record<string, any>[] = field.list && Array.isArray(value) ? value : [value];\n\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (!item || !item._templateId) {\n continue;\n }\n\n const template = templates.find(t => t.id === item._templateId);\n if (!template) {\n continue;\n }\n\n item.__typename = `${typeName}_${template.gqlTypeName}`;\n\n const itemPath = field.list ? `${path}.${i}` : path;\n graphQLTypeMap.set(itemPath, item.__typename);\n }\n });\n}\n"],"names":["injectDynamicZoneTypenames","values","modelAst","singularApiName","traverser","ContentEntryTraverser","graphQLTypeMap","Map","field","value","path","pathParts","parentPrefix","enclosingType","typeName","createTypeName","templates","items","Array","i","item","template","t","itemPath"],"mappings":";;AASO,eAAeA,2BAClBC,MAA2B,EAC3BC,QAAqB,EACrBC,eAAuB;IAEvB,MAAMC,YAAY,IAAIC,sBAAsBH;IAE5C,MAAMI,iBAAiB,IAAIC;IAC3BD,eAAe,GAAG,CAAC,IAAIH;IAEvB,MAAMC,UAAU,QAAQ,CAACH,QAAQ,OAAO,EAAEO,KAAK,EAAEC,KAAK,EAAEC,IAAI,EAAE;QAC1D,IAAIF,AAAe,kBAAfA,MAAM,IAAI,IAAsBC,AAAS,QAATA,OAChC;QAGJ,MAAME,YAAYD,KAAK,KAAK,CAAC;QAC7B,MAAME,eAAeD,UAAU,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC;QACjD,MAAME,gBAAgBP,eAAe,GAAG,CAACM,iBAAiBT;QAC1D,MAAMW,WAAW,GAAGD,cAAc,CAAC,EAAEE,eAAeP,MAAM,OAAO,GAAG;QAEpE,MAAMQ,YAAmCR,MAAM,QAAQ,EAAE,aAAa,EAAE;QACxE,MAAMS,QAA+BT,MAAM,IAAI,IAAIU,MAAM,OAAO,CAACT,SAASA,QAAQ;YAACA;SAAM;QAEzF,IAAK,IAAIU,IAAI,GAAGA,IAAIF,MAAM,MAAM,EAAEE,IAAK;YACnC,MAAMC,OAAOH,KAAK,CAACE,EAAE;YACrB,IAAI,CAACC,QAAQ,CAACA,KAAK,WAAW,EAC1B;YAGJ,MAAMC,WAAWL,UAAU,IAAI,CAACM,CAAAA,IAAKA,EAAE,EAAE,KAAKF,KAAK,WAAW;YAC9D,IAAI,CAACC,UACD;YAGJD,KAAK,UAAU,GAAG,GAAGN,SAAS,CAAC,EAAEO,SAAS,WAAW,EAAE;YAEvD,MAAME,WAAWf,MAAM,IAAI,GAAG,GAAGE,KAAK,CAAC,EAAES,GAAG,GAAGT;YAC/CJ,eAAe,GAAG,CAACiB,UAAUH,KAAK,UAAU;QAChD;IACJ;AACJ"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AiOutputTool } from "@webiny/api-core/features/ai/index.js";
|
|
2
|
+
import { GetFileUseCase } from "@webiny/api-file-manager/features/file/GetFile/index.js";
|
|
3
|
+
import { FileUrlGenerator } from "@webiny/api-file-manager/features/file/FileUrlGenerator/index.js";
|
|
4
|
+
declare class CmsResolveImageToolImpl implements AiOutputTool.Interface {
|
|
5
|
+
private getFile;
|
|
6
|
+
private urlGenerator;
|
|
7
|
+
readonly name = "cmsResolveImage";
|
|
8
|
+
constructor(getFile: GetFileUseCase.Interface, urlGenerator: FileUrlGenerator.Interface);
|
|
9
|
+
execute(params: Record<string, unknown>): Promise<unknown>;
|
|
10
|
+
}
|
|
11
|
+
export declare const CmsResolveImageTool: typeof CmsResolveImageToolImpl & {
|
|
12
|
+
__abstraction: import("@webiny/di").Abstraction<import("@webiny/api-core/features/ai/toolPipeline").IAiOutputTool>;
|
|
13
|
+
};
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AiOutputTool } from "@webiny/api-core/features/ai/index.js";
|
|
2
|
+
import { GetFileUseCase } from "@webiny/api-file-manager/features/file/GetFile/index.js";
|
|
3
|
+
import { FileUrlGenerator } from "@webiny/api-file-manager/features/file/FileUrlGenerator/index.js";
|
|
4
|
+
class CmsResolveImageToolImpl {
|
|
5
|
+
constructor(getFile, urlGenerator){
|
|
6
|
+
this.getFile = getFile;
|
|
7
|
+
this.urlGenerator = urlGenerator;
|
|
8
|
+
this.name = "cmsResolveImage";
|
|
9
|
+
}
|
|
10
|
+
async execute(params) {
|
|
11
|
+
const id = params.id;
|
|
12
|
+
if ("string" != typeof id || !id) return null;
|
|
13
|
+
const result = await this.getFile.execute(id);
|
|
14
|
+
if (result.isFail()) return null;
|
|
15
|
+
return this.urlGenerator.generateUrl(result.value);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const CmsResolveImageTool = AiOutputTool.createImplementation({
|
|
19
|
+
implementation: CmsResolveImageToolImpl,
|
|
20
|
+
dependencies: [
|
|
21
|
+
GetFileUseCase,
|
|
22
|
+
FileUrlGenerator
|
|
23
|
+
]
|
|
24
|
+
});
|
|
25
|
+
export { CmsResolveImageTool };
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=CmsResolveImageTool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/CmsResolveImageTool/CmsResolveImageTool.js","sources":["../../../../src/api/features/CmsResolveImageTool/CmsResolveImageTool.ts"],"sourcesContent":["import { AiOutputTool } from \"@webiny/api-core/features/ai/index.js\";\nimport { GetFileUseCase } from \"@webiny/api-file-manager/features/file/GetFile/index.js\";\nimport { FileUrlGenerator } from \"@webiny/api-file-manager/features/file/FileUrlGenerator/index.js\";\n\nclass CmsResolveImageToolImpl implements AiOutputTool.Interface {\n readonly name = \"cmsResolveImage\";\n\n constructor(\n private getFile: GetFileUseCase.Interface,\n private urlGenerator: FileUrlGenerator.Interface\n ) {}\n\n async execute(params: Record<string, unknown>): Promise<unknown> {\n const id = params.id;\n if (typeof id !== \"string\" || !id) {\n return null;\n }\n\n const result = await this.getFile.execute(id);\n if (result.isFail()) {\n return null;\n }\n\n return this.urlGenerator.generateUrl(result.value);\n }\n}\n\nexport const CmsResolveImageTool = AiOutputTool.createImplementation({\n implementation: CmsResolveImageToolImpl,\n dependencies: [GetFileUseCase, FileUrlGenerator]\n});\n"],"names":["CmsResolveImageToolImpl","getFile","urlGenerator","params","id","result","CmsResolveImageTool","AiOutputTool","GetFileUseCase","FileUrlGenerator"],"mappings":";;;AAIA,MAAMA;IAGF,YACYC,OAAiC,EACjCC,YAAwC,CAClD;aAFUD,OAAO,GAAPA;aACAC,YAAY,GAAZA;aAJH,IAAI,GAAG;IAKb;IAEH,MAAM,QAAQC,MAA+B,EAAoB;QAC7D,MAAMC,KAAKD,OAAO,EAAE;QACpB,IAAI,AAAc,YAAd,OAAOC,MAAmB,CAACA,IAC3B,OAAO;QAGX,MAAMC,SAAS,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAACD;QAC1C,IAAIC,OAAO,MAAM,IACb,OAAO;QAGX,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAACA,OAAO,KAAK;IACrD;AACJ;AAEO,MAAMC,sBAAsBC,aAAa,oBAAoB,CAAC;IACjE,gBAAgBP;IAChB,cAAc;QAACQ;QAAgBC;KAAiB;AACpD"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createFeature } from "@webiny/feature/api";
|
|
2
|
+
import { CmsResolveImageTool } from "./CmsResolveImageTool.js";
|
|
3
|
+
const CmsResolveImageToolFeature = createFeature({
|
|
4
|
+
name: "AiPowerUps/CmsResolveImageTool",
|
|
5
|
+
register (container) {
|
|
6
|
+
container.register(CmsResolveImageTool);
|
|
7
|
+
}
|
|
8
|
+
});
|
|
9
|
+
export { CmsResolveImageToolFeature };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=feature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/CmsResolveImageTool/feature.js","sources":["../../../../src/api/features/CmsResolveImageTool/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { CmsResolveImageTool } from \"./CmsResolveImageTool.js\";\n\nexport const CmsResolveImageToolFeature = createFeature({\n name: \"AiPowerUps/CmsResolveImageTool\",\n register(container) {\n container.register(CmsResolveImageTool);\n }\n});\n"],"names":["CmsResolveImageToolFeature","createFeature","container","CmsResolveImageTool"],"mappings":";;AAGO,MAAMA,6BAA6BC,cAAc;IACpD,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;IACvB;AACJ"}
|
|
@@ -2,7 +2,7 @@ import { GetSettingsUseCase, GetSettingsRepository } from "./abstractions.js";
|
|
|
2
2
|
declare class GetSettingsUseCaseImpl implements GetSettingsUseCase.Interface {
|
|
3
3
|
private repository;
|
|
4
4
|
constructor(repository: GetSettingsRepository.Interface);
|
|
5
|
-
execute(): Promise<import("@webiny/feature/api").Result<import("~/api/types.js").IAiPowerUpsSettings, never>>;
|
|
5
|
+
execute(): Promise<import("@webiny/feature/api/Result.js").Result<import("~/api/types.js").IAiPowerUpsSettings, never>>;
|
|
6
6
|
}
|
|
7
7
|
export declare const GetSettingsUseCaseImplementation: typeof GetSettingsUseCaseImpl & {
|
|
8
8
|
__abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").IGetSettingsUseCase>;
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { Encryption } from "@webiny/api-core/features/encryption/index.js";
|
|
3
3
|
import { Masker } from "@webiny/api-core/features/masker/index.js";
|
|
4
|
-
import { AiModelRegistry } from "@webiny/api-core/features/ai/index.js";
|
|
5
4
|
import { AiPowerUpsSettingsGroupHandler } from "../../../api/features/shared/index.js";
|
|
6
5
|
import type { PersistedProviders, ProvidersSettings } from "./types.js";
|
|
7
6
|
declare class ProvidersHandlerImpl implements AiPowerUpsSettingsGroupHandler.Interface {
|
|
8
7
|
private encryption;
|
|
9
8
|
private masker;
|
|
10
|
-
private modelRegistry;
|
|
11
9
|
readonly name = "providers";
|
|
12
10
|
readonly inputSchema: z.ZodObject<{
|
|
13
11
|
presets: z.ZodArray<z.ZodObject<{
|
|
@@ -18,7 +16,7 @@ declare class ProvidersHandlerImpl implements AiPowerUpsSettingsGroupHandler.Int
|
|
|
18
16
|
apiKey: z.ZodOptional<z.ZodString>;
|
|
19
17
|
}, z.core.$strip>>;
|
|
20
18
|
}, z.core.$strip>;
|
|
21
|
-
constructor(encryption: Encryption.Interface, masker: Masker.Interface
|
|
19
|
+
constructor(encryption: Encryption.Interface, masker: Masker.Interface);
|
|
22
20
|
mapFromStorage(persisted: unknown): ProvidersSettings;
|
|
23
21
|
mapToStorage(internal: unknown, existing: unknown | null): Promise<PersistedProviders>;
|
|
24
22
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { Encryption } from "@webiny/api-core/features/encryption/index.js";
|
|
3
3
|
import { Masker } from "@webiny/api-core/features/masker/index.js";
|
|
4
|
-
import { AiModelRegistry } from "@webiny/api-core/features/ai/index.js";
|
|
5
4
|
import { AiPowerUpsSettingsGroupHandler } from "../shared/index.js";
|
|
6
5
|
const inputSchema = z.object({
|
|
7
6
|
presets: z.array(z.object({
|
|
@@ -13,10 +12,9 @@ const inputSchema = z.object({
|
|
|
13
12
|
}))
|
|
14
13
|
});
|
|
15
14
|
class ProvidersHandlerImpl {
|
|
16
|
-
constructor(encryption, masker
|
|
15
|
+
constructor(encryption, masker){
|
|
17
16
|
this.encryption = encryption;
|
|
18
17
|
this.masker = masker;
|
|
19
|
-
this.modelRegistry = modelRegistry;
|
|
20
18
|
this.name = "providers";
|
|
21
19
|
this.inputSchema = inputSchema;
|
|
22
20
|
}
|
|
@@ -41,16 +39,6 @@ class ProvidersHandlerImpl {
|
|
|
41
39
|
const input = internal;
|
|
42
40
|
const existingData = existing;
|
|
43
41
|
const existingPresets = existingData?.presets ?? [];
|
|
44
|
-
const availableModels = await this.modelRegistry.listModels();
|
|
45
|
-
for (const preset of input.presets){
|
|
46
|
-
if (!preset.model) continue;
|
|
47
|
-
const slashIndex = preset.model.indexOf("/");
|
|
48
|
-
if (-1 === slashIndex) throw new Error(`Invalid model ID "${preset.model}" in preset "${preset.name}". Expected format: "<providerId>/<modelId>".`);
|
|
49
|
-
const providerId = preset.model.slice(0, slashIndex);
|
|
50
|
-
const modelId = preset.model.slice(slashIndex + 1);
|
|
51
|
-
const found = availableModels.some((m)=>m.providerId === providerId && m.modelId === modelId);
|
|
52
|
-
if (!found) throw new Error(`Model "${preset.model}" in preset "${preset.name}" is not available. Use listModels() to see available models.`);
|
|
53
|
-
}
|
|
54
42
|
const presets = await Promise.all(input.presets.map(async (preset)=>{
|
|
55
43
|
const existingMatch = existingPresets.find((ep)=>ep.id === preset.id);
|
|
56
44
|
let apiKeyEncrypted;
|
|
@@ -83,8 +71,7 @@ const ProvidersHandler = AiPowerUpsSettingsGroupHandler.createImplementation({
|
|
|
83
71
|
implementation: ProvidersHandlerImpl,
|
|
84
72
|
dependencies: [
|
|
85
73
|
Encryption,
|
|
86
|
-
Masker
|
|
87
|
-
AiModelRegistry
|
|
74
|
+
Masker
|
|
88
75
|
]
|
|
89
76
|
});
|
|
90
77
|
export default ProvidersHandler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api/features/Providers/ProvidersHandler.js","sources":["../../../../src/api/features/Providers/ProvidersHandler.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 {
|
|
1
|
+
{"version":3,"file":"api/features/Providers/ProvidersHandler.js","sources":["../../../../src/api/features/Providers/ProvidersHandler.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 type { PersistedProviderPreset, PersistedProviders, ProvidersSettings } 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 description: z.string().optional(),\n model: z.string().min(1),\n apiKey: z.string().optional()\n })\n )\n});\n\nclass ProvidersHandlerImpl implements AiPowerUpsSettingsGroupHandler.Interface {\n readonly name = \"providers\";\n readonly inputSchema = inputSchema;\n\n constructor(\n private encryption: Encryption.Interface,\n private masker: Masker.Interface\n ) {}\n\n mapFromStorage(persisted: unknown): ProvidersSettings {\n if (!persisted || typeof persisted !== \"object\") {\n return { presets: [] };\n }\n\n const data = persisted as PersistedProviders;\n const presets = (data.presets ?? []).map(p => ({\n id: p.id,\n name: p.name,\n description: p.description,\n model: p.model,\n apiKeyMasked: p.apiKeyMasked ?? \"\",\n apiKeyEncrypted: p.apiKeyEncrypted ?? \"\"\n }));\n\n return { presets };\n }\n\n async mapToStorage(internal: unknown, existing: unknown | null): Promise<PersistedProviders> {\n const input = internal as ProvidersSettings;\n const existingData = existing as ProvidersSettings | null;\n const existingPresets = existingData?.presets ?? [];\n\n const presets: PersistedProviderPreset[] = 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 // Carry forward existing encrypted key\n apiKeyEncrypted = existingMatch?.apiKeyEncrypted ?? \"\";\n apiKeyMasked = existingMatch?.apiKeyMasked ?? \"\";\n } else {\n // New plaintext key — encrypt and mask\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 description: preset.description,\n model: preset.model,\n apiKeyEncrypted,\n apiKeyMasked\n };\n })\n );\n\n return { presets };\n }\n}\n\nexport default AiPowerUpsSettingsGroupHandler.createImplementation({\n implementation: ProvidersHandlerImpl,\n dependencies: [Encryption, Masker]\n});\n"],"names":["inputSchema","z","ProvidersHandlerImpl","encryption","masker","persisted","data","presets","p","internal","existing","input","existingData","existingPresets","Promise","preset","existingMatch","ep","apiKeyEncrypted","apiKeyMasked","AiPowerUpsSettingsGroupHandler","Encryption","Masker"],"mappings":";;;;AAMA,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,aAAaA,EAAE,MAAM,GAAG,QAAQ;QAChC,OAAOA,EAAE,MAAM,GAAG,GAAG,CAAC;QACtB,QAAQA,EAAE,MAAM,GAAG,QAAQ;IAC/B;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,EAAqB;QAClD,IAAI,CAACA,aAAa,AAAqB,YAArB,OAAOA,WACrB,OAAO;YAAE,SAAS,EAAE;QAAC;QAGzB,MAAMC,OAAOD;QACb,MAAME,UAAWD,AAAAA,CAAAA,KAAK,OAAO,IAAI,EAAC,EAAG,GAAG,CAACE,CAAAA,IAAM;gBAC3C,IAAIA,EAAE,EAAE;gBACR,MAAMA,EAAE,IAAI;gBACZ,aAAaA,EAAE,WAAW;gBAC1B,OAAOA,EAAE,KAAK;gBACd,cAAcA,EAAE,YAAY,IAAI;gBAChC,iBAAiBA,EAAE,eAAe,IAAI;YAC1C;QAEA,OAAO;YAAED;QAAQ;IACrB;IAEA,MAAM,aAAaE,QAAiB,EAAEC,QAAwB,EAA+B;QACzF,MAAMC,QAAQF;QACd,MAAMG,eAAeF;QACrB,MAAMG,kBAAkBD,cAAc,WAAW,EAAE;QAEnD,MAAML,UAAqC,MAAMO,QAAQ,GAAG,CACxDH,MAAM,OAAO,CAAC,GAAG,CAAC,OAAMI;YACpB,MAAMC,gBAAgBH,gBAAgB,IAAI,CAACI,CAAAA,KAAMA,GAAG,EAAE,KAAKF,OAAO,EAAE;YAEpE,IAAIG;YACJ,IAAIC;YAEJ,IAAI,AAACJ,OAAO,MAAM,IAAIA,OAAO,MAAM,KAAKC,eAAe,cAIhD;gBAEHE,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,OARqE;gBAEjEG,kBAAkBF,eAAe,mBAAmB;gBACpDG,eAAeH,eAAe,gBAAgB;YAClD;YAMA,OAAO;gBACH,IAAID,OAAO,EAAE;gBACb,MAAMA,OAAO,IAAI;gBACjB,aAAaA,OAAO,WAAW;gBAC/B,OAAOA,OAAO,KAAK;gBACnBG;gBACAC;YACJ;QACJ;QAGJ,OAAO;YAAEZ;QAAQ;IACrB;AACJ;AAEA,yBAAea,+BAA+B,oBAAoB,CAAC;IAC/D,gBAAgBlB;IAChB,cAAc;QAACmB;QAAYC;KAAO;AACtC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IAiPowerUpsSettings } from "
|
|
1
|
+
import type { IAiPowerUpsSettings } from "../../types.js";
|
|
2
2
|
export interface ProviderPreset {
|
|
3
3
|
id: string;
|
|
4
4
|
name: string;
|
|
@@ -8,7 +8,7 @@ export interface ProviderPreset {
|
|
|
8
8
|
apiKeyMasked: string;
|
|
9
9
|
apiKeyEncrypted: string;
|
|
10
10
|
}
|
|
11
|
-
declare module "
|
|
11
|
+
declare module "../../types.js" {
|
|
12
12
|
interface IAiPowerUpsSettings {
|
|
13
13
|
providers: {
|
|
14
14
|
presets: ProviderPreset[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TaskDefinition } from "@webiny/api-core/features/task/TaskDefinition/index.js";
|
|
2
|
-
import {
|
|
2
|
+
import { WebsocketsSendToIdentityUseCase } from "@webiny/api-websockets/features/SendToIdentity/abstractions.js";
|
|
3
3
|
import { WbGeneratePageContentUseCase } from "../../../api/features/WbGeneratePageContent/index.js";
|
|
4
4
|
import { IdentityContext } from "@webiny/api-core/exports/api/security.js";
|
|
5
5
|
export declare const WB_GENERATE_PAGE_CONTENT_TASK_ID = "aiPowerUpsGeneratePageContent";
|
|
@@ -11,18 +11,19 @@ export interface IWbGeneratePageContentTaskInput {
|
|
|
11
11
|
excludedFileIds?: string[] | null;
|
|
12
12
|
readerPersonaId?: string | null;
|
|
13
13
|
writerPersonaId?: string | null;
|
|
14
|
+
additionalFileIds?: string[] | null;
|
|
14
15
|
}
|
|
15
16
|
declare class WbGeneratePageContentTaskImpl implements TaskDefinition.Interface<IWbGeneratePageContentTaskInput> {
|
|
16
17
|
private identityContext;
|
|
17
18
|
private generatePageContent;
|
|
18
|
-
private
|
|
19
|
+
private sendToIdentity;
|
|
19
20
|
id: string;
|
|
20
21
|
title: string;
|
|
21
22
|
description: string;
|
|
22
23
|
maxIterations: number;
|
|
23
24
|
isPrivate: boolean;
|
|
24
25
|
databaseLogs: boolean;
|
|
25
|
-
constructor(identityContext: IdentityContext.Interface, generatePageContent: WbGeneratePageContentUseCase.Interface,
|
|
26
|
+
constructor(identityContext: IdentityContext.Interface, generatePageContent: WbGeneratePageContentUseCase.Interface, sendToIdentity: WebsocketsSendToIdentityUseCase.Interface);
|
|
26
27
|
run({ input, controller }: TaskDefinition.RunParams<IWbGeneratePageContentTaskInput>): Promise<TaskDefinition.Result<IWbGeneratePageContentTaskInput>>;
|
|
27
28
|
private sendContentToUser;
|
|
28
29
|
private sendErrorToUser;
|