@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/buildSmartPrompt.ts"],"sourcesContent":["'use strict'\n\nimport type { Field, Payload } from 'payload'\n\nimport { getFieldBySchemaPath } from './getFieldBySchemaPath.js'\n\nexport interface SmartPromptContext {\n /** The document data for template interpolation */\n documentData?: Record<string, unknown>\n /** The Payload instance to access collection config */\n payload: Payload\n /** The schema path like 'array-test-cases.teamMembers.contact.email' */\n schemaPath: string\n}\n\ninterface FieldInfo {\n /** The field configuration */\n field: Field | null\n /** Human-readable field label */\n label: string\n /** Field name from the path */\n name: string\n /** Parent field name if nested (e.g., 'teamMembers' for 'teamMembers.name') */\n parentContext: null | string\n /** The field type */\n type: string\n}\n\n/**\n * Extract field information from a schema path\n */\nconst
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/buildSmartPrompt.ts"],"sourcesContent":["'use strict'\n\nimport type { Field, Payload } from 'payload'\n\nimport { getFieldBySchemaPath } from './fields/getFieldBySchemaPath.js'\nimport { stringToLexicalJSON } from './lexical/stringToLexicalJSON.js'\n\nexport interface SmartPromptContext {\n /** The document data for template interpolation */\n documentData?: Record<string, unknown>\n /** The Payload instance to access collection config */\n payload: Payload\n /** The schema path like 'array-test-cases.teamMembers.contact.email' */\n schemaPath: string\n}\n\ninterface FieldInfo {\n /** The field configuration */\n field: Field | null\n /** Human-readable field label */\n label: string\n /** Field name from the path */\n name: string\n /** Parent field name if nested (e.g., 'teamMembers' for 'teamMembers.name') */\n parentContext: null | string\n /** The field type */\n type: string\n}\n\n/**\n * Extract field information from a schema path\n */\nconst extractFieldInfo = (schemaPath: string, payload: Payload): FieldInfo => {\n const parts = schemaPath.split('.')\n const collectionSlug = parts[0]\n const fieldPath = parts.slice(1)\n const fieldName = fieldPath[fieldPath.length - 1] || ''\n\n // Get parent context (e.g., 'teamMembers' for 'teamMembers.name')\n let parentContext: null | string = null\n if (fieldPath.length > 1) {\n parentContext = fieldPath[fieldPath.length - 2]\n }\n\n // Try to get the actual field configuration from the collection\n let field: Field | null = null\n const collection = payload.config.collections.find((c) => c.slug === collectionSlug)\n if (collection) {\n field = getFieldBySchemaPath(collection, schemaPath)\n }\n\n return {\n name: fieldName,\n type: field?.type || 'text',\n field,\n label: (field as { label?: string })?.label || fieldName,\n parentContext,\n }\n}\n\n/**\n * Humanize a camelCase or snake_case field name\n * e.g., 'teamMembers' -> 'team members', 'first_name' -> 'first name'\n */\nconst humanize = (str: string): string => {\n return str\n .replace(/([a-z])([A-Z])/g, '$1 $2') // camelCase to spaces\n .replace(/[_-]/g, ' ') // underscores/dashes to spaces\n .toLowerCase()\n .trim()\n}\n\n/**\n * Get a description snippet from field admin config\n */\nconst getFieldDescription = (field: Field | null): null | string => {\n if (!field) {\n return null\n }\n const admin = (field as { admin?: { description?: string } }).admin\n if (admin?.description && typeof admin.description === 'string') {\n return admin.description\n }\n return null\n}\n\n/**\n * Build type-specific prompt guidance\n */\nconst getTypeGuidance = (type: string, fieldName: string): string => {\n const nameHint = humanize(fieldName)\n\n switch (type) {\n case 'code':\n return `Generate code for ${nameHint}`\n case 'date':\n return `Generate an appropriate date for ${nameHint}`\n case 'email':\n return `Generate a valid professional email address`\n case 'json':\n return `Generate valid JSON data for ${nameHint}`\n case 'number':\n return `Generate an appropriate numeric value for ${nameHint}`\n case 'select':\n return `Select an appropriate option for ${nameHint}`\n case 'text':\n return `Generate appropriate text for ${nameHint}`\n case 'textarea':\n return `Write detailed content for ${nameHint}`\n case 'upload':\n // Explicit image generation instruction for multimodal models\n return `Generate an image of ${nameHint}`\n default:\n return `Generate content for ${nameHint}`\n }\n}\n\n/**\n * Build context from parent field name using generic humanization.\n * Works universally for any collection structure.\n */\nconst getParentContextPhrase = (parentContext: null | string): string => {\n if (!parentContext) {\n return ''\n }\n\n const humanized = humanize(parentContext)\n\n // Use singular form if the name ends with 's' (common for arrays)\n // e.g., \"teamMembers\" → \"team member\", \"products\" → \"product\"\n if (humanized.endsWith('s') && humanized.length > 2) {\n return `for a ${humanized.slice(0, -1)} entry`\n }\n\n return `for ${humanized}`\n}\n\n/**\n * Build a smart contextual prompt based on field metadata.\n * This is used as a fallback when the user hasn't set a custom prompt.\n *\n * @param context - The context containing schema path and document data\n * @returns A contextual prompt string that can be used for AI generation\n */\nexport const buildSmartPrompt = (context: SmartPromptContext): string => {\n const { documentData, payload, schemaPath } = context\n\n const fieldInfo = extractFieldInfo(schemaPath, payload)\n const { name, type, field, label, parentContext } = fieldInfo\n\n // Start with the field's own description if available\n const description = getFieldDescription(field)\n\n // Build the prompt components\n const parts: string[] = []\n\n // Use description as primary guidance if available\n if (description) {\n parts.push(`Field description for user: ${description}\\n`)\n }\n\n parts.push(getTypeGuidance(type, label || name))\n\n // Add parent context if nested\n const parentPhrase = getParentContextPhrase(parentContext)\n if (parentPhrase) {\n parts.push(parentPhrase)\n }\n\n // Add document title context if available\n const title = documentData?.title || documentData?.name\n\n if (title && typeof title === 'string') {\n parts.push(`in the context of \"${title}\"`)\n }\n\n // Build the final prompt\n let prompt = parts.join(' ')\n\n // Ensure first letter is capitalized\n prompt = prompt.charAt(0).toUpperCase() + prompt.slice(1)\n\n // Add instruction suffix for clarity\n if (!prompt.endsWith('.')) {\n prompt += '.'\n }\n\n return prompt\n}\n\n/**\n * Check if a prompt template is empty and should be replaced with a smart prompt.\n * Only triggers when the prompt is completely empty or whitespace-only.\n */\nexport const isGenericPrompt = (template: null | string | undefined): boolean => {\n if (!template) {\n return true\n }\n return template.trim() === ''\n}\n"],"names":["getFieldBySchemaPath","extractFieldInfo","schemaPath","payload","parts","split","collectionSlug","fieldPath","slice","fieldName","length","parentContext","field","collection","config","collections","find","c","slug","name","type","label","humanize","str","replace","toLowerCase","trim","getFieldDescription","admin","description","getTypeGuidance","nameHint","getParentContextPhrase","humanized","endsWith","buildSmartPrompt","context","documentData","fieldInfo","push","parentPhrase","title","prompt","join","charAt","toUpperCase","isGenericPrompt","template"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utilities/fields/fieldToJsonSchema.ts"],"sourcesContent":["/**\n * fieldToJsonSchema\n * Convert a Payload Field (server or client) into a minimal JSON Schema object,\n * wrapped as { type: 'object', properties: { [name]: valueSchema }, required: [...] }\n *\n * Supported types:\n * - text, textarea, select, number, date, code, email, json\n * Arrays are emitted only when field.hasMany is true and the field type supports hasMany\n * (text, textarea, select; for others only if your config truly sets hasMany).\n */\nimport type { Field } from 'payload'\n\nexport type JsonSchema = Record<string, any>;\n\n// Narrowed minimal typing to avoid anywhere possible without pulling the full payload types at runtime.\n// In a Payload project, you can import type { Field, ClientField } from 'payload' and use those instead.\ntype BaseField = {\n admin?: {\n description?: unknown;\n language?: unknown;\n };\n hasMany?: boolean;\n // json\n jsonSchema?: unknown;\n max?: number;\n maxRows?: number;\n // number\n min?: number;\n // text/textarea\n minRows?: number;\n name?: string;\n // select\n options?: Array<\n | {\n label?: unknown;\n value: number | string;\n }\n | number\n | string\n >;\n required?: boolean;\n schema?: unknown;\n type?: string;\n typescriptSchema?: unknown;\n};\n\nfunction isString(s: unknown): s is string {\n return typeof s === 'string';\n}\n\nfunction isPlainObject(o: unknown): o is Record<string, unknown> {\n return !!o && typeof o === 'object' && !Array.isArray(o);\n}\n\nfunction getDescription(field: BaseField): string | undefined {\n const d = field?.admin?.description;\n return typeof d === 'string' ? d : undefined;\n}\n\nfunction stringWithDescription(field: BaseField) {\n const out: Record<string, any> = { type: 'string' };\n const description = getDescription(field);\n if (description) {out.description = description;}\n return out;\n}\n\nfunction numberWithBounds(field: BaseField) {\n const out: Record<string, any> = { type: 'number' };\n if (typeof field.min === 'number') {out.minimum = field.min;}\n if (typeof field.max === 'number') {out.maximum = field.max;}\n const description = getDescription(field);\n if (description) {out.description = description;}\n return out;\n}\n\nfunction dateSchema(field: BaseField) {\n const out: Record<string, any> = { type: 'string', format: 'date-time' };\n const description = getDescription(field);\n if (description) {out.description = description;}\n return out;\n}\n\nfunction codeSchema(field: BaseField) {\n const out: Record<string, any> = { type: 'string' };\n let description = getDescription(field);\n const lang = field?.admin?.language;\n if (typeof lang === 'string' && lang.trim()) {\n description = description ? `${description} (language: ${lang})` : `language: ${lang}`;\n }\n if (description) {out.description = description;}\n return out;\n}\n\nfunction emailSchema(field: BaseField) {\n const out: Record<string, any> = { type: 'string', format: 'email' };\n const description = getDescription(field);\n if (description) {out.description = description;}\n return out;\n}\n\nfunction jsonValueSchema(field: BaseField) {\n // Prefer a provided JSON Schema object\n if (isPlainObject(field.jsonSchema)) {return field.jsonSchema as object;}\n if (isPlainObject(field.schema)) {return field.schema as object;}\n\n // typescriptSchema cannot be executed here; default to object\n return { type: 'object' };\n}\n\nfunction normalizeSelectOptions(field: BaseField): { values: Array<number | string>; valueType: 'number' | 'string' } {\n const raw = field.options || [];\n const values: Array<number | string> = [];\n\n for (const opt of raw) {\n if (typeof opt === 'string' || typeof opt === 'number') {\n values.push(opt);\n } else if (isPlainObject(opt) && ('value' in opt)) {\n const v = (opt as any).value;\n if (typeof v === 'string' || typeof v === 'number') {\n values.push(v);\n }\n }\n }\n\n // Infer primitive type\n const allNumbers = values.length > 0 && values.every((v) => typeof v === 'number');\n const valueType: 'number' | 'string' = allNumbers ? 'number' : 'string';\n return { values, valueType };\n}\n\nfunction supportsHasMany(fieldType: string | undefined): boolean {\n // Out of the box: text, textarea, select support hasMany\n // Others can be arrays only if your config truly sets hasMany; we return boolean based on type here.\n return fieldType === 'text' || fieldType === 'textarea' || fieldType === 'select';\n}\n\nexport function fieldToJsonSchema(\n fieldInput: BaseField & Field,\n opts?: { nameOverride?: string; wrapObject?: boolean },\n): JsonSchema {\n const field = fieldInput || {};\n const name = isString(opts?.nameOverride) && opts?.nameOverride.length ? opts.nameOverride : (field.name || 'value');\n const type = field.type;\n\n let valueSchema: null | Record<string, any> = null;\n\n switch (type) {\n case 'array':\n case 'group': {\n if ('fields' in field && Array.isArray(field.fields)) {\n const properties: Record<string, any> = {}\n const required: string[] = []\n \n const processFields = (fields: any[]) => {\n for (const subField of fields) {\n if (subField.type === 'row' || subField.type === 'collapsible') {\n if (subField.fields) {processFields(subField.fields)}\n continue\n }\n if (!subField.name || subField.name === 'id') {continue}\n\n const subSchema = fieldToJsonSchema(subField, { wrapObject: false })\n if (subSchema && Object.keys(subSchema).length > 0) {\n properties[subField.name] = subSchema\n // OpenAI Strict Mode: All fields must be required\n required.push(subField.name)\n \n // If field is optional in Payload, allow null in schema\n if (!subField.required) {\n // Arrays usually default to empty array [], so we don't make them nullable\n // Groups and other types can be null\n if (subSchema.type !== 'array') {\n if (Array.isArray(subSchema.type)) {\n if (!subSchema.type.includes('null')) {\n subSchema.type.push('null')\n }\n } else if (typeof subSchema.type === 'string' && subSchema.type !== 'null') {\n subSchema.type = [subSchema.type, 'null']\n }\n \n // If enum is present, we must allow null in enum or use anyOf? \n // OpenAI strict mode: \"enum values must be consistent with type\". \n // If type is [string, null], null is a valid value for the type, but if enum is [\"a\"], null is not in enum.\n // valid: { type: [\"string\", \"null\"], enum: [\"a\", null] } \n if (Array.isArray(subSchema.enum) && !subSchema.enum.includes(null)) {\n subSchema.enum.push(null)\n }\n }\n }\n }\n }\n }\n \n processFields(field.fields)\n\n const objSchema = {\n type: 'object',\n additionalProperties: false,\n properties,\n required: required.length ? required : undefined\n }\n\n if (type === 'array') {\n valueSchema = {\n type: 'array',\n items: objSchema\n }\n if (typeof field.maxRows === 'number') {\n valueSchema.maxItems = field.maxRows\n }\n if (typeof field.minRows === 'number') {\n valueSchema.minItems = field.minRows\n }\n } else {\n valueSchema = objSchema\n }\n \n const description = getDescription(field);\n if (description) {valueSchema.description = description;}\n }\n break;\n }\n\n case 'checkbox': {\n valueSchema = { type: 'boolean' };\n const description = getDescription(field);\n if (description) {valueSchema.description = description;}\n break;\n }\n\n case 'code': {\n const base = codeSchema(field);\n if (field.hasMany) {\n valueSchema = { type: 'array', items: base };\n } else {\n valueSchema = base;\n }\n break;\n }\n\n case 'date': {\n const base = dateSchema(field);\n if (field.hasMany) {\n valueSchema = { type: 'array', items: base };\n } else {\n valueSchema = base;\n }\n break;\n }\n\n case 'email': {\n const base = emailSchema(field);\n if (field.hasMany) {\n valueSchema = { type: 'array', items: base };\n } else {\n valueSchema = base;\n }\n break;\n }\n\n case 'json': {\n const base = jsonValueSchema(field);\n if (field.hasMany) {\n valueSchema = { type: 'array', items: base };\n } else {\n valueSchema = base as Record<string, any>;\n }\n break;\n }\n\n case 'number': {\n const base = numberWithBounds(field);\n if (field.hasMany) {\n valueSchema = { type: 'array', items: base };\n } else {\n valueSchema = base;\n }\n break;\n }\n case 'select': {\n const { values, valueType } = normalizeSelectOptions(field);\n const baseSingle: Record<string, any> = { type: valueType, enum: values };\n const description = getDescription(field);\n if (description) {baseSingle.description = description;}\n\n if (field.hasMany && supportsHasMany(type)) {\n valueSchema = {\n type: 'array',\n items: { type: valueType, enum: values },\n ...(description ? { description } : {}),\n };\n } else {\n valueSchema = baseSingle;\n }\n break;\n }\n\n case 'text':\n case 'textarea': {\n const base = stringWithDescription(field);\n if (field.hasMany && supportsHasMany(type)) {\n const arr: Record<string, any> = {\n type: 'array',\n items: { type: 'string' },\n };\n if (typeof field.minRows === 'number') {arr.minItems = field.minRows;}\n if (typeof field.maxRows === 'number') {arr.maxItems = field.maxRows;}\n if (base.description) {arr.description = base.description;}\n valueSchema = arr;\n } else {\n valueSchema = base;\n }\n break;\n }\n \n // Explicitly handle organizational types to avoid default breakage if passed directly\n // though usually they are handled by parent recursion in group/array case above.\n // If passed as root, we can't really return a meaningful single-value schema without a wrapper?\n // But let's leave default for them or handle if necessary. \n // For now, if someone passes a 'row' as root, it will fall to default (null).\n\n default: {\n valueSchema = null;\n break;\n }\n }\n\n const wrap = opts?.wrapObject !== false;\n\n if (!wrap) {\n return (valueSchema || {}) as JsonSchema;\n }\n\n if (!valueSchema) {\n return {} as JsonSchema;\n }\n\n const schema: JsonSchema = {\n type: 'object',\n additionalProperties: false,\n properties: {\n [name]: valueSchema,\n },\n required: [name]\n };\n\n return schema;\n}\n"],"names":["isString","s","isPlainObject","o","Array","isArray","getDescription","field","d","admin","description","undefined","stringWithDescription","out","type","numberWithBounds","min","minimum","max","maximum","dateSchema","format","codeSchema","lang","language","trim","emailSchema","jsonValueSchema","jsonSchema","schema","normalizeSelectOptions","raw","options","values","opt","push","v","value","allNumbers","length","every","valueType","supportsHasMany","fieldType","fieldToJsonSchema","fieldInput","opts","name","nameOverride","valueSchema","fields","properties","required","processFields","subField","subSchema","wrapObject","Object","keys","includes","enum","objSchema","additionalProperties","items","maxRows","maxItems","minRows","minItems","base","hasMany","baseSingle","arr","wrap"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utilities/fields/getFieldBySchemaPath.ts"],"sourcesContent":["import type { ClientCollectionConfig, CollectionConfig, Field } from 'payload'\n\ntype AnyCollectionConfig = ClientCollectionConfig | CollectionConfig\n\n/**\n * Resolve a Payload field definition by a full schemaPath like:\n * \"{collectionSlug}.fieldA.subFieldB.blockSlug.innerField\"\n *\n * Notes:\n * - Tabs are a UI construct and are not part of schemaPath (fields inside tabs are at the same level).\n * - Blocks include the block slug as part of the path (we must consume it between the block field and its inner fields).\n * - Rows are skipped by this plugin's schema path mapping; support added defensively.\n */\nexport const getFieldBySchemaPath = (\n collectionConfig: AnyCollectionConfig,\n schemaPath: string,\n): Field | null => {\n if (!collectionConfig || !schemaPath) {\n return null\n }\n\n const parts = schemaPath.split('.')\n if (!parts.length) {\n return null\n }\n\n // Strip the collection slug prefix if present\n const [collectionSlug, ...rest] = parts\n const pathParts =\n collectionSlug === collectionConfig.slug ? rest.filter(Boolean) : parts.filter(Boolean)\n\n if (!pathParts.length) {\n return null\n }\n\n const findInFields = (fields: Field[], segments: string[]): Field | null => {\n if (!segments.length) {\n return null\n }\n\n const [current, ...remaining] = segments\n\n // First, try to match a field by name\n for (const field of fields) {\n // Tabs do not contribute to path segments; search inside all tabs with the same segments\n if ((field as any).tabs) {\n const tabs = (field as any).tabs as Array<{ fields?: Field[] }>\n for (const tab of tabs) {\n const foundInTab =\n tab.fields && tab.fields.length ? findInFields(tab.fields, segments) : null\n if (foundInTab) {\n return foundInTab\n }\n }\n }\n\n // Handle unnamed groups and collapsibles (they don't contribute to path)\n // Groups without names are just wrappers, their children are at the same path level\n if ((field as any).type === 'group' && !(field as any).name && (field as any).fields) {\n const foundInUnnamedGroup = findInFields((field as any).fields, segments)\n if (foundInUnnamedGroup) {\n return foundInUnnamedGroup\n }\n }\n\n // Handle unnamed collapsibles similarly\n if ((field as any).type === 'collapsible' && (field as any).fields) {\n const foundInCollapsible = findInFields((field as any).fields, segments)\n if (foundInCollapsible) {\n return foundInCollapsible\n }\n }\n\n if ((field as any).name === current) {\n // If this is the last segment, we found the target field\n if (remaining.length === 0) {\n return field\n }\n\n // Recurse into composite field types\n if ((field as any).fields && Array.isArray((field as any).fields)) {\n const found = findInFields((field as any).fields, remaining)\n if (found) {\n return found\n }\n }\n\n if ((field as any).blocks && Array.isArray((field as any).blocks)) {\n // Next segment should be a block slug, then continue into block fields\n if (!remaining.length) {\n return field\n } // path stops at block container (unlikely for our mapping)\n const [blockSlug, ...afterBlock] = remaining\n const blocks = (field as any).blocks as Array<{ fields: Field[]; slug: string }>\n const block = blocks.find((b) => b.slug === blockSlug)\n if (block) {\n const found = findInFields(block.fields, afterBlock)\n if (found) {\n return found\n }\n }\n }\n }\n }\n\n // Not found at this level\n return null\n }\n\n const rootFields = (collectionConfig as any).fields as Field[] | undefined\n if (!rootFields || !Array.isArray(rootFields)) {\n return null\n }\n\n return findInFields(rootFields, pathParts)\n}\n"],"names":["getFieldBySchemaPath","collectionConfig","schemaPath","parts","split","length","collectionSlug","rest","pathParts","slug","filter","Boolean","findInFields","fields","segments","current","remaining","field","tabs","tab","foundInTab","type","name","foundInUnnamedGroup","foundInCollapsible","Array","isArray","found","blocks","blockSlug","afterBlock","block","find","b","rootFields"],"mappings":"AAIA;;;;;;;;CAQC,GACD,OAAO,MAAMA,uBAAuB,CAClCC,kBACAC;IAEA,IAAI,CAACD,oBAAoB,CAACC,YAAY;QACpC,OAAO;IACT;IAEA,MAAMC,QAAQD,WAAWE,KAAK,CAAC;IAC/B,IAAI,CAACD,MAAME,MAAM,EAAE;QACjB,OAAO;IACT;IAEA,8CAA8C;IAC9C,MAAM,CAACC,gBAAgB,GAAGC,KAAK,GAAGJ;IAClC,MAAMK,YACJF,mBAAmBL,iBAAiBQ,IAAI,GAAGF,KAAKG,MAAM,CAACC,WAAWR,MAAMO,MAAM,CAACC;IAEjF,IAAI,CAACH,UAAUH,MAAM,EAAE;QACrB,OAAO;IACT;IAEA,MAAMO,eAAe,CAACC,QAAiBC;QACrC,IAAI,CAACA,SAAST,MAAM,EAAE;YACpB,OAAO;QACT;QAEA,MAAM,CAACU,SAAS,GAAGC,UAAU,GAAGF;QAEhC,sCAAsC;QACtC,KAAK,MAAMG,SAASJ,OAAQ;YAC1B,yFAAyF;YACzF,IAAI,AAACI,MAAcC,IAAI,EAAE;gBACvB,MAAMA,OAAO,AAACD,MAAcC,IAAI;gBAChC,KAAK,MAAMC,OAAOD,KAAM;oBACtB,MAAME,aACJD,IAAIN,MAAM,IAAIM,IAAIN,MAAM,CAACR,MAAM,GAAGO,aAAaO,IAAIN,MAAM,EAAEC,YAAY;oBACzE,IAAIM,YAAY;wBACd,OAAOA;oBACT;gBACF;YACF;YAEA,yEAAyE;YACzE,oFAAoF;YACpF,IAAI,AAACH,MAAcI,IAAI,KAAK,WAAW,CAAC,AAACJ,MAAcK,IAAI,IAAI,AAACL,MAAcJ,MAAM,EAAE;gBACpF,MAAMU,sBAAsBX,aAAa,AAACK,MAAcJ,MAAM,EAAEC;gBAChE,IAAIS,qBAAqB;oBACvB,OAAOA;gBACT;YACF;YAEA,wCAAwC;YACxC,IAAI,AAACN,MAAcI,IAAI,KAAK,iBAAiB,AAACJ,MAAcJ,MAAM,EAAE;gBAClE,MAAMW,qBAAqBZ,aAAa,AAACK,MAAcJ,MAAM,EAAEC;gBAC/D,IAAIU,oBAAoB;oBACtB,OAAOA;gBACT;YACF;YAEA,IAAI,AAACP,MAAcK,IAAI,KAAKP,SAAS;gBACnC,yDAAyD;gBACzD,IAAIC,UAAUX,MAAM,KAAK,GAAG;oBAC1B,OAAOY;gBACT;gBAEA,qCAAqC;gBACrC,IAAI,AAACA,MAAcJ,MAAM,IAAIY,MAAMC,OAAO,CAAC,AAACT,MAAcJ,MAAM,GAAG;oBACjE,MAAMc,QAAQf,aAAa,AAACK,MAAcJ,MAAM,EAAEG;oBAClD,IAAIW,OAAO;wBACT,OAAOA;oBACT;gBACF;gBAEA,IAAI,AAACV,MAAcW,MAAM,IAAIH,MAAMC,OAAO,CAAC,AAACT,MAAcW,MAAM,GAAG;oBACjE,uEAAuE;oBACvE,IAAI,CAACZ,UAAUX,MAAM,EAAE;wBACrB,OAAOY;oBACT,EAAE,2DAA2D;oBAC7D,MAAM,CAACY,WAAW,GAAGC,WAAW,GAAGd;oBACnC,MAAMY,SAAS,AAACX,MAAcW,MAAM;oBACpC,MAAMG,QAAQH,OAAOI,IAAI,CAAC,CAACC,IAAMA,EAAExB,IAAI,KAAKoB;oBAC5C,IAAIE,OAAO;wBACT,MAAMJ,QAAQf,aAAamB,MAAMlB,MAAM,EAAEiB;wBACzC,IAAIH,OAAO;4BACT,OAAOA;wBACT;oBACF;gBACF;YACF;QACF;QAEA,0BAA0B;QAC1B,OAAO;IACT;IAEA,MAAMO,aAAa,AAACjC,iBAAyBY,MAAM;IACnD,IAAI,CAACqB,cAAc,CAACT,MAAMC,OAAO,CAACQ,aAAa;QAC7C,OAAO;IACT;IAEA,OAAOtB,aAAasB,YAAY1B;AAClC,EAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utilities/fields/getFieldInfo.ts"],"sourcesContent":["import type { BasePayload } from 'payload'\n\nimport { getFieldBySchemaPath } from './getFieldBySchemaPath.js'\n\nexport const getFieldInfo = (collections: BasePayload['collections'], schemaPath: string) => {\n let fieldInfo = null\n //TODO: Only run below for enabled collections\n for (const collectionsKey in collections) {\n const collection = collections[collectionsKey]\n fieldInfo = getFieldBySchemaPath(collection.config, schemaPath)\n if (fieldInfo) {\n return fieldInfo\n }\n }\n}\n"],"names":["getFieldBySchemaPath","getFieldInfo","collections","schemaPath","fieldInfo","collectionsKey","collection","config"],"mappings":"AAEA,SAASA,oBAAoB,QAAQ,4BAA2B;AAEhE,OAAO,MAAMC,eAAe,CAACC,aAAyCC;IACpE,IAAIC,YAAY;IAChB,8CAA8C;IAC9C,IAAK,MAAMC,kBAAkBH,YAAa;QACxC,MAAMI,aAAaJ,WAAW,CAACG,eAAe;QAC9CD,YAAYJ,qBAAqBM,WAAWC,MAAM,EAAEJ;QACpD,IAAIC,WAAW;YACb,OAAOA;QACT;IACF;AACF,EAAC"}
|
|
@@ -7,6 +7,9 @@ export const updateFieldsConfig = (collectionConfig)=>{
|
|
|
7
7
|
if (field.admin?.disabled || field.admin?.readOnly || field.admin?.hidden || field.type === 'row') {
|
|
8
8
|
return field;
|
|
9
9
|
}
|
|
10
|
+
// Developer opt-out: custom.ai.enabled === false skips compose injection entirely
|
|
11
|
+
const aiConfig = field.custom?.ai;
|
|
12
|
+
const isAiDisabledByDev = aiConfig?.enabled === false;
|
|
10
13
|
// Map field path for global fieldInstructionsMap to load related instructions
|
|
11
14
|
// This is done due to save extra API call to get instructions when Field components are loaded in admin
|
|
12
15
|
// Doing is will only call instructions data when user clicks on settings
|
|
@@ -16,12 +19,13 @@ export const updateFieldsConfig = (collectionConfig)=>{
|
|
|
16
19
|
'text',
|
|
17
20
|
'textarea',
|
|
18
21
|
'upload'
|
|
19
|
-
].includes(field.type)) {
|
|
22
|
+
].includes(field.type) && !isAiDisabledByDev) {
|
|
20
23
|
schemaPathMap = {
|
|
21
24
|
...schemaPathMap,
|
|
22
25
|
[currentSchemaPath]: {
|
|
23
26
|
type: field.type,
|
|
24
27
|
custom: field.custom,
|
|
28
|
+
hasMany: field.hasMany === true,
|
|
25
29
|
label: field.label || field.name,
|
|
26
30
|
relationTo: field.relationTo
|
|
27
31
|
}
|
|
@@ -34,7 +38,7 @@ export const updateFieldsConfig = (collectionConfig)=>{
|
|
|
34
38
|
'text',
|
|
35
39
|
'textarea',
|
|
36
40
|
'upload'
|
|
37
|
-
].includes(field.type)) {
|
|
41
|
+
].includes(field.type) && !isAiDisabledByDev) {
|
|
38
42
|
let customField = {};
|
|
39
43
|
// Custom fields don't fully adhere to the Payload schema, making it difficult to
|
|
40
44
|
// determine which components support injecting ComposeField as a Description.
|
|
@@ -45,7 +49,7 @@ export const updateFieldsConfig = (collectionConfig)=>{
|
|
|
45
49
|
}
|
|
46
50
|
// Array fields use ArrayComposeField (always visible) since they don't have focus events
|
|
47
51
|
// Other fields use ComposeField with focus-dependent visibility
|
|
48
|
-
const componentPath = field.type === 'array' ? '@ai-stack/payloadcms/fields#ArrayComposeField' : '@ai-stack/payloadcms/fields#ComposeField';
|
|
52
|
+
const componentPath = field.type === 'array' ? '@ai-stack/payloadcms/fields/ArrayComposeField/ArrayComposeField.js#ArrayComposeField' : '@ai-stack/payloadcms/fields/ComposeField/ComposeField.js#ComposeField';
|
|
49
53
|
return {
|
|
50
54
|
...field,
|
|
51
55
|
admin: {
|
|
@@ -54,6 +58,7 @@ export const updateFieldsConfig = (collectionConfig)=>{
|
|
|
54
58
|
...field.admin?.components || {},
|
|
55
59
|
Description: {
|
|
56
60
|
clientProps: {
|
|
61
|
+
alwaysShow: !!aiConfig?.alwaysShow,
|
|
57
62
|
schemaPath: currentSchemaPath
|
|
58
63
|
},
|
|
59
64
|
path: componentPath
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utilities/fields/updateFieldsConfig.ts"],"sourcesContent":["import type { CollectionConfig, GlobalConfig } from 'payload'\n\ninterface UpdateFieldsConfig {\n schemaPathMap: Record<string, any>\n updatedCollectionConfig: CollectionConfig | GlobalConfig\n}\n\nexport const updateFieldsConfig = (collectionConfig: CollectionConfig | GlobalConfig): UpdateFieldsConfig => {\n let schemaPathMap = {}\n\n function updateField(field: any, parentPath = ''): any {\n const currentPath = field.name\n ? parentPath\n ? `${parentPath}.${field.name}`\n : field.name\n : parentPath\n const currentSchemaPath = `${collectionConfig.slug}.${currentPath}`\n\n // Disabled fields/ field types\n if (\n field.admin?.disabled ||\n field.admin?.readOnly ||\n field.admin?.hidden ||\n field.type === 'row'\n ) {\n return field\n }\n\n // Developer opt-out: custom.ai.enabled === false skips compose injection entirely\n const aiConfig = field.custom?.ai\n const isAiDisabledByDev = aiConfig?.enabled === false\n\n // Map field path for global fieldInstructionsMap to load related instructions\n // This is done due to save extra API call to get instructions when Field components are loaded in admin\n // Doing is will only call instructions data when user clicks on settings\n if (['array', 'richText', 'text', 'textarea', 'upload'].includes(field.type) && !isAiDisabledByDev) {\n schemaPathMap = {\n ...schemaPathMap,\n [currentSchemaPath]: {\n type: field.type,\n custom: field.custom,\n hasMany: field.hasMany === true,\n label: field.label || field.name,\n relationTo: field.relationTo,\n },\n }\n }\n\n // Inject AI actions, richText is not included here as it has to be explicitly defined by user\n // Array fields also get AI injection for bulk generation\n if (['array', 'text', 'textarea', 'upload'].includes(field.type) && !isAiDisabledByDev) {\n let customField = {}\n\n // Custom fields don't fully adhere to the Payload schema, making it difficult to\n // determine which components support injecting ComposeField as a Description.\n if (field.admin?.components?.Field || field.admin?.components?.Description) {\n // TODO: If a field already provides its own Description, we still inject our ComposeField\n // by overriding Description. If you need both, consider composing your own wrapper.\n customField = {}\n }\n\n // Array fields use ArrayComposeField (always visible) since they don't have focus events\n // Other fields use ComposeField with focus-dependent visibility\n const componentPath = field.type === 'array'\n ? '@ai-stack/payloadcms/fields/ArrayComposeField/ArrayComposeField.js#ArrayComposeField'\n : '@ai-stack/payloadcms/fields/ComposeField/ComposeField.js#ComposeField'\n\n return {\n ...field,\n admin: {\n ...field.admin,\n components: {\n ...(field.admin?.components || {}),\n Description: {\n clientProps: {\n alwaysShow: !!aiConfig?.alwaysShow,\n schemaPath: currentSchemaPath,\n },\n path: componentPath,\n },\n ...customField,\n },\n },\n }\n }\n\n if (field.fields) {\n return {\n ...field,\n fields: field.fields.map((subField: any) => updateField(subField, currentPath)),\n }\n }\n\n if (field.tabs) {\n return {\n ...field,\n tabs: field.tabs.map((tab: any) => {\n return {\n ...tab,\n // Tabs are a UI construct and should not add to the schema path\n fields: (tab.fields || []).map((subField: any) => updateField(subField, parentPath)),\n }\n }),\n }\n }\n\n if (field.blocks) {\n return {\n ...field,\n blocks: field.blocks.map((block: any) => ({\n ...block,\n fields: block.fields.map((subField: any) =>\n updateField(subField, `${currentPath}.${block.slug}`),\n ),\n })),\n }\n }\n\n return field\n }\n\n const updatedCollectionConfig = {\n ...collectionConfig,\n fields: collectionConfig.fields.map((field) => updateField(field)),\n }\n\n return {\n schemaPathMap,\n updatedCollectionConfig,\n }\n}\n"],"names":["updateFieldsConfig","collectionConfig","schemaPathMap","updateField","field","parentPath","currentPath","name","currentSchemaPath","slug","admin","disabled","readOnly","hidden","type","aiConfig","custom","ai","isAiDisabledByDev","enabled","includes","hasMany","label","relationTo","customField","components","Field","Description","componentPath","clientProps","alwaysShow","schemaPath","path","fields","map","subField","tabs","tab","blocks","block","updatedCollectionConfig"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utilities/images/extractImageData.ts"],"sourcesContent":["type ImageData = {\n image: { name: string; type: string; url: string }\n}[]\n\n/**\n * Extracts hardcoded image URLs from text using regex.\n * \n * NOTE: This only handles direct URLs in the text.\n * For @field references, use resolveImageReferences utility instead.\n * \n * @param input - Text containing image URLs\n * @returns Array of extracted image data\n */\nexport function extractImageData(input: string): ImageData {\n const regex = /(?:https?:)?\\/[\\w%\\-.,/]+\\.(png|jpe?g|webp)/gi\n const matches = input.match(regex)\n\n if (!matches) {return []}\n\n return matches.map((url) => {\n const decodedUrl = decodeURIComponent(url)\n const parts = decodedUrl.split('/')\n const filename = parts[parts.length - 1]\n const name = filename.replace(/\\.(png|jpe?g|webp)$/i, '')\n const typeMatch = filename.match(/\\.(png|jpe?g|webp)$/i)\n const type = typeMatch ? typeMatch[1].toLowerCase() : 'unknown'\n\n return {\n image: {\n name,\n type,\n url,\n },\n }\n })\n}\n"],"names":["extractImageData","input","regex","matches","match","map","url","decodedUrl","decodeURIComponent","parts","split","filename","length","name","replace","typeMatch","type","toLowerCase","image"],"mappings":"AAIA;;;;;;;;CAQC,GACD,OAAO,SAASA,iBAAiBC,KAAa;IAC5C,MAAMC,QAAQ;IACd,MAAMC,UAAUF,MAAMG,KAAK,CAACF;IAE5B,IAAI,CAACC,SAAS;QAAC,OAAO,EAAE;IAAA;IAExB,OAAOA,QAAQE,GAAG,CAAC,CAACC;QAClB,MAAMC,aAAaC,mBAAmBF;QACtC,MAAMG,QAAQF,WAAWG,KAAK,CAAC;QAC/B,MAAMC,WAAWF,KAAK,CAACA,MAAMG,MAAM,GAAG,EAAE;QACxC,MAAMC,OAAOF,SAASG,OAAO,CAAC,wBAAwB;QACtD,MAAMC,YAAYJ,SAASP,KAAK,CAAC;QACjC,MAAMY,OAAOD,YAAYA,SAAS,CAAC,EAAE,CAACE,WAAW,KAAK;QAEtD,OAAO;YACLC,OAAO;gBACLL;gBACAG;gBACAV;YACF;QACF;IACF;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utilities/images/extractPromptAttachments.ts"],"sourcesContent":["import type { ModelMessage } from 'ai'\n\n// Converts prompt into messages, extracting images in the process\nexport function extractPromptAttachments(prompt: string): ModelMessage[] {\n // Regex to match absolute HTTPS URLs with image extensions\n const imageUrlRegex = /https:\\/\\/\\S+\\.(?:png|jpe?g|webp)/gi\n \n const messages: ModelMessage[] = []\n const imageUrls: string[] = []\n \n // Find all image URLs in the prompt\n let match\n while ((match = imageUrlRegex.exec(prompt)) !== null) {\n imageUrls.push(match[0])\n }\n \n // Create image messages first\n for (const imageUrl of imageUrls) {\n messages.push({\n content: [\n {\n type: 'image',\n image: new URL(imageUrl)\n }\n ],\n role: 'user'\n })\n }\n \n // Add the text prompt as a regular user message if there's any text left\n messages.push({\n content: prompt,\n role: 'user'\n })\n\n return messages\n}"],"names":["extractPromptAttachments","prompt","imageUrlRegex","messages","imageUrls","match","exec","push","imageUrl","content","type","image","URL","role"],"mappings":"AAEA,kEAAkE;AAClE,OAAO,SAASA,yBAAyBC,MAAc;IACrD,2DAA2D;IAC3D,MAAMC,gBAAgB;IAEtB,MAAMC,WAA2B,EAAE;IACnC,MAAMC,YAAsB,EAAE;IAE9B,oCAAoC;IACpC,IAAIC;IACJ,MAAO,AAACA,CAAAA,QAAQH,cAAcI,IAAI,CAACL,OAAM,MAAO,KAAM;QACpDG,UAAUG,IAAI,CAACF,KAAK,CAAC,EAAE;IACzB;IAEA,8BAA8B;IAC9B,KAAK,MAAMG,YAAYJ,UAAW;QAChCD,SAASI,IAAI,CAAC;YACZE,SAAS;gBACP;oBACEC,MAAM;oBACNC,OAAO,IAAIC,IAAIJ;gBACjB;aACD;YACDK,MAAM;QACR;IACF;IAEA,yEAAyE;IACzEV,SAASI,IAAI,CAAC;QACZE,SAASR;QACTY,MAAM;IACR;IAEA,OAAOV;AACT"}
|
|
@@ -8,7 +8,7 @@ export interface FetchableImage {
|
|
|
8
8
|
};
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
* Fetches images from a list of objects containing URLs
|
|
11
|
+
* Fetches images in parallel from a list of objects containing URLs
|
|
12
12
|
* and converts them to AI SDK compatible ImageParts.
|
|
13
13
|
*/
|
|
14
14
|
export declare function fetchImages(req: PayloadRequest, images: FetchableImage[]): Promise<ImagePart[]>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as process from 'node:process';
|
|
2
|
+
/**
|
|
3
|
+
* Fetch a single image and convert to an AI SDK ImagePart.
|
|
4
|
+
*/ async function fetchSingleImage(req, img) {
|
|
5
|
+
const serverURL = req.payload.config?.serverURL || process.env.SERVER_URL || process.env.NEXT_PUBLIC_SERVER_URL;
|
|
6
|
+
let url = img.image.thumbnailURL || img.image.url;
|
|
7
|
+
if (!url.startsWith('http')) {
|
|
8
|
+
url = `${String(serverURL)}${String(url)}`;
|
|
9
|
+
}
|
|
10
|
+
const response = await fetch(url, {
|
|
11
|
+
headers: {
|
|
12
|
+
Authorization: `Bearer ${req.headers.get('Authorization')?.split('Bearer ')[1] || ''}`
|
|
13
|
+
},
|
|
14
|
+
method: 'GET'
|
|
15
|
+
});
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
throw new Error(`Failed to fetch image: ${response.statusText}`);
|
|
18
|
+
}
|
|
19
|
+
const blob = await response.blob();
|
|
20
|
+
const arrayBuffer = await blob.arrayBuffer();
|
|
21
|
+
return {
|
|
22
|
+
type: 'image',
|
|
23
|
+
image: arrayBuffer,
|
|
24
|
+
mediaType: img.image.mimeType || blob.type || 'image/png'
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Fetches images in parallel from a list of objects containing URLs
|
|
29
|
+
* and converts them to AI SDK compatible ImageParts.
|
|
30
|
+
*/ export async function fetchImages(req, images) {
|
|
31
|
+
if (images.length === 0) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
const results = await Promise.allSettled(images.map((img)=>fetchSingleImage(req, img)));
|
|
35
|
+
const imageParts = [];
|
|
36
|
+
for (const result of results){
|
|
37
|
+
if (result.status === 'fulfilled') {
|
|
38
|
+
imageParts.push(result.value);
|
|
39
|
+
} else {
|
|
40
|
+
req.payload.logger.error(result.reason, '— AI Plugin: Error fetching reference image');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (imageParts.length === 0 && images.length > 0) {
|
|
44
|
+
throw new Error("We couldn't fetch any of the images. Please ensure the images are accessible and hosted publicly.");
|
|
45
|
+
}
|
|
46
|
+
return imageParts;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
//# sourceMappingURL=fetchImages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utilities/images/fetchImages.ts"],"sourcesContent":["import type { ImagePart } from 'ai'\nimport type { PayloadRequest } from 'payload'\n\nimport * as process from 'node:process'\n\nexport interface FetchableImage {\n image: {\n mimeType?: string\n thumbnailURL?: string\n url: string\n }\n}\n\n/**\n * Fetch a single image and convert to an AI SDK ImagePart.\n */\nasync function fetchSingleImage(\n req: PayloadRequest,\n img: FetchableImage,\n): Promise<ImagePart> {\n const serverURL =\n req.payload.config?.serverURL ||\n process.env.SERVER_URL ||\n process.env.NEXT_PUBLIC_SERVER_URL\n\n let url = img.image.thumbnailURL || img.image.url\n if (!url.startsWith('http')) {\n url = `${String(serverURL)}${String(url)}`\n }\n\n const response = await fetch(url, {\n headers: {\n Authorization: `Bearer ${req.headers.get('Authorization')?.split('Bearer ')[1] || ''}`,\n },\n method: 'GET',\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch image: ${response.statusText}`)\n }\n\n const blob = await response.blob()\n const arrayBuffer = await blob.arrayBuffer()\n\n return {\n type: 'image',\n image: arrayBuffer,\n mediaType: img.image.mimeType || blob.type || 'image/png',\n }\n}\n\n/**\n * Fetches images in parallel from a list of objects containing URLs\n * and converts them to AI SDK compatible ImageParts.\n */\nexport async function fetchImages(\n req: PayloadRequest,\n images: FetchableImage[],\n): Promise<ImagePart[]> {\n if (images.length === 0) {\n return []\n }\n\n const results = await Promise.allSettled(\n images.map((img) => fetchSingleImage(req, img)),\n )\n\n const imageParts: ImagePart[] = []\n for (const result of results) {\n if (result.status === 'fulfilled') {\n imageParts.push(result.value)\n } else {\n req.payload.logger.error(result.reason, '— AI Plugin: Error fetching reference image')\n }\n }\n\n if (imageParts.length === 0 && images.length > 0) {\n throw new Error(\n \"We couldn't fetch any of the images. Please ensure the images are accessible and hosted publicly.\",\n )\n }\n\n return imageParts\n}\n"],"names":["process","fetchSingleImage","req","img","serverURL","payload","config","env","SERVER_URL","NEXT_PUBLIC_SERVER_URL","url","image","thumbnailURL","startsWith","String","response","fetch","headers","Authorization","get","split","method","ok","Error","statusText","blob","arrayBuffer","type","mediaType","mimeType","fetchImages","images","length","results","Promise","allSettled","map","imageParts","result","status","push","value","logger","error","reason"],"mappings":"AAGA,YAAYA,aAAa,eAAc;AAUvC;;CAEC,GACD,eAAeC,iBACbC,GAAmB,EACnBC,GAAmB;IAEnB,MAAMC,YACJF,IAAIG,OAAO,CAACC,MAAM,EAAEF,aACpBJ,QAAQO,GAAG,CAACC,UAAU,IACtBR,QAAQO,GAAG,CAACE,sBAAsB;IAEpC,IAAIC,MAAMP,IAAIQ,KAAK,CAACC,YAAY,IAAIT,IAAIQ,KAAK,CAACD,GAAG;IACjD,IAAI,CAACA,IAAIG,UAAU,CAAC,SAAS;QAC3BH,MAAM,CAAC,EAAEI,OAAOV,WAAW,EAAEU,OAAOJ,KAAK,CAAC;IAC5C;IAEA,MAAMK,WAAW,MAAMC,MAAMN,KAAK;QAChCO,SAAS;YACPC,eAAe,CAAC,OAAO,EAAEhB,IAAIe,OAAO,CAACE,GAAG,CAAC,kBAAkBC,MAAM,UAAU,CAAC,EAAE,IAAI,GAAG,CAAC;QACxF;QACAC,QAAQ;IACV;IAEA,IAAI,CAACN,SAASO,EAAE,EAAE;QAChB,MAAM,IAAIC,MAAM,CAAC,uBAAuB,EAAER,SAASS,UAAU,CAAC,CAAC;IACjE;IAEA,MAAMC,OAAO,MAAMV,SAASU,IAAI;IAChC,MAAMC,cAAc,MAAMD,KAAKC,WAAW;IAE1C,OAAO;QACLC,MAAM;QACNhB,OAAOe;QACPE,WAAWzB,IAAIQ,KAAK,CAACkB,QAAQ,IAAIJ,KAAKE,IAAI,IAAI;IAChD;AACF;AAEA;;;CAGC,GACD,OAAO,eAAeG,YACpB5B,GAAmB,EACnB6B,MAAwB;IAExB,IAAIA,OAAOC,MAAM,KAAK,GAAG;QACvB,OAAO,EAAE;IACX;IAEA,MAAMC,UAAU,MAAMC,QAAQC,UAAU,CACtCJ,OAAOK,GAAG,CAAC,CAACjC,MAAQF,iBAAiBC,KAAKC;IAG5C,MAAMkC,aAA0B,EAAE;IAClC,KAAK,MAAMC,UAAUL,QAAS;QAC5B,IAAIK,OAAOC,MAAM,KAAK,aAAa;YACjCF,WAAWG,IAAI,CAACF,OAAOG,KAAK;QAC9B,OAAO;YACLvC,IAAIG,OAAO,CAACqC,MAAM,CAACC,KAAK,CAACL,OAAOM,MAAM,EAAE;QAC1C;IACF;IAEA,IAAIP,WAAWL,MAAM,KAAK,KAAKD,OAAOC,MAAM,GAAG,GAAG;QAChD,MAAM,IAAIT,MACR;IAEJ;IAEA,OAAOc;AACT"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retrieves a nested value from an object using dot-notation path.
|
|
3
|
+
*/ function getNestedValue(obj, path) {
|
|
4
|
+
return path.split('.').reduce((current, key)=>{
|
|
5
|
+
if (current && typeof current === 'object' && key in current) {
|
|
6
|
+
return current[key];
|
|
7
|
+
}
|
|
8
|
+
return undefined;
|
|
9
|
+
}, obj);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Parses and resolves image references in prompts.
|
|
13
|
+
*
|
|
14
|
+
* Supports two formats:
|
|
15
|
+
* - @fieldName - for single upload fields
|
|
16
|
+
* - @collection.fieldName - schema path format (collection prefix is stripped)
|
|
17
|
+
* - @fieldName:filename.jpg - for specific images in hasMany fields
|
|
18
|
+
*
|
|
19
|
+
* @param prompt - The prompt text containing @field references
|
|
20
|
+
* @param contextData - The document data to resolve field values from
|
|
21
|
+
* @param req - Payload request object for fetching media
|
|
22
|
+
* @param collectionSlug - Optional collection slug to strip from schema path references
|
|
23
|
+
* @returns Processed prompt with references removed and array of resolved images
|
|
24
|
+
*/ export async function resolveImageReferences(prompt, contextData, req, collectionSlug) {
|
|
25
|
+
// Pattern matches: @fieldName or @fieldName:filename.ext
|
|
26
|
+
const pattern = /@([\w.]+)(?::(.+?\.(?:png|jpe?g|webp|gif)))?/gi;
|
|
27
|
+
const references = [];
|
|
28
|
+
let match;
|
|
29
|
+
while((match = pattern.exec(prompt)) !== null){
|
|
30
|
+
references.push({
|
|
31
|
+
fieldName: match[1],
|
|
32
|
+
filename: match[2],
|
|
33
|
+
fullMatch: match[0]
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (references.length === 0) {
|
|
37
|
+
return {
|
|
38
|
+
images: [],
|
|
39
|
+
processedPrompt: prompt
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// Resolve all references in parallel
|
|
43
|
+
const results = await Promise.allSettled(references.map(async (ref)=>{
|
|
44
|
+
// Strip collection prefix from schema path if it matches
|
|
45
|
+
let fieldPath = ref.fieldName;
|
|
46
|
+
if (collectionSlug && fieldPath.startsWith(`${collectionSlug}.`)) {
|
|
47
|
+
fieldPath = fieldPath.slice(collectionSlug.length + 1);
|
|
48
|
+
}
|
|
49
|
+
const fieldValue = getNestedValue(contextData, fieldPath);
|
|
50
|
+
if (!fieldValue) {
|
|
51
|
+
req.payload.logger.warn(`— AI Plugin: Image reference @${ref.fieldName} not found in document context`);
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
if (!ref.filename) {
|
|
55
|
+
if (Array.isArray(fieldValue)) {
|
|
56
|
+
const docs = await Promise.all(fieldValue.map((v)=>resolveMediaDocument(v, req, collectionSlug)));
|
|
57
|
+
const validDocs = docs.filter(Boolean);
|
|
58
|
+
if (validDocs.length > 0) {
|
|
59
|
+
return {
|
|
60
|
+
images: validDocs.map(formatImageData),
|
|
61
|
+
ref
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
} else {
|
|
66
|
+
const mediaDoc = await resolveMediaDocument(fieldValue, req, collectionSlug);
|
|
67
|
+
return mediaDoc ? {
|
|
68
|
+
images: [
|
|
69
|
+
formatImageData(mediaDoc)
|
|
70
|
+
],
|
|
71
|
+
ref
|
|
72
|
+
} : null;
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
const mediaDoc = await resolveMediaFromArray(fieldValue, ref.filename, req, collectionSlug);
|
|
76
|
+
return mediaDoc ? {
|
|
77
|
+
images: [
|
|
78
|
+
formatImageData(mediaDoc)
|
|
79
|
+
],
|
|
80
|
+
ref
|
|
81
|
+
} : null;
|
|
82
|
+
}
|
|
83
|
+
}));
|
|
84
|
+
const resolvedImages = [];
|
|
85
|
+
let processedPrompt = prompt;
|
|
86
|
+
for (const result of results){
|
|
87
|
+
if (result.status === 'fulfilled' && result.value) {
|
|
88
|
+
resolvedImages.push(...result.value.images);
|
|
89
|
+
const replacementText = result.value.images.map((img)=>img.image.name).join(', ');
|
|
90
|
+
processedPrompt = processedPrompt.replace(result.value.ref.fullMatch, replacementText);
|
|
91
|
+
} else if (result.status === 'rejected') {
|
|
92
|
+
req.payload.logger.error(result.reason, '— AI Plugin: Error resolving image reference');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Clean up extra whitespace from removed references
|
|
96
|
+
processedPrompt = processedPrompt.replace(/\s+/g, ' ').trim();
|
|
97
|
+
return {
|
|
98
|
+
images: resolvedImages,
|
|
99
|
+
processedPrompt
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Resolves a single media document from an ID or populated object.
|
|
104
|
+
* Uses the upload collection's `relationTo` from the field config when available,
|
|
105
|
+
* falling back to common collection names.
|
|
106
|
+
*/ async function resolveMediaDocument(value, req, collectionSlug) {
|
|
107
|
+
// If it's already a populated object with required fields
|
|
108
|
+
if (typeof value === 'object' && value !== null && 'url' in value) {
|
|
109
|
+
return value;
|
|
110
|
+
}
|
|
111
|
+
// If it's an ID string or number, fetch the media document
|
|
112
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
113
|
+
// Build collection candidates: prefer the known upload collections from config,
|
|
114
|
+
// then fall back to common names
|
|
115
|
+
const uploadCollections = req.payload.config.collections.filter((c)=>c.upload).map((c)=>c.slug);
|
|
116
|
+
const candidates = uploadCollections.length > 0 ? uploadCollections : [
|
|
117
|
+
'media',
|
|
118
|
+
'uploads'
|
|
119
|
+
];
|
|
120
|
+
for (const slug of candidates){
|
|
121
|
+
try {
|
|
122
|
+
const mediaDoc = await req.payload.findByID({
|
|
123
|
+
id: value,
|
|
124
|
+
collection: slug,
|
|
125
|
+
req
|
|
126
|
+
});
|
|
127
|
+
if (mediaDoc) {
|
|
128
|
+
return mediaDoc;
|
|
129
|
+
}
|
|
130
|
+
} catch {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Resolves a specific media document from an array by matching filename.
|
|
139
|
+
* Resolves items in parallel for better performance.
|
|
140
|
+
*/ async function resolveMediaFromArray(arrayValue, filename, req, collectionSlug) {
|
|
141
|
+
if (!Array.isArray(arrayValue)) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
// Resolve all items in parallel
|
|
145
|
+
const results = await Promise.allSettled(arrayValue.map((item)=>resolveMediaDocument(item, req, collectionSlug)));
|
|
146
|
+
// Find the first match
|
|
147
|
+
for (const result of results){
|
|
148
|
+
if (result.status === 'fulfilled' && result.value && matchesFilename(result.value, filename)) {
|
|
149
|
+
return result.value;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Checks if a media document matches the given filename
|
|
156
|
+
*/ function matchesFilename(mediaDoc, filename) {
|
|
157
|
+
const docFilename = mediaDoc.filename || mediaDoc.name;
|
|
158
|
+
if (!docFilename) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
return docFilename.toLowerCase() === filename.toLowerCase();
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Formats media document into the expected image data structure
|
|
165
|
+
*/ function formatImageData(mediaDoc) {
|
|
166
|
+
return {
|
|
167
|
+
image: {
|
|
168
|
+
name: mediaDoc.filename || mediaDoc.name || 'unknown',
|
|
169
|
+
type: extractFileExtension(mediaDoc.filename || mediaDoc.name || ''),
|
|
170
|
+
mimeType: mediaDoc.mimeType || mediaDoc.mimetype,
|
|
171
|
+
thumbnailURL: mediaDoc.thumbnailURL,
|
|
172
|
+
url: mediaDoc.url
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Extracts file extension from filename
|
|
178
|
+
*/ function extractFileExtension(filename) {
|
|
179
|
+
const match = filename.match(/\.([^.]+)$/);
|
|
180
|
+
return match ? match[1].toLowerCase() : 'unknown';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
//# sourceMappingURL=resolveImageReferences.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utilities/images/resolveImageReferences.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\ninterface ImageReference {\n fieldName: string\n filename?: string\n fullMatch: string\n}\n\nexport interface ResolvedImage {\n image: {\n mimeType?: string\n name: string\n thumbnailURL?: string\n type: string\n url: string\n }\n}\n\ninterface ResolveImageReferencesResult {\n images: ResolvedImage[]\n processedPrompt: string\n}\n\n/**\n * Retrieves a nested value from an object using dot-notation path.\n */\nfunction getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n return path.split('.').reduce((current, key) => {\n if (current && typeof current === 'object' && key in current) {\n return (current as Record<string, unknown>)[key]\n }\n return undefined\n }, obj as unknown)\n}\n\n/**\n * Parses and resolves image references in prompts.\n *\n * Supports two formats:\n * - @fieldName - for single upload fields\n * - @collection.fieldName - schema path format (collection prefix is stripped)\n * - @fieldName:filename.jpg - for specific images in hasMany fields\n *\n * @param prompt - The prompt text containing @field references\n * @param contextData - The document data to resolve field values from\n * @param req - Payload request object for fetching media\n * @param collectionSlug - Optional collection slug to strip from schema path references\n * @returns Processed prompt with references removed and array of resolved images\n */\nexport async function resolveImageReferences(\n prompt: string,\n contextData: Record<string, unknown>,\n req: PayloadRequest,\n collectionSlug?: string,\n): Promise<ResolveImageReferencesResult> {\n // Pattern matches: @fieldName or @fieldName:filename.ext\n const pattern = /@([\\w.]+)(?::(.+?\\.(?:png|jpe?g|webp|gif)))?/gi\n const references: ImageReference[] = []\n let match: null | RegExpExecArray\n\n while ((match = pattern.exec(prompt)) !== null) {\n references.push({\n fieldName: match[1],\n filename: match[2],\n fullMatch: match[0],\n })\n }\n\n if (references.length === 0) {\n return { images: [], processedPrompt: prompt }\n }\n\n // Resolve all references in parallel\n const results = await Promise.allSettled(\n references.map(async (ref) => {\n // Strip collection prefix from schema path if it matches\n let fieldPath = ref.fieldName\n if (collectionSlug && fieldPath.startsWith(`${collectionSlug}.`)) {\n fieldPath = fieldPath.slice(collectionSlug.length + 1)\n }\n\n const fieldValue = getNestedValue(contextData, fieldPath)\n if (!fieldValue) {\n req.payload.logger.warn(\n `— AI Plugin: Image reference @${ref.fieldName} not found in document context`,\n )\n return null\n }\n\n if (!ref.filename) {\n if (Array.isArray(fieldValue)) {\n const docs = await Promise.all(\n fieldValue.map((v) => resolveMediaDocument(v, req, collectionSlug))\n )\n const validDocs = docs.filter(Boolean) as Record<string, unknown>[]\n if (validDocs.length > 0) {\n return { images: validDocs.map(formatImageData), ref }\n }\n return null\n } else {\n const mediaDoc = await resolveMediaDocument(fieldValue, req, collectionSlug)\n return mediaDoc ? { images: [formatImageData(mediaDoc)], ref } : null\n }\n } else {\n const mediaDoc = await resolveMediaFromArray(fieldValue, ref.filename, req, collectionSlug)\n return mediaDoc ? { images: [formatImageData(mediaDoc)], ref } : null\n }\n }),\n )\n\n const resolvedImages: ResolvedImage[] = []\n let processedPrompt = prompt\n\n for (const result of results) {\n if (result.status === 'fulfilled' && result.value) {\n resolvedImages.push(...result.value.images)\n const replacementText = result.value.images.map((img) => img.image.name).join(', ')\n processedPrompt = processedPrompt.replace(result.value.ref.fullMatch, replacementText)\n } else if (result.status === 'rejected') {\n req.payload.logger.error(result.reason, '— AI Plugin: Error resolving image reference')\n }\n }\n\n // Clean up extra whitespace from removed references\n processedPrompt = processedPrompt.replace(/\\s+/g, ' ').trim()\n\n return {\n images: resolvedImages,\n processedPrompt,\n }\n}\n\n/**\n * Resolves a single media document from an ID or populated object.\n * Uses the upload collection's `relationTo` from the field config when available,\n * falling back to common collection names.\n */\nasync function resolveMediaDocument(\n value: unknown,\n req: PayloadRequest,\n collectionSlug?: string,\n): Promise<null | Record<string, unknown>> {\n // If it's already a populated object with required fields\n if (typeof value === 'object' && value !== null && 'url' in value) {\n return value as Record<string, unknown>\n }\n\n // If it's an ID string or number, fetch the media document\n if (typeof value === 'string' || typeof value === 'number') {\n // Build collection candidates: prefer the known upload collections from config,\n // then fall back to common names\n const uploadCollections = req.payload.config.collections\n .filter((c) => c.upload)\n .map((c) => c.slug)\n\n const candidates = uploadCollections.length > 0\n ? uploadCollections\n : ['media', 'uploads']\n\n for (const slug of candidates) {\n try {\n const mediaDoc = await req.payload.findByID({\n id: value,\n collection: slug,\n req,\n })\n if (mediaDoc) {\n return mediaDoc as Record<string, unknown>\n }\n } catch {\n // Continue to next collection\n continue\n }\n }\n }\n\n return null\n}\n\n/**\n * Resolves a specific media document from an array by matching filename.\n * Resolves items in parallel for better performance.\n */\nasync function resolveMediaFromArray(\n arrayValue: unknown,\n filename: string,\n req: PayloadRequest,\n collectionSlug?: string,\n): Promise<null | Record<string, unknown>> {\n if (!Array.isArray(arrayValue)) {\n return null\n }\n\n // Resolve all items in parallel\n const results = await Promise.allSettled(\n arrayValue.map((item) => resolveMediaDocument(item, req, collectionSlug)),\n )\n\n // Find the first match\n for (const result of results) {\n if (result.status === 'fulfilled' && result.value && matchesFilename(result.value, filename)) {\n return result.value\n }\n }\n\n return null\n}\n\n/**\n * Checks if a media document matches the given filename\n */\nfunction matchesFilename(mediaDoc: Record<string, unknown>, filename: string): boolean {\n const docFilename = mediaDoc.filename || mediaDoc.name\n if (!docFilename) {\n return false\n }\n return (docFilename as string).toLowerCase() === filename.toLowerCase()\n}\n\n/**\n * Formats media document into the expected image data structure\n */\nfunction formatImageData(mediaDoc: Record<string, unknown>): ResolvedImage {\n return {\n image: {\n name: (mediaDoc.filename || mediaDoc.name || 'unknown') as string,\n type: extractFileExtension((mediaDoc.filename || mediaDoc.name || '') as string),\n mimeType: (mediaDoc.mimeType || mediaDoc.mimetype) as string | undefined,\n thumbnailURL: mediaDoc.thumbnailURL as string | undefined,\n url: mediaDoc.url as string,\n },\n }\n}\n\n/**\n * Extracts file extension from filename\n */\nfunction extractFileExtension(filename: string): string {\n const match = filename.match(/\\.([^.]+)$/)\n return match ? match[1].toLowerCase() : 'unknown'\n}\n"],"names":["getNestedValue","obj","path","split","reduce","current","key","undefined","resolveImageReferences","prompt","contextData","req","collectionSlug","pattern","references","match","exec","push","fieldName","filename","fullMatch","length","images","processedPrompt","results","Promise","allSettled","map","ref","fieldPath","startsWith","slice","fieldValue","payload","logger","warn","Array","isArray","docs","all","v","resolveMediaDocument","validDocs","filter","Boolean","formatImageData","mediaDoc","resolveMediaFromArray","resolvedImages","result","status","value","replacementText","img","image","name","join","replace","error","reason","trim","uploadCollections","config","collections","c","upload","slug","candidates","findByID","id","collection","arrayValue","item","matchesFilename","docFilename","toLowerCase","type","extractFileExtension","mimeType","mimetype","thumbnailURL","url"],"mappings":"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"}
|