@ai-stack/payloadcms 3.68.0-beta.1 → 3.68.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.
Files changed (134) hide show
  1. package/dist/ai/core/media/image/generateImage.js +2 -6
  2. package/dist/ai/core/media/image/generateImage.js.map +1 -1
  3. package/dist/ai/core/media/image/handlers/multimodal.js +5 -0
  4. package/dist/ai/core/media/image/handlers/multimodal.js.map +1 -1
  5. package/dist/ai/core/streamObject.js +0 -3
  6. package/dist/ai/core/streamObject.js.map +1 -1
  7. package/dist/ai/providers/blocks/anthropic.js +2 -1
  8. package/dist/ai/providers/blocks/anthropic.js.map +1 -1
  9. package/dist/ai/providers/blocks/elevenlabs.js +3 -2
  10. package/dist/ai/providers/blocks/elevenlabs.js.map +1 -1
  11. package/dist/ai/providers/blocks/fal.js +2 -1
  12. package/dist/ai/providers/blocks/fal.js.map +1 -1
  13. package/dist/ai/providers/blocks/google.js +11 -6
  14. package/dist/ai/providers/blocks/google.js.map +1 -1
  15. package/dist/ai/providers/blocks/openai-compatible.js +2 -1
  16. package/dist/ai/providers/blocks/openai-compatible.js.map +1 -1
  17. package/dist/ai/providers/blocks/openai.js +3 -2
  18. package/dist/ai/providers/blocks/openai.js.map +1 -1
  19. package/dist/ai/providers/blocks/xai.js +2 -1
  20. package/dist/ai/providers/blocks/xai.js.map +1 -1
  21. package/dist/ai/providers/icons.d.ts +7 -0
  22. package/dist/ai/providers/icons.js +9 -0
  23. package/dist/ai/providers/icons.js.map +1 -0
  24. package/dist/ai/providers/registry.js +34 -23
  25. package/dist/ai/providers/registry.js.map +1 -1
  26. package/dist/collections/AISettings.js +44 -17
  27. package/dist/collections/AISettings.js.map +1 -1
  28. package/dist/collections/Instructions.js +37 -0
  29. package/dist/collections/Instructions.js.map +1 -1
  30. package/dist/defaults.d.ts +1 -0
  31. package/dist/defaults.js +8 -0
  32. package/dist/defaults.js.map +1 -1
  33. package/dist/endpoints/chat.d.ts +4 -0
  34. package/dist/endpoints/fetchFields.js +10 -0
  35. package/dist/endpoints/fetchFields.js.map +1 -1
  36. package/dist/endpoints/index.js +86 -10
  37. package/dist/endpoints/index.js.map +1 -1
  38. package/dist/exports/fields.d.ts +1 -0
  39. package/dist/exports/fields.js +1 -0
  40. package/dist/exports/fields.js.map +1 -1
  41. package/dist/fields/ArrayComposeField/ArrayComposeField.d.ts +15 -0
  42. package/dist/fields/ArrayComposeField/ArrayComposeField.js +87 -0
  43. package/dist/fields/ArrayComposeField/ArrayComposeField.js.map +1 -0
  44. package/dist/fields/ArrayComposeField/ArrayComposeField.jsx +73 -0
  45. package/dist/fields/PromptEditorField/PromptEditorField.js +7 -2
  46. package/dist/fields/PromptEditorField/PromptEditorField.js.map +1 -1
  47. package/dist/fields/PromptEditorField/PromptEditorField.jsx +5 -2
  48. package/dist/index.d.ts +2 -0
  49. package/dist/index.js +1 -0
  50. package/dist/index.js.map +1 -1
  51. package/dist/payload-ai.d.ts +149 -0
  52. package/dist/plugin.js +16 -32
  53. package/dist/plugin.js.map +1 -1
  54. package/dist/providers/InstructionsProvider/InstructionsProvider.js +47 -15
  55. package/dist/providers/InstructionsProvider/InstructionsProvider.js.map +1 -1
  56. package/dist/providers/InstructionsProvider/InstructionsProvider.jsx +39 -16
  57. package/dist/providers/InstructionsProvider/context.d.ts +3 -0
  58. package/dist/providers/InstructionsProvider/context.js +2 -0
  59. package/dist/providers/InstructionsProvider/context.js.map +1 -1
  60. package/dist/providers/InstructionsProvider/useInstructions.js +21 -2
  61. package/dist/providers/InstructionsProvider/useInstructions.js.map +1 -1
  62. package/dist/styles.d.ts +11 -0
  63. package/dist/types/handlebars-async-helpers.d.ts +1 -0
  64. package/dist/types/handlebars-dist-handlebars.d.ts +1 -0
  65. package/dist/types/react-mentions.d.ts +1 -0
  66. package/dist/types.d.ts +0 -3
  67. package/dist/types.js.map +1 -1
  68. package/dist/ui/AIConfigDashboard/index.js +198 -22
  69. package/dist/ui/AIConfigDashboard/index.js.map +1 -1
  70. package/dist/ui/AIConfigDashboard/index.jsx +159 -13
  71. package/dist/ui/Compose/Compose.d.ts +1 -0
  72. package/dist/ui/Compose/Compose.js +7 -5
  73. package/dist/ui/Compose/Compose.js.map +1 -1
  74. package/dist/ui/Compose/Compose.jsx +5 -5
  75. package/dist/ui/Compose/UndoRedoActions.d.ts +2 -2
  76. package/dist/ui/Compose/UndoRedoActions.js +8 -5
  77. package/dist/ui/Compose/UndoRedoActions.js.map +1 -1
  78. package/dist/ui/Compose/UndoRedoActions.jsx +6 -5
  79. package/dist/ui/Compose/compose.module.css +56 -16
  80. package/dist/ui/Compose/hooks/menu/itemsMap.js +12 -6
  81. package/dist/ui/Compose/hooks/menu/itemsMap.js.map +1 -1
  82. package/dist/ui/Compose/hooks/menu/useMenu.js +26 -15
  83. package/dist/ui/Compose/hooks/menu/useMenu.js.map +1 -1
  84. package/dist/ui/Compose/hooks/menu/useMenu.jsx +25 -12
  85. package/dist/ui/Compose/hooks/useGenerate.js +34 -131
  86. package/dist/ui/Compose/hooks/useGenerate.js.map +1 -1
  87. package/dist/ui/Compose/hooks/useGenerateUpload.d.ts +11 -0
  88. package/dist/ui/Compose/hooks/useGenerateUpload.js +123 -0
  89. package/dist/ui/Compose/hooks/useGenerateUpload.js.map +1 -0
  90. package/dist/ui/Compose/hooks/useHistory.d.ts +0 -1
  91. package/dist/ui/Compose/hooks/useHistory.js +65 -25
  92. package/dist/ui/Compose/hooks/useHistory.js.map +1 -1
  93. package/dist/ui/Compose/hooks/useStreamingUpdate.d.ts +8 -0
  94. package/dist/ui/Compose/hooks/useStreamingUpdate.js +48 -0
  95. package/dist/ui/Compose/hooks/useStreamingUpdate.js.map +1 -0
  96. package/dist/ui/DynamicVoiceSelect/index.js +63 -11
  97. package/dist/ui/DynamicVoiceSelect/index.js.map +1 -1
  98. package/dist/ui/DynamicVoiceSelect/index.jsx +47 -14
  99. package/dist/ui/EncryptedTextField/index.js +4 -4
  100. package/dist/ui/EncryptedTextField/index.js.map +1 -1
  101. package/dist/ui/EncryptedTextField/index.jsx +4 -4
  102. package/dist/ui/VoicesFetcher/index.js +54 -8
  103. package/dist/ui/VoicesFetcher/index.js.map +1 -1
  104. package/dist/ui/VoicesFetcher/index.jsx +32 -9
  105. package/dist/utilities/buildSmartPrompt.d.ts +22 -0
  106. package/dist/utilities/buildSmartPrompt.js +143 -0
  107. package/dist/utilities/buildSmartPrompt.js.map +1 -0
  108. package/dist/utilities/resolveImageReferences.d.ts +3 -1
  109. package/dist/utilities/resolveImageReferences.js +21 -2
  110. package/dist/utilities/resolveImageReferences.js.map +1 -1
  111. package/dist/utilities/seedProperties.d.ts +7 -0
  112. package/dist/utilities/seedProperties.js +117 -0
  113. package/dist/utilities/seedProperties.js.map +1 -0
  114. package/dist/utilities/setSafeLexicalState.js +80 -6
  115. package/dist/utilities/setSafeLexicalState.js.map +1 -1
  116. package/dist/utilities/updateFieldsConfig.d.ts +1 -1
  117. package/dist/utilities/updateFieldsConfig.js +8 -1
  118. package/dist/utilities/updateFieldsConfig.js.map +1 -1
  119. package/package.json +4 -3
  120. package/dist/endpoints/chat.d.js +0 -3
  121. package/dist/endpoints/chat.d.js.map +0 -1
  122. package/dist/init.d.ts +0 -7
  123. package/dist/init.js +0 -135
  124. package/dist/init.js.map +0 -1
  125. package/dist/payload-ai.d.js +0 -3
  126. package/dist/payload-ai.d.js.map +0 -1
  127. package/dist/styles.d.js +0 -2
  128. package/dist/styles.d.js.map +0 -1
  129. package/dist/types/handlebars-async-helpers.d.js +0 -2
  130. package/dist/types/handlebars-async-helpers.d.js.map +0 -1
  131. package/dist/types/handlebars-dist-handlebars.d.js +0 -2
  132. package/dist/types/handlebars-dist-handlebars.d.js.map +0 -1
  133. package/dist/types/react-mentions.d.js +0 -2
  134. package/dist/types/react-mentions.d.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/fields/PromptEditorField/PromptEditorField.tsx"],"sourcesContent":["'use client'\n\nimport type { TextareaFieldClientProps } from 'payload'\n\nimport { FieldDescription, FieldLabel, useConfig, useField } from '@payloadcms/ui'\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { Mention, MentionsInput } from 'react-mentions/dist/react-mentions.cjs.js'\n\nimport { useInstructions } from '../../providers/InstructionsProvider/useInstructions.js'\nimport { defaultStyle } from './defaultStyle.js'\n\nexport const PromptEditorField: React.FC<TextareaFieldClientProps> = (props) => {\n const { field, path: pathFromContext } = props\n const { setValue, value: payloadValue } = useField<string>({\n path: pathFromContext,\n })\n\n const [localValue, setLocalValue] = useState(payloadValue || '')\n const hasInitialized = useRef(false)\n\n const { activeCollection, promptEditorSuggestions } = useInstructions()\n const { config } = useConfig()\n\n const suggestions = useMemo(\n () =>\n promptEditorSuggestions.map((suggestion: string) => ({\n id: suggestion,\n display: suggestion,\n })),\n [promptEditorSuggestions],\n )\n\n // Extract document ID from URL if available (to get specific filenames)\n const [documentData, setDocumentData] = useState<null | Record<string, unknown>>(null)\n \n useEffect(() => {\n // Only run in browser\n if (typeof window === 'undefined') {\n return\n }\n\n // Allow time for verify window.location is stable (unlikely to change but good practice)\n const segments = window.location.pathname.split('/')\n const collectionsIndex = segments.indexOf('collections')\n \n if (collectionsIndex > -1 && segments.length > collectionsIndex + 2) {\n const urlCollectionSlug = segments[collectionsIndex + 1]\n const urlId = segments[collectionsIndex + 2]\n\n // Only fetch if we are editing instructions for the same collection we are viewing\n // and we haven't fetched yet (or ID changed)\n if (urlCollectionSlug === activeCollection && urlId && urlId !== 'create') {\n const fetchDocument = async () => {\n try {\n \n const response = await fetch(`${String(config.serverURL)}${String(config.routes.api)}/${String(urlCollectionSlug)}/${String(urlId)}`)\n if (response.ok) {\n const data = await response.json()\n setDocumentData(data)\n }\n } catch (_err) {\n // Ignore error\n }\n }\n void fetchDocument()\n }\n }\n }, [activeCollection, config])\n\n // Extract all upload fields from the current collection schema\n const imageFieldSuggestions = useMemo(() => {\n const suggestions: { display: string; id: string }[] = []\n \n // Use activeCollection from context which holds the target collection slug\n const targetSlug = activeCollection\n \n if (!targetSlug || !config?.collections) {\n return []\n }\n\n const collection = config.collections.find((c) => c.slug === targetSlug)\n if (!collection?.fields) {\n return []\n }\n\n const uploadFields: { hasMany: boolean; name: string }[] = []\n\n // Recursive function to find upload fields\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const findUploadFields = (fields: any[], prefix = ''): void => {\n for (const field of fields) {\n if (field.type === 'upload' && field.name) {\n const fieldPath = prefix ? `${prefix}.${String(field.name)}` : String(field.name)\n uploadFields.push({ name: fieldPath, hasMany: field.hasMany === true })\n }\n // Check nested fields in groups, arrays, etc.\n if (field.fields && Array.isArray(field.fields)) {\n const newPrefix = field.name ? (prefix ? `${prefix}.${String(field.name)}` : String(field.name)) : prefix\n findUploadFields(field.fields, newPrefix)\n }\n }\n }\n\n findUploadFields(collection.fields)\n \n // Add generic field names (base suggestions) - ONLY for single uploads (not hasMany arrays)\n uploadFields.forEach(({ name, hasMany }) => {\n // User requested to hide the array itself for hasMany fields\n if (!hasMany) {\n suggestions.push({ id: name, display: name })\n }\n })\n\n // If we have document data, add specific filename suggestions\n if (documentData) {\n uploadFields.forEach(({ name, hasMany }) => {\n const value = documentData[name] // Note: nested access logic simplified for now\n \n // Helper to extract filename from media doc (which might be ID or object)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const getFilename = (item: any): null | string => {\n if (typeof item === 'object' && item && (item.filename || item.name)) {\n return item.filename || item.name\n }\n // If it's just an ID, we can't show filename without populating. \n // Assuming compose view usually fetches with depth > 0 or we rely on what we have.\n return null\n }\n\n if (value) {\n if (hasMany && Array.isArray(value)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value.forEach((item: any) => {\n const fname = getFilename(item)\n if (fname) {\n const suggestion = `${name}:${fname}`\n suggestions.push({ id: suggestion, display: suggestion })\n }\n })\n } else if (!hasMany) {\n // Single image - we already added the base name above.\n // We can optionally add the specific filename too if desired, \n // but user request focused on arrays.\n // Adding the specific filename option for Single images too as it's explicit.\n const fname = getFilename(value)\n if (fname) {\n const suggestion = `${name}:${fname}`\n suggestions.push({ id: suggestion, display: suggestion })\n }\n }\n }\n })\n }\n \n return suggestions\n }, [activeCollection, config, documentData])\n\n useEffect(() => {\n if (!hasInitialized.current || payloadValue === '') {\n setLocalValue(payloadValue || '')\n hasInitialized.current = true\n }\n }, [payloadValue])\n\n const handleChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setLocalValue(e.target.value)\n }, [])\n\n const handleBlur = useCallback(() => {\n setValue(localValue)\n }, [localValue, setValue])\n\n const displayTransform = useCallback((id: string) => `{{ ${id} }}`, [])\n const imageDisplayTransform = useCallback((id: string) => `@${id}`, [])\n\n return (\n <div className=\"field-type textarea\">\n <FieldLabel label={field.label} />\n <MentionsInput\n onBlur={handleBlur}\n onChange={handleChange}\n placeholder=\"Type {{ for fields }} or @imageField for images. For specific images use @imageField:filename.jpg\"\n style={defaultStyle}\n value={localValue}\n >\n <Mention\n data={suggestions}\n displayTransform={displayTransform}\n markup=\"{{__id__}}\"\n style={{\n backgroundColor: 'var(--theme-elevation-100)',\n padding: '2px 0',\n }}\n trigger=\"{\"\n />\n <Mention\n data={imageFieldSuggestions}\n displayTransform={imageDisplayTransform}\n markup=\"@__id__\"\n style={{\n backgroundColor: 'var(--theme-elevation-150)',\n padding: '2px 0',\n }}\n trigger=\"@\"\n />\n </MentionsInput>\n <FieldDescription description={field?.admin?.description} path=\"\" />\n </div>\n )\n}\n"],"names":["FieldDescription","FieldLabel","useConfig","useField","React","useCallback","useEffect","useMemo","useRef","useState","Mention","MentionsInput","useInstructions","defaultStyle","PromptEditorField","props","field","path","pathFromContext","setValue","value","payloadValue","localValue","setLocalValue","hasInitialized","activeCollection","promptEditorSuggestions","config","suggestions","map","suggestion","id","display","documentData","setDocumentData","window","segments","location","pathname","split","collectionsIndex","indexOf","length","urlCollectionSlug","urlId","fetchDocument","response","fetch","String","serverURL","routes","api","ok","data","json","_err","imageFieldSuggestions","targetSlug","collections","collection","find","c","slug","fields","uploadFields","findUploadFields","prefix","type","name","fieldPath","push","hasMany","Array","isArray","newPrefix","forEach","getFilename","item","filename","fname","current","handleChange","e","target","handleBlur","displayTransform","imageDisplayTransform","div","className","label","onBlur","onChange","placeholder","style","markup","backgroundColor","padding","trigger","description","admin"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/fields/PromptEditorField/PromptEditorField.tsx"],"sourcesContent":["'use client'\n\nimport type { TextareaFieldClientProps } from 'payload'\n\nimport { FieldDescription, FieldLabel, useConfig, useField } from '@payloadcms/ui'\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { Mention, MentionsInput } from 'react-mentions/dist/react-mentions.cjs.js'\n\nimport { useInstructions } from '../../providers/InstructionsProvider/useInstructions.js'\nimport { defaultStyle } from './defaultStyle.js'\n\nexport const PromptEditorField: React.FC<TextareaFieldClientProps> = (props) => {\n const { field, path: pathFromContext } = props\n const { setValue, value: payloadValue } = useField<string>({\n path: pathFromContext,\n })\n\n const [localValue, setLocalValue] = useState(payloadValue || '')\n const hasInitialized = useRef(false)\n\n const { activeCollection, promptEditorSuggestions } = useInstructions()\n const { config } = useConfig()\n\n const suggestions = useMemo(\n () =>\n promptEditorSuggestions.map((suggestion: string) => ({\n id: suggestion,\n display: suggestion,\n })),\n [promptEditorSuggestions],\n )\n\n // Extract document ID from URL if available (to get specific filenames)\n const [documentData, setDocumentData] = useState<null | Record<string, unknown>>(null)\n \n useEffect(() => {\n // Only run in browser\n if (typeof window === 'undefined') {\n return\n }\n\n // Allow time for verify window.location is stable (unlikely to change but good practice)\n const segments = window.location.pathname.split('/')\n const collectionsIndex = segments.indexOf('collections')\n \n if (collectionsIndex > -1 && segments.length > collectionsIndex + 2) {\n const urlCollectionSlug = segments[collectionsIndex + 1]\n const urlId = segments[collectionsIndex + 2]\n\n // Only fetch if we are editing instructions for the same collection we are viewing\n // and we haven't fetched yet (or ID changed)\n if (urlCollectionSlug === activeCollection && urlId && urlId !== 'create') {\n const fetchDocument = async () => {\n try {\n \n const response = await fetch(`${String(config.serverURL)}${String(config.routes.api)}/${String(urlCollectionSlug)}/${String(urlId)}`)\n if (response.ok) {\n const data = await response.json()\n setDocumentData(data)\n }\n } catch (_err) {\n // Ignore error\n }\n }\n void fetchDocument()\n }\n }\n }, [activeCollection, config])\n\n // Extract all upload fields from the current collection schema\n const imageFieldSuggestions = useMemo(() => {\n const suggestions: { display: string; id: string }[] = []\n \n // Use activeCollection from context which holds the target collection slug\n const targetSlug = activeCollection\n \n if (!targetSlug || !config?.collections) {\n return []\n }\n\n const collection = config.collections.find((c) => c.slug === targetSlug)\n if (!collection?.fields) {\n return []\n }\n\n const uploadFields: { hasMany: boolean; name: string }[] = []\n\n // Recursive function to find upload fields\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const findUploadFields = (fields: any[], prefix = ''): void => {\n for (const field of fields) {\n if (field.type === 'upload' && field.name) {\n const fieldPath = prefix ? `${prefix}.${String(field.name)}` : String(field.name)\n uploadFields.push({ name: fieldPath, hasMany: field.hasMany === true })\n }\n // Check nested fields in groups, arrays, etc.\n if (field.fields && Array.isArray(field.fields)) {\n const newPrefix = field.name ? (prefix ? `${prefix}.${String(field.name)}` : String(field.name)) : prefix\n findUploadFields(field.fields, newPrefix)\n }\n }\n }\n\n findUploadFields(collection.fields)\n \n // Add generic field names (base suggestions) - ONLY for single uploads (not hasMany arrays)\n uploadFields.forEach(({ name, hasMany }) => {\n // User requested to hide the array itself for hasMany fields\n if (!hasMany) {\n suggestions.push({ id: name, display: name })\n }\n })\n\n // If we have document data, add specific filename suggestions\n if (documentData) {\n uploadFields.forEach(({ name, hasMany }) => {\n const value = documentData[name] // Note: nested access logic simplified for now\n \n // Helper to extract filename from media doc (which might be ID or object)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const getFilename = (item: any): null | string => {\n if (typeof item === 'object' && item && (item.filename || item.name)) {\n return item.filename || item.name\n }\n // If it's just an ID, we can't show filename without populating. \n // Assuming compose view usually fetches with depth > 0 or we rely on what we have.\n return null\n }\n\n if (value) {\n if (hasMany && Array.isArray(value)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value.forEach((item: any) => {\n const fname = getFilename(item)\n if (fname) {\n const suggestion = `${name}:${fname}`\n suggestions.push({ id: suggestion, display: suggestion })\n }\n })\n } else if (!hasMany) {\n // Single image - we already added the base name above.\n // We can optionally add the specific filename too if desired, \n // but user request focused on arrays.\n // Adding the specific filename option for Single images too as it's explicit.\n const fname = getFilename(value)\n if (fname) {\n const suggestion = `${name}:${fname}`\n suggestions.push({ id: suggestion, display: suggestion })\n }\n }\n }\n })\n }\n \n return suggestions\n }, [activeCollection, config, documentData])\n\n useEffect(() => {\n if (!hasInitialized.current || payloadValue === '') {\n setLocalValue(payloadValue || '')\n hasInitialized.current = true\n }\n }, [payloadValue])\n\n const handleChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newValue = e.target.value\n setLocalValue(newValue)\n // Also update Payload value immediately to prevent loss when Save is clicked\n setValue(newValue)\n }, [setValue])\n\n const handleBlur = useCallback(() => {\n setValue(localValue)\n }, [localValue, setValue])\n\n const displayTransform = useCallback((id: string) => `{{ ${id} }}`, [])\n const imageDisplayTransform = useCallback((id: string) => `@${id}`, [])\n\n return (\n <div className=\"field-type textarea\">\n <FieldLabel label={field.label} />\n <MentionsInput\n onBlur={handleBlur}\n onChange={handleChange}\n placeholder=\"Type {{ for fields }} or @imageField for images. For specific images use @imageField:filename.jpg\"\n style={defaultStyle}\n value={localValue}\n >\n <Mention\n data={suggestions}\n displayTransform={displayTransform}\n markup=\"{{__id__}}\"\n style={{\n backgroundColor: 'var(--theme-elevation-100)',\n padding: '2px 0',\n }}\n trigger=\"{\"\n />\n <Mention\n data={imageFieldSuggestions}\n displayTransform={imageDisplayTransform}\n markup=\"@__id__\"\n style={{\n backgroundColor: 'var(--theme-elevation-150)',\n padding: '2px 0',\n }}\n trigger=\"@\"\n />\n </MentionsInput>\n <FieldDescription description={field?.admin?.description} path=\"\" />\n </div>\n )\n}\n"],"names":["FieldDescription","FieldLabel","useConfig","useField","React","useCallback","useEffect","useMemo","useRef","useState","Mention","MentionsInput","useInstructions","defaultStyle","PromptEditorField","props","field","path","pathFromContext","setValue","value","payloadValue","localValue","setLocalValue","hasInitialized","activeCollection","promptEditorSuggestions","config","suggestions","map","suggestion","id","display","documentData","setDocumentData","window","segments","location","pathname","split","collectionsIndex","indexOf","length","urlCollectionSlug","urlId","fetchDocument","response","fetch","String","serverURL","routes","api","ok","data","json","_err","imageFieldSuggestions","targetSlug","collections","collection","find","c","slug","fields","uploadFields","findUploadFields","prefix","type","name","fieldPath","push","hasMany","Array","isArray","newPrefix","forEach","getFilename","item","filename","fname","current","handleChange","e","newValue","target","handleBlur","displayTransform","imageDisplayTransform","div","className","label","onBlur","onChange","placeholder","style","markup","backgroundColor","padding","trigger","description","admin"],"mappings":"AAAA;;AAIA,SAASA,gBAAgB,EAAEC,UAAU,EAAEC,SAAS,EAAEC,QAAQ,QAAQ,iBAAgB;AAClF,OAAOC,SAASC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AAChF,SAASC,OAAO,EAAEC,aAAa,QAAQ,4CAA2C;AAElF,SAASC,eAAe,QAAQ,0DAAyD;AACzF,SAASC,YAAY,QAAQ,oBAAmB;AAEhD,OAAO,MAAMC,oBAAwD,CAACC;IACpE,MAAM,EAAEC,KAAK,EAAEC,MAAMC,eAAe,EAAE,GAAGH;IACzC,MAAM,EAAEI,QAAQ,EAAEC,OAAOC,YAAY,EAAE,GAAGlB,SAAiB;QACzDc,MAAMC;IACR;IAEA,MAAM,CAACI,YAAYC,cAAc,GAAGd,SAASY,gBAAgB;IAC7D,MAAMG,iBAAiBhB,OAAO;IAE9B,MAAM,EAAEiB,gBAAgB,EAAEC,uBAAuB,EAAE,GAAGd;IACtD,MAAM,EAAEe,MAAM,EAAE,GAAGzB;IAEnB,MAAM0B,cAAcrB,QAClB,IACEmB,wBAAwBG,GAAG,CAAC,CAACC,aAAwB,CAAA;gBACnDC,IAAID;gBACJE,SAASF;YACX,CAAA,IACF;QAACJ;KAAwB;IAG3B,wEAAwE;IACxE,MAAM,CAACO,cAAcC,gBAAgB,GAAGzB,SAAyC;IAEjFH,UAAU;QACR,sBAAsB;QACtB,IAAI,OAAO6B,WAAW,aAAa;YACjC;QACF;QAEA,yFAAyF;QACzF,MAAMC,WAAWD,OAAOE,QAAQ,CAACC,QAAQ,CAACC,KAAK,CAAC;QAChD,MAAMC,mBAAmBJ,SAASK,OAAO,CAAC;QAE1C,IAAID,mBAAmB,CAAC,KAAKJ,SAASM,MAAM,GAAGF,mBAAmB,GAAG;YACnE,MAAMG,oBAAoBP,QAAQ,CAACI,mBAAmB,EAAE;YACxD,MAAMI,QAAQR,QAAQ,CAACI,mBAAmB,EAAE;YAE5C,mFAAmF;YACnF,6CAA6C;YAC7C,IAAIG,sBAAsBlB,oBAAoBmB,SAASA,UAAU,UAAU;gBACxE,MAAMC,gBAAgB;oBACpB,IAAI;wBAEF,MAAMC,WAAW,MAAMC,MAAM,CAAC,EAAEC,OAAOrB,OAAOsB,SAAS,EAAE,EAAED,OAAOrB,OAAOuB,MAAM,CAACC,GAAG,EAAE,CAAC,EAAEH,OAAOL,mBAAmB,CAAC,EAAEK,OAAOJ,OAAO,CAAC;wBACpI,IAAIE,SAASM,EAAE,EAAE;4BACf,MAAMC,OAAO,MAAMP,SAASQ,IAAI;4BAChCpB,gBAAgBmB;wBAClB;oBACF,EAAE,OAAOE,MAAM;oBACb,eAAe;oBACjB;gBACF;gBACA,KAAKV;YACR;QACF;IACF,GAAG;QAACpB;QAAkBE;KAAO;IAE7B,+DAA+D;IAC/D,MAAM6B,wBAAwBjD,QAAQ;QACpC,MAAMqB,cAAiD,EAAE;QAEzD,2EAA2E;QAC3E,MAAM6B,aAAahC;QAEnB,IAAI,CAACgC,cAAc,CAAC9B,QAAQ+B,aAAa;YACvC,OAAO,EAAE;QACX;QAEA,MAAMC,aAAahC,OAAO+B,WAAW,CAACE,IAAI,CAAC,CAACC,IAAMA,EAAEC,IAAI,KAAKL;QAC7D,IAAI,CAACE,YAAYI,QAAQ;YACvB,OAAO,EAAE;QACX;QAEA,MAAMC,eAAqD,EAAE;QAE7D,2CAA2C;QAC3C,8DAA8D;QAC9D,MAAMC,mBAAmB,CAACF,QAAeG,SAAS,EAAE;YAClD,KAAK,MAAMlD,SAAS+C,OAAQ;gBAC1B,IAAI/C,MAAMmD,IAAI,KAAK,YAAYnD,MAAMoD,IAAI,EAAE;oBACzC,MAAMC,YAAYH,SAAS,CAAC,EAAEA,OAAO,CAAC,EAAElB,OAAOhC,MAAMoD,IAAI,EAAE,CAAC,GAAGpB,OAAOhC,MAAMoD,IAAI;oBAChFJ,aAAaM,IAAI,CAAC;wBAAEF,MAAMC;wBAAWE,SAASvD,MAAMuD,OAAO,KAAK;oBAAK;gBACvE;gBACA,8CAA8C;gBAC9C,IAAIvD,MAAM+C,MAAM,IAAIS,MAAMC,OAAO,CAACzD,MAAM+C,MAAM,GAAG;oBAC/C,MAAMW,YAAY1D,MAAMoD,IAAI,GAAIF,SAAS,CAAC,EAAEA,OAAO,CAAC,EAAElB,OAAOhC,MAAMoD,IAAI,EAAE,CAAC,GAAGpB,OAAOhC,MAAMoD,IAAI,IAAKF;oBACnGD,iBAAiBjD,MAAM+C,MAAM,EAAEW;gBACjC;YACF;QACF;QAEAT,iBAAiBN,WAAWI,MAAM;QAElC,4FAA4F;QAC5FC,aAAaW,OAAO,CAAC,CAAC,EAAEP,IAAI,EAAEG,OAAO,EAAE;YACrC,6DAA6D;YAC7D,IAAI,CAACA,SAAS;gBACZ3C,YAAY0C,IAAI,CAAC;oBAAEvC,IAAIqC;oBAAMpC,SAASoC;gBAAK;YAC7C;QACF;QAEA,8DAA8D;QAC9D,IAAInC,cAAc;YAChB+B,aAAaW,OAAO,CAAC,CAAC,EAAEP,IAAI,EAAEG,OAAO,EAAE;gBACrC,MAAMnD,QAAQa,YAAY,CAACmC,KAAK,CAAC,+CAA+C;;gBAEhF,0EAA0E;gBAC1E,8DAA8D;gBAC9D,MAAMQ,cAAc,CAACC;oBAClB,IAAI,OAAOA,SAAS,YAAYA,QAASA,CAAAA,KAAKC,QAAQ,IAAID,KAAKT,IAAI,AAAD,GAAI;wBACpE,OAAOS,KAAKC,QAAQ,IAAID,KAAKT,IAAI;oBACnC;oBACA,kEAAkE;oBAClE,mFAAmF;oBACnF,OAAO;gBACV;gBAEA,IAAIhD,OAAO;oBACR,IAAImD,WAAWC,MAAMC,OAAO,CAACrD,QAAQ;wBACnC,8DAA8D;wBAC9DA,MAAMuD,OAAO,CAAC,CAACE;4BACb,MAAME,QAAQH,YAAYC;4BAC1B,IAAIE,OAAO;gCACT,MAAMjD,aAAa,CAAC,EAAEsC,KAAK,CAAC,EAAEW,MAAM,CAAC;gCACrCnD,YAAY0C,IAAI,CAAC;oCAAEvC,IAAID;oCAAYE,SAASF;gCAAW;4BACzD;wBACF;oBACF,OAAO,IAAI,CAACyC,SAAS;wBACnB,uDAAuD;wBACvD,+DAA+D;wBAC/D,sCAAsC;wBACtC,8EAA8E;wBAC9E,MAAMQ,QAAQH,YAAYxD;wBAC1B,IAAI2D,OAAO;4BACP,MAAMjD,aAAa,CAAC,EAAEsC,KAAK,CAAC,EAAEW,MAAM,CAAC;4BACrCnD,YAAY0C,IAAI,CAAC;gCAAEvC,IAAID;gCAAYE,SAASF;4BAAW;wBAC3D;oBACF;gBACH;YACF;QACF;QAEA,OAAOF;IACT,GAAG;QAACH;QAAkBE;QAAQM;KAAa;IAE3C3B,UAAU;QACR,IAAI,CAACkB,eAAewD,OAAO,IAAI3D,iBAAiB,IAAI;YAClDE,cAAcF,gBAAgB;YAC9BG,eAAewD,OAAO,GAAG;QAC3B;IACF,GAAG;QAAC3D;KAAa;IAEjB,MAAM4D,eAAe5E,YAAY,CAAC6E;QAChC,MAAMC,WAAWD,EAAEE,MAAM,CAAChE,KAAK;QAC/BG,cAAc4D;QACd,6EAA6E;QAC7EhE,SAASgE;IACX,GAAG;QAAChE;KAAS;IAEb,MAAMkE,aAAahF,YAAY;QAC7Bc,SAASG;IACX,GAAG;QAACA;QAAYH;KAAS;IAEzB,MAAMmE,mBAAmBjF,YAAY,CAAC0B,KAAe,CAAC,GAAG,EAAEA,GAAG,GAAG,CAAC,EAAE,EAAE;IACtE,MAAMwD,wBAAwBlF,YAAY,CAAC0B,KAAe,CAAC,CAAC,EAAEA,GAAG,CAAC,EAAE,EAAE;IAEtE,qBACE,MAACyD;QAAIC,WAAU;;0BACb,KAACxF;gBAAWyF,OAAO1E,MAAM0E,KAAK;;0BAC9B,MAAC/E;gBACCgF,QAAQN;gBACRO,UAAUX;gBACVY,aAAY;gBACZC,OAAOjF;gBACPO,OAAOE;;kCAEP,KAACZ;wBACC2C,MAAMzB;wBACN0D,kBAAkBA;wBAClBS,QAAO;wBACPD,OAAO;4BACLE,iBAAiB;4BACjBC,SAAS;wBACX;wBACAC,SAAQ;;kCAEV,KAACxF;wBACC2C,MAAMG;wBACN8B,kBAAkBC;wBAClBQ,QAAO;wBACPD,OAAO;4BACLE,iBAAiB;4BACjBC,SAAS;wBACX;wBACAC,SAAQ;;;;0BAGZ,KAAClG;gBAAiBmG,aAAanF,OAAOoF,OAAOD;gBAAalF,MAAK;;;;AAGrE,EAAC"}
@@ -133,8 +133,11 @@ export const PromptEditorField = (props) => {
133
133
  }
134
134
  }, [payloadValue]);
135
135
  const handleChange = useCallback((e) => {
136
- setLocalValue(e.target.value);
137
- }, []);
136
+ const newValue = e.target.value;
137
+ setLocalValue(newValue);
138
+ // Also update Payload value immediately to prevent loss when Save is clicked
139
+ setValue(newValue);
140
+ }, [setValue]);
138
141
  const handleBlur = useCallback(() => {
139
142
  setValue(localValue);
140
143
  }, [localValue, setValue]);
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export type { GenerateArgs } from './ai/index.js';
2
2
  export { defaultPrompts, defaultSeedPrompts } from './ai/prompts.js';
3
3
  export { PayloadAiPluginLexicalEditorFeature } from './fields/LexicalEditor/feature.server.js';
4
+ export type {} from './payload-ai.d.ts';
4
5
  export { payloadAiPlugin } from './plugin.js';
6
+ export { fieldToJsonSchema } from './utilities/fieldToJsonSchema.js';
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { defaultPrompts, defaultSeedPrompts } from './ai/prompts.js';
2
2
  export { PayloadAiPluginLexicalEditorFeature } from './fields/LexicalEditor/feature.server.js';
3
3
  export { payloadAiPlugin } from './plugin.js';
4
+ export { fieldToJsonSchema } from './utilities/fieldToJsonSchema.js';
4
5
 
5
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type { GenerateArgs } from './ai/index.js'\n\nexport { defaultPrompts, defaultSeedPrompts } from './ai/prompts.js'\nexport { PayloadAiPluginLexicalEditorFeature } from './fields/LexicalEditor/feature.server.js'\n\nexport { payloadAiPlugin } from './plugin.js'\n"],"names":["defaultPrompts","defaultSeedPrompts","PayloadAiPluginLexicalEditorFeature","payloadAiPlugin"],"mappings":"AAEA,SAASA,cAAc,EAAEC,kBAAkB,QAAQ,kBAAiB;AACpE,SAASC,mCAAmC,QAAQ,2CAA0C;AAE9F,SAASC,eAAe,QAAQ,cAAa"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type { GenerateArgs } from './ai/index.js'\n\nexport { defaultPrompts, defaultSeedPrompts } from './ai/prompts.js'\n\nexport { PayloadAiPluginLexicalEditorFeature } from './fields/LexicalEditor/feature.server.js'\n// Re-export to ensure payload.ai module augmentation is included\nexport type {} from './payload-ai.d.ts'\n\nexport { payloadAiPlugin } from './plugin.js'\nexport { fieldToJsonSchema } from './utilities/fieldToJsonSchema.js'\n"],"names":["defaultPrompts","defaultSeedPrompts","PayloadAiPluginLexicalEditorFeature","payloadAiPlugin","fieldToJsonSchema"],"mappings":"AAEA,SAASA,cAAc,EAAEC,kBAAkB,QAAQ,kBAAiB;AAEpE,SAASC,mCAAmC,QAAQ,2CAA0C;AAI9F,SAASC,eAAe,QAAQ,cAAa;AAC7C,SAASC,iBAAiB,QAAQ,mCAAkC"}
@@ -0,0 +1,149 @@
1
+ // Global type definitions for @ai-stack/payloadcms
2
+ // This file augments the Payload types using inline type definitions
3
+
4
+ import type { GenerateObjectResult, ImagePart, JSONValue, ModelMessage } from 'ai'
5
+ import type { z } from 'zod'
6
+
7
+ /**
8
+ * Provider options compatible with AI SDK
9
+ */
10
+ type ProviderOptions = Record<string, Record<string, JSONValue>>
11
+
12
+ /**
13
+ * Base arguments for all generation methods
14
+ */
15
+ interface PayloadGenerationBaseArgs {
16
+ extractAttachments?: boolean
17
+ maxTokens?: number
18
+ messages?: ModelMessage[]
19
+ model?: string
20
+ prompt: string
21
+ provider?: string
22
+ providerOptions?: ProviderOptions
23
+ system?: string
24
+ temperature?: number
25
+ }
26
+
27
+ /**
28
+ * Arguments for generateObject - structured output generation
29
+ */
30
+ interface PayloadGenerateObjectArgs extends PayloadGenerationBaseArgs {
31
+ images?: ImagePart[]
32
+ mode?: 'auto' | 'json' | 'tool'
33
+ schema?: Record<string, unknown> | z.ZodTypeAny
34
+ }
35
+
36
+ /**
37
+ * Arguments for generateText - simple text generation
38
+ */
39
+ interface PayloadGenerateTextArgs extends PayloadGenerationBaseArgs {
40
+ // No additional fields needed for basic text generation
41
+ }
42
+
43
+ /**
44
+ * Arguments for generateMedia - image/video generation
45
+ */
46
+ interface PayloadGenerateMediaArgs {
47
+ aspectRatio?: string
48
+ audioFormat?: string
49
+ callbackUrl?: string
50
+ duration?: number
51
+ fps?: number
52
+ images?: ImagePart[]
53
+ instructionId?: number | string
54
+ mode?: 'i2v' | 't2v'
55
+ model?: string
56
+ n?: number
57
+ prompt: string
58
+ provider?: string
59
+ providerOptions?: ProviderOptions
60
+ seed?: number
61
+ size?: { height: number; width: number }
62
+ speed?: number
63
+ voice?: string
64
+ }
65
+
66
+ /**
67
+ * Result from generateMedia - can be immediate file or async job
68
+ */
69
+ interface MediaResult {
70
+ // Immediate result (image generation)
71
+ file?: {
72
+ data: Buffer
73
+ mimetype: string
74
+ name: string
75
+ size: number
76
+ }
77
+
78
+ // Async job result (video generation)
79
+ jobId?: string
80
+ progress?: number
81
+ status?: 'completed' | 'failed' | 'queued' | 'running'
82
+ taskId?: string
83
+ }
84
+
85
+ declare module 'payload' {
86
+ interface BasePayload {
87
+ ai: {
88
+ /**
89
+ * @deprecated Use generateObject or generateText instead
90
+ * Legacy generate method for backward compatibility
91
+ */
92
+ generate: (args: unknown) => Promise<unknown>
93
+
94
+ /**
95
+ * Generate media (images or videos)
96
+ * @param args - Generation arguments including provider, model, prompt, and media options
97
+ * @returns Promise resolving to either a file or async job info
98
+ */
99
+ generateMedia: (args: PayloadGenerateMediaArgs) => Promise<MediaResult>
100
+
101
+ /**
102
+ * Generate structured output with schema validation
103
+ * @param args - Generation arguments including provider, model, prompt, and schema
104
+ * @returns Promise resolving to the generated object
105
+ */
106
+ generateObject: <T = unknown>(args: PayloadGenerateObjectArgs) => Promise<GenerateObjectResult<T>>
107
+
108
+ /**
109
+ * Generate simple text output
110
+ * @param args - Generation arguments including provider, model, and prompt
111
+ * @returns Promise resolving to the generated text
112
+ */
113
+ generateText: (args: PayloadGenerateTextArgs) => Promise<string>
114
+
115
+ /**
116
+ * Get a specific model instance
117
+ * @param provider - Provider name (e.g., 'openai', 'anthropic')
118
+ * @param modelId - Model ID (e.g., 'gpt-4', 'claude-3')
119
+ * @param type - Model type ('text', 'image', or 'tts')
120
+ * @returns Promise resolving to the model instance
121
+ */
122
+ getModel: (provider: string, modelId: string, type?: 'image' | 'text' | 'tts') => Promise<unknown>
123
+
124
+ /**
125
+ * Get the provider registry
126
+ * @returns Promise resolving to the provider registry
127
+ */
128
+ getRegistry: () => Promise<Record<string, unknown>>
129
+
130
+ /**
131
+ * Stream structured output with schema validation
132
+ * @param args - Generation arguments including provider, model, prompt, and schema
133
+ * @returns Response stream
134
+ */
135
+ streamObject: <T = unknown>(
136
+ args: PayloadGenerateObjectArgs,
137
+ ) => Promise<Response>
138
+
139
+ /**
140
+ * Stream text output
141
+ * @param args - Generation arguments including provider, model, and prompt
142
+ * @returns Response stream
143
+ */
144
+ streamText: (args: PayloadGenerateTextArgs) => Promise<Response>
145
+ }
146
+ }
147
+ }
148
+
149
+ export {}
package/dist/plugin.js CHANGED
@@ -7,7 +7,6 @@ import { PLUGIN_NAME } from './defaults.js';
7
7
  import { fetchFields } from './endpoints/fetchFields.js';
8
8
  import { fetchVoices } from './endpoints/fetchVoices.js';
9
9
  import { endpoints } from './endpoints/index.js';
10
- import { init } from './init.js';
11
10
  import { translations } from './translations/index.js';
12
11
  import { isPluginActivated } from './utilities/isPluginActivated.js';
13
12
  import { updateFieldsConfig } from './utilities/updateFieldsConfig.js';
@@ -16,9 +15,7 @@ const defaultPluginConfig = {
16
15
  generate: ({ req })=>!!req.user,
17
16
  settings: ({ req })=>!!req.user
18
17
  },
19
- collections: {},
20
- disableSponsorMessage: false,
21
- generatePromptOnInit: true
18
+ disableSponsorMessage: false
22
19
  };
23
20
  const sponsorMessage = `
24
21
  ╔═══════════════════════════════════════════════════════════════╗
@@ -66,7 +63,6 @@ const payloadAiPlugin = (pluginConfig)=>(incomingConfig)=>{
66
63
  let updatedConfig = {
67
64
  ...incomingConfig
68
65
  };
69
- let collectionsFieldPathMap = {};
70
66
  if (isActivated) {
71
67
  const Instructions = instructionsCollection(pluginConfig);
72
68
  const AIJobs = aiJobsCollection();
@@ -96,7 +92,7 @@ const payloadAiPlugin = (pluginConfig)=>(incomingConfig)=>{
96
92
  ...incomingConfig.globals ?? [],
97
93
  aiSettingsGlobal
98
94
  ];
99
- const { collections: collectionSlugs, globals: globalsSlugs } = pluginConfig;
95
+ const { globals: globalsSlugs } = pluginConfig;
100
96
  const { components: { providers = [] } = {} } = incomingConfig.admin || {};
101
97
  const updatedProviders = [
102
98
  ...providers ?? [],
@@ -115,15 +111,9 @@ const payloadAiPlugin = (pluginConfig)=>(incomingConfig)=>{
115
111
  updatedConfig = {
116
112
  ...incomingConfig,
117
113
  collections: collections.map((collection)=>{
118
- if (collectionSlugs[collection.slug]) {
119
- const { schemaPathMap, updatedCollectionConfig } = updateFieldsConfig(collection);
120
- collectionsFieldPathMap = {
121
- ...collectionsFieldPathMap,
122
- ...schemaPathMap
123
- };
124
- return updatedCollectionConfig;
125
- }
126
- return collection;
114
+ // Always inject fields, but they will be dynamically enabled/disabled by the InstructionsProvider
115
+ const { updatedCollectionConfig } = updateFieldsConfig(collection);
116
+ return updatedCollectionConfig;
127
117
  }),
128
118
  endpoints: [
129
119
  ...incomingConfig.endpoints ?? [],
@@ -137,11 +127,7 @@ const payloadAiPlugin = (pluginConfig)=>(incomingConfig)=>{
137
127
  ],
138
128
  globals: globals.map((global)=>{
139
129
  if (globalsSlugs && globalsSlugs[global.slug]) {
140
- const { schemaPathMap, updatedCollectionConfig } = updateFieldsConfig(global);
141
- collectionsFieldPathMap = {
142
- ...collectionsFieldPathMap,
143
- ...schemaPathMap
144
- };
130
+ const { updatedCollectionConfig } = updateFieldsConfig(global);
145
131
  return updatedCollectionConfig;
146
132
  }
147
133
  return global;
@@ -162,18 +148,16 @@ const payloadAiPlugin = (pluginConfig)=>(incomingConfig)=>{
162
148
  payload.logger.warn(`— AI Plugin: Not activated. Please verify your environment keys.`);
163
149
  return;
164
150
  }
165
- await init(payload, collectionsFieldPathMap, pluginConfig).catch((error)=>{
166
- payload.logger.error(error, `— AI Plugin: Initialization Error`);
167
- }).finally(()=>{
168
- if (!pluginConfig.disableSponsorMessage) {
169
- setTimeout(()=>{
170
- payload.logger.info(securityMessage);
171
- }, 1000);
172
- setTimeout(()=>{
173
- payload.logger.info(sponsorMessage);
174
- }, 3000);
175
- }
176
- });
151
+ if (!pluginConfig.disableSponsorMessage) {
152
+ setTimeout(()=>{
153
+ payload.logger.info(securityMessage);
154
+ }, 1000);
155
+ setTimeout(()=>{
156
+ payload.logger.info(sponsorMessage);
157
+ }, 3000);
158
+ }
159
+ // Inject AI capabilities with enhanced abstraction layer
160
+ ;
177
161
  payload.ai = {
178
162
  // Core generation methods
179
163
  generateObject: async (args)=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugin.ts"],"sourcesContent":["import type { CollectionConfig, Config, GlobalConfig } from 'payload'\n\nimport { deepMerge } from 'payload/shared'\n\nimport type { PluginConfig } from './types.js'\n\nimport { lexicalJsonSchema } from './ai/schemas/lexicalJsonSchema.js'\nimport { aiJobsCollection } from './collections/AIJobs.js'\nimport { aiSettingsGlobal } from './collections/AISettings.js'\nimport { instructionsCollection } from './collections/Instructions.js'\nimport { PLUGIN_NAME } from './defaults.js'\nimport { fetchFields } from './endpoints/fetchFields.js'\nimport { fetchVoices } from './endpoints/fetchVoices.js'\nimport { endpoints } from './endpoints/index.js'\nimport { init } from './init.js'\nimport { translations } from './translations/index.js'\nimport { isPluginActivated } from './utilities/isPluginActivated.js'\nimport { updateFieldsConfig } from './utilities/updateFieldsConfig.js'\n\nconst defaultPluginConfig: PluginConfig = {\n access: {\n generate: ({ req }) => !!req.user,\n settings: ({ req }) => !!req.user,\n },\n collections: {},\n disableSponsorMessage: false,\n generatePromptOnInit: true,\n}\n\nconst sponsorMessage = `\n╔═══════════════════════════════════════════════════════════════╗\n║ THANK YOU FOR USING THE PAYLOAD AI PLUGIN! ║\n║ ║\n║ If this plugin makes your life easier, please ║\n║ consider supporting its development and maintenance: ║\n║ ║\n║ • Buy me a coffee: https://buymeacoffee.com/ashbuilds ║\n║ • Sponsor on GitHub: https://github.com/sponsors/ashbuilds ║\n║ ║\n║ Your support fuels continued improvements, ║\n║ new features, and more caffeinated coding sessions! ☕ ║\n║ ║\n║ Got feedback or need help? Submit an issue here: ║\n║ • https://github.com/ashbuilds/payload-ai/issues/new ║\n║ ║\n║ Thank you again, and happy building! ║\n╚═══════════════════════════════════════════════════════════════╝\n`\n\nconst securityMessage = `\n╔═══════════════════════════════════════════════════════════════╗\n║ SECURITY NOTICE ║\n║ ║\n║ The AI Plugin now requires authentication by default. ║\n║ All AI features are restricted to authenticated users. ║\n║ ║\n║ To customize access control, configure the 'access' option ║\n║ in your plugin settings. See documentation for details. ║\n║ ║\n║ If you need different access patterns, please configure ║\n║ them explicitly in your plugin configuration. ║\n╚═══════════════════════════════════════════════════════════════╝\n`\n\nconst payloadAiPlugin =\n (pluginConfig: PluginConfig) =>\n (incomingConfig: Config): Config => {\n pluginConfig = {\n ...defaultPluginConfig,\n ...pluginConfig,\n access: {\n ...defaultPluginConfig.access,\n ...pluginConfig.access,\n },\n }\n\n const isActivated = isPluginActivated(pluginConfig)\n let updatedConfig: Config = { ...incomingConfig }\n let collectionsFieldPathMap = {}\n\n if (isActivated) {\n const Instructions = instructionsCollection(pluginConfig)\n const AIJobs = aiJobsCollection()\n // Inject editor schema to config, so that it can be accessed when /textarea endpoint will hit\n const lexicalSchema = lexicalJsonSchema(pluginConfig.editorConfig?.nodes)\n\n Instructions.admin = {\n ...Instructions.admin,\n }\n\n if (pluginConfig.debugging) {\n Instructions.admin.hidden = false\n }\n\n Instructions.admin.custom = {\n ...(Instructions.admin.custom || {}),\n [PLUGIN_NAME]: {\n editorConfig: {\n // Used in admin client for useObject hook\n schema: lexicalSchema,\n },\n },\n }\n\n const collections = [...(incomingConfig.collections ?? []), Instructions, AIJobs]\n const globals = [...(incomingConfig.globals ?? []), aiSettingsGlobal]\n const { collections: collectionSlugs, globals: globalsSlugs } = pluginConfig\n\n const { components: { providers = [] } = {} } = incomingConfig.admin || {}\n const updatedProviders = [\n ...(providers ?? []),\n {\n path: '@ai-stack/payloadcms/client#InstructionsProvider',\n },\n ]\n\n incomingConfig.admin = {\n ...(incomingConfig.admin || {}),\n components: {\n ...(incomingConfig.admin?.components ?? {}),\n providers: updatedProviders,\n },\n }\n\n const pluginEndpoints = endpoints(pluginConfig)\n updatedConfig = {\n ...incomingConfig,\n collections: collections.map((collection) => {\n if (collectionSlugs[collection.slug]) {\n const { schemaPathMap, updatedCollectionConfig } = updateFieldsConfig(collection)\n collectionsFieldPathMap = {\n ...collectionsFieldPathMap,\n ...schemaPathMap,\n }\n return updatedCollectionConfig as CollectionConfig\n }\n\n return collection\n }),\n endpoints: [\n ...(incomingConfig.endpoints ?? []),\n pluginEndpoints.textarea,\n pluginEndpoints.upload,\n ...(pluginEndpoints.videogenWebhook ? [pluginEndpoints.videogenWebhook] : []),\n fetchFields(pluginConfig),\n fetchVoices,\n ],\n globals: globals.map((global) => {\n if (globalsSlugs && globalsSlugs[global.slug]) {\n const { schemaPathMap, updatedCollectionConfig } = updateFieldsConfig(global)\n collectionsFieldPathMap = {\n ...collectionsFieldPathMap,\n ...schemaPathMap,\n }\n return updatedCollectionConfig as GlobalConfig\n }\n\n return global\n }),\n i18n: {\n ...(incomingConfig.i18n || {}),\n translations: {\n ...deepMerge(translations, incomingConfig.i18n?.translations ?? {}),\n },\n },\n }\n }\n\n updatedConfig.onInit = async (payload) => {\n if (incomingConfig.onInit) {\n await incomingConfig.onInit(payload)\n }\n\n if (!isActivated) {\n payload.logger.warn(`— AI Plugin: Not activated. Please verify your environment keys.`)\n return\n }\n\n await init(payload, collectionsFieldPathMap, pluginConfig)\n .catch((error) => {\n payload.logger.error(error, `— AI Plugin: Initialization Error`)\n })\n .finally(() => {\n if (!pluginConfig.disableSponsorMessage) {\n setTimeout(() => {\n payload.logger.info(securityMessage)\n }, 1000)\n setTimeout(() => {\n payload.logger.info(sponsorMessage)\n }, 3000)\n }\n })\n\n // Inject AI capabilities with enhanced abstraction layer\n ;(payload as any).ai = {\n // Core generation methods\n generateObject: async (args: any) => {\n const { generateObject } = await import('./ai/core/index.js')\n return generateObject({ ...args, payload })\n },\n\n generateText: async (args: any) => {\n const { generateText } = await import('./ai/core/index.js')\n return generateText({ ...args, payload })\n },\n\n generateMedia: async (args: any) => {\n const { generateMedia } = await import('./ai/core/index.js')\n return generateMedia({ ...args, payload })\n },\n\n // Streaming variants\n streamObject: async (args: any) => {\n const { streamObject } = await import('./ai/core/index.js')\n const result = await streamObject({ ...args, payload })\n return result.toTextStreamResponse()\n },\n\n streamText: async (args: any) => {\n const { streamText } = await import('./ai/core/index.js')\n return streamText({ ...args, payload })\n },\n\n // Helper utilities\n getModel: async (provider: string, modelId: string, type?: 'image' | 'text' | 'tts') => {\n const { getImageModel, getLanguageModel, getTTSModel } = await import(\n './ai/providers/registry.js'\n )\n if (type === 'image') {\n return getImageModel(payload, provider, modelId)\n }\n if (type === 'tts') {\n return getTTSModel(payload, provider, modelId)\n }\n return getLanguageModel(payload, provider, modelId)\n },\n\n getRegistry: async () => {\n const { getProviderRegistry } = await import('./ai/providers/registry.js')\n return getProviderRegistry(payload)\n },\n\n // Legacy method for backward compatibility\n /** @deprecated Use generateObject or generateText instead */\n generate: async (args: any) => {\n const { generate } = await import('./ai/index.js')\n return generate({ ...args, payload })\n },\n }\n }\n\n return updatedConfig\n }\n\nexport { payloadAiPlugin }\n"],"names":["deepMerge","lexicalJsonSchema","aiJobsCollection","aiSettingsGlobal","instructionsCollection","PLUGIN_NAME","fetchFields","fetchVoices","endpoints","init","translations","isPluginActivated","updateFieldsConfig","defaultPluginConfig","access","generate","req","user","settings","collections","disableSponsorMessage","generatePromptOnInit","sponsorMessage","securityMessage","payloadAiPlugin","pluginConfig","incomingConfig","isActivated","updatedConfig","collectionsFieldPathMap","Instructions","AIJobs","lexicalSchema","editorConfig","nodes","admin","debugging","hidden","custom","schema","globals","collectionSlugs","globalsSlugs","components","providers","updatedProviders","path","pluginEndpoints","map","collection","slug","schemaPathMap","updatedCollectionConfig","textarea","upload","videogenWebhook","global","i18n","onInit","payload","logger","warn","catch","error","finally","setTimeout","info","ai","generateObject","args","generateText","generateMedia","streamObject","result","toTextStreamResponse","streamText","getModel","provider","modelId","type","getImageModel","getLanguageModel","getTTSModel","getRegistry","getProviderRegistry"],"mappings":"AAEA,SAASA,SAAS,QAAQ,iBAAgB;AAI1C,SAASC,iBAAiB,QAAQ,oCAAmC;AACrE,SAASC,gBAAgB,QAAQ,0BAAyB;AAC1D,SAASC,gBAAgB,QAAQ,8BAA6B;AAC9D,SAASC,sBAAsB,QAAQ,gCAA+B;AACtE,SAASC,WAAW,QAAQ,gBAAe;AAC3C,SAASC,WAAW,QAAQ,6BAA4B;AACxD,SAASC,WAAW,QAAQ,6BAA4B;AACxD,SAASC,SAAS,QAAQ,uBAAsB;AAChD,SAASC,IAAI,QAAQ,YAAW;AAChC,SAASC,YAAY,QAAQ,0BAAyB;AACtD,SAASC,iBAAiB,QAAQ,mCAAkC;AACpE,SAASC,kBAAkB,QAAQ,oCAAmC;AAEtE,MAAMC,sBAAoC;IACxCC,QAAQ;QACNC,UAAU,CAAC,EAAEC,GAAG,EAAE,GAAK,CAAC,CAACA,IAAIC,IAAI;QACjCC,UAAU,CAAC,EAAEF,GAAG,EAAE,GAAK,CAAC,CAACA,IAAIC,IAAI;IACnC;IACAE,aAAa,CAAC;IACdC,uBAAuB;IACvBC,sBAAsB;AACxB;AAEA,MAAMC,iBAAiB,CAAC;;;;;;;;;;;;;;;;;;AAkBxB,CAAC;AAED,MAAMC,kBAAkB,CAAC;;;;;;;;;;;;;AAazB,CAAC;AAED,MAAMC,kBACJ,CAACC,eACD,CAACC;QACCD,eAAe;YACb,GAAGZ,mBAAmB;YACtB,GAAGY,YAAY;YACfX,QAAQ;gBACN,GAAGD,oBAAoBC,MAAM;gBAC7B,GAAGW,aAAaX,MAAM;YACxB;QACF;QAEA,MAAMa,cAAchB,kBAAkBc;QACtC,IAAIG,gBAAwB;YAAE,GAAGF,cAAc;QAAC;QAChD,IAAIG,0BAA0B,CAAC;QAE/B,IAAIF,aAAa;YACf,MAAMG,eAAe1B,uBAAuBqB;YAC5C,MAAMM,SAAS7B;YACf,8FAA8F;YAC9F,MAAM8B,gBAAgB/B,kBAAkBwB,aAAaQ,YAAY,EAAEC;YAEnEJ,aAAaK,KAAK,GAAG;gBACnB,GAAGL,aAAaK,KAAK;YACvB;YAEA,IAAIV,aAAaW,SAAS,EAAE;gBAC1BN,aAAaK,KAAK,CAACE,MAAM,GAAG;YAC9B;YAEAP,aAAaK,KAAK,CAACG,MAAM,GAAG;gBAC1B,GAAIR,aAAaK,KAAK,CAACG,MAAM,IAAI,CAAC,CAAC;gBACnC,CAACjC,YAAY,EAAE;oBACb4B,cAAc;wBACZ,0CAA0C;wBAC1CM,QAAQP;oBACV;gBACF;YACF;YAEA,MAAMb,cAAc;mBAAKO,eAAeP,WAAW,IAAI,EAAE;gBAAGW;gBAAcC;aAAO;YACjF,MAAMS,UAAU;mBAAKd,eAAec,OAAO,IAAI,EAAE;gBAAGrC;aAAiB;YACrE,MAAM,EAAEgB,aAAasB,eAAe,EAAED,SAASE,YAAY,EAAE,GAAGjB;YAEhE,MAAM,EAAEkB,YAAY,EAAEC,YAAY,EAAE,EAAE,GAAG,CAAC,CAAC,EAAE,GAAGlB,eAAeS,KAAK,IAAI,CAAC;YACzE,MAAMU,mBAAmB;mBACnBD,aAAa,EAAE;gBACnB;oBACEE,MAAM;gBACR;aACD;YAEDpB,eAAeS,KAAK,GAAG;gBACrB,GAAIT,eAAeS,KAAK,IAAI,CAAC,CAAC;gBAC9BQ,YAAY;oBACV,GAAIjB,eAAeS,KAAK,EAAEQ,cAAc,CAAC,CAAC;oBAC1CC,WAAWC;gBACb;YACF;YAEA,MAAME,kBAAkBvC,UAAUiB;YAClCG,gBAAgB;gBACd,GAAGF,cAAc;gBACjBP,aAAaA,YAAY6B,GAAG,CAAC,CAACC;oBAC5B,IAAIR,eAAe,CAACQ,WAAWC,IAAI,CAAC,EAAE;wBACpC,MAAM,EAAEC,aAAa,EAAEC,uBAAuB,EAAE,GAAGxC,mBAAmBqC;wBACtEpB,0BAA0B;4BACxB,GAAGA,uBAAuB;4BAC1B,GAAGsB,aAAa;wBAClB;wBACA,OAAOC;oBACT;oBAEA,OAAOH;gBACT;gBACAzC,WAAW;uBACLkB,eAAelB,SAAS,IAAI,EAAE;oBAClCuC,gBAAgBM,QAAQ;oBACxBN,gBAAgBO,MAAM;uBAClBP,gBAAgBQ,eAAe,GAAG;wBAACR,gBAAgBQ,eAAe;qBAAC,GAAG,EAAE;oBAC5EjD,YAAYmB;oBACZlB;iBACD;gBACDiC,SAASA,QAAQQ,GAAG,CAAC,CAACQ;oBACpB,IAAId,gBAAgBA,YAAY,CAACc,OAAON,IAAI,CAAC,EAAE;wBAC7C,MAAM,EAAEC,aAAa,EAAEC,uBAAuB,EAAE,GAAGxC,mBAAmB4C;wBACtE3B,0BAA0B;4BACxB,GAAGA,uBAAuB;4BAC1B,GAAGsB,aAAa;wBAClB;wBACA,OAAOC;oBACT;oBAEA,OAAOI;gBACT;gBACAC,MAAM;oBACJ,GAAI/B,eAAe+B,IAAI,IAAI,CAAC,CAAC;oBAC7B/C,cAAc;wBACZ,GAAGV,UAAUU,cAAcgB,eAAe+B,IAAI,EAAE/C,gBAAgB,CAAC,EAAE;oBACrE;gBACF;YACF;QACF;QAEAkB,cAAc8B,MAAM,GAAG,OAAOC;YAC5B,IAAIjC,eAAegC,MAAM,EAAE;gBACzB,MAAMhC,eAAegC,MAAM,CAACC;YAC9B;YAEA,IAAI,CAAChC,aAAa;gBAChBgC,QAAQC,MAAM,CAACC,IAAI,CAAC,CAAC,gEAAgE,CAAC;gBACtF;YACF;YAEA,MAAMpD,KAAKkD,SAAS9B,yBAAyBJ,cAC1CqC,KAAK,CAAC,CAACC;gBACNJ,QAAQC,MAAM,CAACG,KAAK,CAACA,OAAO,CAAC,iCAAiC,CAAC;YACjE,GACCC,OAAO,CAAC;gBACP,IAAI,CAACvC,aAAaL,qBAAqB,EAAE;oBACvC6C,WAAW;wBACTN,QAAQC,MAAM,CAACM,IAAI,CAAC3C;oBACtB,GAAG;oBACH0C,WAAW;wBACTN,QAAQC,MAAM,CAACM,IAAI,CAAC5C;oBACtB,GAAG;gBACL;YACF;YAGAqC,QAAgBQ,EAAE,GAAG;gBACrB,0BAA0B;gBAC1BC,gBAAgB,OAAOC;oBACrB,MAAM,EAAED,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC;oBACxC,OAAOA,eAAe;wBAAE,GAAGC,IAAI;wBAAEV;oBAAQ;gBAC3C;gBAEAW,cAAc,OAAOD;oBACnB,MAAM,EAAEC,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC;oBACtC,OAAOA,aAAa;wBAAE,GAAGD,IAAI;wBAAEV;oBAAQ;gBACzC;gBAEAY,eAAe,OAAOF;oBACpB,MAAM,EAAEE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC;oBACvC,OAAOA,cAAc;wBAAE,GAAGF,IAAI;wBAAEV;oBAAQ;gBAC1C;gBAEA,qBAAqB;gBACrBa,cAAc,OAAOH;oBACnB,MAAM,EAAEG,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC;oBACtC,MAAMC,SAAS,MAAMD,aAAa;wBAAE,GAAGH,IAAI;wBAAEV;oBAAQ;oBACrD,OAAOc,OAAOC,oBAAoB;gBACpC;gBAEAC,YAAY,OAAON;oBACjB,MAAM,EAAEM,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC;oBACpC,OAAOA,WAAW;wBAAE,GAAGN,IAAI;wBAAEV;oBAAQ;gBACvC;gBAEA,mBAAmB;gBACnBiB,UAAU,OAAOC,UAAkBC,SAAiBC;oBAClD,MAAM,EAAEC,aAAa,EAAEC,gBAAgB,EAAEC,WAAW,EAAE,GAAG,MAAM,MAAM,CACnE;oBAEF,IAAIH,SAAS,SAAS;wBACpB,OAAOC,cAAcrB,SAASkB,UAAUC;oBAC1C;oBACA,IAAIC,SAAS,OAAO;wBAClB,OAAOG,YAAYvB,SAASkB,UAAUC;oBACxC;oBACA,OAAOG,iBAAiBtB,SAASkB,UAAUC;gBAC7C;gBAEAK,aAAa;oBACX,MAAM,EAAEC,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC;oBAC7C,OAAOA,oBAAoBzB;gBAC7B;gBAEA,2CAA2C;gBAC3C,2DAA2D,GAC3D5C,UAAU,OAAOsD;oBACf,MAAM,EAAEtD,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC;oBAClC,OAAOA,SAAS;wBAAE,GAAGsD,IAAI;wBAAEV;oBAAQ;gBACrC;YACF;QACF;QAEA,OAAO/B;IACT;AAEF,SAASJ,eAAe,GAAE"}
1
+ {"version":3,"sources":["../src/plugin.ts"],"sourcesContent":["import type { CollectionConfig, Config, GlobalConfig } from 'payload'\n\nimport { deepMerge } from 'payload/shared'\n\nimport type { PluginConfig } from './types.js'\n\nimport { lexicalJsonSchema } from './ai/schemas/lexicalJsonSchema.js'\nimport { aiJobsCollection } from './collections/AIJobs.js'\nimport { aiSettingsGlobal } from './collections/AISettings.js'\nimport { instructionsCollection } from './collections/Instructions.js'\nimport { PLUGIN_NAME } from './defaults.js'\nimport { fetchFields } from './endpoints/fetchFields.js'\nimport { fetchVoices } from './endpoints/fetchVoices.js'\nimport { endpoints } from './endpoints/index.js'\nimport { translations } from './translations/index.js'\nimport { isPluginActivated } from './utilities/isPluginActivated.js'\nimport { updateFieldsConfig } from './utilities/updateFieldsConfig.js'\n\nconst defaultPluginConfig: PluginConfig = {\n access: {\n generate: ({ req }) => !!req.user,\n settings: ({ req }) => !!req.user,\n },\n disableSponsorMessage: false,\n}\n\nconst sponsorMessage = `\n╔═══════════════════════════════════════════════════════════════╗\n║ THANK YOU FOR USING THE PAYLOAD AI PLUGIN! ║\n║ ║\n║ If this plugin makes your life easier, please ║\n║ consider supporting its development and maintenance: ║\n║ ║\n║ • Buy me a coffee: https://buymeacoffee.com/ashbuilds ║\n║ • Sponsor on GitHub: https://github.com/sponsors/ashbuilds ║\n║ ║\n║ Your support fuels continued improvements, ║\n║ new features, and more caffeinated coding sessions! ☕ ║\n║ ║\n║ Got feedback or need help? Submit an issue here: ║\n║ • https://github.com/ashbuilds/payload-ai/issues/new ║\n║ ║\n║ Thank you again, and happy building! ║\n╚═══════════════════════════════════════════════════════════════╝\n`\n\nconst securityMessage = `\n╔═══════════════════════════════════════════════════════════════╗\n║ SECURITY NOTICE ║\n║ ║\n║ The AI Plugin now requires authentication by default. ║\n║ All AI features are restricted to authenticated users. ║\n║ ║\n║ To customize access control, configure the 'access' option ║\n║ in your plugin settings. See documentation for details. ║\n║ ║\n║ If you need different access patterns, please configure ║\n║ them explicitly in your plugin configuration. ║\n╚═══════════════════════════════════════════════════════════════╝\n`\n\nconst payloadAiPlugin =\n (pluginConfig: PluginConfig) =>\n (incomingConfig: Config): Config => {\n pluginConfig = {\n ...defaultPluginConfig,\n ...pluginConfig,\n access: {\n ...defaultPluginConfig.access,\n ...pluginConfig.access,\n },\n }\n\n const isActivated = isPluginActivated(pluginConfig)\n let updatedConfig: Config = { ...incomingConfig }\n\n if (isActivated) {\n const Instructions = instructionsCollection(pluginConfig)\n const AIJobs = aiJobsCollection()\n // Inject editor schema to config, so that it can be accessed when /textarea endpoint will hit\n const lexicalSchema = lexicalJsonSchema(pluginConfig.editorConfig?.nodes)\n\n Instructions.admin = {\n ...Instructions.admin,\n }\n\n if (pluginConfig.debugging) {\n Instructions.admin.hidden = false\n }\n\n Instructions.admin.custom = {\n ...(Instructions.admin.custom || {}),\n [PLUGIN_NAME]: {\n editorConfig: {\n // Used in admin client for useObject hook\n schema: lexicalSchema,\n },\n },\n }\n\n const collections = [...(incomingConfig.collections ?? []), Instructions, AIJobs]\n const globals = [...(incomingConfig.globals ?? []), aiSettingsGlobal]\n const { globals: globalsSlugs } = pluginConfig\n\n const { components: { providers = [] } = {} } = incomingConfig.admin || {}\n const updatedProviders = [\n ...(providers ?? []),\n {\n path: '@ai-stack/payloadcms/client#InstructionsProvider',\n },\n ]\n\n incomingConfig.admin = {\n ...(incomingConfig.admin || {}),\n components: {\n ...(incomingConfig.admin?.components ?? {}),\n providers: updatedProviders,\n },\n }\n\n const pluginEndpoints = endpoints(pluginConfig)\n updatedConfig = {\n ...incomingConfig,\n collections: collections.map((collection) => {\n // Always inject fields, but they will be dynamically enabled/disabled by the InstructionsProvider\n const { updatedCollectionConfig } = updateFieldsConfig(collection)\n return updatedCollectionConfig as CollectionConfig\n }),\n endpoints: [\n ...(incomingConfig.endpoints ?? []),\n pluginEndpoints.textarea,\n pluginEndpoints.upload,\n ...(pluginEndpoints.videogenWebhook ? [pluginEndpoints.videogenWebhook] : []),\n fetchFields(pluginConfig),\n fetchVoices,\n ],\n globals: globals.map((global) => {\n if (globalsSlugs && globalsSlugs[global.slug]) {\n const { updatedCollectionConfig } = updateFieldsConfig(global)\n return updatedCollectionConfig as GlobalConfig\n }\n\n return global\n }),\n i18n: {\n ...(incomingConfig.i18n || {}),\n translations: {\n ...deepMerge(translations, incomingConfig.i18n?.translations ?? {}),\n },\n },\n }\n }\n\n updatedConfig.onInit = async (payload) => {\n if (incomingConfig.onInit) {\n await incomingConfig.onInit(payload)\n }\n\n if (!isActivated) {\n payload.logger.warn(`— AI Plugin: Not activated. Please verify your environment keys.`)\n return\n }\n\n if (!pluginConfig.disableSponsorMessage) {\n setTimeout(() => {\n payload.logger.info(securityMessage)\n }, 1000)\n setTimeout(() => {\n payload.logger.info(sponsorMessage)\n }, 3000)\n }\n\n // Inject AI capabilities with enhanced abstraction layer\n ;(payload as any).ai = {\n // Core generation methods\n generateObject: async (args: any) => {\n const { generateObject } = await import('./ai/core/index.js')\n return generateObject({ ...args, payload })\n },\n\n generateText: async (args: any) => {\n const { generateText } = await import('./ai/core/index.js')\n return generateText({ ...args, payload })\n },\n\n generateMedia: async (args: any) => {\n const { generateMedia } = await import('./ai/core/index.js')\n return generateMedia({ ...args, payload })\n },\n\n // Streaming variants\n streamObject: async (args: any) => {\n const { streamObject } = await import('./ai/core/index.js')\n const result = await streamObject({ ...args, payload })\n return result.toTextStreamResponse()\n },\n\n streamText: async (args: any) => {\n const { streamText } = await import('./ai/core/index.js')\n return streamText({ ...args, payload })\n },\n\n // Helper utilities\n getModel: async (provider: string, modelId: string, type?: 'image' | 'text' | 'tts') => {\n const { getImageModel, getLanguageModel, getTTSModel } = await import(\n './ai/providers/registry.js'\n )\n if (type === 'image') {\n return getImageModel(payload, provider, modelId)\n }\n if (type === 'tts') {\n return getTTSModel(payload, provider, modelId)\n }\n return getLanguageModel(payload, provider, modelId)\n },\n\n getRegistry: async () => {\n const { getProviderRegistry } = await import('./ai/providers/registry.js')\n return getProviderRegistry(payload)\n },\n\n // Legacy method for backward compatibility\n /** @deprecated Use generateObject or generateText instead */\n generate: async (args: any) => {\n const { generate } = await import('./ai/index.js')\n return generate({ ...args, payload })\n },\n }\n }\n\n return updatedConfig\n }\n\nexport { payloadAiPlugin }\n"],"names":["deepMerge","lexicalJsonSchema","aiJobsCollection","aiSettingsGlobal","instructionsCollection","PLUGIN_NAME","fetchFields","fetchVoices","endpoints","translations","isPluginActivated","updateFieldsConfig","defaultPluginConfig","access","generate","req","user","settings","disableSponsorMessage","sponsorMessage","securityMessage","payloadAiPlugin","pluginConfig","incomingConfig","isActivated","updatedConfig","Instructions","AIJobs","lexicalSchema","editorConfig","nodes","admin","debugging","hidden","custom","schema","collections","globals","globalsSlugs","components","providers","updatedProviders","path","pluginEndpoints","map","collection","updatedCollectionConfig","textarea","upload","videogenWebhook","global","slug","i18n","onInit","payload","logger","warn","setTimeout","info","ai","generateObject","args","generateText","generateMedia","streamObject","result","toTextStreamResponse","streamText","getModel","provider","modelId","type","getImageModel","getLanguageModel","getTTSModel","getRegistry","getProviderRegistry"],"mappings":"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"}
@@ -3,13 +3,17 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useAuth, useConfig, useDocumentDrawer } from '@payloadcms/ui';
4
4
  import React, { useCallback, useEffect, useState } from 'react';
5
5
  import { PLUGIN_FETCH_FIELDS_ENDPOINT, PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js';
6
+ import { useActiveFieldTracking } from '../../ui/Compose/hooks/useActiveFieldTracking.js';
6
7
  import { InstructionsContext } from './context.js';
7
8
  export const InstructionsProvider = ({ children })=>{
9
+ // Initialize field tracking globally so ai-plugin-active class is added on field focus
10
+ useActiveFieldTracking();
8
11
  const [instructions, setInstructionsState] = useState({});
9
12
  const [promptFields, setPromptFields] = useState([]);
10
13
  const [activeCollection, setActiveCollection] = useState('');
11
14
  const [isConfigAllowed, setIsConfigAllowed] = useState(false);
12
15
  const [enabledLanguages, setEnabledLanguages] = useState();
16
+ const [enabledCollections, setEnabledCollections] = useState();
13
17
  const [debugging, setDebugging] = useState(false);
14
18
  const { user } = useAuth();
15
19
  const { config } = useConfig();
@@ -34,44 +38,72 @@ export const InstructionsProvider = ({ children })=>{
34
38
  drawerOpenCount,
35
39
  openPayloadDrawer
36
40
  ]);
37
- // This is here because each field have separate instructions and
38
- // their ID is needed to edit them for Drawer
39
- useEffect(()=>{
41
+ const handleSave = useCallback(({ doc })=>{
42
+ setInstructionsState((prev)=>{
43
+ return {
44
+ ...prev,
45
+ [doc['schema-path']]: {
46
+ id: doc.id,
47
+ disabled: !!doc.disabled,
48
+ fieldType: doc['field-type']
49
+ }
50
+ };
51
+ });
52
+ }, [
53
+ setInstructionsState
54
+ ]);
55
+ const fetchFieldsData = useCallback(async ()=>{
40
56
  // Only fetch if we have a user ID - prevents fetching on every user object reference change
41
57
  if (!user?.id) {
42
58
  return;
43
59
  }
44
- fetch(`${serverURL}${api}${PLUGIN_FETCH_FIELDS_ENDPOINT}`).then(async (res)=>{
45
- await res.json().then((data)=>{
46
- setIsConfigAllowed(data?.isConfigAllowed || false);
47
- setEnabledLanguages(data?.enabledLanguages || []);
48
- setInstructionsState(data?.fields || {});
49
- setPromptFields(data?.promptFields || []);
50
- setDebugging(data?.debugging || false);
51
- });
52
- }).catch((err)=>{
60
+ try {
61
+ const res = await fetch(`${serverURL}${api}${PLUGIN_FETCH_FIELDS_ENDPOINT}`);
62
+ const data = await res.json();
63
+ setIsConfigAllowed(data?.isConfigAllowed || false);
64
+ setEnabledLanguages(data?.enabledLanguages || []);
65
+ setEnabledCollections(data?.enabledCollections || []);
66
+ setInstructionsState(data?.fields || {});
67
+ setPromptFields(data?.promptFields || []);
68
+ setDebugging(data?.debugging || false);
69
+ } catch (err) {
53
70
  console.error('InstructionsProvider:', err);
54
- });
71
+ }
55
72
  }, [
56
73
  api,
57
74
  serverURL,
58
75
  user?.id
59
76
  ]);
77
+ useEffect(()=>{
78
+ void fetchFieldsData();
79
+ }, [
80
+ fetchFieldsData
81
+ ]);
82
+ const refresh = useCallback(async ()=>{
83
+ await fetchFieldsData();
84
+ }, [
85
+ fetchFieldsData
86
+ ]);
60
87
  return /*#__PURE__*/ _jsxs(InstructionsContext.Provider, {
61
88
  value: {
62
89
  activeCollection,
63
90
  debugging,
91
+ enabledCollections,
64
92
  enabledLanguages,
65
93
  hasInstructions: instructions && Object.keys(instructions).length > 0,
66
94
  instructions,
67
95
  isConfigAllowed,
68
96
  openDrawer,
69
97
  promptFields,
70
- setActiveCollection
98
+ refresh,
99
+ setActiveCollection,
100
+ setEnabledCollections
71
101
  },
72
102
  children: [
73
103
  children,
74
- /*#__PURE__*/ _jsx(DocumentDrawer, {})
104
+ /*#__PURE__*/ _jsx(DocumentDrawer, {
105
+ onSave: handleSave
106
+ })
75
107
  ]
76
108
  });
77
109
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/providers/InstructionsProvider/InstructionsProvider.tsx"],"sourcesContent":["'use client'\n\nimport { useAuth, useConfig, useDocumentDrawer } from '@payloadcms/ui'\nimport React, { useCallback, useEffect, useState } from 'react'\n\nimport type { SerializedPromptField } from '../../types.js'\n\nimport { PLUGIN_FETCH_FIELDS_ENDPOINT, PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js'\nimport { InstructionsContext } from './context.js'\n\nexport const InstructionsProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const [instructions, setInstructionsState] = useState({})\n const [promptFields, setPromptFields] = useState<SerializedPromptField[]>([])\n const [activeCollection, setActiveCollection] = useState('')\n const [isConfigAllowed, setIsConfigAllowed] = useState(false)\n const [enabledLanguages, setEnabledLanguages] = useState<string[]>()\n const [debugging, setDebugging] = useState(false)\n const { user } = useAuth()\n\n const { config } = useConfig()\n const {\n routes: { api },\n serverURL,\n } = config\n\n // Global Document Drawer state\n const [drawerInstructionId, setDrawerInstructionId] = useState<string>('')\n const [drawerOpenCount, setDrawerOpenCount] = useState(0)\n\n const [DocumentDrawer, _, { openDrawer: openPayloadDrawer }] = useDocumentDrawer({\n id: drawerInstructionId,\n collectionSlug: PLUGIN_INSTRUCTIONS_TABLE,\n })\n\n const openDrawer = useCallback((id: string) => {\n setDrawerInstructionId(id)\n setDrawerOpenCount((prev) => prev + 1)\n }, [])\n\n // Open drawer when count changes\n useEffect(() => {\n if (drawerOpenCount > 0) {\n openPayloadDrawer()\n }\n }, [drawerOpenCount, openPayloadDrawer])\n\n // This is here because each field have separate instructions and\n // their ID is needed to edit them for Drawer\n useEffect(() => {\n // Only fetch if we have a user ID - prevents fetching on every user object reference change\n if (!user?.id) {\n return\n }\n\n fetch(`${serverURL}${api}${PLUGIN_FETCH_FIELDS_ENDPOINT}`)\n .then(async (res) => {\n await res.json().then((data) => {\n setIsConfigAllowed(data?.isConfigAllowed || false)\n setEnabledLanguages(data?.enabledLanguages || [])\n setInstructionsState(data?.fields || {})\n setPromptFields(data?.promptFields || [])\n setDebugging(data?.debugging || false)\n })\n })\n .catch((err) => {\n console.error('InstructionsProvider:', err)\n })\n }, [api, serverURL, user?.id])\n\n return (\n <InstructionsContext.Provider\n value={{\n activeCollection,\n debugging,\n enabledLanguages,\n hasInstructions: instructions && Object.keys(instructions).length > 0,\n instructions,\n isConfigAllowed,\n openDrawer,\n promptFields,\n setActiveCollection,\n }}\n >\n {children}\n <DocumentDrawer />\n </InstructionsContext.Provider>\n )\n}\n"],"names":["useAuth","useConfig","useDocumentDrawer","React","useCallback","useEffect","useState","PLUGIN_FETCH_FIELDS_ENDPOINT","PLUGIN_INSTRUCTIONS_TABLE","InstructionsContext","InstructionsProvider","children","instructions","setInstructionsState","promptFields","setPromptFields","activeCollection","setActiveCollection","isConfigAllowed","setIsConfigAllowed","enabledLanguages","setEnabledLanguages","debugging","setDebugging","user","config","routes","api","serverURL","drawerInstructionId","setDrawerInstructionId","drawerOpenCount","setDrawerOpenCount","DocumentDrawer","_","openDrawer","openPayloadDrawer","id","collectionSlug","prev","fetch","then","res","json","data","fields","catch","err","console","error","Provider","value","hasInstructions","Object","keys","length"],"mappings":"AAAA;;AAEA,SAASA,OAAO,EAAEC,SAAS,EAAEC,iBAAiB,QAAQ,iBAAgB;AACtE,OAAOC,SAASC,WAAW,EAAEC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAI/D,SAASC,4BAA4B,EAAEC,yBAAyB,QAAQ,oBAAmB;AAC3F,SAASC,mBAAmB,QAAQ,eAAc;AAElD,OAAO,MAAMC,uBAAgE,CAAC,EAAEC,QAAQ,EAAE;IACxF,MAAM,CAACC,cAAcC,qBAAqB,GAAGP,SAAS,CAAC;IACvD,MAAM,CAACQ,cAAcC,gBAAgB,GAAGT,SAAkC,EAAE;IAC5E,MAAM,CAACU,kBAAkBC,oBAAoB,GAAGX,SAAS;IACzD,MAAM,CAACY,iBAAiBC,mBAAmB,GAAGb,SAAS;IACvD,MAAM,CAACc,kBAAkBC,oBAAoB,GAAGf;IAChD,MAAM,CAACgB,WAAWC,aAAa,GAAGjB,SAAS;IAC3C,MAAM,EAAEkB,IAAI,EAAE,GAAGxB;IAEjB,MAAM,EAAEyB,MAAM,EAAE,GAAGxB;IACnB,MAAM,EACJyB,QAAQ,EAAEC,GAAG,EAAE,EACfC,SAAS,EACV,GAAGH;IAEJ,+BAA+B;IAC/B,MAAM,CAACI,qBAAqBC,uBAAuB,GAAGxB,SAAiB;IACvE,MAAM,CAACyB,iBAAiBC,mBAAmB,GAAG1B,SAAS;IAEvD,MAAM,CAAC2B,gBAAgBC,GAAG,EAAEC,YAAYC,iBAAiB,EAAE,CAAC,GAAGlC,kBAAkB;QAC/EmC,IAAIR;QACJS,gBAAgB9B;IAClB;IAEA,MAAM2B,aAAa/B,YAAY,CAACiC;QAC9BP,uBAAuBO;QACvBL,mBAAmB,CAACO,OAASA,OAAO;IACtC,GAAG,EAAE;IAEL,iCAAiC;IACjClC,UAAU;QACR,IAAI0B,kBAAkB,GAAG;YACvBK;QACF;IACF,GAAG;QAACL;QAAiBK;KAAkB;IAEvC,iEAAiE;IACjE,6CAA6C;IAC7C/B,UAAU;QACR,4FAA4F;QAC5F,IAAI,CAACmB,MAAMa,IAAI;YACb;QACF;QAEAG,MAAM,CAAC,EAAEZ,UAAU,EAAED,IAAI,EAAEpB,6BAA6B,CAAC,EACtDkC,IAAI,CAAC,OAAOC;YACX,MAAMA,IAAIC,IAAI,GAAGF,IAAI,CAAC,CAACG;gBACrBzB,mBAAmByB,MAAM1B,mBAAmB;gBAC5CG,oBAAoBuB,MAAMxB,oBAAoB,EAAE;gBAChDP,qBAAqB+B,MAAMC,UAAU,CAAC;gBACtC9B,gBAAgB6B,MAAM9B,gBAAgB,EAAE;gBACxCS,aAAaqB,MAAMtB,aAAa;YAClC;QACF,GACCwB,KAAK,CAAC,CAACC;YACNC,QAAQC,KAAK,CAAC,yBAAyBF;QACzC;IACJ,GAAG;QAACpB;QAAKC;QAAWJ,MAAMa;KAAG;IAE7B,qBACE,MAAC5B,oBAAoByC,QAAQ;QAC3BC,OAAO;YACLnC;YACAM;YACAF;YACAgC,iBAAiBxC,gBAAgByC,OAAOC,IAAI,CAAC1C,cAAc2C,MAAM,GAAG;YACpE3C;YACAM;YACAiB;YACArB;YACAG;QACF;;YAECN;0BACD,KAACsB;;;AAGP,EAAC"}
1
+ {"version":3,"sources":["../../../src/providers/InstructionsProvider/InstructionsProvider.tsx"],"sourcesContent":["'use client'\n\nimport { useAuth, useConfig, useDocumentDrawer } from '@payloadcms/ui'\nimport React, { useCallback, useEffect, useState } from 'react'\n\nimport type { SerializedPromptField } from '../../types.js'\n\nimport { PLUGIN_FETCH_FIELDS_ENDPOINT, PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js'\nimport { useActiveFieldTracking } from '../../ui/Compose/hooks/useActiveFieldTracking.js'\nimport { InstructionsContext } from './context.js'\n\nexport const InstructionsProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n // Initialize field tracking globally so ai-plugin-active class is added on field focus\n useActiveFieldTracking()\n\n const [instructions, setInstructionsState] = useState({})\n const [promptFields, setPromptFields] = useState<SerializedPromptField[]>([])\n const [activeCollection, setActiveCollection] = useState('')\n const [isConfigAllowed, setIsConfigAllowed] = useState(false)\n const [enabledLanguages, setEnabledLanguages] = useState<string[]>()\n const [enabledCollections, setEnabledCollections] = useState<string[]>()\n const [debugging, setDebugging] = useState(false)\n const { user } = useAuth()\n\n const { config } = useConfig()\n const {\n routes: { api },\n serverURL,\n } = config\n\n // Global Document Drawer state\n const [drawerInstructionId, setDrawerInstructionId] = useState<string>('')\n const [drawerOpenCount, setDrawerOpenCount] = useState(0)\n\n const [DocumentDrawer, _, { openDrawer: openPayloadDrawer }] = useDocumentDrawer({\n id: drawerInstructionId,\n collectionSlug: PLUGIN_INSTRUCTIONS_TABLE,\n })\n\n const openDrawer = useCallback((id: string) => {\n setDrawerInstructionId(id)\n setDrawerOpenCount((prev) => prev + 1)\n }, [])\n\n // Open drawer when count changes\n useEffect(() => {\n if (drawerOpenCount > 0) {\n openPayloadDrawer()\n }\n }, [drawerOpenCount, openPayloadDrawer])\n\n const handleSave = useCallback(\n ({ doc }: { doc: any }) => {\n setInstructionsState((prev) => {\n return {\n ...prev,\n [doc['schema-path']]: {\n id: doc.id,\n disabled: !!doc.disabled,\n fieldType: doc['field-type'],\n },\n }\n })\n },\n [setInstructionsState],\n )\n\n const fetchFieldsData = useCallback(async () => {\n // Only fetch if we have a user ID - prevents fetching on every user object reference change\n if (!user?.id) {\n return\n }\n\n try {\n const res = await fetch(`${serverURL}${api}${PLUGIN_FETCH_FIELDS_ENDPOINT}`)\n const data = await res.json()\n setIsConfigAllowed(data?.isConfigAllowed || false)\n setEnabledLanguages(data?.enabledLanguages || [])\n setEnabledCollections(data?.enabledCollections || [])\n setInstructionsState(data?.fields || {})\n setPromptFields(data?.promptFields || [])\n setDebugging(data?.debugging || false)\n } catch (err) {\n console.error('InstructionsProvider:', err)\n }\n }, [api, serverURL, user?.id])\n\n useEffect(() => {\n void fetchFieldsData()\n }, [fetchFieldsData])\n\n const refresh = useCallback(async () => {\n await fetchFieldsData()\n }, [fetchFieldsData])\n\n return (\n <InstructionsContext.Provider\n value={{\n activeCollection,\n debugging,\n enabledCollections,\n enabledLanguages,\n hasInstructions: instructions && Object.keys(instructions).length > 0,\n instructions,\n isConfigAllowed,\n openDrawer,\n promptFields,\n refresh,\n setActiveCollection,\n setEnabledCollections,\n }}\n >\n {children}\n <DocumentDrawer onSave={handleSave} />\n </InstructionsContext.Provider>\n )\n}\n"],"names":["useAuth","useConfig","useDocumentDrawer","React","useCallback","useEffect","useState","PLUGIN_FETCH_FIELDS_ENDPOINT","PLUGIN_INSTRUCTIONS_TABLE","useActiveFieldTracking","InstructionsContext","InstructionsProvider","children","instructions","setInstructionsState","promptFields","setPromptFields","activeCollection","setActiveCollection","isConfigAllowed","setIsConfigAllowed","enabledLanguages","setEnabledLanguages","enabledCollections","setEnabledCollections","debugging","setDebugging","user","config","routes","api","serverURL","drawerInstructionId","setDrawerInstructionId","drawerOpenCount","setDrawerOpenCount","DocumentDrawer","_","openDrawer","openPayloadDrawer","id","collectionSlug","prev","handleSave","doc","disabled","fieldType","fetchFieldsData","res","fetch","data","json","fields","err","console","error","refresh","Provider","value","hasInstructions","Object","keys","length","onSave"],"mappings":"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"}