@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.
- package/AiPowerups.d.ts +12 -0
- package/AiPowerups.js +1 -2
- package/AiPowerups.js.map +1 -1
- package/admin/Extension.d.ts +1 -1
- package/admin/Extension.js +6 -2
- package/admin/Extension.js.map +1 -1
- package/admin/domain/modelRoles.d.ts +17 -0
- package/admin/domain/modelRoles.js +8 -0
- package/admin/domain/modelRoles.js.map +1 -0
- package/admin/features/feature.js +2 -0
- package/admin/features/feature.js.map +1 -1
- package/admin/features/listCapabilities/ListCapabilitiesGateway.d.ts +12 -0
- package/admin/features/listCapabilities/ListCapabilitiesGateway.js +34 -0
- package/admin/features/listCapabilities/ListCapabilitiesGateway.js.map +1 -0
- package/admin/features/listCapabilities/ListCapabilitiesRepository.d.ts +13 -0
- package/admin/features/listCapabilities/ListCapabilitiesRepository.js +27 -0
- package/admin/features/listCapabilities/ListCapabilitiesRepository.js.map +1 -0
- package/admin/features/listCapabilities/ListCapabilitiesUseCase.d.ts +10 -0
- package/admin/features/listCapabilities/ListCapabilitiesUseCase.js +18 -0
- package/admin/features/listCapabilities/ListCapabilitiesUseCase.js.map +1 -0
- package/admin/features/listCapabilities/abstractions.d.ts +28 -0
- package/admin/features/listCapabilities/abstractions.js +7 -0
- package/admin/features/listCapabilities/abstractions.js.map +1 -0
- package/admin/features/listCapabilities/feature.d.ts +3 -0
- package/admin/features/listCapabilities/feature.js +21 -0
- package/admin/features/listCapabilities/feature.js.map +1 -0
- package/admin/features/listCapabilities/index.d.ts +3 -0
- package/admin/features/listCapabilities/index.js +2 -0
- package/admin/features/settings/shared/abstractions.d.ts +58 -25
- package/admin/features/settings/shared/abstractions.js.map +1 -1
- package/admin/presentation/AiPowerUpsSettings/AiPowerUpsSettingsPresenter.js +13 -1
- package/admin/presentation/AiPowerUpsSettings/AiPowerUpsSettingsPresenter.js.map +1 -1
- package/admin/presentation/AiPowerUpsSettings/feature.js +6 -2
- package/admin/presentation/AiPowerUpsSettings/feature.js.map +1 -1
- package/admin/presentation/AiPowerUpsSettings/hasUsableModel.d.ts +13 -0
- package/admin/presentation/AiPowerUpsSettings/hasUsableModel.js +9 -0
- package/admin/presentation/AiPowerUpsSettings/hasUsableModel.js.map +1 -0
- package/admin/presentation/AiPowerUpsSettings/index.d.ts +1 -0
- package/admin/presentation/AiPowerUpsSettings/index.js +1 -0
- package/admin/presentation/AiPowerUpsSettings/settingsGroup.d.ts +9 -0
- package/admin/presentation/AiPowerUpsSettings/settingsGroup.js.map +1 -1
- package/admin/presentation/CapabilitiesSettings.d.ts +39 -0
- package/admin/presentation/CapabilitiesSettings.js +104 -0
- package/admin/presentation/CapabilitiesSettings.js.map +1 -0
- package/admin/presentation/CmsContentGeneration/CmsGenerateContentButton.js +2 -2
- package/admin/presentation/CmsContentGeneration/CmsGenerateContentButton.js.map +1 -1
- package/admin/presentation/ConnectionsSettings.d.ts +25 -0
- package/admin/presentation/ConnectionsSettings.js +52 -0
- package/admin/presentation/ConnectionsSettings.js.map +1 -0
- package/admin/presentation/ModelRolesSettings.d.ts +29 -0
- package/admin/presentation/ModelRolesSettings.js +67 -0
- package/admin/presentation/ModelRolesSettings.js.map +1 -0
- package/admin/presentation/WbContentGeneration/GenerateContentButton.js +2 -2
- package/admin/presentation/WbContentGeneration/GenerateContentButton.js.map +1 -1
- package/admin/presentation/modelRoles.d.ts +10 -0
- package/admin/presentation/modelRoles.js +23 -0
- package/admin/presentation/modelRoles.js.map +1 -0
- package/api/Extension.js +10 -2
- package/api/Extension.js.map +1 -1
- package/api/features/AdminAssistant/AdminAssistantStreamRoute.d.ts +34 -0
- package/api/features/AdminAssistant/AdminAssistantStreamRoute.js +42 -0
- package/api/features/AdminAssistant/AdminAssistantStreamRoute.js.map +1 -0
- package/api/features/AdminAssistant/AdminAssistantUseCase.d.ts +42 -0
- package/api/features/AdminAssistant/AdminAssistantUseCase.js +170 -0
- package/api/features/AdminAssistant/AdminAssistantUseCase.js.map +1 -0
- package/api/features/AdminAssistant/abstractions.d.ts +38 -0
- package/api/features/AdminAssistant/abstractions.js +6 -0
- package/api/features/AdminAssistant/abstractions.js.map +1 -0
- package/api/features/AdminAssistant/approvals.d.ts +29 -0
- package/api/features/AdminAssistant/approvals.js +30 -0
- package/api/features/AdminAssistant/approvals.js.map +1 -0
- package/api/features/AdminAssistant/capability.d.ts +31 -0
- package/api/features/AdminAssistant/capability.js +19 -0
- package/api/features/AdminAssistant/capability.js.map +1 -0
- package/api/features/AdminAssistant/events.d.ts +54 -0
- package/api/features/AdminAssistant/events.js +0 -0
- package/api/features/AdminAssistant/feature.d.ts +12 -0
- package/api/features/AdminAssistant/feature.js +23 -0
- package/api/features/AdminAssistant/feature.js.map +1 -0
- package/api/features/AdminAssistant/index.d.ts +5 -0
- package/api/features/AdminAssistant/index.js +3 -0
- package/api/features/AdminAssistant/parseChatBody.d.ts +14 -0
- package/api/features/AdminAssistant/parseChatBody.js +33 -0
- package/api/features/AdminAssistant/parseChatBody.js.map +1 -0
- package/api/features/AdminAssistant/systemPrompt.d.ts +7 -0
- package/api/features/AdminAssistant/systemPrompt.js +24 -0
- package/api/features/AdminAssistant/systemPrompt.js.map +1 -0
- package/api/features/AiImageEnrichment/PrepareImageEnrichmentUseCase.d.ts +3 -5
- package/api/features/AiImageEnrichment/PrepareImageEnrichmentUseCase.js +11 -16
- package/api/features/AiImageEnrichment/PrepareImageEnrichmentUseCase.js.map +1 -1
- package/api/features/AiImageEnrichment/abstractions.d.ts +6 -0
- package/api/features/AiImageEnrichment/abstractions.js.map +1 -1
- package/api/features/AiImageEnrichment/buildEnrichmentAiRequest.js +2 -2
- package/api/features/AiImageEnrichment/buildEnrichmentAiRequest.js.map +1 -1
- package/api/features/AiImageEnrichment/capability.d.ts +18 -0
- package/api/features/AiImageEnrichment/capability.js +19 -0
- package/api/features/AiImageEnrichment/capability.js.map +1 -0
- package/api/features/AiImageEnrichment/errors.d.ts +6 -1
- package/api/features/AiImageEnrichment/errors.js +2 -2
- package/api/features/AiImageEnrichment/errors.js.map +1 -1
- package/api/features/AiImageEnrichment/feature.js +2 -0
- package/api/features/AiImageEnrichment/feature.js.map +1 -1
- package/api/features/Capabilities/CapabilitiesHandler.d.ts +28 -0
- package/api/features/Capabilities/CapabilitiesHandler.js +56 -0
- package/api/features/Capabilities/CapabilitiesHandler.js.map +1 -0
- package/api/features/Capabilities/ListAiCapabilitiesUseCase.d.ts +18 -0
- package/api/features/Capabilities/ListAiCapabilitiesUseCase.js +28 -0
- package/api/features/Capabilities/ListAiCapabilitiesUseCase.js.map +1 -0
- package/api/features/Capabilities/ResolveAiCapabilityUseCase.d.ts +30 -0
- package/api/features/Capabilities/ResolveAiCapabilityUseCase.js +88 -0
- package/api/features/Capabilities/ResolveAiCapabilityUseCase.js.map +1 -0
- package/api/features/Capabilities/abstractions.d.ts +77 -0
- package/api/features/Capabilities/abstractions.js +7 -0
- package/api/features/Capabilities/abstractions.js.map +1 -0
- package/api/features/Capabilities/composeSystemPrompt.d.ts +14 -0
- package/api/features/Capabilities/composeSystemPrompt.js +13 -0
- package/api/features/Capabilities/composeSystemPrompt.js.map +1 -0
- package/api/features/Capabilities/feature.d.ts +4 -0
- package/api/features/Capabilities/feature.js +15 -0
- package/api/features/Capabilities/feature.js.map +1 -0
- package/api/features/Capabilities/index.d.ts +5 -0
- package/api/features/Capabilities/index.js +3 -0
- package/api/features/Capabilities/types.d.ts +86 -0
- package/api/features/Capabilities/types.js +4 -0
- package/api/features/Capabilities/types.js.map +1 -0
- package/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.d.ts +3 -5
- package/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.js +11 -65
- package/api/features/CmsCompareEntryRevisions/CmsCompareEntryRevisionsUseCase.js.map +1 -1
- package/api/features/CmsCompareEntryRevisions/capability.d.ts +13 -0
- package/api/features/CmsCompareEntryRevisions/capability.js +64 -0
- package/api/features/CmsCompareEntryRevisions/capability.js.map +1 -0
- package/api/features/CmsCompareEntryRevisions/feature.js +2 -0
- package/api/features/CmsCompareEntryRevisions/feature.js.map +1 -1
- package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.d.ts +3 -5
- package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.js +11 -19
- package/api/features/CmsGenerateEntryContent/CmsGenerateEntryContentUseCase.js.map +1 -1
- package/api/features/CmsGenerateEntryContent/capability.d.ts +17 -0
- package/api/features/CmsGenerateEntryContent/capability.js +17 -0
- package/api/features/CmsGenerateEntryContent/capability.js.map +1 -0
- package/api/features/CmsGenerateEntryContent/feature.js +2 -0
- package/api/features/CmsGenerateEntryContent/feature.js.map +1 -1
- package/api/features/Connections/ConnectionsGraphQLMapper.d.ts +20 -0
- package/api/features/Connections/ConnectionsGraphQLMapper.js +37 -0
- package/api/features/Connections/ConnectionsGraphQLMapper.js.map +1 -0
- package/api/features/Connections/ConnectionsHandler.d.ts +25 -0
- package/api/features/Connections/ConnectionsHandler.js +84 -0
- package/api/features/Connections/ConnectionsHandler.js.map +1 -0
- package/api/features/Connections/feature.d.ts +4 -0
- package/api/features/Connections/feature.js +13 -0
- package/api/features/Connections/feature.js.map +1 -0
- package/api/features/Connections/index.d.ts +2 -0
- package/api/features/Connections/index.js +1 -0
- package/api/features/Connections/legacyProviders.d.ts +26 -0
- package/api/features/Connections/legacyProviders.js +9 -0
- package/api/features/Connections/legacyProviders.js.map +1 -0
- package/api/features/Connections/types.d.ts +36 -0
- package/api/features/Connections/types.js +0 -0
- package/api/features/GetSettings/GetSettingsRepository.js +1 -1
- package/api/features/GetSettings/GetSettingsRepository.js.map +1 -1
- package/api/features/ModelRoles/ModelRolesHandler.d.ts +15 -0
- package/api/features/ModelRoles/ModelRolesHandler.js +68 -0
- package/api/features/ModelRoles/ModelRolesHandler.js.map +1 -0
- package/api/features/ModelRoles/feature.d.ts +4 -0
- package/api/features/ModelRoles/feature.js +11 -0
- package/api/features/ModelRoles/feature.js.map +1 -0
- package/api/features/ModelRoles/index.d.ts +4 -0
- package/api/features/ModelRoles/index.js +2 -0
- package/api/features/ModelRoles/roles.d.ts +16 -0
- package/api/features/ModelRoles/roles.js +9 -0
- package/api/features/ModelRoles/roles.js.map +1 -0
- package/api/features/ModelRoles/types.d.ts +21 -0
- package/api/features/ModelRoles/types.js +7 -0
- package/api/features/ModelRoles/types.js.map +1 -0
- package/api/features/UpdateSettings/UpdateSettingsRepository.js +2 -2
- package/api/features/UpdateSettings/UpdateSettingsRepository.js.map +1 -1
- package/api/features/WbGeneratePageContent/WbGeneratePageContentUseCase.d.ts +3 -5
- package/api/features/WbGeneratePageContent/WbGeneratePageContentUseCase.js +11 -19
- package/api/features/WbGeneratePageContent/WbGeneratePageContentUseCase.js.map +1 -1
- package/api/features/WbGeneratePageContent/capability.d.ts +16 -0
- package/api/features/WbGeneratePageContent/capability.js +17 -0
- package/api/features/WbGeneratePageContent/capability.js.map +1 -0
- package/api/features/WbGeneratePageContent/feature.js +2 -0
- package/api/features/WbGeneratePageContent/feature.js.map +1 -1
- package/api/features/WbTranslatePage/WbTranslatePageDecorator.d.ts +5 -5
- package/api/features/WbTranslatePage/WbTranslatePageDecorator.js +19 -19
- package/api/features/WbTranslatePage/WbTranslatePageDecorator.js.map +1 -1
- package/api/features/WbTranslatePage/capability.d.ts +13 -0
- package/api/features/WbTranslatePage/capability.js +19 -0
- package/api/features/WbTranslatePage/capability.js.map +1 -0
- package/api/features/WbTranslatePage/feature.js +2 -0
- package/api/features/WbTranslatePage/feature.js.map +1 -1
- package/api/features/shared/abstractions.d.ts +6 -1
- package/api/features/shared/abstractions.js.map +1 -1
- package/api/features/shared/modelId.d.ts +11 -0
- package/api/features/shared/modelId.js +4 -0
- package/api/features/shared/modelId.js.map +1 -0
- package/api/graphql/BaseGraphQLSchema.js +16 -0
- package/api/graphql/BaseGraphQLSchema.js.map +1 -1
- package/api/types.d.ts +3 -0
- package/api/types.js +3 -0
- package/exports/api/ai-powerups.d.ts +5 -0
- package/exports/api/ai-powerups.js +3 -0
- package/package.json +24 -26
- package/api/features/AiChatProvider/PowerUpsAiChatProvider.d.ts +0 -24
- package/api/features/AiChatProvider/PowerUpsAiChatProvider.js +0 -31
- package/api/features/AiChatProvider/PowerUpsAiChatProvider.js.map +0 -1
- package/api/features/AiChatProvider/feature.d.ts +0 -9
- package/api/features/AiChatProvider/feature.js +0 -11
- package/api/features/AiChatProvider/feature.js.map +0 -1
- package/api/features/AiChatProvider/index.d.ts +0 -2
- package/api/features/AiChatProvider/index.js +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/Capabilities/CapabilitiesHandler.js","sources":["../../../../src/api/features/Capabilities/CapabilitiesHandler.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { AiPowerUpsSettingsGroupHandler } from \"~/api/features/shared/index.js\";\nimport { AI_MODEL_ROLE_IDS } from \"~/api/features/ModelRoles/index.js\";\nimport type { AiCapabilityEntry } from \"./types.js\";\nimport type { AiCapabilityOverride } from \"./types.js\";\nimport type { CapabilitiesSettings } from \"./types.js\";\nimport type { PersistedCapabilities } from \"./types.js\";\n\n/*\n * Every field here is empty by default and the admin form sends `null` for an untouched one, so\n * each has to accept it. `mapToStorage` drops the nulls rather than persisting them.\n */\nconst overrideSchema = z.object({\n roleId: z.union([z.enum(AI_MODEL_ROLE_IDS), z.literal(\"\")]).nullish(),\n connectionId: z.string().nullish(),\n model: z.string().nullish(),\n additionalInstructions: z.string().nullish()\n});\n\n/*\n * `enabled` is `nullish` for the same reason the strings are: an untouched switch can arrive as\n * `null`. `mapToStorage` settles it to a real boolean before storing.\n */\nconst entrySchema = z.object({\n enabled: z.boolean().nullish(),\n overrides: overrideSchema.nullish()\n});\n\nconst inputSchema = z.object({\n items: z.record(z.string(), entrySchema)\n});\n\n/**\n * Keeps values that mean \"not set\" out of a stored override. The form sends `null` for an untouched\n * field, and persisting those would fill the blob with keys nobody chose. Applies to the overrides\n * only: `enabled` is always written, because \"on\" is a state worth reading back.\n */\nconst dropEmptyValues = (override: AiCapabilityOverride): AiCapabilityOverride =>\n Object.fromEntries(\n Object.entries(override).filter(([, value]) => {\n if (value === null || value === undefined) {\n return false;\n }\n // Whitespace counts as empty. A textarea someone tabbed through holds \" \", which would\n // otherwise be stored and then appended to the prompt as blank noise.\n return typeof value === \"string\" ? value.trim() !== \"\" : true;\n })\n ) as AiCapabilityOverride;\n\n/**\n * The form sends `null` for a switch nobody touched, and that reads as enabled, same as absence.\n * Only an explicit `false` turns a capability off.\n */\nconst normaliseEnabled = (enabled: boolean | null | undefined): boolean => enabled !== false;\n\nclass CapabilitiesHandlerImpl implements AiPowerUpsSettingsGroupHandler.Interface {\n readonly name = \"capabilities\";\n readonly inputSchema = inputSchema;\n\n mapFromStorage(persisted: unknown): CapabilitiesSettings {\n const stored = (persisted ?? {}) as PersistedCapabilities;\n return { items: stored.items ?? {} };\n }\n\n async mapToStorage(internal: unknown): Promise<PersistedCapabilities> {\n const input = internal as CapabilitiesSettings;\n\n /*\n * Every capability the form sent gets a key, `enabled` included, so the stored blob says\n * plainly what the screen said. Entries are not dropped for being \"empty\": a row that only\n * carries `enabled: true` is the normal state and worth seeing.\n *\n * Reading still has to treat a *missing* entry as enabled, because a capability registered\n * after the last save has no key at all. `isCapabilityEnabled` is where that lives.\n */\n const entries = Object.entries(input.items ?? {})\n // A type guard, not a plain predicate: a bare `Boolean(...)` filter reads the same but\n // narrows nothing, so the `undefined` this exists to drop would flow straight on.\n .filter((entry): entry is [string, AiCapabilityEntry] => Boolean(entry[1]))\n .map(\n ([id, entry]) =>\n [\n id,\n {\n enabled: normaliseEnabled(entry.enabled),\n overrides: dropEmptyValues(entry.overrides ?? {})\n }\n ] as const\n );\n\n return { items: Object.fromEntries(entries) };\n }\n}\n\nexport default AiPowerUpsSettingsGroupHandler.createImplementation({\n implementation: CapabilitiesHandlerImpl,\n dependencies: []\n});\n"],"names":["overrideSchema","z","AI_MODEL_ROLE_IDS","entrySchema","inputSchema","dropEmptyValues","override","Object","value","normaliseEnabled","enabled","CapabilitiesHandlerImpl","persisted","stored","internal","input","entries","entry","Boolean","id","AiPowerUpsSettingsGroupHandler"],"mappings":";;;AAYA,MAAMA,iBAAiBC,EAAE,MAAM,CAAC;IAC5B,QAAQA,EAAE,KAAK,CAAC;QAACA,CAAC,CAADA,OAAM,CAACC;QAAoBD,EAAE,OAAO,CAAC;KAAI,EAAE,OAAO;IACnE,cAAcA,EAAE,MAAM,GAAG,OAAO;IAChC,OAAOA,EAAE,MAAM,GAAG,OAAO;IACzB,wBAAwBA,EAAE,MAAM,GAAG,OAAO;AAC9C;AAMA,MAAME,cAAcF,EAAE,MAAM,CAAC;IACzB,SAASA,EAAE,OAAO,GAAG,OAAO;IAC5B,WAAWD,eAAe,OAAO;AACrC;AAEA,MAAMI,cAAcH,EAAE,MAAM,CAAC;IACzB,OAAOA,EAAE,MAAM,CAACA,EAAE,MAAM,IAAIE;AAChC;AAOA,MAAME,kBAAkB,CAACC,WACrBC,OAAO,WAAW,CACdA,OAAO,OAAO,CAACD,UAAU,MAAM,CAAC,CAAC,GAAGE,MAAM;QACtC,IAAIA,QAAAA,OACA,OAAO;QAIX,OAAO,AAAiB,YAAjB,OAAOA,QAAqBA,AAAiB,OAAjBA,MAAM,IAAI,KAAY;IAC7D;AAOR,MAAMC,mBAAmB,CAACC,UAAiDA,AAAY,UAAZA;AAE3E,MAAMC;IAIF,eAAeC,SAAkB,EAAwB;QACrD,MAAMC,SAAUD,aAAa,CAAC;QAC9B,OAAO;YAAE,OAAOC,OAAO,KAAK,IAAI,CAAC;QAAE;IACvC;IAEA,MAAM,aAAaC,QAAiB,EAAkC;QAClE,MAAMC,QAAQD;QAUd,MAAME,UAAUT,OAAO,OAAO,CAACQ,MAAM,KAAK,IAAI,CAAC,GAG1C,MAAM,CAAC,CAACE,QAAgDC,QAAQD,KAAK,CAAC,EAAE,GACxE,GAAG,CACA,CAAC,CAACE,IAAIF,MAAM,GACR;gBACIE;gBACA;oBACI,SAASV,iBAAiBQ,MAAM,OAAO;oBACvC,WAAWZ,gBAAgBY,MAAM,SAAS,IAAI,CAAC;gBACnD;aACH;QAGb,OAAO;YAAE,OAAOV,OAAO,WAAW,CAACS;QAAS;IAChD;;aAnCS,IAAI,GAAG;aACP,WAAW,GAAGZ;;AAmC3B;AAEA,4BAAegB,+BAA+B,oBAAoB,CAAC;IAC/D,gBAAgBT;IAChB,cAAc,EAAE;AACpB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AiCapability, ListAiCapabilitiesUseCase } from "./abstractions.js";
|
|
2
|
+
import type { IAiCapabilitySummary } from "./abstractions.js";
|
|
3
|
+
/**
|
|
4
|
+
* Lists the registered capabilities for callers outside the api.
|
|
5
|
+
*
|
|
6
|
+
* The mapping lives here rather than in the GraphQL resolver so the shape sent over the wire is
|
|
7
|
+
* decided once, next to the abstraction it describes. It also keeps `guidance` from leaking: a
|
|
8
|
+
* capability's prompt is implementation, and the summary simply has no field for it.
|
|
9
|
+
*/
|
|
10
|
+
declare class ListAiCapabilitiesUseCaseImpl implements ListAiCapabilitiesUseCase.Interface {
|
|
11
|
+
private capabilities;
|
|
12
|
+
constructor(capabilities: AiCapability.Interface[]);
|
|
13
|
+
execute(): Promise<IAiCapabilitySummary[]>;
|
|
14
|
+
}
|
|
15
|
+
export declare const ListAiCapabilitiesUseCaseImplementation: typeof ListAiCapabilitiesUseCaseImpl & {
|
|
16
|
+
__abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").IListAiCapabilitiesUseCase>;
|
|
17
|
+
};
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AiCapability, ListAiCapabilitiesUseCase } from "./abstractions.js";
|
|
2
|
+
class ListAiCapabilitiesUseCaseImpl {
|
|
3
|
+
constructor(capabilities){
|
|
4
|
+
this.capabilities = capabilities;
|
|
5
|
+
}
|
|
6
|
+
async execute() {
|
|
7
|
+
return this.capabilities.map((capability)=>({
|
|
8
|
+
id: capability.id,
|
|
9
|
+
label: capability.label,
|
|
10
|
+
description: capability.description,
|
|
11
|
+
defaultRole: capability.defaultRole
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const ListAiCapabilitiesUseCaseImplementation = ListAiCapabilitiesUseCase.createImplementation({
|
|
16
|
+
implementation: ListAiCapabilitiesUseCaseImpl,
|
|
17
|
+
dependencies: [
|
|
18
|
+
[
|
|
19
|
+
AiCapability,
|
|
20
|
+
{
|
|
21
|
+
multiple: true
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
]
|
|
25
|
+
});
|
|
26
|
+
export { ListAiCapabilitiesUseCaseImplementation };
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=ListAiCapabilitiesUseCase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/Capabilities/ListAiCapabilitiesUseCase.js","sources":["../../../../src/api/features/Capabilities/ListAiCapabilitiesUseCase.ts"],"sourcesContent":["import { AiCapability, ListAiCapabilitiesUseCase } from \"./abstractions.js\";\nimport type { IAiCapabilitySummary } from \"./abstractions.js\";\n\n/**\n * Lists the registered capabilities for callers outside the api.\n *\n * The mapping lives here rather than in the GraphQL resolver so the shape sent over the wire is\n * decided once, next to the abstraction it describes. It also keeps `guidance` from leaking: a\n * capability's prompt is implementation, and the summary simply has no field for it.\n */\nclass ListAiCapabilitiesUseCaseImpl implements ListAiCapabilitiesUseCase.Interface {\n constructor(private capabilities: AiCapability.Interface[]) {}\n\n async execute(): Promise<IAiCapabilitySummary[]> {\n return this.capabilities.map(capability => ({\n id: capability.id,\n label: capability.label,\n description: capability.description,\n defaultRole: capability.defaultRole\n }));\n }\n}\n\nexport const ListAiCapabilitiesUseCaseImplementation =\n ListAiCapabilitiesUseCase.createImplementation({\n implementation: ListAiCapabilitiesUseCaseImpl,\n dependencies: [[AiCapability, { multiple: true }]]\n });\n"],"names":["ListAiCapabilitiesUseCaseImpl","capabilities","capability","ListAiCapabilitiesUseCaseImplementation","ListAiCapabilitiesUseCase","AiCapability"],"mappings":";AAUA,MAAMA;IACF,YAAoBC,YAAsC,CAAE;aAAxCA,YAAY,GAAZA;IAAyC;IAE7D,MAAM,UAA2C;QAC7C,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAACC,CAAAA,aAAe;gBACxC,IAAIA,WAAW,EAAE;gBACjB,OAAOA,WAAW,KAAK;gBACvB,aAAaA,WAAW,WAAW;gBACnC,aAAaA,WAAW,WAAW;YACvC;IACJ;AACJ;AAEO,MAAMC,0CACTC,0BAA0B,oBAAoB,CAAC;IAC3C,gBAAgBJ;IAChB,cAAc;QAAC;YAACK;YAAc;gBAAE,UAAU;YAAK;SAAE;KAAC;AACtD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Result } from "@webiny/feature/api";
|
|
2
|
+
import { Encryption } from "@webiny/api-core/features/encryption/index.js";
|
|
3
|
+
import { GetSettingsUseCase } from "../../../api/features/GetSettings/index.js";
|
|
4
|
+
import { AiCapability, ResolveAiCapabilityUseCase } from "./abstractions.js";
|
|
5
|
+
import type { IResolvedAiCapability } from "./abstractions.js";
|
|
6
|
+
/**
|
|
7
|
+
* Turns a capability id into the model, credential and prompt text a use case needs.
|
|
8
|
+
*
|
|
9
|
+
* This is the single place that knows the precedence rules. Before it existed, six use cases each
|
|
10
|
+
* read `providers.presets[0]`, re-derived the SDK name from the model string and decrypted the key
|
|
11
|
+
* themselves, so "which model runs this feature" had six answers that only happened to agree.
|
|
12
|
+
*
|
|
13
|
+
* Precedence: a capability's pinned connection+model, else its chosen role, else its declared
|
|
14
|
+
* default role, else the `standard` role.
|
|
15
|
+
*
|
|
16
|
+
* There is deliberately no environment-variable fallback. A project whose settings say one thing
|
|
17
|
+
* and whose requests use another is the exact confusion this replaces.
|
|
18
|
+
*/
|
|
19
|
+
declare class ResolveAiCapabilityUseCaseImpl implements ResolveAiCapabilityUseCase.Interface {
|
|
20
|
+
private getSettings;
|
|
21
|
+
private encryption;
|
|
22
|
+
private capabilityLookup;
|
|
23
|
+
constructor(capabilities: AiCapability.Interface[], getSettings: GetSettingsUseCase.Interface, encryption: Encryption.Interface);
|
|
24
|
+
execute(capabilityId: string): Promise<Result<IResolvedAiCapability, Error>>;
|
|
25
|
+
private selectModel;
|
|
26
|
+
}
|
|
27
|
+
export declare const ResolveAiCapabilityUseCaseImplementation: typeof ResolveAiCapabilityUseCaseImpl & {
|
|
28
|
+
__abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").IResolveAiCapabilityUseCase>;
|
|
29
|
+
};
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Result } from "@webiny/feature/api";
|
|
2
|
+
import { Encryption } from "@webiny/api-core/features/encryption/index.js";
|
|
3
|
+
import { GetSettingsUseCase } from "../GetSettings/index.js";
|
|
4
|
+
import { sdkNameFromModel } from "../shared/modelId.js";
|
|
5
|
+
import { AiCapability, ResolveAiCapabilityUseCase } from "./abstractions.js";
|
|
6
|
+
import { isCapabilityEnabled } from "./types.js";
|
|
7
|
+
const SETTINGS_PATH = "Settings → AI Power-Ups";
|
|
8
|
+
class ResolveAiCapabilityUseCaseImpl {
|
|
9
|
+
constructor(capabilities, getSettings, encryption){
|
|
10
|
+
this.getSettings = getSettings;
|
|
11
|
+
this.encryption = encryption;
|
|
12
|
+
this.capabilityLookup = new Map(capabilities.map((c)=>[
|
|
13
|
+
c.id,
|
|
14
|
+
c
|
|
15
|
+
]));
|
|
16
|
+
}
|
|
17
|
+
async execute(capabilityId) {
|
|
18
|
+
const capability = this.capabilityLookup.get(capabilityId);
|
|
19
|
+
if (!capability) return Result.fail(new Error(`Unknown AI capability "${capabilityId}". Register it with the AiCapability abstraction.`));
|
|
20
|
+
const settingsResult = await this.getSettings.execute();
|
|
21
|
+
if (settingsResult.isFail()) return Result.fail(new Error("Failed to load AI Power-Ups settings."));
|
|
22
|
+
const settings = settingsResult.value;
|
|
23
|
+
const entry = settings.capabilities?.items?.[capabilityId];
|
|
24
|
+
if (!isCapabilityEnabled(entry)) return Result.fail(new Error(`"${capability.label}" is switched off. Turn it back on under ${SETTINGS_PATH} → Capabilities.`));
|
|
25
|
+
const override = entry?.overrides ?? {};
|
|
26
|
+
const selection = this.selectModel(settings, capability.defaultRole, override);
|
|
27
|
+
if (selection.isFail()) return Result.fail(selection.error);
|
|
28
|
+
const { connectionId, model, roleId, fellBackToStandard } = selection.value;
|
|
29
|
+
const connection = settings.connections?.presets?.find((c)=>c.id === connectionId);
|
|
30
|
+
if (!connection) return Result.fail(new Error(`"${capability.label}" points at a connection that no longer exists. Pick one under ${SETTINGS_PATH} → Model roles.`));
|
|
31
|
+
if (!connection.apiKeyEncrypted) return Result.fail(new Error(`The connection "${connection.name}" has no API key. Add one under ${SETTINGS_PATH} → Connections.`));
|
|
32
|
+
const modelSdkName = sdkNameFromModel(model);
|
|
33
|
+
if (modelSdkName && connection.sdkName && modelSdkName !== connection.sdkName) return Result.fail(new Error(`The model "${model}" cannot run on the "${connection.name}" connection, which is a ${connection.sdkName} credential. Fix the pairing under ${SETTINGS_PATH} → Model roles.`));
|
|
34
|
+
return Result.ok({
|
|
35
|
+
capabilityId,
|
|
36
|
+
model,
|
|
37
|
+
connection: {
|
|
38
|
+
sdkName: modelSdkName || connection.sdkName,
|
|
39
|
+
apiKey: await this.encryption.decrypt(connection.apiKeyEncrypted)
|
|
40
|
+
},
|
|
41
|
+
roleId,
|
|
42
|
+
fellBackToStandard,
|
|
43
|
+
guidance: capability.guidance ?? "",
|
|
44
|
+
additionalInstructions: override.additionalInstructions?.trim() ?? ""
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
selectModel(settings, defaultRole, override) {
|
|
48
|
+
if (override.connectionId && override.model) return Result.ok({
|
|
49
|
+
connectionId: override.connectionId,
|
|
50
|
+
model: override.model,
|
|
51
|
+
roleId: null,
|
|
52
|
+
fellBackToStandard: false
|
|
53
|
+
});
|
|
54
|
+
const roles = settings.modelRoles?.roles;
|
|
55
|
+
const requestedRole = override.roleId || defaultRole;
|
|
56
|
+
const requested = roles?.[requestedRole];
|
|
57
|
+
if (requested?.connectionId && requested.model) return Result.ok({
|
|
58
|
+
connectionId: requested.connectionId,
|
|
59
|
+
model: requested.model,
|
|
60
|
+
roleId: requestedRole,
|
|
61
|
+
fellBackToStandard: false
|
|
62
|
+
});
|
|
63
|
+
const standard = roles?.standard;
|
|
64
|
+
if (standard?.connectionId && standard.model) return Result.ok({
|
|
65
|
+
connectionId: standard.connectionId,
|
|
66
|
+
model: standard.model,
|
|
67
|
+
roleId: "standard",
|
|
68
|
+
fellBackToStandard: "standard" !== requestedRole
|
|
69
|
+
});
|
|
70
|
+
return Result.fail(new Error(`No model is configured for the "${requestedRole}" role. Pick one under ${SETTINGS_PATH} → Model roles.`));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const ResolveAiCapabilityUseCaseImplementation = ResolveAiCapabilityUseCase.createImplementation({
|
|
74
|
+
implementation: ResolveAiCapabilityUseCaseImpl,
|
|
75
|
+
dependencies: [
|
|
76
|
+
[
|
|
77
|
+
AiCapability,
|
|
78
|
+
{
|
|
79
|
+
multiple: true
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
GetSettingsUseCase,
|
|
83
|
+
Encryption
|
|
84
|
+
]
|
|
85
|
+
});
|
|
86
|
+
export { ResolveAiCapabilityUseCaseImplementation };
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=ResolveAiCapabilityUseCase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/Capabilities/ResolveAiCapabilityUseCase.js","sources":["../../../../src/api/features/Capabilities/ResolveAiCapabilityUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { Encryption } from \"@webiny/api-core/features/encryption/index.js\";\nimport { GetSettingsUseCase } from \"~/api/features/GetSettings/index.js\";\nimport { sdkNameFromModel } from \"~/api/features/shared/modelId.js\";\nimport { AiCapability, ResolveAiCapabilityUseCase } from \"./abstractions.js\";\nimport type { IResolvedAiCapability } from \"./abstractions.js\";\nimport { isCapabilityEnabled } from \"./types.js\";\nimport type { AiCapabilityOverride } from \"./types.js\";\nimport type { AiModelRoleId } from \"~/api/features/ModelRoles/index.js\";\nimport type { IAiPowerUpsSettings } from \"~/api/types.js\";\n\nconst SETTINGS_PATH = \"Settings → AI Power-Ups\";\n\n/**\n * Turns a capability id into the model, credential and prompt text a use case needs.\n *\n * This is the single place that knows the precedence rules. Before it existed, six use cases each\n * read `providers.presets[0]`, re-derived the SDK name from the model string and decrypted the key\n * themselves, so \"which model runs this feature\" had six answers that only happened to agree.\n *\n * Precedence: a capability's pinned connection+model, else its chosen role, else its declared\n * default role, else the `standard` role.\n *\n * There is deliberately no environment-variable fallback. A project whose settings say one thing\n * and whose requests use another is the exact confusion this replaces.\n */\nclass ResolveAiCapabilityUseCaseImpl implements ResolveAiCapabilityUseCase.Interface {\n private capabilityLookup: Map<string, AiCapability.Interface>;\n\n constructor(\n capabilities: AiCapability.Interface[],\n private getSettings: GetSettingsUseCase.Interface,\n private encryption: Encryption.Interface\n ) {\n this.capabilityLookup = new Map(capabilities.map(c => [c.id, c]));\n }\n\n async execute(capabilityId: string): Promise<Result<IResolvedAiCapability, Error>> {\n const capability = this.capabilityLookup.get(capabilityId);\n\n if (!capability) {\n // Nothing a project can do about this one: the caller passed an unregistered id.\n return Result.fail(\n new Error(\n `Unknown AI capability \"${capabilityId}\". Register it with the AiCapability abstraction.`\n )\n );\n }\n\n const settingsResult = await this.getSettings.execute();\n if (settingsResult.isFail()) {\n return Result.fail(new Error(\"Failed to load AI Power-Ups settings.\"));\n }\n\n const settings = settingsResult.value;\n const entry = settings.capabilities?.items?.[capabilityId];\n\n /*\n * Checked here rather than at every call site, so a capability switched off in settings is\n * off for the GraphQL mutation as much as for the button that usually triggers it. The\n * admin hides the affordance too, but that is a courtesy and this is the actual gate.\n */\n if (!isCapabilityEnabled(entry)) {\n return Result.fail(\n new Error(\n `\"${capability.label}\" is switched off. Turn it back on under ${SETTINGS_PATH} → Capabilities.`\n )\n );\n }\n\n const override: AiCapabilityOverride = entry?.overrides ?? {};\n\n const selection = this.selectModel(settings, capability.defaultRole, override);\n if (selection.isFail()) {\n return Result.fail(selection.error);\n }\n\n const { connectionId, model, roleId, fellBackToStandard } = selection.value;\n\n const connection = settings.connections?.presets?.find(c => c.id === connectionId);\n\n if (!connection) {\n return Result.fail(\n new Error(\n `\"${capability.label}\" points at a connection that no longer exists. Pick one under ${SETTINGS_PATH} → Model roles.`\n )\n );\n }\n\n if (!connection.apiKeyEncrypted) {\n return Result.fail(\n new Error(\n `The connection \"${connection.name}\" has no API key. Add one under ${SETTINGS_PATH} → Connections.`\n )\n );\n }\n\n /*\n * A model is stored fully qualified (\"anthropic/claude-sonnet-4-5\") and a connection stores\n * its vendor separately, so the two can disagree if a connection is re-pointed at another\n * vendor after a role was filled. Catching it here beats a provider-side auth error.\n */\n const modelSdkName = sdkNameFromModel(model);\n if (modelSdkName && connection.sdkName && modelSdkName !== connection.sdkName) {\n return Result.fail(\n new Error(\n `The model \"${model}\" cannot run on the \"${connection.name}\" connection, which is a ${connection.sdkName} credential. Fix the pairing under ${SETTINGS_PATH} → Model roles.`\n )\n );\n }\n\n return Result.ok({\n capabilityId,\n model,\n connection: {\n sdkName: modelSdkName || connection.sdkName,\n apiKey: await this.encryption.decrypt(connection.apiKeyEncrypted)\n },\n roleId,\n fellBackToStandard,\n // Always the capability's own. Projects adjust prompts by appending, never by\n // replacing, because for most capabilities the prompt is the output contract.\n guidance: capability.guidance ?? \"\",\n additionalInstructions: override.additionalInstructions?.trim() ?? \"\"\n });\n }\n\n private selectModel(\n settings: IAiPowerUpsSettings,\n defaultRole: AiModelRoleId,\n override: AiCapabilityOverride\n ): Result<\n {\n connectionId: string;\n model: string;\n roleId: AiModelRoleId | null;\n fellBackToStandard: boolean;\n },\n Error\n > {\n // A pinned connection+model wins outright. Both halves are required; one alone is a\n // half-finished edit, so it is ignored rather than guessed at.\n if (override.connectionId && override.model) {\n return Result.ok({\n connectionId: override.connectionId,\n model: override.model,\n roleId: null,\n fellBackToStandard: false\n });\n }\n\n const roles = settings.modelRoles?.roles;\n const requestedRole = (override.roleId || defaultRole) as AiModelRoleId;\n const requested = roles?.[requestedRole];\n\n if (requested?.connectionId && requested.model) {\n return Result.ok({\n connectionId: requested.connectionId,\n model: requested.model,\n roleId: requestedRole,\n fellBackToStandard: false\n });\n }\n\n /*\n * An unfilled role falls back to `standard` rather than failing. That is what keeps an\n * upgrade quiet: migration fills only `standard`, and every feature that used to read\n * `providers.presets[0]` keeps running on exactly the model it ran on before.\n *\n * It does mean an unfilled `vision` role sends images to whatever `standard` holds. Same\n * as today's behaviour, and the settings screen says so next to the role.\n */\n const standard = roles?.standard;\n\n if (standard?.connectionId && standard.model) {\n return Result.ok({\n connectionId: standard.connectionId,\n model: standard.model,\n roleId: \"standard\",\n fellBackToStandard: requestedRole !== \"standard\"\n });\n }\n\n return Result.fail(\n new Error(\n `No model is configured for the \"${requestedRole}\" role. Pick one under ${SETTINGS_PATH} → Model roles.`\n )\n );\n }\n}\n\nexport const ResolveAiCapabilityUseCaseImplementation =\n ResolveAiCapabilityUseCase.createImplementation({\n implementation: ResolveAiCapabilityUseCaseImpl,\n dependencies: [[AiCapability, { multiple: true }], GetSettingsUseCase, Encryption]\n });\n"],"names":["SETTINGS_PATH","ResolveAiCapabilityUseCaseImpl","capabilities","getSettings","encryption","Map","c","capabilityId","capability","Result","Error","settingsResult","settings","entry","isCapabilityEnabled","override","selection","connectionId","model","roleId","fellBackToStandard","connection","modelSdkName","sdkNameFromModel","defaultRole","roles","requestedRole","requested","standard","ResolveAiCapabilityUseCaseImplementation","ResolveAiCapabilityUseCase","AiCapability","GetSettingsUseCase","Encryption"],"mappings":";;;;;;AAWA,MAAMA,gBAAgB;AAetB,MAAMC;IAGF,YACIC,YAAsC,EAC9BC,WAAyC,EACzCC,UAAgC,CAC1C;aAFUD,WAAW,GAAXA;aACAC,UAAU,GAAVA;QAER,IAAI,CAAC,gBAAgB,GAAG,IAAIC,IAAIH,aAAa,GAAG,CAACI,CAAAA,IAAK;gBAACA,EAAE,EAAE;gBAAEA;aAAE;IACnE;IAEA,MAAM,QAAQC,YAAoB,EAAiD;QAC/E,MAAMC,aAAa,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAACD;QAE7C,IAAI,CAACC,YAED,OAAOC,OAAO,IAAI,CACd,IAAIC,MACA,CAAC,uBAAuB,EAAEH,aAAa,iDAAiD,CAAC;QAKrG,MAAMI,iBAAiB,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO;QACrD,IAAIA,eAAe,MAAM,IACrB,OAAOF,OAAO,IAAI,CAAC,IAAIC,MAAM;QAGjC,MAAME,WAAWD,eAAe,KAAK;QACrC,MAAME,QAAQD,SAAS,YAAY,EAAE,OAAO,CAACL,aAAa;QAO1D,IAAI,CAACO,oBAAoBD,QACrB,OAAOJ,OAAO,IAAI,CACd,IAAIC,MACA,CAAC,CAAC,EAAEF,WAAW,KAAK,CAAC,yCAAyC,EAAER,cAAc,gBAAgB,CAAC;QAK3G,MAAMe,WAAiCF,OAAO,aAAa,CAAC;QAE5D,MAAMG,YAAY,IAAI,CAAC,WAAW,CAACJ,UAAUJ,WAAW,WAAW,EAAEO;QACrE,IAAIC,UAAU,MAAM,IAChB,OAAOP,OAAO,IAAI,CAACO,UAAU,KAAK;QAGtC,MAAM,EAAEC,YAAY,EAAEC,KAAK,EAAEC,MAAM,EAAEC,kBAAkB,EAAE,GAAGJ,UAAU,KAAK;QAE3E,MAAMK,aAAaT,SAAS,WAAW,EAAE,SAAS,KAAKN,CAAAA,IAAKA,EAAE,EAAE,KAAKW;QAErE,IAAI,CAACI,YACD,OAAOZ,OAAO,IAAI,CACd,IAAIC,MACA,CAAC,CAAC,EAAEF,WAAW,KAAK,CAAC,+DAA+D,EAAER,cAAc,eAAe,CAAC;QAKhI,IAAI,CAACqB,WAAW,eAAe,EAC3B,OAAOZ,OAAO,IAAI,CACd,IAAIC,MACA,CAAC,gBAAgB,EAAEW,WAAW,IAAI,CAAC,gCAAgC,EAAErB,cAAc,eAAe,CAAC;QAU/G,MAAMsB,eAAeC,iBAAiBL;QACtC,IAAII,gBAAgBD,WAAW,OAAO,IAAIC,iBAAiBD,WAAW,OAAO,EACzE,OAAOZ,OAAO,IAAI,CACd,IAAIC,MACA,CAAC,WAAW,EAAEQ,MAAM,qBAAqB,EAAEG,WAAW,IAAI,CAAC,yBAAyB,EAAEA,WAAW,OAAO,CAAC,mCAAmC,EAAErB,cAAc,eAAe,CAAC;QAKxL,OAAOS,OAAO,EAAE,CAAC;YACbF;YACAW;YACA,YAAY;gBACR,SAASI,gBAAgBD,WAAW,OAAO;gBAC3C,QAAQ,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAACA,WAAW,eAAe;YACpE;YACAF;YACAC;YAGA,UAAUZ,WAAW,QAAQ,IAAI;YACjC,wBAAwBO,SAAS,sBAAsB,EAAE,UAAU;QACvE;IACJ;IAEQ,YACJH,QAA6B,EAC7BY,WAA0B,EAC1BT,QAA8B,EAShC;QAGE,IAAIA,SAAS,YAAY,IAAIA,SAAS,KAAK,EACvC,OAAON,OAAO,EAAE,CAAC;YACb,cAAcM,SAAS,YAAY;YACnC,OAAOA,SAAS,KAAK;YACrB,QAAQ;YACR,oBAAoB;QACxB;QAGJ,MAAMU,QAAQb,SAAS,UAAU,EAAE;QACnC,MAAMc,gBAAiBX,SAAS,MAAM,IAAIS;QAC1C,MAAMG,YAAYF,OAAO,CAACC,cAAc;QAExC,IAAIC,WAAW,gBAAgBA,UAAU,KAAK,EAC1C,OAAOlB,OAAO,EAAE,CAAC;YACb,cAAckB,UAAU,YAAY;YACpC,OAAOA,UAAU,KAAK;YACtB,QAAQD;YACR,oBAAoB;QACxB;QAWJ,MAAME,WAAWH,OAAO;QAExB,IAAIG,UAAU,gBAAgBA,SAAS,KAAK,EACxC,OAAOnB,OAAO,EAAE,CAAC;YACb,cAAcmB,SAAS,YAAY;YACnC,OAAOA,SAAS,KAAK;YACrB,QAAQ;YACR,oBAAoBF,AAAkB,eAAlBA;QACxB;QAGJ,OAAOjB,OAAO,IAAI,CACd,IAAIC,MACA,CAAC,gCAAgC,EAAEgB,cAAc,uBAAuB,EAAE1B,cAAc,eAAe,CAAC;IAGpH;AACJ;AAEO,MAAM6B,2CACTC,2BAA2B,oBAAoB,CAAC;IAC5C,gBAAgB7B;IAChB,cAAc;QAAC;YAAC8B;YAAc;gBAAE,UAAU;YAAK;SAAE;QAAEC;QAAoBC;KAAW;AACtF"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Result } from "@webiny/feature/api";
|
|
2
|
+
import type { AiModelRoleId } from "../../../api/features/ModelRoles/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* One AI feature, declared so the settings screen can list it and a project can point it at a
|
|
5
|
+
* different model or adjust its prompt.
|
|
6
|
+
*
|
|
7
|
+
* Features register these; nothing hardcodes the list. An extension that adds an AI feature gets a
|
|
8
|
+
* row in Settings for free by registering a capability alongside it.
|
|
9
|
+
*/
|
|
10
|
+
export interface IAiCapability {
|
|
11
|
+
/** Stable, namespaced, and persisted as a settings key. Renaming one orphans its overrides. */
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly label: string;
|
|
14
|
+
readonly description: string;
|
|
15
|
+
/** Which role supplies the model when the project has not overridden this capability. */
|
|
16
|
+
readonly defaultRole: AiModelRoleId;
|
|
17
|
+
/**
|
|
18
|
+
* The capability's fixed system-prompt block, owned by the code and not configurable.
|
|
19
|
+
*
|
|
20
|
+
* Leave it undefined when the prompt is assembled per request (from a content model schema, a
|
|
21
|
+
* component catalog, a persona) and the use case builds its own system text instead.
|
|
22
|
+
*
|
|
23
|
+
* Either way a project can only append to it, via `additionalInstructions`. These prompts carry
|
|
24
|
+
* the output contract the surrounding code parses, so they are implementation, not settings.
|
|
25
|
+
*/
|
|
26
|
+
readonly guidance?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare const AiCapability: import("@webiny/di").Abstraction<IAiCapability>;
|
|
29
|
+
export declare namespace AiCapability {
|
|
30
|
+
type Interface = IAiCapability;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* What a capability looks like to a caller outside the api.
|
|
34
|
+
*
|
|
35
|
+
* `guidance` is deliberately absent: a prompt is implementation, and there is no reason to ship ours
|
|
36
|
+
* over the wire to anyone who can read settings.
|
|
37
|
+
*/
|
|
38
|
+
export interface IAiCapabilitySummary {
|
|
39
|
+
id: string;
|
|
40
|
+
label: string;
|
|
41
|
+
description: string;
|
|
42
|
+
defaultRole: AiModelRoleId;
|
|
43
|
+
}
|
|
44
|
+
export interface IListAiCapabilitiesUseCase {
|
|
45
|
+
execute(): Promise<IAiCapabilitySummary[]>;
|
|
46
|
+
}
|
|
47
|
+
/** Everything registered, for the settings screen to render a row per feature. */
|
|
48
|
+
export declare const ListAiCapabilitiesUseCase: import("@webiny/di").Abstraction<IListAiCapabilitiesUseCase>;
|
|
49
|
+
export declare namespace ListAiCapabilitiesUseCase {
|
|
50
|
+
type Interface = IListAiCapabilitiesUseCase;
|
|
51
|
+
type Summary = IAiCapabilitySummary;
|
|
52
|
+
}
|
|
53
|
+
export interface IResolvedAiCapability {
|
|
54
|
+
capabilityId: string;
|
|
55
|
+
/** Fully qualified, e.g. `"anthropic/claude-sonnet-4-5"`. */
|
|
56
|
+
model: string;
|
|
57
|
+
connection: {
|
|
58
|
+
sdkName: string;
|
|
59
|
+
apiKey: string;
|
|
60
|
+
};
|
|
61
|
+
/** Which role supplied the model. `null` when a capability override pinned it directly. */
|
|
62
|
+
roleId: AiModelRoleId | null;
|
|
63
|
+
/** True when the requested role was empty and `standard` filled in for it. */
|
|
64
|
+
fellBackToStandard: boolean;
|
|
65
|
+
/** The capability's own guidance. Empty when it assembles its prompt per request. */
|
|
66
|
+
guidance: string;
|
|
67
|
+
/** Project text to append to the system prompt. Empty when unset. */
|
|
68
|
+
additionalInstructions: string;
|
|
69
|
+
}
|
|
70
|
+
export interface IResolveAiCapabilityUseCase {
|
|
71
|
+
execute(capabilityId: string): Promise<Result<IResolvedAiCapability, Error>>;
|
|
72
|
+
}
|
|
73
|
+
export declare const ResolveAiCapabilityUseCase: import("@webiny/di").Abstraction<IResolveAiCapabilityUseCase>;
|
|
74
|
+
export declare namespace ResolveAiCapabilityUseCase {
|
|
75
|
+
type Interface = IResolveAiCapabilityUseCase;
|
|
76
|
+
type Resolution = IResolvedAiCapability;
|
|
77
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createAbstraction } from "@webiny/feature/api";
|
|
2
|
+
const AiCapability = createAbstraction("AiPowerUpsAiCapability");
|
|
3
|
+
const ListAiCapabilitiesUseCase = createAbstraction("AiPowerUpsListAiCapabilitiesUseCase");
|
|
4
|
+
const ResolveAiCapabilityUseCase = createAbstraction("AiPowerUpsResolveAiCapabilityUseCase");
|
|
5
|
+
export { AiCapability, ListAiCapabilitiesUseCase, ResolveAiCapabilityUseCase };
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=abstractions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/Capabilities/abstractions.js","sources":["../../../../src/api/features/Capabilities/abstractions.ts"],"sourcesContent":["import { createAbstraction, Result } from \"@webiny/feature/api\";\nimport type { AiModelRoleId } from \"~/api/features/ModelRoles/index.js\";\n\n/**\n * One AI feature, declared so the settings screen can list it and a project can point it at a\n * different model or adjust its prompt.\n *\n * Features register these; nothing hardcodes the list. An extension that adds an AI feature gets a\n * row in Settings for free by registering a capability alongside it.\n */\nexport interface IAiCapability {\n /** Stable, namespaced, and persisted as a settings key. Renaming one orphans its overrides. */\n readonly id: string;\n readonly label: string;\n readonly description: string;\n /** Which role supplies the model when the project has not overridden this capability. */\n readonly defaultRole: AiModelRoleId;\n /**\n * The capability's fixed system-prompt block, owned by the code and not configurable.\n *\n * Leave it undefined when the prompt is assembled per request (from a content model schema, a\n * component catalog, a persona) and the use case builds its own system text instead.\n *\n * Either way a project can only append to it, via `additionalInstructions`. These prompts carry\n * the output contract the surrounding code parses, so they are implementation, not settings.\n */\n readonly guidance?: string;\n}\n\nexport const AiCapability = createAbstraction<IAiCapability>(\"AiPowerUpsAiCapability\");\n\nexport namespace AiCapability {\n export type Interface = IAiCapability;\n}\n\n/**\n * What a capability looks like to a caller outside the api.\n *\n * `guidance` is deliberately absent: a prompt is implementation, and there is no reason to ship ours\n * over the wire to anyone who can read settings.\n */\nexport interface IAiCapabilitySummary {\n id: string;\n label: string;\n description: string;\n defaultRole: AiModelRoleId;\n}\n\nexport interface IListAiCapabilitiesUseCase {\n execute(): Promise<IAiCapabilitySummary[]>;\n}\n\n/** Everything registered, for the settings screen to render a row per feature. */\nexport const ListAiCapabilitiesUseCase = createAbstraction<IListAiCapabilitiesUseCase>(\n \"AiPowerUpsListAiCapabilitiesUseCase\"\n);\n\nexport namespace ListAiCapabilitiesUseCase {\n export type Interface = IListAiCapabilitiesUseCase;\n export type Summary = IAiCapabilitySummary;\n}\n\nexport interface IResolvedAiCapability {\n capabilityId: string;\n /** Fully qualified, e.g. `\"anthropic/claude-sonnet-4-5\"`. */\n model: string;\n connection: {\n sdkName: string;\n apiKey: string;\n };\n /** Which role supplied the model. `null` when a capability override pinned it directly. */\n roleId: AiModelRoleId | null;\n /** True when the requested role was empty and `standard` filled in for it. */\n fellBackToStandard: boolean;\n /** The capability's own guidance. Empty when it assembles its prompt per request. */\n guidance: string;\n /** Project text to append to the system prompt. Empty when unset. */\n additionalInstructions: string;\n}\n\nexport interface IResolveAiCapabilityUseCase {\n execute(capabilityId: string): Promise<Result<IResolvedAiCapability, Error>>;\n}\n\nexport const ResolveAiCapabilityUseCase = createAbstraction<IResolveAiCapabilityUseCase>(\n \"AiPowerUpsResolveAiCapabilityUseCase\"\n);\n\nexport namespace ResolveAiCapabilityUseCase {\n export type Interface = IResolveAiCapabilityUseCase;\n export type Resolution = IResolvedAiCapability;\n}\n"],"names":["AiCapability","createAbstraction","ListAiCapabilitiesUseCase","ResolveAiCapabilityUseCase"],"mappings":";AA6BO,MAAMA,eAAeC,kBAAiC;AAwBtD,MAAMC,4BAA4BD,kBACrC;AA8BG,MAAME,6BAA6BF,kBACtC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { IResolvedAiCapability } from "./abstractions.js";
|
|
2
|
+
/**
|
|
3
|
+
* Appends a project's additional instructions to a capability's system prompt.
|
|
4
|
+
*
|
|
5
|
+
* Appending is the only way a project adjusts a prompt, and the reason is upgrades: a project that
|
|
6
|
+
* appends keeps getting our prompt improvements, while one that replaced the prompt would be frozen
|
|
7
|
+
* at whatever we shipped the day they edited it. The heading is there so the model reads the
|
|
8
|
+
* project's text as instructions rather than as more of ours.
|
|
9
|
+
*
|
|
10
|
+
* `baseText` defaults to the capability's own guidance, which is what most callers want. The two
|
|
11
|
+
* generation use cases pass their own, because they build a prompt per request from a content model
|
|
12
|
+
* schema or a component catalog and the capability declares no fixed guidance of its own.
|
|
13
|
+
*/
|
|
14
|
+
export declare const withAdditionalInstructions: (resolved: Pick<IResolvedAiCapability, "guidance" | "additionalInstructions">, baseText?: string) => string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const withAdditionalInstructions = (resolved, baseText = resolved.guidance)=>{
|
|
2
|
+
if (!resolved.additionalInstructions) return baseText;
|
|
3
|
+
return `${baseText}
|
|
4
|
+
|
|
5
|
+
### Project instructions
|
|
6
|
+
|
|
7
|
+
These come from this project's settings and take precedence over the general guidance above.
|
|
8
|
+
|
|
9
|
+
${resolved.additionalInstructions}`;
|
|
10
|
+
};
|
|
11
|
+
export { withAdditionalInstructions };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=composeSystemPrompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/Capabilities/composeSystemPrompt.js","sources":["../../../../src/api/features/Capabilities/composeSystemPrompt.ts"],"sourcesContent":["import type { IResolvedAiCapability } from \"./abstractions.js\";\n\n/**\n * Appends a project's additional instructions to a capability's system prompt.\n *\n * Appending is the only way a project adjusts a prompt, and the reason is upgrades: a project that\n * appends keeps getting our prompt improvements, while one that replaced the prompt would be frozen\n * at whatever we shipped the day they edited it. The heading is there so the model reads the\n * project's text as instructions rather than as more of ours.\n *\n * `baseText` defaults to the capability's own guidance, which is what most callers want. The two\n * generation use cases pass their own, because they build a prompt per request from a content model\n * schema or a component catalog and the capability declares no fixed guidance of its own.\n */\nexport const withAdditionalInstructions = (\n resolved: Pick<IResolvedAiCapability, \"guidance\" | \"additionalInstructions\">,\n baseText: string = resolved.guidance\n): string => {\n if (!resolved.additionalInstructions) {\n return baseText;\n }\n\n return `${baseText}\n\n### Project instructions\n\nThese come from this project's settings and take precedence over the general guidance above.\n\n${resolved.additionalInstructions}`;\n};\n"],"names":["withAdditionalInstructions","resolved","baseText"],"mappings":"AAcO,MAAMA,6BAA6B,CACtCC,UACAC,WAAmBD,SAAS,QAAQ;IAEpC,IAAI,CAACA,SAAS,sBAAsB,EAChC,OAAOC;IAGX,OAAO,GAAGA,SAAS;;;;;;AAMvB,EAAED,SAAS,sBAAsB,EAAE;AACnC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createFeature } from "@webiny/feature/api";
|
|
2
|
+
import CapabilitiesHandler from "./CapabilitiesHandler.js";
|
|
3
|
+
import { ResolveAiCapabilityUseCaseImplementation } from "./ResolveAiCapabilityUseCase.js";
|
|
4
|
+
import { ListAiCapabilitiesUseCaseImplementation } from "./ListAiCapabilitiesUseCase.js";
|
|
5
|
+
const CapabilitiesFeature = createFeature({
|
|
6
|
+
name: "AiPowerUpsCapabilities",
|
|
7
|
+
register (container) {
|
|
8
|
+
container.register(CapabilitiesHandler);
|
|
9
|
+
container.register(ResolveAiCapabilityUseCaseImplementation);
|
|
10
|
+
container.register(ListAiCapabilitiesUseCaseImplementation);
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
export { CapabilitiesFeature };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=feature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/Capabilities/feature.js","sources":["../../../../src/api/features/Capabilities/feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport CapabilitiesHandler from \"./CapabilitiesHandler.js\";\nimport { ResolveAiCapabilityUseCaseImplementation } from \"./ResolveAiCapabilityUseCase.js\";\nimport { ListAiCapabilitiesUseCaseImplementation } from \"./ListAiCapabilitiesUseCase.js\";\n\nexport const CapabilitiesFeature = createFeature({\n name: \"AiPowerUpsCapabilities\",\n register(container) {\n container.register(CapabilitiesHandler);\n container.register(ResolveAiCapabilityUseCaseImplementation);\n container.register(ListAiCapabilitiesUseCaseImplementation);\n }\n});\n"],"names":["CapabilitiesFeature","createFeature","container","CapabilitiesHandler","ResolveAiCapabilityUseCaseImplementation","ListAiCapabilitiesUseCaseImplementation"],"mappings":";;;;AAKO,MAAMA,sBAAsBC,cAAc;IAC7C,MAAM;IACN,UAASC,SAAS;QACdA,UAAU,QAAQ,CAACC;QACnBD,UAAU,QAAQ,CAACE;QACnBF,UAAU,QAAQ,CAACG;IACvB;AACJ"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { AiCapability, ResolveAiCapabilityUseCase, ListAiCapabilitiesUseCase } from "./abstractions.js";
|
|
2
|
+
export type { IAiCapability, IResolvedAiCapability, IAiCapabilitySummary } from "./abstractions.js";
|
|
3
|
+
export { withAdditionalInstructions } from "./composeSystemPrompt.js";
|
|
4
|
+
export type { AiCapabilityOverride, CapabilitiesSettings } from "./types.js";
|
|
5
|
+
export { CapabilitiesFeature } from "./feature.js";
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { IAiPowerUpsSettings } from "../../../api/types.js";
|
|
2
|
+
import type { AiModelRoleId } from "../../../api/features/ModelRoles/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* What a project changed about one capability. Every field is optional and empty by default: an
|
|
5
|
+
* untouched capability runs on its declared role with its declared prompt.
|
|
6
|
+
*/
|
|
7
|
+
export interface AiCapabilityOverride {
|
|
8
|
+
/** Run this capability on a different role. Empty means use the capability's default. */
|
|
9
|
+
roleId?: AiModelRoleId | "";
|
|
10
|
+
/** Pin an exact connection, bypassing roles entirely. Requires `model` too. */
|
|
11
|
+
connectionId?: string;
|
|
12
|
+
/** Pin an exact model. Only read when `connectionId` is also set. */
|
|
13
|
+
model?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Appended to the capability's prompt.
|
|
16
|
+
*
|
|
17
|
+
* The only prompt customisation there is, and deliberately so. Replacing a prompt outright
|
|
18
|
+
* used to be offered here and is not any more: for most capabilities the prompt *is* the output
|
|
19
|
+
* contract the surrounding code parses, so replacing it means replacing part of the
|
|
20
|
+
* implementation. Revision comparison regex-matches the HTML table its prompt specifies, and
|
|
21
|
+
* page translation `JSON.parse`s a shape its prompt dictates, both failing silently if the
|
|
22
|
+
* format goes away. Appending leaves the contract in place.
|
|
23
|
+
*
|
|
24
|
+
* A project that genuinely needs different behaviour decorates the use case in code, which is
|
|
25
|
+
* how the AI translation itself is built.
|
|
26
|
+
*/
|
|
27
|
+
additionalInstructions?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Everything a project decided about one capability.
|
|
31
|
+
*
|
|
32
|
+
* Two separate concerns, deliberately not flattened into one bag of optional fields. `enabled` is a
|
|
33
|
+
* boolean and the rest are strings, and an emptiness check that has to judge both at once is how
|
|
34
|
+
* "the user switched this off" ends up indistinguishable from "the user typed nothing".
|
|
35
|
+
*/
|
|
36
|
+
export interface AiCapabilityEntry {
|
|
37
|
+
/**
|
|
38
|
+
* Absent means enabled.
|
|
39
|
+
*
|
|
40
|
+
* A licence that grants a capability turns it on immediately; nobody opens settings to opt in.
|
|
41
|
+
* A save writes this explicitly either way, so a stored blob says plainly what the screen said,
|
|
42
|
+
* but absence still has to read as enabled: a capability registered since the last save has no
|
|
43
|
+
* entry at all.
|
|
44
|
+
*
|
|
45
|
+
* Read it as `enabled !== false`, never as `!enabled`. The second is true for `undefined` too,
|
|
46
|
+
* which silently disables every capability nobody has saved yet.
|
|
47
|
+
*/
|
|
48
|
+
enabled?: boolean;
|
|
49
|
+
overrides: AiCapabilityOverride;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Keyed by capability id.
|
|
53
|
+
*
|
|
54
|
+
* Unlike model roles this cannot be a union of known keys: features register capabilities at
|
|
55
|
+
* runtime and an extension can add its own, so there is no compile-time set to enumerate.
|
|
56
|
+
*
|
|
57
|
+
* `Partial` is doing real work though. A bare `Record<string, T>` claims every string key is
|
|
58
|
+
* present, so a lookup types as `T` and the `?? {}` every caller writes looks redundant to the
|
|
59
|
+
* compiler. Most capabilities are untouched, so a miss is the common case.
|
|
60
|
+
*/
|
|
61
|
+
export type AiCapabilityEntries = Partial<Record<string, AiCapabilityEntry>>;
|
|
62
|
+
declare module "~/api/types.js" {
|
|
63
|
+
interface IAiPowerUpsSettings {
|
|
64
|
+
capabilities: {
|
|
65
|
+
items: AiCapabilityEntries;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export type CapabilitiesSettings = IAiPowerUpsSettings["capabilities"];
|
|
70
|
+
/**
|
|
71
|
+
* What `mapToStorage` writes, where `enabled` is required.
|
|
72
|
+
*
|
|
73
|
+
* Reading has to tolerate its absence, because an entry saved before this flag existed, or a
|
|
74
|
+
* capability registered since the last save, has no value for it. Writing never does: every entry
|
|
75
|
+
* the form posts is settled to a real boolean. Saying so here is what makes the compiler check the
|
|
76
|
+
* one place that writes the flag this feature is about.
|
|
77
|
+
*/
|
|
78
|
+
export interface PersistedAiCapabilityEntry {
|
|
79
|
+
enabled: boolean;
|
|
80
|
+
overrides: AiCapabilityOverride;
|
|
81
|
+
}
|
|
82
|
+
export interface PersistedCapabilities {
|
|
83
|
+
items?: Partial<Record<string, PersistedAiCapabilityEntry>>;
|
|
84
|
+
}
|
|
85
|
+
/** Absent means enabled. Spelled out once so no call site has to get the comparison right. */
|
|
86
|
+
export declare const isCapabilityEnabled: (entry: AiCapabilityEntry | undefined) => boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/features/Capabilities/types.js","sources":["../../../../src/api/features/Capabilities/types.ts"],"sourcesContent":["import type { IAiPowerUpsSettings } from \"~/api/types.js\";\nimport type { AiModelRoleId } from \"~/api/features/ModelRoles/index.js\";\n\n/**\n * What a project changed about one capability. Every field is optional and empty by default: an\n * untouched capability runs on its declared role with its declared prompt.\n */\nexport interface AiCapabilityOverride {\n /** Run this capability on a different role. Empty means use the capability's default. */\n roleId?: AiModelRoleId | \"\";\n /** Pin an exact connection, bypassing roles entirely. Requires `model` too. */\n connectionId?: string;\n /** Pin an exact model. Only read when `connectionId` is also set. */\n model?: string;\n /**\n * Appended to the capability's prompt.\n *\n * The only prompt customisation there is, and deliberately so. Replacing a prompt outright\n * used to be offered here and is not any more: for most capabilities the prompt *is* the output\n * contract the surrounding code parses, so replacing it means replacing part of the\n * implementation. Revision comparison regex-matches the HTML table its prompt specifies, and\n * page translation `JSON.parse`s a shape its prompt dictates, both failing silently if the\n * format goes away. Appending leaves the contract in place.\n *\n * A project that genuinely needs different behaviour decorates the use case in code, which is\n * how the AI translation itself is built.\n */\n additionalInstructions?: string;\n}\n\n/**\n * Everything a project decided about one capability.\n *\n * Two separate concerns, deliberately not flattened into one bag of optional fields. `enabled` is a\n * boolean and the rest are strings, and an emptiness check that has to judge both at once is how\n * \"the user switched this off\" ends up indistinguishable from \"the user typed nothing\".\n */\nexport interface AiCapabilityEntry {\n /**\n * Absent means enabled.\n *\n * A licence that grants a capability turns it on immediately; nobody opens settings to opt in.\n * A save writes this explicitly either way, so a stored blob says plainly what the screen said,\n * but absence still has to read as enabled: a capability registered since the last save has no\n * entry at all.\n *\n * Read it as `enabled !== false`, never as `!enabled`. The second is true for `undefined` too,\n * which silently disables every capability nobody has saved yet.\n */\n enabled?: boolean;\n overrides: AiCapabilityOverride;\n}\n\n/**\n * Keyed by capability id.\n *\n * Unlike model roles this cannot be a union of known keys: features register capabilities at\n * runtime and an extension can add its own, so there is no compile-time set to enumerate.\n *\n * `Partial` is doing real work though. A bare `Record<string, T>` claims every string key is\n * present, so a lookup types as `T` and the `?? {}` every caller writes looks redundant to the\n * compiler. Most capabilities are untouched, so a miss is the common case.\n */\nexport type AiCapabilityEntries = Partial<Record<string, AiCapabilityEntry>>;\n\ndeclare module \"~/api/types.js\" {\n interface IAiPowerUpsSettings {\n capabilities: {\n items: AiCapabilityEntries;\n };\n }\n}\n\nexport type CapabilitiesSettings = IAiPowerUpsSettings[\"capabilities\"];\n\n/**\n * What `mapToStorage` writes, where `enabled` is required.\n *\n * Reading has to tolerate its absence, because an entry saved before this flag existed, or a\n * capability registered since the last save, has no value for it. Writing never does: every entry\n * the form posts is settled to a real boolean. Saying so here is what makes the compiler check the\n * one place that writes the flag this feature is about.\n */\nexport interface PersistedAiCapabilityEntry {\n enabled: boolean;\n overrides: AiCapabilityOverride;\n}\n\nexport interface PersistedCapabilities {\n items?: Partial<Record<string, PersistedAiCapabilityEntry>>;\n}\n\n/** Absent means enabled. Spelled out once so no call site has to get the comparison right. */\nexport const isCapabilityEnabled = (entry: AiCapabilityEntry | undefined): boolean =>\n entry?.enabled !== false;\n"],"names":["isCapabilityEnabled","entry"],"mappings":"AA6FO,MAAMA,sBAAsB,CAACC,QAChCA,OAAO,YAAY"}
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import { Ai } from "@webiny/api-core/features/ai/index.js";
|
|
2
|
-
import { Encryption } from "@webiny/api-core/features/encryption/index.js";
|
|
3
2
|
import { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
|
|
4
3
|
import { ModelToAstConverter } from "@webiny/api-headless-cms/features/contentModel/ModelToAstConverter/index.js";
|
|
5
4
|
import { GetRevisionByIdUseCase } from "@webiny/api-headless-cms/features/contentEntry/GetRevisionById/index.js";
|
|
6
|
-
import {
|
|
5
|
+
import { ResolveAiCapabilityUseCase } from "../../../api/features/Capabilities/index.js";
|
|
7
6
|
import { CmsCompareEntryRevisionsUseCase } from "./abstractions.js";
|
|
8
7
|
import type { ICmsCompareEntryRevisionsParams, ICmsCompareEntryRevisionsResult } from "./abstractions.js";
|
|
9
8
|
declare class CmsCompareEntryRevisionsUseCaseImpl implements CmsCompareEntryRevisionsUseCase.Interface {
|
|
10
|
-
private
|
|
9
|
+
private resolveCapability;
|
|
11
10
|
private ai;
|
|
12
|
-
private encryption;
|
|
13
11
|
private getModel;
|
|
14
12
|
private getRevisionById;
|
|
15
13
|
private modelToAst;
|
|
16
|
-
constructor(
|
|
14
|
+
constructor(resolveCapability: ResolveAiCapabilityUseCase.Interface, ai: Ai.Interface, getModel: GetModelUseCase.Interface, getRevisionById: GetRevisionByIdUseCase.Interface, modelToAst: ModelToAstConverter.Interface);
|
|
17
15
|
execute(params: ICmsCompareEntryRevisionsParams): Promise<ICmsCompareEntryRevisionsResult>;
|
|
18
16
|
}
|
|
19
17
|
export declare const CmsCompareEntryRevisionsUseCaseImplementation: typeof CmsCompareEntryRevisionsUseCaseImpl & {
|