@ai-stack/payloadcms 3.76.0-beta.1 → 3.76.0-beta.3
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/dist/ai/core/generateObject.js +1 -4
- package/dist/ai/core/generateObject.js.map +1 -1
- package/dist/ai/core/generateText.js +1 -5
- package/dist/ai/core/generateText.js.map +1 -1
- package/dist/ai/core/media/generateMedia.js +1 -4
- package/dist/ai/core/media/generateMedia.js.map +1 -1
- package/dist/ai/core/media/image/generateImage.js +4 -14
- package/dist/ai/core/media/image/generateImage.js.map +1 -1
- package/dist/ai/core/media/image/handlers/multimodal.js +7 -24
- package/dist/ai/core/media/image/handlers/multimodal.js.map +1 -1
- package/dist/ai/core/media/image/handlers/standard.js +7 -2
- package/dist/ai/core/media/image/handlers/standard.js.map +1 -1
- package/dist/ai/core/media/speech/generateSpeech.js +2 -3
- package/dist/ai/core/media/speech/generateSpeech.js.map +1 -1
- package/dist/ai/core/media/types.d.ts +2 -3
- package/dist/ai/core/media/types.js.map +1 -1
- package/dist/ai/core/streamObject.js +0 -3
- package/dist/ai/core/streamObject.js.map +1 -1
- package/dist/ai/core/streamText.js +1 -4
- package/dist/ai/core/streamText.js.map +1 -1
- package/dist/ai/core/types.d.ts +2 -2
- package/dist/ai/core/types.js.map +1 -1
- package/dist/ai/providers/blocks/anthropic.js +2 -44
- package/dist/ai/providers/blocks/anthropic.js.map +1 -1
- package/dist/ai/providers/blocks/elevenlabs.js +4 -109
- package/dist/ai/providers/blocks/elevenlabs.js.map +1 -1
- package/dist/ai/providers/blocks/fal.js +2 -120
- package/dist/ai/providers/blocks/fal.js.map +1 -1
- package/dist/ai/providers/blocks/google.js +6 -240
- package/dist/ai/providers/blocks/google.js.map +1 -1
- package/dist/ai/providers/blocks/openai-compatible.js +2 -146
- package/dist/ai/providers/blocks/openai-compatible.js.map +1 -1
- package/dist/ai/providers/blocks/openai.js +2 -202
- package/dist/ai/providers/blocks/openai.js.map +1 -1
- package/dist/ai/providers/blocks/xai.js +2 -55
- package/dist/ai/providers/blocks/xai.js.map +1 -1
- package/dist/ai/providers/index.d.ts +1 -1
- package/dist/ai/providers/index.js +0 -2
- package/dist/ai/providers/index.js.map +1 -1
- package/dist/ai/providers/registry.d.ts +24 -28
- package/dist/ai/providers/registry.js +184 -138
- package/dist/ai/providers/registry.js.map +1 -1
- package/dist/ai/providers/types.d.ts +12 -33
- package/dist/ai/providers/types.js +0 -1
- package/dist/ai/providers/types.js.map +1 -1
- package/dist/ai/schemas/lexicalJsonSchema.js +1 -1
- package/dist/ai/schemas/lexicalJsonSchema.js.map +1 -1
- package/dist/ai/utilities/filterEditorSchemaByNodes.js.map +1 -0
- package/dist/ai/utilities/generateFileNameByPrompt.js.map +1 -0
- package/dist/ai/utilities/isObjectSchema.js.map +1 -0
- package/dist/ai/{utils → utilities}/nodeToSchemaMap.js +6 -6
- package/dist/ai/utilities/nodeToSchemaMap.js.map +1 -0
- package/dist/ai/{prompts.d.ts → utilities/prompts.d.ts} +1 -1
- package/dist/ai/utilities/prompts.js.map +1 -0
- package/dist/ai/utilities/systemGenerate.js.map +1 -0
- package/dist/collections/AIJobs.js +3 -12
- package/dist/collections/AIJobs.js.map +1 -1
- package/dist/collections/AIProviders.js +56 -29
- package/dist/collections/AIProviders.js.map +1 -1
- package/dist/collections/Instructions.js +91 -59
- package/dist/collections/Instructions.js.map +1 -1
- package/dist/collections/shared.d.ts +30 -0
- package/dist/collections/shared.js +15 -0
- package/dist/collections/shared.js.map +1 -0
- package/dist/endpoints/fetchFields.js +14 -6
- package/dist/endpoints/fetchFields.js.map +1 -1
- package/dist/endpoints/fetchVoices.js +1 -1
- package/dist/endpoints/fetchVoices.js.map +1 -1
- package/dist/endpoints/generate.d.ts +7 -0
- package/dist/endpoints/generate.js +268 -0
- package/dist/endpoints/generate.js.map +1 -0
- package/dist/endpoints/index.js +9 -639
- package/dist/endpoints/index.js.map +1 -1
- package/dist/endpoints/promptMentions.d.ts +2 -0
- package/dist/endpoints/promptMentions.js +166 -0
- package/dist/endpoints/promptMentions.js.map +1 -0
- package/dist/endpoints/upload.d.ts +7 -0
- package/dist/endpoints/upload.js +294 -0
- package/dist/endpoints/upload.js.map +1 -0
- package/dist/endpoints/videogenWebhook.d.ts +7 -0
- package/dist/endpoints/videogenWebhook.js +132 -0
- package/dist/endpoints/videogenWebhook.js.map +1 -0
- package/dist/exports/client.d.ts +2 -1
- package/dist/exports/client.js +2 -1
- package/dist/exports/client.js.map +1 -1
- package/dist/exports/fields.d.ts +2 -1
- package/dist/exports/fields.js +2 -1
- package/dist/exports/fields.js.map +1 -1
- package/dist/fields/ArrayComposeField/ArrayComposeField.js +1 -1
- package/dist/fields/ArrayComposeField/ArrayComposeField.js.map +1 -1
- package/dist/fields/ArrayComposeField/ArrayComposeField.jsx +1 -1
- package/dist/fields/ComposeField/ComposeField.d.ts +1 -0
- package/dist/fields/ComposeField/ComposeField.js +18 -8
- package/dist/fields/ComposeField/ComposeField.js.map +1 -1
- package/dist/fields/ComposeField/ComposeField.jsx +12 -7
- package/dist/fields/LexicalEditor/feature.server.js +1 -1
- package/dist/fields/LexicalEditor/feature.server.js.map +1 -1
- package/dist/fields/PromptEditorField/feature.client.d.ts +1 -0
- package/dist/fields/PromptEditorField/feature.client.js +173 -0
- package/dist/fields/PromptEditorField/feature.client.js.map +1 -0
- package/dist/fields/PromptEditorField/feature.client.jsx +148 -0
- package/dist/fields/PromptEditorField/feature.server.d.ts +1 -0
- package/dist/fields/PromptEditorField/feature.server.js +30 -0
- package/dist/fields/PromptEditorField/feature.server.js.map +1 -0
- package/dist/fields/PromptField.d.ts +4 -0
- package/dist/fields/PromptField.js +18 -0
- package/dist/fields/PromptField.js.map +1 -0
- package/dist/fields/SelectField/SelectField.js +0 -1
- package/dist/fields/SelectField/SelectField.js.map +1 -1
- package/dist/fields/SelectField/SelectField.jsx +0 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/libraries/handlebars/helpers.js +2 -2
- package/dist/libraries/handlebars/helpers.js.map +1 -1
- package/dist/libraries/handlebars/replacePlaceholders.js +5 -1
- package/dist/libraries/handlebars/replacePlaceholders.js.map +1 -1
- package/dist/payload-ai.d.ts +5 -19
- package/dist/plugin.js +18 -21
- package/dist/plugin.js.map +1 -1
- package/dist/providers/FieldProvider/FieldProvider.js +11 -20
- package/dist/providers/FieldProvider/FieldProvider.js.map +1 -1
- package/dist/providers/FieldProvider/FieldProvider.jsx +8 -18
- package/dist/providers/InstructionsProvider/InstructionsProvider.js +5 -2
- package/dist/providers/InstructionsProvider/InstructionsProvider.js.map +1 -1
- package/dist/providers/InstructionsProvider/InstructionsProvider.jsx +5 -2
- package/dist/translations/de.json +47 -0
- package/dist/translations/en.json +45 -2
- package/dist/translations/es.json +45 -2
- package/dist/translations/fa.json +45 -2
- package/dist/translations/fr.json +46 -3
- package/dist/translations/hi.json +47 -0
- package/dist/translations/index.d.ts +88 -26
- package/dist/translations/index.js +18 -32
- package/dist/translations/index.js.map +1 -1
- package/dist/translations/ja.json +47 -0
- package/dist/translations/nb.json +47 -0
- package/dist/translations/nl.json +47 -0
- package/dist/translations/pl.json +45 -2
- package/dist/translations/pt.json +47 -0
- package/dist/translations/ru.json +45 -2
- package/dist/translations/th.json +47 -0
- package/dist/translations/translation-schema.json +184 -11
- package/dist/translations/uk.json +45 -2
- package/dist/translations/zh.json +47 -0
- package/dist/types.d.ts +64 -28
- package/dist/types.js.map +1 -1
- package/dist/ui/Compose/Compose.js +42 -79
- package/dist/ui/Compose/Compose.js.map +1 -1
- package/dist/ui/Compose/Compose.jsx +32 -86
- package/dist/ui/Compose/ComposePlaceholder.js +1 -1
- package/dist/ui/Compose/ComposePlaceholder.js.map +1 -1
- package/dist/ui/Compose/ComposePlaceholder.jsx +1 -1
- package/dist/ui/Compose/{compose.module.css → compose.module.scss} +3 -5
- package/dist/ui/Compose/hooks/menu/Item.d.ts +1 -1
- package/dist/ui/Compose/hooks/menu/Item.js +7 -3
- package/dist/ui/Compose/hooks/menu/Item.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/Item.jsx +11 -5
- package/dist/ui/Compose/hooks/menu/TranslateMenu.js +15 -5
- package/dist/ui/Compose/hooks/menu/TranslateMenu.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/TranslateMenu.jsx +11 -5
- package/dist/ui/Compose/hooks/menu/items.d.ts +8 -8
- package/dist/ui/Compose/hooks/menu/itemsMap.d.ts +2 -1
- package/dist/ui/Compose/hooks/menu/itemsMap.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/types.d.ts +21 -0
- package/dist/ui/Compose/hooks/menu/types.js +3 -0
- package/dist/ui/Compose/hooks/menu/types.js.map +1 -0
- package/dist/ui/Compose/hooks/menu/useMenu.d.ts +2 -2
- package/dist/ui/Compose/hooks/menu/useMenu.js +45 -23
- package/dist/ui/Compose/hooks/menu/useMenu.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/useMenu.jsx +43 -23
- package/dist/ui/Compose/hooks/mergeGeneratedValue.d.ts +14 -0
- package/dist/ui/Compose/hooks/mergeGeneratedValue.js +38 -0
- package/dist/ui/Compose/hooks/mergeGeneratedValue.js.map +1 -0
- package/dist/ui/Compose/hooks/useGenerate.js +37 -12
- package/dist/ui/Compose/hooks/useGenerate.js.map +1 -1
- package/dist/ui/Compose/hooks/useGenerateUpload.js +66 -24
- package/dist/ui/Compose/hooks/useGenerateUpload.js.map +1 -1
- package/dist/ui/Compose/hooks/useHistory.js +1 -1
- package/dist/ui/Compose/hooks/useHistory.js.map +1 -1
- package/dist/ui/Compose/hooks/useStreamingUpdate.js +4 -4
- package/dist/ui/Compose/hooks/useStreamingUpdate.js.map +1 -1
- package/dist/ui/ConfigDashboard/configDashboard.module.css +94 -0
- package/dist/ui/ConfigDashboard/index.js +27 -92
- package/dist/ui/ConfigDashboard/index.js.map +1 -1
- package/dist/ui/ConfigDashboard/index.jsx +24 -77
- package/dist/ui/DynamicModelSelect/index.js +6 -27
- package/dist/ui/DynamicModelSelect/index.js.map +1 -1
- package/dist/ui/DynamicModelSelect/index.jsx +6 -29
- package/dist/ui/DynamicProviderSelect/index.js +6 -27
- package/dist/ui/DynamicProviderSelect/index.js.map +1 -1
- package/dist/ui/DynamicProviderSelect/index.jsx +6 -29
- package/dist/ui/DynamicVoiceSelect/index.js +34 -83
- package/dist/ui/DynamicVoiceSelect/index.js.map +1 -1
- package/dist/ui/DynamicVoiceSelect/index.jsx +16 -53
- package/dist/ui/GlobalProviderOptions/index.d.ts +2 -0
- package/dist/ui/GlobalProviderOptions/index.js +118 -0
- package/dist/ui/GlobalProviderOptions/index.js.map +1 -0
- package/dist/ui/GlobalProviderOptions/index.jsx +60 -0
- package/dist/ui/Icons/Icons.js +1 -1
- package/dist/ui/Icons/Icons.js.map +1 -1
- package/dist/ui/Icons/Icons.jsx +1 -1
- package/dist/ui/Icons/LottieAnimation.js +1 -1
- package/dist/ui/Icons/LottieAnimation.js.map +1 -1
- package/dist/ui/Icons/LottieAnimation.jsx +1 -1
- package/dist/ui/InstructionProviderOptions/ProviderOptionsTree.d.ts +12 -0
- package/dist/ui/InstructionProviderOptions/ProviderOptionsTree.js +166 -0
- package/dist/ui/InstructionProviderOptions/ProviderOptionsTree.js.map +1 -0
- package/dist/ui/InstructionProviderOptions/ProviderOptionsTree.jsx +83 -0
- package/dist/ui/InstructionProviderOptions/index.d.ts +2 -0
- package/dist/ui/InstructionProviderOptions/index.js +157 -0
- package/dist/ui/InstructionProviderOptions/index.js.map +1 -0
- package/dist/ui/InstructionProviderOptions/index.jsx +92 -0
- package/dist/ui/VoicesFetcher/index.js.map +1 -1
- package/dist/ui/hooks/useAISettings.d.ts +26 -0
- package/dist/ui/hooks/useAISettings.js +73 -0
- package/dist/ui/hooks/useAISettings.js.map +1 -0
- package/dist/ui/providerOptions/updateProviderOptionsValue.d.ts +6 -0
- package/dist/ui/providerOptions/updateProviderOptionsValue.js +50 -0
- package/dist/ui/providerOptions/updateProviderOptionsValue.js.map +1 -0
- package/dist/ui/shared/handleSelectChange.d.ts +5 -0
- package/dist/ui/shared/handleSelectChange.js +12 -0
- package/dist/ui/shared/handleSelectChange.js.map +1 -0
- package/dist/ui/shared/types.d.ts +11 -0
- package/dist/ui/shared/types.js +5 -0
- package/dist/ui/shared/types.js.map +1 -0
- package/dist/utilities/ai/resolveEffectiveInstructionSettings.d.ts +15 -0
- package/dist/utilities/ai/resolveEffectiveInstructionSettings.js +136 -0
- package/dist/utilities/ai/resolveEffectiveInstructionSettings.js.map +1 -0
- package/dist/{endpoints → utilities}/buildPromptUtils.js +14 -5
- package/dist/utilities/buildPromptUtils.js.map +1 -0
- package/dist/utilities/buildSmartPrompt.js +3 -3
- package/dist/utilities/buildSmartPrompt.js.map +1 -1
- package/dist/utilities/fields/fieldToJsonSchema.js.map +1 -0
- package/dist/utilities/fields/getFieldBySchemaPath.js.map +1 -0
- package/dist/utilities/fields/getFieldInfo.js.map +1 -0
- package/dist/utilities/{updateFieldsConfig.js → fields/updateFieldsConfig.js} +8 -3
- package/dist/utilities/fields/updateFieldsConfig.js.map +1 -0
- package/dist/utilities/images/extractImageData.js.map +1 -0
- package/dist/utilities/images/extractPromptAttachments.js.map +1 -0
- package/dist/utilities/{fetchImages.d.ts → images/fetchImages.d.ts} +1 -1
- package/dist/utilities/images/fetchImages.js +49 -0
- package/dist/utilities/images/fetchImages.js.map +1 -0
- package/dist/utilities/images/resolveImageReferences.js +183 -0
- package/dist/utilities/images/resolveImageReferences.js.map +1 -0
- package/dist/utilities/init/autoSetupProviders.d.ts +3 -0
- package/dist/utilities/init/autoSetupProviders.js +216 -0
- package/dist/utilities/init/autoSetupProviders.js.map +1 -0
- package/dist/utilities/lexical/editorSchemaValidator.js.map +1 -0
- package/dist/utilities/lexical/lexicalToHTML.js.map +1 -0
- package/dist/utilities/lexical/lexicalToPromptTemplate.d.ts +2 -0
- package/dist/utilities/lexical/lexicalToPromptTemplate.js +50 -0
- package/dist/utilities/lexical/lexicalToPromptTemplate.js.map +1 -0
- package/dist/utilities/lexical/setSafeLexicalState.js.map +1 -0
- package/dist/utilities/lexical/stringToLexicalJSON.d.ts +2 -0
- package/dist/utilities/lexical/stringToLexicalJSON.js +39 -0
- package/dist/utilities/lexical/stringToLexicalJSON.js.map +1 -0
- package/dist/utilities/sanitizeLog.d.ts +1 -0
- package/dist/utilities/sanitizeLog.js +39 -0
- package/dist/utilities/sanitizeLog.js.map +1 -0
- package/dist/utilities/seedProperties.js +54 -22
- package/dist/utilities/seedProperties.js.map +1 -1
- package/package.json +36 -2
- package/dist/ai/analyse.d.ts +0 -1
- package/dist/ai/analyse.js +0 -3
- package/dist/ai/analyse.js.map +0 -1
- package/dist/ai/index.d.ts +0 -11
- package/dist/ai/index.js +0 -25
- package/dist/ai/index.js.map +0 -1
- package/dist/ai/prompts.js.map +0 -1
- package/dist/ai/utils/filterEditorSchemaByNodes.js.map +0 -1
- package/dist/ai/utils/generateFileNameByPrompt.js.map +0 -1
- package/dist/ai/utils/isObjectSchema.js.map +0 -1
- package/dist/ai/utils/nodeToSchemaMap.js.map +0 -1
- package/dist/ai/utils/systemGenerate.js.map +0 -1
- package/dist/endpoints/buildPromptUtils.js.map +0 -1
- package/dist/endpoints/chat.d.ts +0 -4
- package/dist/fields/PromptEditorField/PromptEditorField.d.ts +0 -3
- package/dist/fields/PromptEditorField/PromptEditorField.js +0 -217
- package/dist/fields/PromptEditorField/PromptEditorField.js.map +0 -1
- package/dist/fields/PromptEditorField/PromptEditorField.jsx +0 -160
- package/dist/ui/AIConfigDashboard/index.d.ts +0 -2
- package/dist/ui/AIConfigDashboard/index.js +0 -224
- package/dist/ui/AIConfigDashboard/index.js.map +0 -1
- package/dist/ui/AIConfigDashboard/index.jsx +0 -175
- package/dist/ui/ProviderOptionsEditor/index.d.ts +0 -7
- package/dist/ui/ProviderOptionsEditor/index.js +0 -291
- package/dist/ui/ProviderOptionsEditor/index.js.map +0 -1
- package/dist/ui/ProviderOptionsEditor/index.jsx +0 -210
- package/dist/utilities/editorSchemaValidator.js.map +0 -1
- package/dist/utilities/extractImageData.js.map +0 -1
- package/dist/utilities/extractPromptAttachments.js.map +0 -1
- package/dist/utilities/fetchImages.js +0 -38
- package/dist/utilities/fetchImages.js.map +0 -1
- package/dist/utilities/fieldToJsonSchema.js.map +0 -1
- package/dist/utilities/getFieldBySchemaPath.js.map +0 -1
- package/dist/utilities/getFieldInfo.js.map +0 -1
- package/dist/utilities/getProviderOptionsFields.d.ts +0 -16
- package/dist/utilities/getProviderOptionsFields.js +0 -80
- package/dist/utilities/getProviderOptionsFields.js.map +0 -1
- package/dist/utilities/isPluginActivated.d.ts +0 -2
- package/dist/utilities/isPluginActivated.js +0 -5
- package/dist/utilities/isPluginActivated.js.map +0 -1
- package/dist/utilities/lexicalToHTML.js.map +0 -1
- package/dist/utilities/resolveImageReferences.js +0 -167
- package/dist/utilities/resolveImageReferences.js.map +0 -1
- package/dist/utilities/schemaConverter.d.ts +0 -3
- package/dist/utilities/schemaConverter.js +0 -93
- package/dist/utilities/schemaConverter.js.map +0 -1
- package/dist/utilities/setSafeLexicalState.js.map +0 -1
- package/dist/utilities/updateFieldsConfig.js.map +0 -1
- /package/dist/ai/{utils → utilities}/filterEditorSchemaByNodes.d.ts +0 -0
- /package/dist/ai/{utils → utilities}/filterEditorSchemaByNodes.js +0 -0
- /package/dist/ai/{utils → utilities}/generateFileNameByPrompt.d.ts +0 -0
- /package/dist/ai/{utils → utilities}/generateFileNameByPrompt.js +0 -0
- /package/dist/ai/{utils → utilities}/isObjectSchema.d.ts +0 -0
- /package/dist/ai/{utils → utilities}/isObjectSchema.js +0 -0
- /package/dist/ai/{utils → utilities}/nodeToSchemaMap.d.ts +0 -0
- /package/dist/ai/{prompts.js → utilities/prompts.js} +0 -0
- /package/dist/ai/{utils → utilities}/systemGenerate.d.ts +0 -0
- /package/dist/ai/{utils → utilities}/systemGenerate.js +0 -0
- /package/dist/ui/Icons/{icons.module.css → icons.module.scss} +0 -0
- /package/dist/{endpoints → utilities}/buildPromptUtils.d.ts +0 -0
- /package/dist/utilities/{fieldToJsonSchema.d.ts → fields/fieldToJsonSchema.d.ts} +0 -0
- /package/dist/utilities/{fieldToJsonSchema.js → fields/fieldToJsonSchema.js} +0 -0
- /package/dist/utilities/{getFieldBySchemaPath.d.ts → fields/getFieldBySchemaPath.d.ts} +0 -0
- /package/dist/utilities/{getFieldBySchemaPath.js → fields/getFieldBySchemaPath.js} +0 -0
- /package/dist/utilities/{getFieldInfo.d.ts → fields/getFieldInfo.d.ts} +0 -0
- /package/dist/utilities/{getFieldInfo.js → fields/getFieldInfo.js} +0 -0
- /package/dist/utilities/{updateFieldsConfig.d.ts → fields/updateFieldsConfig.d.ts} +0 -0
- /package/dist/utilities/{extractImageData.d.ts → images/extractImageData.d.ts} +0 -0
- /package/dist/utilities/{extractImageData.js → images/extractImageData.js} +0 -0
- /package/dist/utilities/{extractPromptAttachments.d.ts → images/extractPromptAttachments.d.ts} +0 -0
- /package/dist/utilities/{extractPromptAttachments.js → images/extractPromptAttachments.js} +0 -0
- /package/dist/utilities/{resolveImageReferences.d.ts → images/resolveImageReferences.d.ts} +0 -0
- /package/dist/utilities/{editorSchemaValidator.d.ts → lexical/editorSchemaValidator.d.ts} +0 -0
- /package/dist/utilities/{editorSchemaValidator.js → lexical/editorSchemaValidator.js} +0 -0
- /package/dist/utilities/{lexicalToHTML.d.ts → lexical/lexicalToHTML.d.ts} +0 -0
- /package/dist/utilities/{lexicalToHTML.js → lexical/lexicalToHTML.js} +0 -0
- /package/dist/utilities/{setSafeLexicalState.d.ts → lexical/setSafeLexicalState.d.ts} +0 -0
- /package/dist/utilities/{setSafeLexicalState.js → lexical/setSafeLexicalState.js} +0 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useField, useFormFields } from '@payloadcms/ui';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { useCallback, useMemo } from 'react';
|
|
5
|
+
import { useAISettings } from '../hooks/useAISettings.js';
|
|
6
|
+
import { updateProviderOptionsValue } from '../providerOptions/updateProviderOptionsValue.js';
|
|
7
|
+
import { ProviderOptionsTree } from './ProviderOptionsTree.js';
|
|
8
|
+
function inferUseCase(fieldPath) {
|
|
9
|
+
const parentName = fieldPath.split('.').slice(-2)[0];
|
|
10
|
+
if (parentName === 'image-settings') {
|
|
11
|
+
return 'image';
|
|
12
|
+
}
|
|
13
|
+
if (parentName === 'tts-settings') {
|
|
14
|
+
return 'tts';
|
|
15
|
+
}
|
|
16
|
+
if (parentName === 'video-settings') {
|
|
17
|
+
return 'video';
|
|
18
|
+
}
|
|
19
|
+
return 'text';
|
|
20
|
+
}
|
|
21
|
+
export const InstructionProviderOptions = ({ path }) => {
|
|
22
|
+
const { data: aiSettings } = useAISettings();
|
|
23
|
+
const fieldPath = path || '';
|
|
24
|
+
const groupPath = fieldPath.split('.').slice(0, -1).join('.');
|
|
25
|
+
const providerPath = `${groupPath}.provider`;
|
|
26
|
+
const useCase = useMemo(() => inferUseCase(fieldPath), [fieldPath]);
|
|
27
|
+
const providerField = useFormFields(([fields]) => fields[providerPath]);
|
|
28
|
+
const provider = providerField?.value;
|
|
29
|
+
const { setValue: setProviderOptionsValues, value: providerOptionsValues } = useField({
|
|
30
|
+
path: fieldPath,
|
|
31
|
+
});
|
|
32
|
+
// 1. Find the provider's schema for this use case
|
|
33
|
+
const schema = useMemo(() => {
|
|
34
|
+
if (!provider || !aiSettings?.defaults) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const useCaseDefaults = aiSettings.defaults[useCase];
|
|
38
|
+
// We stored the raw schema object directly under schemas[provider] during autoSetup
|
|
39
|
+
const schemas = useCaseDefaults?.schema;
|
|
40
|
+
return schemas?.[provider] || null;
|
|
41
|
+
}, [aiSettings, provider, useCase]);
|
|
42
|
+
const providerLabel = useMemo(() => {
|
|
43
|
+
if (!provider) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const providers = Array.isArray(aiSettings?.providers) ? aiSettings.providers : [];
|
|
47
|
+
const configuredProvider = providers.find((item) => item &&
|
|
48
|
+
typeof item === 'object' &&
|
|
49
|
+
'blockType' in item &&
|
|
50
|
+
item.blockType === provider);
|
|
51
|
+
if (configuredProvider?.providerName) {
|
|
52
|
+
return configuredProvider.providerName;
|
|
53
|
+
}
|
|
54
|
+
return provider;
|
|
55
|
+
}, [aiSettings?.providers, provider]);
|
|
56
|
+
const handleOptionChange = useCallback((keyPath, targetValue) => {
|
|
57
|
+
const nextValue = updateProviderOptionsValue({
|
|
58
|
+
currentValue: providerOptionsValues,
|
|
59
|
+
keyPath,
|
|
60
|
+
provider,
|
|
61
|
+
targetValue,
|
|
62
|
+
});
|
|
63
|
+
setProviderOptionsValues(nextValue);
|
|
64
|
+
}, [providerOptionsValues, provider, setProviderOptionsValues]);
|
|
65
|
+
if (!provider) {
|
|
66
|
+
return (<div className="field-type" style={{ marginTop: '1rem' }}>
|
|
67
|
+
<div className="field-label">Provider Options</div>
|
|
68
|
+
<p style={{ color: 'var(--theme-elevation-500)', margin: 0 }}>
|
|
69
|
+
Select a provider to configure provider options.
|
|
70
|
+
</p>
|
|
71
|
+
</div>);
|
|
72
|
+
}
|
|
73
|
+
if (!schema || typeof schema !== 'object' || Object.keys(schema).length === 0) {
|
|
74
|
+
return (<div className="field-type" style={{ marginTop: '1rem' }}>
|
|
75
|
+
<div className="field-label">Provider Options</div>
|
|
76
|
+
<p style={{ color: 'var(--theme-elevation-500)', margin: 0 }}>
|
|
77
|
+
No provider options are configured for this provider and capability.
|
|
78
|
+
</p>
|
|
79
|
+
</div>);
|
|
80
|
+
}
|
|
81
|
+
const selectedProviderValues = providerOptionsValues?.[provider] || {};
|
|
82
|
+
return (<div className="field-type" style={{ marginTop: '1rem' }}>
|
|
83
|
+
<div className="field-label">Provider Options</div>
|
|
84
|
+
<p style={{ color: 'var(--theme-elevation-500)', marginBottom: '0.75rem', marginTop: 0 }}>
|
|
85
|
+
Override {providerLabel || provider} provider options for this field.
|
|
86
|
+
</p>
|
|
87
|
+
|
|
88
|
+
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
|
89
|
+
<ProviderOptionsTree onChange={handleOptionChange} path={[]} schemaValue={schema} selectedValue={selectedProviderValues}/>
|
|
90
|
+
</div>
|
|
91
|
+
</div>);
|
|
92
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/ui/VoicesFetcher/index.tsx"],"sourcesContent":["'use client'\n\nimport type { FieldClientComponent } from 'payload'\n\nimport { Button, toast, useField
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/VoicesFetcher/index.tsx"],"sourcesContent":["'use client'\n\nimport type { FieldClientComponent } from 'payload'\n\nimport { Button, toast, useField } from '@payloadcms/ui'\nimport React, { useCallback, useState } from 'react'\n\nimport type { Voice } from '../shared/types.js'\n\nimport { PLUGIN_API_ENDPOINT_FETCH_VOICES } from '../../defaults.js'\n\n\n/**\n * VoicesFetcher Component\n * Fetches voices from ElevenLabs API (server-side) and populates the voices array field\n * SECURE: API key is never exposed to the client\n */\nexport const VoicesFetcher: FieldClientComponent = ({ path }) => {\n const [loading, setLoading] = useState(false)\n\n // Get the parent path (the block path)\n const fieldPath = (path as string) || ''\n const blockPath = fieldPath.split('.').slice(0, -1).join('.')\n const voicesPath = `${blockPath}.voices`\n\n const { setValue } = useField<Voice[]>({ path: voicesPath })\n\n const fetchVoices = useCallback(async () => {\n setLoading(true)\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), 30000) // 30s timeout\n\n try {\n // Call server endpoint - it will read the API key from the database\n const response = await fetch(`/api${PLUGIN_API_ENDPOINT_FETCH_VOICES}`, {\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n\n if (!response.ok) {\n let errorMessage = 'Failed to fetch voices'\n try {\n const error = await response.json()\n errorMessage = error.message || errorMessage\n } catch (e) {\n // If response is not JSON (e.g. 504 Gateway Timeout HTML), use status text\n errorMessage = `Error ${response.status}: ${response.statusText}`\n }\n throw new Error(errorMessage)\n }\n\n const data = await response.json()\n const voices: Voice[] = data.voices || []\n\n // Replace the entire array value at once\n // This is much more performant than dispatching ADD_ROW actions in a loop\n setValue(voices)\n\n toast.success(`Successfully fetched ${voices.length} voices!`)\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : 'Failed to fetch voices'\n if (error instanceof Error && error.name === 'AbortError') {\n toast.error('Request timed out. Please try again.')\n } else {\n toast.error(`Error: ${msg}`)\n }\n } finally {\n setLoading(false)\n clearTimeout(timeoutId)\n }\n }, [setValue])\n\n return (\n <div style={{ marginBottom: '20px' }}>\n <Button buttonStyle=\"secondary\" disabled={loading} margin={false} onClick={fetchVoices} size=\"medium\">\n {loading ? 'Fetching Voices...' : 'Fetch Voices'}\n </Button>\n <p style={{ color: 'var(--theme-elevation-600)', fontSize: '13px', marginTop: '8px' }}>\n This will fetch all available voices from your ElevenLabs account. Make sure you have saved\n your API key in the Setup tab first.\n </p>\n </div>\n )\n}\n"],"names":["Button","toast","useField","React","useCallback","useState","PLUGIN_API_ENDPOINT_FETCH_VOICES","VoicesFetcher","path","loading","setLoading","fieldPath","blockPath","split","slice","join","voicesPath","setValue","fetchVoices","controller","AbortController","timeoutId","setTimeout","abort","response","fetch","headers","method","signal","clearTimeout","ok","errorMessage","error","json","message","e","status","statusText","Error","data","voices","success","length","msg","name","div","style","marginBottom","buttonStyle","disabled","margin","onClick","size","p","color","fontSize","marginTop"],"mappings":"AAAA;;AAIA,SAASA,MAAM,EAAEC,KAAK,EAAEC,QAAQ,QAAQ,iBAAgB;AACxD,OAAOC,SAASC,WAAW,EAAEC,QAAQ,QAAQ,QAAO;AAIpD,SAASC,gCAAgC,QAAQ,oBAAmB;AAGpE;;;;CAIC,GACD,OAAO,MAAMC,gBAAsC,CAAC,EAAEC,IAAI,EAAE;IAC1D,MAAM,CAACC,SAASC,WAAW,GAAGL,SAAS;IAEvC,uCAAuC;IACvC,MAAMM,YAAY,AAACH,QAAmB;IACtC,MAAMI,YAAYD,UAAUE,KAAK,CAAC,KAAKC,KAAK,CAAC,GAAG,CAAC,GAAGC,IAAI,CAAC;IACzD,MAAMC,aAAa,CAAC,EAAEJ,UAAU,OAAO,CAAC;IAExC,MAAM,EAAEK,QAAQ,EAAE,GAAGf,SAAkB;QAAEM,MAAMQ;IAAW;IAE1D,MAAME,cAAcd,YAAY;QAC9BM,WAAW;QAEX,MAAMS,aAAa,IAAIC;QACvB,MAAMC,YAAYC,WAAW,IAAMH,WAAWI,KAAK,IAAI,OAAO,cAAc;;QAE5E,IAAI;YACF,oEAAoE;YACpE,MAAMC,WAAW,MAAMC,MAAM,CAAC,IAAI,EAAEnB,iCAAiC,CAAC,EAAE;gBACtEoB,SAAS;oBACP,gBAAgB;gBAClB;gBACAC,QAAQ;gBACRC,QAAQT,WAAWS,MAAM;YAC3B;YAEAC,aAAaR;YAEb,IAAI,CAACG,SAASM,EAAE,EAAE;gBAChB,IAAIC,eAAe;gBACnB,IAAI;oBACF,MAAMC,QAAQ,MAAMR,SAASS,IAAI;oBACjCF,eAAeC,MAAME,OAAO,IAAIH;gBAClC,EAAE,OAAOI,GAAG;oBACV,2EAA2E;oBAC3EJ,eAAe,CAAC,MAAM,EAAEP,SAASY,MAAM,CAAC,EAAE,EAAEZ,SAASa,UAAU,CAAC,CAAC;gBACnE;gBACA,MAAM,IAAIC,MAAMP;YAClB;YAEA,MAAMQ,OAAO,MAAMf,SAASS,IAAI;YAChC,MAAMO,SAAkBD,KAAKC,MAAM,IAAI,EAAE;YAEzC,yCAAyC;YACzC,0EAA0E;YAC1EvB,SAASuB;YAETvC,MAAMwC,OAAO,CAAC,CAAC,qBAAqB,EAAED,OAAOE,MAAM,CAAC,QAAQ,CAAC;QAC/D,EAAE,OAAOV,OAAgB;YACvB,MAAMW,MAAMX,iBAAiBM,QAAQN,MAAME,OAAO,GAAG;YACrD,IAAIF,iBAAiBM,SAASN,MAAMY,IAAI,KAAK,cAAc;gBACzD3C,MAAM+B,KAAK,CAAC;YACd,OAAO;gBACL/B,MAAM+B,KAAK,CAAC,CAAC,OAAO,EAAEW,IAAI,CAAC;YAC7B;QACF,SAAU;YACRjC,WAAW;YACXmB,aAAaR;QACf;IACF,GAAG;QAACJ;KAAS;IAEb,qBACE,MAAC4B;QAAIC,OAAO;YAAEC,cAAc;QAAO;;0BACjC,KAAC/C;gBAAOgD,aAAY;gBAAYC,UAAUxC;gBAASyC,QAAQ;gBAAOC,SAASjC;gBAAakC,MAAK;0BAC1F3C,UAAU,uBAAuB;;0BAEpC,KAAC4C;gBAAEP,OAAO;oBAAEQ,OAAO;oBAA8BC,UAAU;oBAAQC,WAAW;gBAAM;0BAAG;;;;AAM7F,EAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AISettingsData } from '../../ai/providers/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Shared hook for fetching AI settings from `/api/globals/ai-providers`.
|
|
4
|
+
*
|
|
5
|
+
* Features:
|
|
6
|
+
* - Module-level cache to prevent redundant fetches across components
|
|
7
|
+
* - Deduplicates in-flight requests (if 3 components mount at once, only 1 fetch fires)
|
|
8
|
+
* - Optional `depth` parameter for controlling response depth
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const { data, isLoading } = useAISettings()
|
|
13
|
+
* const providers = data?.providers ?? []
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function useAISettings(options?: {
|
|
17
|
+
depth?: number;
|
|
18
|
+
}): {
|
|
19
|
+
data: AISettingsData | null;
|
|
20
|
+
isLoading: boolean;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Invalidate the cached AI settings, forcing the next `useAISettings` call to re-fetch.
|
|
24
|
+
* Useful after saving settings.
|
|
25
|
+
*/
|
|
26
|
+
export declare function invalidateAISettings(): void;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Cached AI settings per depth.
|
|
5
|
+
* We still cache to avoid duplicate requests during a single render/mount cycle,
|
|
6
|
+
* but we always revalidate on mount so changes made in AI Providers appear in Instructions.
|
|
7
|
+
*/ const cachedDataByDepth = new Map();
|
|
8
|
+
const fetchPromiseByDepth = new Map();
|
|
9
|
+
/**
|
|
10
|
+
* Shared hook for fetching AI settings from `/api/globals/ai-providers`.
|
|
11
|
+
*
|
|
12
|
+
* Features:
|
|
13
|
+
* - Module-level cache to prevent redundant fetches across components
|
|
14
|
+
* - Deduplicates in-flight requests (if 3 components mount at once, only 1 fetch fires)
|
|
15
|
+
* - Optional `depth` parameter for controlling response depth
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const { data, isLoading } = useAISettings()
|
|
20
|
+
* const providers = data?.providers ?? []
|
|
21
|
+
* ```
|
|
22
|
+
*/ export function useAISettings(options) {
|
|
23
|
+
const depth = options?.depth ?? 1;
|
|
24
|
+
const initialCached = cachedDataByDepth.get(depth) ?? null;
|
|
25
|
+
const [data, setData] = useState(initialCached);
|
|
26
|
+
const [isLoading, setIsLoading] = useState(!initialCached);
|
|
27
|
+
useEffect(()=>{
|
|
28
|
+
const cached = cachedDataByDepth.get(depth) ?? null;
|
|
29
|
+
if (cached) {
|
|
30
|
+
setData(cached);
|
|
31
|
+
setIsLoading(false);
|
|
32
|
+
} else {
|
|
33
|
+
setIsLoading(true);
|
|
34
|
+
}
|
|
35
|
+
// Deduplicate in-flight requests per depth and always revalidate on mount.
|
|
36
|
+
let fetchPromise = fetchPromiseByDepth.get(depth) ?? null;
|
|
37
|
+
if (!fetchPromise) {
|
|
38
|
+
fetchPromise = fetch(`/api/globals/ai-providers?depth=${depth}`, {
|
|
39
|
+
cache: 'no-store',
|
|
40
|
+
credentials: 'include'
|
|
41
|
+
}).then(async (res)=>{
|
|
42
|
+
if (res.ok) {
|
|
43
|
+
const json = await res.json();
|
|
44
|
+
cachedDataByDepth.set(depth, json);
|
|
45
|
+
return json;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}).catch(()=>null).finally(()=>{
|
|
49
|
+
fetchPromiseByDepth.delete(depth);
|
|
50
|
+
});
|
|
51
|
+
fetchPromiseByDepth.set(depth, fetchPromise);
|
|
52
|
+
}
|
|
53
|
+
void fetchPromise.then((result)=>{
|
|
54
|
+
setData(result);
|
|
55
|
+
setIsLoading(false);
|
|
56
|
+
});
|
|
57
|
+
}, [
|
|
58
|
+
depth
|
|
59
|
+
]);
|
|
60
|
+
return {
|
|
61
|
+
data,
|
|
62
|
+
isLoading
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Invalidate the cached AI settings, forcing the next `useAISettings` call to re-fetch.
|
|
67
|
+
* Useful after saving settings.
|
|
68
|
+
*/ export function invalidateAISettings() {
|
|
69
|
+
cachedDataByDepth.clear();
|
|
70
|
+
fetchPromiseByDepth.clear();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
//# sourceMappingURL=useAISettings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/hooks/useAISettings.ts"],"sourcesContent":["'use client'\n\nimport { useEffect, useState } from 'react'\n\nimport type { AISettingsData } from '../../ai/providers/types.js'\n\n/**\n * Cached AI settings per depth.\n * We still cache to avoid duplicate requests during a single render/mount cycle,\n * but we always revalidate on mount so changes made in AI Providers appear in Instructions.\n */\nconst cachedDataByDepth = new Map<number, AISettingsData | null>()\nconst fetchPromiseByDepth = new Map<number, Promise<AISettingsData | null>>()\n\n/**\n * Shared hook for fetching AI settings from `/api/globals/ai-providers`.\n *\n * Features:\n * - Module-level cache to prevent redundant fetches across components\n * - Deduplicates in-flight requests (if 3 components mount at once, only 1 fetch fires)\n * - Optional `depth` parameter for controlling response depth\n *\n * @example\n * ```ts\n * const { data, isLoading } = useAISettings()\n * const providers = data?.providers ?? []\n * ```\n */\nexport function useAISettings(options?: { depth?: number }) {\n const depth = options?.depth ?? 1\n const initialCached = cachedDataByDepth.get(depth) ?? null\n const [data, setData] = useState<AISettingsData | null>(initialCached)\n const [isLoading, setIsLoading] = useState(!initialCached)\n\n useEffect(() => {\n const cached = cachedDataByDepth.get(depth) ?? null\n if (cached) {\n setData(cached)\n setIsLoading(false)\n } else {\n setIsLoading(true)\n }\n\n // Deduplicate in-flight requests per depth and always revalidate on mount.\n let fetchPromise = fetchPromiseByDepth.get(depth) ?? null\n if (!fetchPromise) {\n fetchPromise = fetch(`/api/globals/ai-providers?depth=${depth}`, {\n cache: 'no-store',\n credentials: 'include',\n })\n .then(async (res) => {\n if (res.ok) {\n const json = await res.json()\n cachedDataByDepth.set(depth, json as AISettingsData)\n return json as AISettingsData\n }\n return null\n })\n .catch(() => null)\n .finally(() => {\n fetchPromiseByDepth.delete(depth)\n })\n\n fetchPromiseByDepth.set(depth, fetchPromise)\n }\n\n void fetchPromise.then((result) => {\n setData(result)\n setIsLoading(false)\n })\n }, [depth])\n\n return { data, isLoading }\n}\n\n/**\n * Invalidate the cached AI settings, forcing the next `useAISettings` call to re-fetch.\n * Useful after saving settings.\n */\nexport function invalidateAISettings(): void {\n cachedDataByDepth.clear()\n fetchPromiseByDepth.clear()\n}\n"],"names":["useEffect","useState","cachedDataByDepth","Map","fetchPromiseByDepth","useAISettings","options","depth","initialCached","get","data","setData","isLoading","setIsLoading","cached","fetchPromise","fetch","cache","credentials","then","res","ok","json","set","catch","finally","delete","result","invalidateAISettings","clear"],"mappings":"AAAA;AAEA,SAASA,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAI3C;;;;CAIC,GACD,MAAMC,oBAAoB,IAAIC;AAC9B,MAAMC,sBAAsB,IAAID;AAEhC;;;;;;;;;;;;;CAaC,GACD,OAAO,SAASE,cAAcC,OAA4B;IACxD,MAAMC,QAAQD,SAASC,SAAS;IAChC,MAAMC,gBAAgBN,kBAAkBO,GAAG,CAACF,UAAU;IACtD,MAAM,CAACG,MAAMC,QAAQ,GAAGV,SAAgCO;IACxD,MAAM,CAACI,WAAWC,aAAa,GAAGZ,SAAS,CAACO;IAE5CR,UAAU;QACR,MAAMc,SAASZ,kBAAkBO,GAAG,CAACF,UAAU;QAC/C,IAAIO,QAAQ;YACVH,QAAQG;YACRD,aAAa;QACf,OAAO;YACLA,aAAa;QACf;QAEA,2EAA2E;QAC3E,IAAIE,eAAeX,oBAAoBK,GAAG,CAACF,UAAU;QACrD,IAAI,CAACQ,cAAc;YACjBA,eAAeC,MAAM,CAAC,gCAAgC,EAAET,MAAM,CAAC,EAAE;gBAC/DU,OAAO;gBACPC,aAAa;YACf,GACGC,IAAI,CAAC,OAAOC;gBACX,IAAIA,IAAIC,EAAE,EAAE;oBACV,MAAMC,OAAO,MAAMF,IAAIE,IAAI;oBAC3BpB,kBAAkBqB,GAAG,CAAChB,OAAOe;oBAC7B,OAAOA;gBACT;gBACA,OAAO;YACT,GACCE,KAAK,CAAC,IAAM,MACZC,OAAO,CAAC;gBACPrB,oBAAoBsB,MAAM,CAACnB;YAC7B;YAEFH,oBAAoBmB,GAAG,CAAChB,OAAOQ;QACjC;QAEA,KAAKA,aAAaI,IAAI,CAAC,CAACQ;YACtBhB,QAAQgB;YACRd,aAAa;QACf;IACF,GAAG;QAACN;KAAM;IAEV,OAAO;QAAEG;QAAME;IAAU;AAC3B;AAEA;;;CAGC,GACD,OAAO,SAASgB;IACd1B,kBAAkB2B,KAAK;IACvBzB,oBAAoByB,KAAK;AAC3B"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
function isRecord(value) {
|
|
2
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
function cloneRecord(value) {
|
|
5
|
+
if (!isRecord(value)) {
|
|
6
|
+
return {};
|
|
7
|
+
}
|
|
8
|
+
return JSON.parse(JSON.stringify(value));
|
|
9
|
+
}
|
|
10
|
+
function pruneEmptyObjects(node) {
|
|
11
|
+
for (const [key, value] of Object.entries(node)){
|
|
12
|
+
if (!isRecord(value)) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
pruneEmptyObjects(value);
|
|
16
|
+
if (Object.keys(value).length === 0) {
|
|
17
|
+
delete node[key];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function updateProviderOptionsValue({ currentValue, keyPath, provider, targetValue }) {
|
|
22
|
+
if (!provider || keyPath.length === 0) {
|
|
23
|
+
return isRecord(currentValue) ? cloneRecord(currentValue) : null;
|
|
24
|
+
}
|
|
25
|
+
const nextProviderOptions = cloneRecord(currentValue);
|
|
26
|
+
const currentProviderOptions = isRecord(nextProviderOptions[provider]) ? cloneRecord(nextProviderOptions[provider]) : {};
|
|
27
|
+
let targetNode = currentProviderOptions;
|
|
28
|
+
for(let i = 0; i < keyPath.length - 1; i++){
|
|
29
|
+
const segment = keyPath[i];
|
|
30
|
+
if (!isRecord(targetNode[segment])) {
|
|
31
|
+
targetNode[segment] = {};
|
|
32
|
+
}
|
|
33
|
+
targetNode = targetNode[segment];
|
|
34
|
+
}
|
|
35
|
+
const finalKey = keyPath[keyPath.length - 1];
|
|
36
|
+
if (targetValue === undefined) {
|
|
37
|
+
delete targetNode[finalKey];
|
|
38
|
+
} else {
|
|
39
|
+
targetNode[finalKey] = targetValue;
|
|
40
|
+
}
|
|
41
|
+
pruneEmptyObjects(currentProviderOptions);
|
|
42
|
+
if (Object.keys(currentProviderOptions).length === 0) {
|
|
43
|
+
delete nextProviderOptions[provider];
|
|
44
|
+
} else {
|
|
45
|
+
nextProviderOptions[provider] = currentProviderOptions;
|
|
46
|
+
}
|
|
47
|
+
return Object.keys(nextProviderOptions).length > 0 ? nextProviderOptions : null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
//# sourceMappingURL=updateProviderOptionsValue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/providerOptions/updateProviderOptionsValue.ts"],"sourcesContent":["function isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction cloneRecord(value: unknown): Record<string, unknown> {\n if (!isRecord(value)) {\n return {}\n }\n\n return JSON.parse(JSON.stringify(value)) as Record<string, unknown>\n}\n\nfunction pruneEmptyObjects(node: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(node)) {\n if (!isRecord(value)) {\n continue\n }\n\n pruneEmptyObjects(value)\n if (Object.keys(value).length === 0) {\n delete node[key]\n }\n }\n}\n\nexport function updateProviderOptionsValue({\n currentValue,\n keyPath,\n provider,\n targetValue,\n}: {\n currentValue: unknown\n keyPath: string[]\n provider?: string\n targetValue: unknown\n}): null | Record<string, unknown> {\n if (!provider || keyPath.length === 0) {\n return isRecord(currentValue) ? cloneRecord(currentValue) : null\n }\n\n const nextProviderOptions = cloneRecord(currentValue)\n const currentProviderOptions = isRecord(nextProviderOptions[provider])\n ? cloneRecord(nextProviderOptions[provider])\n : {}\n\n let targetNode = currentProviderOptions\n for (let i = 0; i < keyPath.length - 1; i++) {\n const segment = keyPath[i]\n if (!isRecord(targetNode[segment])) {\n targetNode[segment] = {}\n }\n targetNode = targetNode[segment] as Record<string, unknown>\n }\n\n const finalKey = keyPath[keyPath.length - 1]\n if (targetValue === undefined) {\n delete targetNode[finalKey]\n } else {\n targetNode[finalKey] = targetValue\n }\n\n pruneEmptyObjects(currentProviderOptions)\n\n if (Object.keys(currentProviderOptions).length === 0) {\n delete nextProviderOptions[provider]\n } else {\n nextProviderOptions[provider] = currentProviderOptions\n }\n\n return Object.keys(nextProviderOptions).length > 0 ? nextProviderOptions : null\n}\n"],"names":["isRecord","value","Array","isArray","cloneRecord","JSON","parse","stringify","pruneEmptyObjects","node","key","Object","entries","keys","length","updateProviderOptionsValue","currentValue","keyPath","provider","targetValue","nextProviderOptions","currentProviderOptions","targetNode","i","segment","finalKey","undefined"],"mappings":"AAAA,SAASA,SAASC,KAAc;IAC9B,OAAO,CAAC,CAACA,SAAS,OAAOA,UAAU,YAAY,CAACC,MAAMC,OAAO,CAACF;AAChE;AAEA,SAASG,YAAYH,KAAc;IACjC,IAAI,CAACD,SAASC,QAAQ;QACpB,OAAO,CAAC;IACV;IAEA,OAAOI,KAAKC,KAAK,CAACD,KAAKE,SAAS,CAACN;AACnC;AAEA,SAASO,kBAAkBC,IAA6B;IACtD,KAAK,MAAM,CAACC,KAAKT,MAAM,IAAIU,OAAOC,OAAO,CAACH,MAAO;QAC/C,IAAI,CAACT,SAASC,QAAQ;YACpB;QACF;QAEAO,kBAAkBP;QAClB,IAAIU,OAAOE,IAAI,CAACZ,OAAOa,MAAM,KAAK,GAAG;YACnC,OAAOL,IAAI,CAACC,IAAI;QAClB;IACF;AACF;AAEA,OAAO,SAASK,2BAA2B,EACzCC,YAAY,EACZC,OAAO,EACPC,QAAQ,EACRC,WAAW,EAMZ;IACC,IAAI,CAACD,YAAYD,QAAQH,MAAM,KAAK,GAAG;QACrC,OAAOd,SAASgB,gBAAgBZ,YAAYY,gBAAgB;IAC9D;IAEA,MAAMI,sBAAsBhB,YAAYY;IACxC,MAAMK,yBAAyBrB,SAASoB,mBAAmB,CAACF,SAAS,IACjEd,YAAYgB,mBAAmB,CAACF,SAAS,IACzC,CAAC;IAEL,IAAII,aAAaD;IACjB,IAAK,IAAIE,IAAI,GAAGA,IAAIN,QAAQH,MAAM,GAAG,GAAGS,IAAK;QAC3C,MAAMC,UAAUP,OAAO,CAACM,EAAE;QAC1B,IAAI,CAACvB,SAASsB,UAAU,CAACE,QAAQ,GAAG;YAClCF,UAAU,CAACE,QAAQ,GAAG,CAAC;QACzB;QACAF,aAAaA,UAAU,CAACE,QAAQ;IAClC;IAEA,MAAMC,WAAWR,OAAO,CAACA,QAAQH,MAAM,GAAG,EAAE;IAC5C,IAAIK,gBAAgBO,WAAW;QAC7B,OAAOJ,UAAU,CAACG,SAAS;IAC7B,OAAO;QACLH,UAAU,CAACG,SAAS,GAAGN;IACzB;IAEAX,kBAAkBa;IAElB,IAAIV,OAAOE,IAAI,CAACQ,wBAAwBP,MAAM,KAAK,GAAG;QACpD,OAAOM,mBAAmB,CAACF,SAAS;IACtC,OAAO;QACLE,mBAAmB,CAACF,SAAS,GAAGG;IAClC;IAEA,OAAOV,OAAOE,IAAI,CAACO,qBAAqBN,MAAM,GAAG,IAAIM,sBAAsB;AAC7E"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared onChange handler for Payload SelectInput components.
|
|
3
|
+
* Handles both object options `{ value: string }` and raw string values.
|
|
4
|
+
*/ export function handleSelectChange(setValue, option) {
|
|
5
|
+
if (option && typeof option === 'object' && 'value' in option) {
|
|
6
|
+
setValue(option.value);
|
|
7
|
+
} else {
|
|
8
|
+
setValue(option);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=handleSelectChange.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/shared/handleSelectChange.ts"],"sourcesContent":["/**\n * Shared onChange handler for Payload SelectInput components.\n * Handles both object options `{ value: string }` and raw string values.\n */\nexport function handleSelectChange(\n setValue: (value: unknown) => void,\n option: unknown,\n): void {\n if (option && typeof option === 'object' && 'value' in option) {\n setValue((option as { value: string }).value)\n } else {\n setValue(option)\n }\n}\n"],"names":["handleSelectChange","setValue","option","value"],"mappings":"AAAA;;;CAGC,GACD,OAAO,SAASA,mBACdC,QAAkC,EAClCC,MAAe;IAEf,IAAIA,UAAU,OAAOA,WAAW,YAAY,WAAWA,QAAQ;QAC7DD,SAAS,AAACC,OAA6BC,KAAK;IAC9C,OAAO;QACLF,SAASC;IACX;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/shared/types.ts"],"sourcesContent":["/**\n * Shared UI types used across multiple components.\n */\nexport interface Voice {\n category?: string\n enabled?: boolean\n id: string\n labels?: Record<string, unknown>\n name: string\n preview_url?: string\n}\n\n"],"names":[],"mappings":"AAAA;;CAEC,GACD,WAOC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type InstructionUseCase = 'image' | 'text' | 'tts' | 'video';
|
|
2
|
+
export declare function getInstructionSettingsName(modelId: unknown): string | undefined;
|
|
3
|
+
export declare function getInstructionUseCase(modelId: unknown): InstructionUseCase | undefined;
|
|
4
|
+
export declare function resolveEffectiveInstructionSettings({ defaults, instructions, }: {
|
|
5
|
+
defaults?: Record<string, any>;
|
|
6
|
+
instructions: Record<string, any>;
|
|
7
|
+
}): {
|
|
8
|
+
effectiveSettings: Record<string, unknown>;
|
|
9
|
+
settingsName?: string;
|
|
10
|
+
useCase?: InstructionUseCase;
|
|
11
|
+
};
|
|
12
|
+
export declare function applyInstructionDefaultsForDisplay({ defaults, instructions, }: {
|
|
13
|
+
defaults?: Record<string, any>;
|
|
14
|
+
instructions: Record<string, any>;
|
|
15
|
+
}): Record<string, any>;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
const hasMeaningfulValue = (value)=>{
|
|
2
|
+
if (value === null || value === undefined) {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
if (typeof value === 'string') {
|
|
6
|
+
return value.trim() !== '';
|
|
7
|
+
}
|
|
8
|
+
return true;
|
|
9
|
+
};
|
|
10
|
+
function isRecord(value) {
|
|
11
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
12
|
+
}
|
|
13
|
+
function deepMergeRecords(base, override) {
|
|
14
|
+
const merged = {
|
|
15
|
+
...base
|
|
16
|
+
};
|
|
17
|
+
for (const [key, value] of Object.entries(override)){
|
|
18
|
+
const current = merged[key];
|
|
19
|
+
if (isRecord(current) && isRecord(value)) {
|
|
20
|
+
merged[key] = deepMergeRecords(current, value);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
merged[key] = value;
|
|
24
|
+
}
|
|
25
|
+
return merged;
|
|
26
|
+
}
|
|
27
|
+
export function getInstructionSettingsName(modelId) {
|
|
28
|
+
if (modelId === 'text') {
|
|
29
|
+
return 'text-settings';
|
|
30
|
+
}
|
|
31
|
+
if (modelId === 'richtext') {
|
|
32
|
+
return 'richtext-settings';
|
|
33
|
+
}
|
|
34
|
+
if (modelId === 'array') {
|
|
35
|
+
return 'array-settings';
|
|
36
|
+
}
|
|
37
|
+
if (modelId === 'image') {
|
|
38
|
+
return 'image-settings';
|
|
39
|
+
}
|
|
40
|
+
if (modelId === 'tts') {
|
|
41
|
+
return 'tts-settings';
|
|
42
|
+
}
|
|
43
|
+
if (modelId === 'video') {
|
|
44
|
+
return 'video-settings';
|
|
45
|
+
}
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
export function getInstructionUseCase(modelId) {
|
|
49
|
+
if (modelId === 'text' || modelId === 'richtext' || modelId === 'array') {
|
|
50
|
+
return 'text';
|
|
51
|
+
}
|
|
52
|
+
if (modelId === 'image') {
|
|
53
|
+
return 'image';
|
|
54
|
+
}
|
|
55
|
+
if (modelId === 'tts') {
|
|
56
|
+
return 'tts';
|
|
57
|
+
}
|
|
58
|
+
if (modelId === 'video') {
|
|
59
|
+
return 'video';
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
export function resolveEffectiveInstructionSettings({ defaults, instructions }) {
|
|
64
|
+
const modelId = instructions['model-id'];
|
|
65
|
+
const settingsName = getInstructionSettingsName(modelId);
|
|
66
|
+
const useCase = getInstructionUseCase(modelId);
|
|
67
|
+
if (!settingsName || !useCase) {
|
|
68
|
+
return {
|
|
69
|
+
effectiveSettings: {},
|
|
70
|
+
settingsName,
|
|
71
|
+
useCase
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const defaultsForUseCase = defaults?.[useCase] || {};
|
|
75
|
+
const instructionSettings = instructions[settingsName] || {};
|
|
76
|
+
const effectiveSettings = {
|
|
77
|
+
...defaultsForUseCase
|
|
78
|
+
};
|
|
79
|
+
for (const [key, value] of Object.entries(instructionSettings)){
|
|
80
|
+
if (key === 'providerOptions') {
|
|
81
|
+
const selectedProvider = typeof instructionSettings.provider === 'string' ? instructionSettings.provider : typeof defaultsForUseCase.provider === 'string' ? defaultsForUseCase.provider : undefined;
|
|
82
|
+
if (selectedProvider && isRecord(value) && isRecord(value[selectedProvider])) {
|
|
83
|
+
const existingOpts = isRecord(effectiveSettings.providerOptions) ? effectiveSettings.providerOptions : {};
|
|
84
|
+
const existingProviderOpts = isRecord(existingOpts[selectedProvider]) ? existingOpts[selectedProvider] : {};
|
|
85
|
+
const incomingProviderOpts = value[selectedProvider];
|
|
86
|
+
effectiveSettings.providerOptions = {
|
|
87
|
+
...existingOpts,
|
|
88
|
+
[selectedProvider]: {
|
|
89
|
+
...deepMergeRecords(existingProviderOpts, incomingProviderOpts)
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (hasMeaningfulValue(value)) {
|
|
96
|
+
effectiveSettings[key] = value;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
effectiveSettings,
|
|
101
|
+
settingsName,
|
|
102
|
+
useCase
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export function applyInstructionDefaultsForDisplay({ defaults, instructions }) {
|
|
106
|
+
const { settingsName, useCase } = resolveEffectiveInstructionSettings({
|
|
107
|
+
defaults,
|
|
108
|
+
instructions
|
|
109
|
+
});
|
|
110
|
+
if (!settingsName || !useCase) {
|
|
111
|
+
return instructions;
|
|
112
|
+
}
|
|
113
|
+
const defaultsForUseCase = defaults?.[useCase] || {};
|
|
114
|
+
const group = instructions[settingsName] || {};
|
|
115
|
+
const updatedGroup = {
|
|
116
|
+
...group
|
|
117
|
+
};
|
|
118
|
+
if (!hasMeaningfulValue(updatedGroup.provider) && hasMeaningfulValue(defaultsForUseCase.provider)) {
|
|
119
|
+
updatedGroup.provider = defaultsForUseCase.provider;
|
|
120
|
+
}
|
|
121
|
+
if (!hasMeaningfulValue(updatedGroup.model) && hasMeaningfulValue(defaultsForUseCase.model)) {
|
|
122
|
+
updatedGroup.model = defaultsForUseCase.model;
|
|
123
|
+
}
|
|
124
|
+
if (useCase === 'tts' && !hasMeaningfulValue(updatedGroup.voice) && hasMeaningfulValue(defaultsForUseCase.voice)) {
|
|
125
|
+
updatedGroup.voice = defaultsForUseCase.voice;
|
|
126
|
+
}
|
|
127
|
+
if (JSON.stringify(group) === JSON.stringify(updatedGroup)) {
|
|
128
|
+
return instructions;
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
...instructions,
|
|
132
|
+
[settingsName]: updatedGroup
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
//# sourceMappingURL=resolveEffectiveInstructionSettings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utilities/ai/resolveEffectiveInstructionSettings.ts"],"sourcesContent":["export type InstructionUseCase = 'image' | 'text' | 'tts' | 'video'\n\nconst hasMeaningfulValue = (value: unknown): boolean => {\n if (value === null || value === undefined) {\n return false\n }\n\n if (typeof value === 'string') {\n return value.trim() !== ''\n }\n\n return true\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nfunction deepMergeRecords(\n base: Record<string, unknown>,\n override: Record<string, unknown>,\n): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...base }\n\n for (const [key, value] of Object.entries(override)) {\n const current = merged[key]\n if (isRecord(current) && isRecord(value)) {\n merged[key] = deepMergeRecords(current, value)\n continue\n }\n merged[key] = value\n }\n\n return merged\n}\n\nexport function getInstructionSettingsName(modelId: unknown): string | undefined {\n if (modelId === 'text') {\n return 'text-settings'\n }\n if (modelId === 'richtext') {\n return 'richtext-settings'\n }\n if (modelId === 'array') {\n return 'array-settings'\n }\n if (modelId === 'image') {\n return 'image-settings'\n }\n if (modelId === 'tts') {\n return 'tts-settings'\n }\n if (modelId === 'video') {\n return 'video-settings'\n }\n\n return undefined\n}\n\nexport function getInstructionUseCase(modelId: unknown): InstructionUseCase | undefined {\n if (modelId === 'text' || modelId === 'richtext' || modelId === 'array') {\n return 'text'\n }\n if (modelId === 'image') {\n return 'image'\n }\n if (modelId === 'tts') {\n return 'tts'\n }\n if (modelId === 'video') {\n return 'video'\n }\n\n return undefined\n}\nexport function resolveEffectiveInstructionSettings({\n defaults,\n instructions,\n}: {\n defaults?: Record<string, any>\n instructions: Record<string, any>\n}): {\n effectiveSettings: Record<string, unknown>\n settingsName?: string\n useCase?: InstructionUseCase\n} {\n const modelId = instructions['model-id']\n const settingsName = getInstructionSettingsName(modelId)\n const useCase = getInstructionUseCase(modelId)\n\n if (!settingsName || !useCase) {\n return { effectiveSettings: {}, settingsName, useCase }\n }\n\n const defaultsForUseCase = (defaults?.[useCase] || {}) as Record<string, unknown>\n const instructionSettings = (instructions[settingsName] || {}) as Record<string, unknown>\n const effectiveSettings: Record<string, unknown> = {\n ...defaultsForUseCase,\n }\n\n for (const [key, value] of Object.entries(instructionSettings)) {\n if (key === 'providerOptions') {\n const selectedProvider =\n typeof instructionSettings.provider === 'string'\n ? instructionSettings.provider\n : typeof defaultsForUseCase.provider === 'string'\n ? defaultsForUseCase.provider\n : undefined\n\n if (selectedProvider && isRecord(value) && isRecord(value[selectedProvider])) {\n const existingOpts = isRecord(effectiveSettings.providerOptions)\n ? effectiveSettings.providerOptions\n : {}\n const existingProviderOpts = isRecord(existingOpts[selectedProvider])\n ? existingOpts[selectedProvider]\n : {}\n const incomingProviderOpts = value[selectedProvider]\n\n effectiveSettings.providerOptions = {\n ...existingOpts,\n [selectedProvider]: {\n ...deepMergeRecords(existingProviderOpts, incomingProviderOpts),\n },\n }\n }\n continue\n }\n\n if (hasMeaningfulValue(value)) {\n effectiveSettings[key] = value\n }\n }\n\n return {\n effectiveSettings,\n settingsName,\n useCase,\n }\n}\n\nexport function applyInstructionDefaultsForDisplay({\n defaults,\n instructions,\n}: {\n defaults?: Record<string, any>\n instructions: Record<string, any>\n}): Record<string, any> {\n const { settingsName, useCase } = resolveEffectiveInstructionSettings({ defaults, instructions })\n\n if (!settingsName || !useCase) {\n return instructions\n }\n\n const defaultsForUseCase = (defaults?.[useCase] || {}) as Record<string, unknown>\n const group = ((instructions[settingsName] || {}) as Record<string, unknown>)\n const updatedGroup: Record<string, unknown> = {\n ...group,\n }\n\n if (!hasMeaningfulValue(updatedGroup.provider) && hasMeaningfulValue(defaultsForUseCase.provider)) {\n updatedGroup.provider = defaultsForUseCase.provider\n }\n\n if (!hasMeaningfulValue(updatedGroup.model) && hasMeaningfulValue(defaultsForUseCase.model)) {\n updatedGroup.model = defaultsForUseCase.model\n }\n\n if (useCase === 'tts' && !hasMeaningfulValue(updatedGroup.voice) && hasMeaningfulValue(defaultsForUseCase.voice)) {\n updatedGroup.voice = defaultsForUseCase.voice\n }\n\n if (JSON.stringify(group) === JSON.stringify(updatedGroup)) {\n return instructions\n }\n\n return {\n ...instructions,\n [settingsName]: updatedGroup,\n }\n}\n"],"names":["hasMeaningfulValue","value","undefined","trim","isRecord","Array","isArray","deepMergeRecords","base","override","merged","key","Object","entries","current","getInstructionSettingsName","modelId","getInstructionUseCase","resolveEffectiveInstructionSettings","defaults","instructions","settingsName","useCase","effectiveSettings","defaultsForUseCase","instructionSettings","selectedProvider","provider","existingOpts","providerOptions","existingProviderOpts","incomingProviderOpts","applyInstructionDefaultsForDisplay","group","updatedGroup","model","voice","JSON","stringify"],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { defaultPrompts } from '../ai/prompts.js';
|
|
1
|
+
import { defaultPrompts } from '../ai/utilities/prompts.js';
|
|
2
2
|
import { asyncHandlebars } from '../libraries/handlebars/asyncHandlebars.js';
|
|
3
3
|
import { handlebarsHelpersMap } from '../libraries/handlebars/helpersMap.js';
|
|
4
4
|
import { replacePlaceholders } from '../libraries/handlebars/replacePlaceholders.js';
|
|
5
|
+
import { lexicalToPromptTemplate } from '../utilities/lexical/lexicalToPromptTemplate.js';
|
|
5
6
|
const buildRichTextSystem = (baseSystem, layout)=>{
|
|
6
7
|
return `${baseSystem}
|
|
7
8
|
|
|
@@ -65,7 +66,7 @@ export const assignPrompt = async (action, { type, actionParams, collection, con
|
|
|
65
66
|
systemPrompt
|
|
66
67
|
}) : '';
|
|
67
68
|
return {
|
|
68
|
-
layout: updatedLayout,
|
|
69
|
+
layout: type === 'richText' ? updatedLayout : undefined,
|
|
69
70
|
// TODO: revisit this toLexicalHTML
|
|
70
71
|
prompt: await replacePlaceholders(`{{${toLexicalHTML} ${field}}}`, extendedContext),
|
|
71
72
|
system: type === 'richText' ? buildRichTextSystem(system, updatedLayout) : system
|
|
@@ -73,19 +74,27 @@ export const assignPrompt = async (action, { type, actionParams, collection, con
|
|
|
73
74
|
};
|
|
74
75
|
export const extendContextWithPromptFields = (data, ctx, pluginConfig)=>{
|
|
75
76
|
const { promptFields = [] } = pluginConfig;
|
|
76
|
-
const fieldsMap = new Map(promptFields.filter((f)=>!f.collections || f.collections.includes(ctx.collection)).map((f)=>[
|
|
77
|
+
const fieldsMap = new Map((promptFields || []).filter((f)=>!f.collections || f.collections.includes(ctx.collection)).map((f)=>[
|
|
77
78
|
f.name,
|
|
78
79
|
f
|
|
79
80
|
]));
|
|
80
81
|
return new Proxy(data, {
|
|
81
82
|
get: (target, prop)=>{
|
|
82
83
|
const field = fieldsMap.get(prop);
|
|
83
|
-
if (field
|
|
84
|
+
if (field && 'getter' in field && typeof field.getter === 'function') {
|
|
84
85
|
const value = field.getter(data, ctx);
|
|
85
86
|
return Promise.resolve(value).then((v)=>new asyncHandlebars.SafeString(v));
|
|
86
87
|
}
|
|
87
88
|
// {{prop}} escapes content by default. Here we make sure it won't be escaped.
|
|
88
89
|
const value = typeof target === 'object' ? target[prop] : undefined;
|
|
90
|
+
// If the value is a Lexical JSON object (e.g. a PromptField / richText field),
|
|
91
|
+
// convert it to a template string AND resolve any internal mention variables
|
|
92
|
+
// (like {{name}}) against the raw document data to avoid unresolved placeholders.
|
|
93
|
+
if (value && typeof value === 'object' && value.root && Array.isArray(value.root.children)) {
|
|
94
|
+
const template = lexicalToPromptTemplate(value);
|
|
95
|
+
// Resolve inner variables using the raw target (not the Proxy) to avoid recursion
|
|
96
|
+
return replacePlaceholders(template, target).then((resolved)=>new asyncHandlebars.SafeString(resolved));
|
|
97
|
+
}
|
|
89
98
|
return typeof value === 'string' ? new asyncHandlebars.SafeString(value) : value;
|
|
90
99
|
},
|
|
91
100
|
// It's used by the handlebars library to determine if the property is enumerable
|
|
@@ -104,7 +113,7 @@ export const extendContextWithPromptFields = (data, ctx, pluginConfig)=>{
|
|
|
104
113
|
},
|
|
105
114
|
ownKeys: (target)=>{
|
|
106
115
|
return [
|
|
107
|
-
...fieldsMap.keys(),
|
|
116
|
+
...Array.from(fieldsMap.keys()),
|
|
108
117
|
...Object.keys(target || {})
|
|
109
118
|
];
|
|
110
119
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/buildPromptUtils.ts"],"sourcesContent":["import type { CollectionSlug } from 'payload'\n\nimport type { ActionMenuItems, PluginConfig, PromptFieldGetterContext } from '../types.js'\n\nimport { defaultPrompts } from '../ai/utilities/prompts.js'\nimport { asyncHandlebars } from '../libraries/handlebars/asyncHandlebars.js'\nimport { handlebarsHelpersMap } from '../libraries/handlebars/helpersMap.js'\nimport { replacePlaceholders } from '../libraries/handlebars/replacePlaceholders.js'\nimport { lexicalToPromptTemplate } from '../utilities/lexical/lexicalToPromptTemplate.js'\n\nconst buildRichTextSystem = (baseSystem: string, layout: string) => {\n return `${baseSystem}\n\nRULES:\n- Generate original and unique content based on the given topic.\n- Strictly adhere to the specified layout and formatting instructions.\n- Utilize the provided rich text editor tools for appropriate formatting.\n- Ensure the output follows the structure of the sample output object.\n- Produce valid JSON with no undefined or null values.\n---\nLAYOUT INSTRUCTIONS:\n${layout}\n\n---\nADDITIONAL GUIDELINES:\n- Ensure coherence and logical flow between all sections.\n- Maintain a consistent tone and style throughout the content.\n- Use clear and concise language appropriate for the target audience.\n`\n}\n\nexport const assignPrompt = async (\n action: ActionMenuItems,\n {\n type,\n actionParams,\n collection,\n context,\n field,\n layout,\n locale,\n pluginConfig,\n systemPrompt = '',\n template,\n }: {\n actionParams: Record<any, any>\n collection: CollectionSlug\n context: object\n field: string\n layout: string\n locale: string\n pluginConfig: PluginConfig\n systemPrompt: string\n template: string\n type: string\n },\n) => {\n const extendedContext = extendContextWithPromptFields(context, { type, collection }, pluginConfig)\n const prompt = await replacePlaceholders(template, extendedContext)\n const toLexicalHTML = type === 'richText' ? handlebarsHelpersMap.toHTML.name : ''\n\n const assignedPrompts = {\n layout: type === 'richText' ? layout : undefined,\n prompt,\n //TODO: Define only once on a collection level\n system: type === 'richText' ? buildRichTextSystem(systemPrompt, layout) : undefined,\n }\n\n if (action === 'Compose') {\n if (locale && locale !== 'en') {\n /**\n * NOTE: Avoid using the \"system prompt\" for setting the output language,\n * as it causes quotation marks to appear in the output (Currently only tested with openai models).\n * Appending the language instruction directly to the prompt resolves this issue. - revalidate\n **/\n assignedPrompts.prompt += `\n --- \n OUTPUT LANGUAGE: ${locale}\n `\n }\n\n return assignedPrompts\n }\n\n const prompts = [...(pluginConfig.prompts || []), ...defaultPrompts]\n const foundPrompt = prompts.find((p) => p.name === action)\n const getLayout = foundPrompt?.layout\n const getSystemPrompt = foundPrompt?.system\n\n let updatedLayout = layout\n if (getLayout) {\n updatedLayout = getLayout()\n }\n\n const system = getSystemPrompt\n ? getSystemPrompt({\n ...(actionParams || {}),\n prompt,\n systemPrompt,\n })\n : ''\n\n return {\n layout: type === 'richText' ? updatedLayout : undefined,\n // TODO: revisit this toLexicalHTML\n prompt: await replacePlaceholders(`{{${toLexicalHTML} ${field}}}`, extendedContext),\n system: type === 'richText' ? buildRichTextSystem(system, updatedLayout) : system,\n }\n}\n\nexport const extendContextWithPromptFields = (\n data: object,\n ctx: PromptFieldGetterContext,\n pluginConfig: PluginConfig,\n) => {\n const { promptFields = [] } = pluginConfig\n const fieldsMap = new Map(\n (promptFields || [])\n .filter((f: any) => !f.collections || f.collections.includes(ctx.collection))\n .map((f: any) => [f.name, f]),\n )\n return new Proxy(data, {\n get: (target, prop: string) => {\n const field = fieldsMap.get(prop)\n if (field && 'getter' in field && typeof field.getter === 'function') {\n const value = field.getter(data, ctx)\n return Promise.resolve(value).then((v) => new asyncHandlebars.SafeString(v))\n }\n // {{prop}} escapes content by default. Here we make sure it won't be escaped.\n const value = typeof target === 'object' ? (target as any)[prop] : undefined\n\n // If the value is a Lexical JSON object (e.g. a PromptField / richText field),\n // convert it to a template string AND resolve any internal mention variables\n // (like {{name}}) against the raw document data to avoid unresolved placeholders.\n if (value && typeof value === 'object' && value.root && Array.isArray(value.root.children)) {\n const template = lexicalToPromptTemplate(value)\n // Resolve inner variables using the raw target (not the Proxy) to avoid recursion\n return replacePlaceholders(template, target).then(\n (resolved) => new asyncHandlebars.SafeString(resolved),\n )\n }\n\n return typeof value === 'string' ? new asyncHandlebars.SafeString(value) : value\n },\n // It's used by the handlebars library to determine if the property is enumerable\n getOwnPropertyDescriptor: (target, prop) => {\n const field = fieldsMap.get(prop as string)\n if (field) {\n return {\n configurable: true,\n enumerable: true,\n }\n }\n return Object.getOwnPropertyDescriptor(target, prop)\n },\n has: (target, prop) => {\n return fieldsMap.has(prop as string) || (target && prop in target)\n },\n ownKeys: (target) => {\n return [...Array.from(fieldsMap.keys()), ...Object.keys(target || {})]\n },\n })\n}\n"],"names":["defaultPrompts","asyncHandlebars","handlebarsHelpersMap","replacePlaceholders","lexicalToPromptTemplate","buildRichTextSystem","baseSystem","layout","assignPrompt","action","type","actionParams","collection","context","field","locale","pluginConfig","systemPrompt","template","extendedContext","extendContextWithPromptFields","prompt","toLexicalHTML","toHTML","name","assignedPrompts","undefined","system","prompts","foundPrompt","find","p","getLayout","getSystemPrompt","updatedLayout","data","ctx","promptFields","fieldsMap","Map","filter","f","collections","includes","map","Proxy","get","target","prop","getter","value","Promise","resolve","then","v","SafeString","root","Array","isArray","children","resolved","getOwnPropertyDescriptor","configurable","enumerable","Object","has","ownKeys","from","keys"],"mappings":"AAIA,SAASA,cAAc,QAAQ,6BAA4B;AAC3D,SAASC,eAAe,QAAQ,6CAA4C;AAC5E,SAASC,oBAAoB,QAAQ,wCAAuC;AAC5E,SAASC,mBAAmB,QAAQ,iDAAgD;AACpF,SAASC,uBAAuB,QAAQ,kDAAiD;AAEzF,MAAMC,sBAAsB,CAACC,YAAoBC;IAC/C,OAAO,CAAC,EAAED,WAAW;;;;;;;;;;AAUvB,EAAEC,OAAO;;;;;;;AAOT,CAAC;AACD;AAEA,OAAO,MAAMC,eAAe,OAC1BC,QACA,EACEC,IAAI,EACJC,YAAY,EACZC,UAAU,EACVC,OAAO,EACPC,KAAK,EACLP,MAAM,EACNQ,MAAM,EACNC,YAAY,EACZC,eAAe,EAAE,EACjBC,QAAQ,EAYT;IAED,MAAMC,kBAAkBC,8BAA8BP,SAAS;QAAEH;QAAME;IAAW,GAAGI;IACrF,MAAMK,SAAS,MAAMlB,oBAAoBe,UAAUC;IACnD,MAAMG,gBAAgBZ,SAAS,aAAaR,qBAAqBqB,MAAM,CAACC,IAAI,GAAG;IAE/E,MAAMC,kBAAkB;QACtBlB,QAAQG,SAAS,aAAaH,SAASmB;QACvCL;QACA,8CAA8C;QAC9CM,QAAQjB,SAAS,aAAaL,oBAAoBY,cAAcV,UAAUmB;IAC5E;IAEA,IAAIjB,WAAW,WAAW;QACxB,IAAIM,UAAUA,WAAW,MAAM;YAC7B;;;;QAIE,GACFU,gBAAgBJ,MAAM,IAAI,CAAC;;qBAEZ,EAAEN,OAAO;IAC1B,CAAC;QACD;QAEA,OAAOU;IACT;IAEA,MAAMG,UAAU;WAAKZ,aAAaY,OAAO,IAAI,EAAE;WAAM5B;KAAe;IACpE,MAAM6B,cAAcD,QAAQE,IAAI,CAAC,CAACC,IAAMA,EAAEP,IAAI,KAAKf;IACnD,MAAMuB,YAAYH,aAAatB;IAC/B,MAAM0B,kBAAkBJ,aAAaF;IAErC,IAAIO,gBAAgB3B;IACpB,IAAIyB,WAAW;QACbE,gBAAgBF;IAClB;IAEA,MAAML,SAASM,kBACXA,gBAAgB;QACd,GAAItB,gBAAgB,CAAC,CAAC;QACtBU;QACAJ;IACF,KACA;IAEJ,OAAO;QACLV,QAAQG,SAAS,aAAawB,gBAAgBR;QAC9C,mCAAmC;QACnCL,QAAQ,MAAMlB,oBAAoB,CAAC,EAAE,EAAEmB,cAAc,CAAC,EAAER,MAAM,EAAE,CAAC,EAAEK;QACnEQ,QAAQjB,SAAS,aAAaL,oBAAoBsB,QAAQO,iBAAiBP;IAC7E;AACF,EAAC;AAED,OAAO,MAAMP,gCAAgC,CAC3Ce,MACAC,KACApB;IAEA,MAAM,EAAEqB,eAAe,EAAE,EAAE,GAAGrB;IAC9B,MAAMsB,YAAY,IAAIC,IACpB,AAACF,CAAAA,gBAAgB,EAAE,AAAD,EACfG,MAAM,CAAC,CAACC,IAAW,CAACA,EAAEC,WAAW,IAAID,EAAEC,WAAW,CAACC,QAAQ,CAACP,IAAIxB,UAAU,GAC1EgC,GAAG,CAAC,CAACH,IAAW;YAACA,EAAEjB,IAAI;YAAEiB;SAAE;IAEhC,OAAO,IAAII,MAAMV,MAAM;QACrBW,KAAK,CAACC,QAAQC;YACZ,MAAMlC,QAAQwB,UAAUQ,GAAG,CAACE;YAC5B,IAAIlC,SAAS,YAAYA,SAAS,OAAOA,MAAMmC,MAAM,KAAK,YAAY;gBACpE,MAAMC,QAAQpC,MAAMmC,MAAM,CAACd,MAAMC;gBACjC,OAAOe,QAAQC,OAAO,CAACF,OAAOG,IAAI,CAAC,CAACC,IAAM,IAAIrD,gBAAgBsD,UAAU,CAACD;YAC3E;YACA,8EAA8E;YAC9E,MAAMJ,QAAQ,OAAOH,WAAW,WAAW,AAACA,MAAc,CAACC,KAAK,GAAGtB;YAEnE,+EAA+E;YAC/E,6EAA6E;YAC7E,kFAAkF;YAClF,IAAIwB,SAAS,OAAOA,UAAU,YAAYA,MAAMM,IAAI,IAAIC,MAAMC,OAAO,CAACR,MAAMM,IAAI,CAACG,QAAQ,GAAG;gBAC1F,MAAMzC,WAAWd,wBAAwB8C;gBACzC,kFAAkF;gBAClF,OAAO/C,oBAAoBe,UAAU6B,QAAQM,IAAI,CAC/C,CAACO,WAAa,IAAI3D,gBAAgBsD,UAAU,CAACK;YAEjD;YAEA,OAAO,OAAOV,UAAU,WAAW,IAAIjD,gBAAgBsD,UAAU,CAACL,SAASA;QAC7E;QACA,iFAAiF;QACjFW,0BAA0B,CAACd,QAAQC;YACjC,MAAMlC,QAAQwB,UAAUQ,GAAG,CAACE;YAC5B,IAAIlC,OAAO;gBACT,OAAO;oBACLgD,cAAc;oBACdC,YAAY;gBACd;YACF;YACA,OAAOC,OAAOH,wBAAwB,CAACd,QAAQC;QACjD;QACAiB,KAAK,CAAClB,QAAQC;YACZ,OAAOV,UAAU2B,GAAG,CAACjB,SAAoBD,UAAUC,QAAQD;QAC7D;QACAmB,SAAS,CAACnB;YACR,OAAO;mBAAIU,MAAMU,IAAI,CAAC7B,UAAU8B,IAAI;mBAAQJ,OAAOI,IAAI,CAACrB,UAAU,CAAC;aAAG;QACxE;IACF;AACF,EAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
import { getFieldBySchemaPath } from './getFieldBySchemaPath.js';
|
|
2
|
+
import { getFieldBySchemaPath } from './fields/getFieldBySchemaPath.js';
|
|
3
3
|
/**
|
|
4
4
|
* Extract field information from a schema path
|
|
5
|
-
*/ const
|
|
5
|
+
*/ const extractFieldInfo = (schemaPath, payload)=>{
|
|
6
6
|
const parts = schemaPath.split('.');
|
|
7
7
|
const collectionSlug = parts[0];
|
|
8
8
|
const fieldPath = parts.slice(1);
|
|
@@ -97,7 +97,7 @@ import { getFieldBySchemaPath } from './getFieldBySchemaPath.js';
|
|
|
97
97
|
* @returns A contextual prompt string that can be used for AI generation
|
|
98
98
|
*/ export const buildSmartPrompt = (context)=>{
|
|
99
99
|
const { documentData, payload, schemaPath } = context;
|
|
100
|
-
const fieldInfo =
|
|
100
|
+
const fieldInfo = extractFieldInfo(schemaPath, payload);
|
|
101
101
|
const { name, type, field, label, parentContext } = fieldInfo;
|
|
102
102
|
// Start with the field's own description if available
|
|
103
103
|
const description = getFieldDescription(field);
|