@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,6 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { useField } from '@payloadcms/ui';
3
+ import { useForm } from '@payloadcms/ui';
4
+ import { getSiblingData } from 'payload/shared';
4
5
  import React, { useEffect, useMemo, useState } from 'react';
5
6
  import { useFieldProps } from '../../../../providers/FieldProvider/useFieldProps.js';
6
7
  import { Compose, Proofread, Rephrase } from './items.js';
@@ -19,14 +20,27 @@ const getActiveComponent = (ac)=>{
19
20
  }
20
21
  };
21
22
  export const useMenu = (menuEvents, options)=>{
22
- const { field: { type: fieldType } = {}, path: pathFromContext } = useFieldProps();
23
- const field = useField({
24
- path: pathFromContext ?? ''
25
- });
23
+ const { field: { type: fieldType } = {}, path } = useFieldProps();
24
+ const { getData } = useForm();
26
25
  const [activeComponent, setActiveComponent] = useState('Rephrase');
27
- const { initialValue, value } = field;
26
+ // Check value once on mount or when path/type changes
28
27
  useEffect(()=>{
29
- if (!value) {
28
+ let hasValue = false;
29
+ try {
30
+ const data = getData();
31
+ if (path) {
32
+ const val = getSiblingData(data, path);
33
+ hasValue = val !== undefined && val !== null;
34
+ // For richTextFields, we might need a more robust check (e.g. check for root.children.length > 0)
35
+ // But for now, simple truthiness covers most cases or at least defaults safely
36
+ if (fieldType === 'richText' && val && typeof val === 'object' && 'root' in val) {
37
+ // Basic lexical check could go here if needed
38
+ }
39
+ }
40
+ } catch (e) {
41
+ // ignore
42
+ }
43
+ if (!hasValue) {
30
44
  setActiveComponent('Compose');
31
45
  return;
32
46
  }
@@ -34,15 +48,12 @@ export const useMenu = (menuEvents, options)=>{
34
48
  setActiveComponent('Compose');
35
49
  return;
36
50
  }
37
- if (typeof value === 'string' && value !== initialValue) {
38
- setActiveComponent('Proofread');
39
- } else {
40
- setActiveComponent('Rephrase');
41
- }
51
+ // Default to Rephrase if value exists
52
+ setActiveComponent('Rephrase');
42
53
  }, [
43
- initialValue,
44
- value,
45
- fieldType
54
+ fieldType,
55
+ getData,
56
+ path
46
57
  ]);
47
58
  const MemoizedActiveComponent = useMemo(()=>{
48
59
  return ({ isLoading, loadingLabel, stop })=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/ui/Compose/hooks/menu/useMenu.tsx"],"sourcesContent":["'use client'\n\nimport { useField } from '@payloadcms/ui'\nimport React, { useEffect, useMemo, useState } from 'react'\n\nimport type { ActionMenuItems, UseMenuEvents, UseMenuOptions } from '../../../../types.js'\n\nimport { useFieldProps } from '../../../../providers/FieldProvider/useFieldProps.js'\nimport { Compose, Proofread, Rephrase } from './items.js'\nimport { menuItemsMap } from './itemsMap.js'\nimport styles from './menu.module.scss'\n\nconst getActiveComponent = (ac: ActionMenuItems) => {\n switch (ac) {\n case 'Compose':\n return Compose\n case 'Proofread':\n return Proofread\n case 'Rephrase':\n return Rephrase\n default:\n return Rephrase\n }\n}\n\nexport const useMenu = (menuEvents: UseMenuEvents, options: UseMenuOptions) => {\n const { field:{ type: fieldType } = {}, path: pathFromContext } = useFieldProps()\n const field = useField({ path: pathFromContext ?? '' })\n const [activeComponent, setActiveComponent] = useState<ActionMenuItems>('Rephrase')\n\n const { initialValue, value } = field\n\n useEffect(() => {\n if (!value) {\n setActiveComponent('Compose')\n return\n }\n\n if (menuItemsMap.some((i) => i.excludedFor?.includes(fieldType ?? ''))) {\n setActiveComponent('Compose')\n return\n }\n\n if (typeof value === 'string' && value !== initialValue) {\n setActiveComponent('Proofread')\n } else {\n setActiveComponent('Rephrase')\n }\n }, [initialValue, value, fieldType])\n\n const MemoizedActiveComponent = useMemo(() => {\n return ({ isLoading, loadingLabel, stop }: { isLoading: boolean; loadingLabel?: string; stop: () => void }) => {\n const ActiveComponent = getActiveComponent(activeComponent)\n const activeItem = menuItemsMap.find((i) => i.name === activeComponent)!\n return (\n <ActiveComponent\n hideIcon\n onClick={(data: unknown) => {\n if (!isLoading) {\n const trigger = menuEvents[`on${activeComponent}`]\n if (typeof trigger === 'function') {\n trigger(data)\n } else {\n console.error('No trigger found for', activeComponent)\n }\n } else {\n stop()\n }\n }}\n title={isLoading ? 'Click to stop' : activeItem.name}\n >\n {isLoading && (loadingLabel ?? activeItem.loadingText)}\n </ActiveComponent>\n )\n }\n }, [activeComponent, menuEvents])\n\n const filteredMenuItems = useMemo(\n () =>\n menuItemsMap.filter((i) => {\n if (i.name === 'Settings' && !options.isConfigAllowed) {\n return false\n } // Disable settings if a user role is not permitted\n return i.name !== activeComponent && !i.excludedFor?.includes(fieldType ?? '')\n }),\n [activeComponent, fieldType, options.isConfigAllowed],\n )\n\n const MemoizedMenu = useMemo(() => {\n return ({ isLoading, onClose }: { isLoading: boolean; onClose: () => void }) => (\n <div className={styles.menu}>\n {filteredMenuItems.map((i) => {\n const Action = i.component\n return (\n <Action\n disabled={isLoading}\n key={i.name}\n onClick={(data: unknown) => {\n if (i.name !== 'Settings') {\n setActiveComponent(i.name)\n }\n\n menuEvents[`on${i.name}`]?.(data)\n onClose()\n }}\n >\n {isLoading && i.loadingText}\n </Action>\n )\n })}\n </div>\n )\n }, [filteredMenuItems, menuEvents])\n\n return {\n ActiveComponent: MemoizedActiveComponent,\n Menu: MemoizedMenu,\n }\n}\n"],"names":["useField","React","useEffect","useMemo","useState","useFieldProps","Compose","Proofread","Rephrase","menuItemsMap","styles","getActiveComponent","ac","useMenu","menuEvents","options","field","type","fieldType","path","pathFromContext","activeComponent","setActiveComponent","initialValue","value","some","i","excludedFor","includes","MemoizedActiveComponent","isLoading","loadingLabel","stop","ActiveComponent","activeItem","find","name","hideIcon","onClick","data","trigger","console","error","title","loadingText","filteredMenuItems","filter","isConfigAllowed","MemoizedMenu","onClose","div","className","menu","map","Action","component","disabled","Menu"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/ui/Compose/hooks/menu/useMenu.tsx"],"sourcesContent":["'use client'\n\nimport { useForm } from '@payloadcms/ui'\nimport { getSiblingData } from 'payload/shared'\nimport React, { useEffect, useMemo, useState } from 'react'\n\nimport type { ActionMenuItems, UseMenuEvents, UseMenuOptions } from '../../../../types.js'\n\nimport { useFieldProps } from '../../../../providers/FieldProvider/useFieldProps.js'\nimport { Compose, Proofread, Rephrase } from './items.js'\nimport { menuItemsMap } from './itemsMap.js'\nimport styles from './menu.module.scss'\n\nconst getActiveComponent = (ac: ActionMenuItems) => {\n switch (ac) {\n case 'Compose':\n return Compose\n case 'Proofread':\n return Proofread\n case 'Rephrase':\n return Rephrase\n default:\n return Rephrase\n }\n}\n\nexport const useMenu = (menuEvents: UseMenuEvents, options: UseMenuOptions) => {\n const { field: { type: fieldType } = {}, path } = useFieldProps()\n const { getData } = useForm()\n const [activeComponent, setActiveComponent] = useState<ActionMenuItems>('Rephrase')\n\n // Check value once on mount or when path/type changes\n useEffect(() => {\n let hasValue = false\n\n try {\n const data = getData()\n if (path) {\n const val = getSiblingData(data, path)\n hasValue = val !== undefined && val !== null\n // For richTextFields, we might need a more robust check (e.g. check for root.children.length > 0)\n // But for now, simple truthiness covers most cases or at least defaults safely\n if (fieldType === 'richText' && val && typeof val === 'object' && 'root' in val) {\n // Basic lexical check could go here if needed\n }\n }\n } catch (e) {\n // ignore\n }\n\n if (!hasValue) {\n setActiveComponent('Compose')\n return\n }\n\n if (menuItemsMap.some((i) => i.excludedFor?.includes(fieldType ?? ''))) {\n setActiveComponent('Compose')\n return\n }\n\n // Default to Rephrase if value exists\n setActiveComponent('Rephrase')\n }, [fieldType, getData, path])\n\n const MemoizedActiveComponent = useMemo(() => {\n return ({ isLoading, loadingLabel, stop }: { isLoading: boolean; loadingLabel?: string; stop: () => void }) => {\n const ActiveComponent = getActiveComponent(activeComponent)\n const activeItem = menuItemsMap.find((i) => i.name === activeComponent)!\n return (\n <ActiveComponent\n hideIcon\n onClick={(data: unknown) => {\n if (!isLoading) {\n const trigger = menuEvents[`on${activeComponent}`]\n if (typeof trigger === 'function') {\n trigger(data)\n } else {\n console.error('No trigger found for', activeComponent)\n }\n } else {\n stop()\n }\n }}\n title={isLoading ? 'Click to stop' : activeItem.name}\n >\n {isLoading && (loadingLabel ?? activeItem.loadingText)}\n </ActiveComponent>\n )\n }\n }, [activeComponent, menuEvents])\n\n const filteredMenuItems = useMemo(\n () =>\n menuItemsMap.filter((i) => {\n if (i.name === 'Settings' && !options.isConfigAllowed) {\n return false\n } // Disable settings if a user role is not permitted\n return i.name !== activeComponent && !i.excludedFor?.includes(fieldType ?? '')\n }),\n [activeComponent, fieldType, options.isConfigAllowed],\n )\n\n const MemoizedMenu = useMemo(() => {\n return ({ isLoading, onClose }: { isLoading: boolean; onClose: () => void }) => (\n <div className={styles.menu}>\n {filteredMenuItems.map((i) => {\n const Action = i.component\n return (\n <Action\n disabled={isLoading}\n key={i.name}\n onClick={(data: unknown) => {\n if (i.name !== 'Settings') {\n setActiveComponent(i.name)\n }\n\n menuEvents[`on${i.name}`]?.(data)\n onClose()\n }}\n >\n {isLoading && i.loadingText}\n </Action>\n )\n })}\n </div>\n )\n }, [filteredMenuItems, menuEvents])\n\n return {\n ActiveComponent: MemoizedActiveComponent,\n Menu: MemoizedMenu,\n }\n}\n\n"],"names":["useForm","getSiblingData","React","useEffect","useMemo","useState","useFieldProps","Compose","Proofread","Rephrase","menuItemsMap","styles","getActiveComponent","ac","useMenu","menuEvents","options","field","type","fieldType","path","getData","activeComponent","setActiveComponent","hasValue","data","val","undefined","e","some","i","excludedFor","includes","MemoizedActiveComponent","isLoading","loadingLabel","stop","ActiveComponent","activeItem","find","name","hideIcon","onClick","trigger","console","error","title","loadingText","filteredMenuItems","filter","isConfigAllowed","MemoizedMenu","onClose","div","className","menu","map","Action","component","disabled","Menu"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  'use client';
2
- import { useField } from '@payloadcms/ui';
2
+ import { useForm } from '@payloadcms/ui';
3
+ import { getSiblingData } from 'payload/shared';
3
4
  import React, { useEffect, useMemo, useState } from 'react';
4
5
  import { useFieldProps } from '../../../../providers/FieldProvider/useFieldProps.js';
5
6
  import { Compose, Proofread, Rephrase } from './items.js';
@@ -18,12 +19,28 @@ const getActiveComponent = (ac) => {
18
19
  }
19
20
  };
20
21
  export const useMenu = (menuEvents, options) => {
21
- const { field: { type: fieldType } = {}, path: pathFromContext } = useFieldProps();
22
- const field = useField({ path: pathFromContext ?? '' });
22
+ const { field: { type: fieldType } = {}, path } = useFieldProps();
23
+ const { getData } = useForm();
23
24
  const [activeComponent, setActiveComponent] = useState('Rephrase');
24
- const { initialValue, value } = field;
25
+ // Check value once on mount or when path/type changes
25
26
  useEffect(() => {
26
- if (!value) {
27
+ let hasValue = false;
28
+ try {
29
+ const data = getData();
30
+ if (path) {
31
+ const val = getSiblingData(data, path);
32
+ hasValue = val !== undefined && val !== null;
33
+ // For richTextFields, we might need a more robust check (e.g. check for root.children.length > 0)
34
+ // But for now, simple truthiness covers most cases or at least defaults safely
35
+ if (fieldType === 'richText' && val && typeof val === 'object' && 'root' in val) {
36
+ // Basic lexical check could go here if needed
37
+ }
38
+ }
39
+ }
40
+ catch (e) {
41
+ // ignore
42
+ }
43
+ if (!hasValue) {
27
44
  setActiveComponent('Compose');
28
45
  return;
29
46
  }
@@ -31,13 +48,9 @@ export const useMenu = (menuEvents, options) => {
31
48
  setActiveComponent('Compose');
32
49
  return;
33
50
  }
34
- if (typeof value === 'string' && value !== initialValue) {
35
- setActiveComponent('Proofread');
36
- }
37
- else {
38
- setActiveComponent('Rephrase');
39
- }
40
- }, [initialValue, value, fieldType]);
51
+ // Default to Rephrase if value exists
52
+ setActiveComponent('Rephrase');
53
+ }, [fieldType, getData, path]);
41
54
  const MemoizedActiveComponent = useMemo(() => {
42
55
  return ({ isLoading, loadingLabel, stop }) => {
43
56
  const ActiveComponent = getActiveComponent(activeComponent);
@@ -2,40 +2,35 @@ import { experimental_useObject as useObject } from '@ai-sdk/react';
2
2
  import { useEditorConfigContext } from '@payloadcms/richtext-lexical/client';
3
3
  import { toast, useConfig, useDocumentInfo, useField, useForm, useLocale } from '@payloadcms/ui';
4
4
  import { jsonSchema } from 'ai';
5
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
6
- import { PLUGIN_AI_JOBS_TABLE, PLUGIN_API_ENDPOINT_GENERATE, PLUGIN_API_ENDPOINT_GENERATE_UPLOAD, PLUGIN_INSTRUCTIONS_TABLE, PLUGIN_NAME } from '../../../defaults.js';
5
+ import { useCallback, useMemo, useRef } from 'react';
6
+ import { PLUGIN_API_ENDPOINT_GENERATE, PLUGIN_INSTRUCTIONS_TABLE, PLUGIN_NAME } from '../../../defaults.js';
7
7
  import { useFieldProps } from '../../../providers/FieldProvider/useFieldProps.js';
8
8
  import { editorSchemaValidator } from '../../../utilities/editorSchemaValidator.js';
9
9
  import { fieldToJsonSchema } from '../../../utilities/fieldToJsonSchema.js';
10
10
  import { setSafeLexicalState } from '../../../utilities/setSafeLexicalState.js';
11
+ import { useGenerateUpload } from './useGenerateUpload.js';
11
12
  import { useHistory } from './useHistory.js';
13
+ import { useStreamingUpdate } from './useStreamingUpdate.js';
12
14
  export const useGenerate = ({ instructionId })=>{
13
- // Create a ref to hold the current instructionId
14
15
  const instructionIdRef = useRef(instructionId);
15
- // Update the ref whenever instructionId changes
16
- useEffect(()=>{
17
- instructionIdRef.current = instructionId;
18
- }, [
19
- instructionId
20
- ]);
16
+ // Sync ref
17
+ instructionIdRef.current = instructionId;
21
18
  const { field, path: pathFromContext } = useFieldProps();
22
- const editorConfigContext = useEditorConfigContext();
23
- const { editor } = editorConfigContext;
19
+ const { editor } = useEditorConfigContext();
24
20
  const { config } = useConfig();
25
- const { routes: { api }, serverURL } = config;
21
+ const { collections } = config;
22
+ // Use dispatchFields to update values without subscribing to them, avoiding re-renders during streaming
23
+ // dispatchFields is handled inside useStreamingUpdate now, so we don't need it here
24
+ // const { dispatchFields } = useForm()
25
+ // Keep setValue for non-streaming updates (one-off), but do NOT destructure 'value' to avoid subscriptions
26
26
  const { setValue } = useField({
27
27
  path: pathFromContext ?? ''
28
28
  });
29
29
  const { set: setHistory } = useHistory();
30
- // Async job UI state
31
- const [jobStatus, setJobStatus] = useState(undefined);
32
- const [jobProgress, setJobProgress] = useState(0);
33
- const [isJobActive, setIsJobActive] = useState(false);
34
30
  const { getData } = useForm();
35
- const { id: documentId, collectionSlug } = useDocumentInfo();
31
+ const { id: documentId } = useDocumentInfo();
36
32
  const localFromContext = useLocale();
37
- // Reuse config from above instead of calling useConfig again
38
- const { collections } = config;
33
+ // Editor Schema Setup
39
34
  const collection = collections.find((collection)=>collection.slug === PLUGIN_INSTRUCTIONS_TABLE);
40
35
  const { custom: { [PLUGIN_NAME]: { editorConfig = {} } = {} } = {} } = collection?.admin ?? {};
41
36
  const { schema: editorSchema = {} } = editorConfig;
@@ -89,8 +84,15 @@ export const useGenerate = ({ instructionId })=>{
89
84
  onFinish: (result)=>{
90
85
  if (result.object && field) {
91
86
  if (field.type === 'richText') {
87
+ // Set state directly to editor first for immediate feedback
88
+ setSafeLexicalState(result.object, editor);
89
+ // Update history
92
90
  setHistory(result.object);
93
- setValue(result.object);
91
+ // Delay Payload's setValue slightly to ensure editor stability
92
+ // and prevent field-level re-renders from interfering with the final state.
93
+ setTimeout(()=>{
94
+ setValue(result.object);
95
+ }, 150);
94
96
  } else if ('name' in field) {
95
97
  setHistory(result.object[field.name]);
96
98
  setValue(result.object[field.name]);
@@ -101,23 +103,17 @@ export const useGenerate = ({ instructionId })=>{
101
103
  },
102
104
  schema: activeSchema
103
105
  });
104
- useEffect(()=>{
105
- if (!object) {
106
- return;
107
- }
108
- requestAnimationFrame(()=>{
109
- if (field?.type === 'richText') {
110
- setSafeLexicalState(object, editor);
111
- } else if (field && 'name' in field && object[field.name]) {
112
- setValue(object[field.name]);
113
- }
114
- });
115
- }, [
116
- object,
106
+ // Hook 1: Handle high-frequency streaming updates
107
+ useStreamingUpdate({
117
108
  editor,
118
- field,
109
+ isLoading: loadingObject,
110
+ object
111
+ });
112
+ // Hook 2: Handle Upload generation and polling
113
+ const { generateUpload, isJobActive, jobProgress, jobStatus } = useGenerateUpload({
114
+ instructionIdRef,
119
115
  setValue
120
- ]);
116
+ });
121
117
  const streamObject = useCallback(({ action = 'Compose', params })=>{
122
118
  const doc = getData();
123
119
  const currentInstructionId = instructionIdRef.current;
@@ -138,103 +134,10 @@ export const useGenerate = ({ instructionId })=>{
138
134
  }, [
139
135
  localFromContext?.code,
140
136
  instructionIdRef,
141
- documentId
142
- ]);
143
- const generateUpload = useCallback(async ()=>{
144
- const doc = getData();
145
- const currentInstructionId = instructionIdRef.current;
146
- return fetch(`${serverURL}${api}${PLUGIN_API_ENDPOINT_GENERATE_UPLOAD}`, {
147
- body: JSON.stringify({
148
- collectionSlug: collectionSlug ?? '',
149
- doc,
150
- documentId,
151
- locale: localFromContext?.code,
152
- options: {
153
- instructionId: currentInstructionId
154
- }
155
- }),
156
- credentials: 'include',
157
- headers: {
158
- 'Content-Type': 'application/json'
159
- },
160
- method: 'POST'
161
- }).then(async (uploadResponse)=>{
162
- if (uploadResponse.ok) {
163
- const json = await uploadResponse.json();
164
- const { job, result } = json || {};
165
- if (result) {
166
- // Set the upload ID
167
- setValue(result?.id);
168
- setHistory(result?.id);
169
- // Show toast to prompt user to save
170
- toast.success('Image generated successfully! Click Save to see the preview.');
171
- return uploadResponse;
172
- }
173
- // Async job: poll AI Jobs collection for status/progress/result_id
174
- if (job && job.id) {
175
- setIsJobActive(true);
176
- const cancelled = false;
177
- let attempts = 0;
178
- const maxAttempts = 600 // up to ~10 minutes @ 1s
179
- ;
180
- // Basic in-hook state via closure variables; UI will re-render off fetches below
181
- const poll = async ()=>{
182
- if (cancelled) {
183
- return;
184
- }
185
- try {
186
- const res = await fetch(`${serverURL}${api}/${PLUGIN_AI_JOBS_TABLE}/${job.id}`, {
187
- credentials: 'include'
188
- });
189
- if (res.ok) {
190
- const jobDoc = await res.json();
191
- const { progress, result_id, status } = jobDoc || {};
192
- setJobStatus(status);
193
- setJobProgress(progress ?? 0);
194
- // When result present, set field and finish
195
- if (status === 'completed' && result_id) {
196
- // Force upload field to refetch by clearing then setting the ID
197
- setValue(null);
198
- setTimeout(()=>{
199
- setValue(result_id);
200
- }, 0);
201
- setHistory(result_id);
202
- setIsJobActive(false);
203
- return;
204
- }
205
- if (status === 'failed') {
206
- setIsJobActive(false);
207
- throw new Error('Video generation failed');
208
- }
209
- }
210
- } catch (e) {
211
- // silent retry
212
- }
213
- attempts += 1;
214
- if (!cancelled && attempts < maxAttempts) {
215
- setTimeout(poll, 1000);
216
- }
217
- };
218
- setTimeout(poll, 1000);
219
- return uploadResponse;
220
- }
221
- throw new Error('generateUpload: Unexpected response');
222
- } else {
223
- const { errors = [] } = await uploadResponse.json();
224
- const errStr = errors.map((error)=>error.message).join(', ');
225
- throw new Error(errStr);
226
- }
227
- }).catch((error)=>{
228
- toast.error(`Failed to generate: ${error.message}`);
229
- console.error('Error generating or setting your upload, please set it manually if its saved in your media files.', error);
230
- });
231
- }, [
232
- getData,
233
- localFromContext?.code,
234
- instructionIdRef,
235
- setValue,
236
137
  documentId,
237
- collectionSlug
138
+ getData,
139
+ submit,
140
+ editor
238
141
  ]);
239
142
  const generate = useCallback(async (options)=>{
240
143
  if (field?.type === 'upload') {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/ui/Compose/hooks/useGenerate.ts"],"sourcesContent":["import { experimental_useObject as useObject } from '@ai-sdk/react'\nimport { useEditorConfigContext } from '@payloadcms/richtext-lexical/client'\nimport { toast, useConfig, useDocumentInfo, useField, useForm, useLocale } from '@payloadcms/ui'\nimport { jsonSchema } from 'ai'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport type { ActionMenuItems, GenerateTextarea } from '../../../types.js'\n\nimport {\n PLUGIN_AI_JOBS_TABLE,\n PLUGIN_API_ENDPOINT_GENERATE,\n PLUGIN_API_ENDPOINT_GENERATE_UPLOAD,\n PLUGIN_INSTRUCTIONS_TABLE,\n PLUGIN_NAME,\n} from '../../../defaults.js'\nimport { useFieldProps } from '../../../providers/FieldProvider/useFieldProps.js'\nimport { editorSchemaValidator } from '../../../utilities/editorSchemaValidator.js'\nimport { fieldToJsonSchema } from '../../../utilities/fieldToJsonSchema.js'\nimport { setSafeLexicalState } from '../../../utilities/setSafeLexicalState.js'\nimport { useHistory } from './useHistory.js'\n\ntype ActionCallbackParams = { action: ActionMenuItems; params?: unknown }\n\nexport const useGenerate = ({ instructionId }: { instructionId: string }) => {\n // Create a ref to hold the current instructionId\n const instructionIdRef = useRef(instructionId)\n\n // Update the ref whenever instructionId changes\n useEffect(() => {\n instructionIdRef.current = instructionId\n }, [instructionId])\n\n const { field, path: pathFromContext } = useFieldProps()\n const editorConfigContext = useEditorConfigContext()\n\n const { editor } = editorConfigContext\n\n const { config } = useConfig()\n const {\n routes: { api },\n serverURL,\n } = config\n\n const { setValue } = useField<any>({\n path: pathFromContext ?? '',\n })\n\n const { set: setHistory } = useHistory()\n\n // Async job UI state\n const [jobStatus, setJobStatus] = useState<string | undefined>(undefined)\n const [jobProgress, setJobProgress] = useState<number>(0)\n const [isJobActive, setIsJobActive] = useState<boolean>(false)\n\n const { getData } = useForm()\n const { id: documentId, collectionSlug } = useDocumentInfo()\n\n const localFromContext = useLocale()\n \n // Reuse config from above instead of calling useConfig again\n const { collections } = config\n\n const collection = collections.find((collection) => collection.slug === PLUGIN_INSTRUCTIONS_TABLE)\n const { custom: { [PLUGIN_NAME]: { editorConfig = {} } = {} } = {} } = collection?.admin ?? {}\n const { schema: editorSchema = {} } = editorConfig\n\n const memoizedValidator = useMemo(() => {\n return editorSchemaValidator(editorSchema)\n }, [editorSchema])\n\n const memoizedSchema = useMemo(\n () =>\n jsonSchema(editorSchema, {\n validate: (value) => {\n const isValid = memoizedValidator(value)\n\n if (isValid) {\n return {\n success: true,\n value,\n }\n } else {\n return {\n error: new Error('Invalid schema'),\n success: false,\n }\n }\n },\n }),\n [memoizedValidator],\n )\n\n // Active JSON schema for useObject based on field type\n const activeSchema = useMemo(() => {\n const f = field as any\n const fieldType = f?.type as string | undefined\n if (fieldType === 'richText') {\n return memoizedSchema\n }\n if (f && f.name && fieldType) {\n const schemaJson = fieldToJsonSchema(f)\n if (schemaJson && Object.keys(schemaJson).length > 0) {\n return jsonSchema(schemaJson)\n }\n }\n return undefined\n }, [field, memoizedSchema])\n\n const {\n isLoading: loadingObject,\n object,\n stop: objectStop,\n submit,\n } = useObject({\n api: `/api${PLUGIN_API_ENDPOINT_GENERATE}`,\n onError: (error: any) => {\n toast.error(`Failed to generate: ${error.message}`)\n console.error('Error generating object:', error)\n },\n onFinish: (result) => {\n if (result.object && field) {\n if (field.type === 'richText') {\n setHistory(result.object)\n setValue(result.object)\n } else if ('name' in field) {\n setHistory(result.object[field.name])\n setValue(result.object[field.name])\n }\n } else {\n console.log('onFinish: result, field ', result, field)\n }\n },\n schema: activeSchema as any,\n })\n\n useEffect(() => {\n if (!object) {\n return\n }\n\n requestAnimationFrame(() => {\n if (field?.type === 'richText') {\n setSafeLexicalState(object, editor)\n } else if (field && 'name' in field && object[field.name]) {\n setValue(object[field.name])\n }\n })\n }, [object, editor, field, setValue])\n\n const streamObject = useCallback(\n ({ action = 'Compose', params }: ActionCallbackParams) => {\n const doc = getData()\n\n const currentInstructionId = instructionIdRef.current\n\n const options = {\n action,\n actionParams: params,\n instructionId: currentInstructionId,\n }\n\n submit({\n allowedEditorNodes: Array.from(editor?._nodes?.keys() || []),\n doc: {\n ...doc,\n id: documentId,\n },\n locale: localFromContext?.code,\n options,\n })\n },\n [localFromContext?.code, instructionIdRef, documentId],\n )\n\n const generateUpload = useCallback(async () => {\n const doc = getData()\n const currentInstructionId = instructionIdRef.current\n\n return fetch(`${serverURL}${api}${PLUGIN_API_ENDPOINT_GENERATE_UPLOAD}`, {\n body: JSON.stringify({\n collectionSlug: collectionSlug ?? '',\n doc,\n documentId,\n locale: localFromContext?.code,\n options: {\n instructionId: currentInstructionId,\n },\n } satisfies Parameters<GenerateTextarea>[0]),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n .then(async (uploadResponse) => {\n if (uploadResponse.ok) {\n const json = await uploadResponse.json()\n const { job, result } = json || {}\n if (result) {\n // Set the upload ID\n setValue(result?.id)\n setHistory(result?.id)\n \n // Show toast to prompt user to save\n toast.success('Image generated successfully! Click Save to see the preview.')\n \n return uploadResponse\n }\n\n // Async job: poll AI Jobs collection for status/progress/result_id\n if (job && job.id) {\n setIsJobActive(true)\n const cancelled = false\n let attempts = 0\n const maxAttempts = 600 // up to ~10 minutes @ 1s\n\n // Basic in-hook state via closure variables; UI will re-render off fetches below\n const poll = async (): Promise<void> => {\n if (cancelled) {\n return\n }\n try {\n const res = await fetch(\n `${serverURL}${api}/${PLUGIN_AI_JOBS_TABLE}/${job.id}`,\n { credentials: 'include' },\n )\n if (res.ok) {\n const jobDoc = await res.json()\n const { progress, result_id, status } = jobDoc || {}\n setJobStatus(status)\n setJobProgress(progress ?? 0)\n // When result present, set field and finish\n if (status === 'completed' && result_id) {\n // Force upload field to refetch by clearing then setting the ID\n setValue(null)\n setTimeout(() => {\n setValue(result_id)\n }, 0)\n setHistory(result_id)\n setIsJobActive(false)\n return\n }\n if (status === 'failed') {\n setIsJobActive(false)\n throw new Error('Video generation failed')\n }\n }\n } catch (e) {\n // silent retry\n }\n\n attempts += 1\n if (!cancelled && attempts < maxAttempts) {\n setTimeout(poll, 1000)\n }\n }\n setTimeout(poll, 1000)\n return uploadResponse\n }\n\n throw new Error('generateUpload: Unexpected response')\n } else {\n const { errors = [] } = await uploadResponse.json()\n const errStr = errors.map((error: any) => error.message).join(', ')\n throw new Error(errStr)\n }\n })\n .catch((error) => {\n toast.error(`Failed to generate: ${error.message}`)\n console.error(\n 'Error generating or setting your upload, please set it manually if its saved in your media files.',\n error,\n )\n })\n }, [getData, localFromContext?.code, instructionIdRef, setValue, documentId, collectionSlug])\n\n const generate = useCallback(\n async (options?: ActionCallbackParams) => {\n if ((field as any)?.type === 'upload') {\n return generateUpload()\n }\n // All supported types use structured object generation when schema is provided server-side\n return streamObject(options ?? { action: 'Compose' })\n },\n [generateUpload, streamObject, field],\n )\n\n const stop = useCallback(() => {\n console.log('Stopping...')\n objectStop()\n }, [objectStop])\n\n return {\n generate,\n isJobActive,\n isLoading: loadingObject,\n jobProgress,\n jobStatus,\n stop,\n }\n}\n"],"names":["experimental_useObject","useObject","useEditorConfigContext","toast","useConfig","useDocumentInfo","useField","useForm","useLocale","jsonSchema","useCallback","useEffect","useMemo","useRef","useState","PLUGIN_AI_JOBS_TABLE","PLUGIN_API_ENDPOINT_GENERATE","PLUGIN_API_ENDPOINT_GENERATE_UPLOAD","PLUGIN_INSTRUCTIONS_TABLE","PLUGIN_NAME","useFieldProps","editorSchemaValidator","fieldToJsonSchema","setSafeLexicalState","useHistory","useGenerate","instructionId","instructionIdRef","current","field","path","pathFromContext","editorConfigContext","editor","config","routes","api","serverURL","setValue","set","setHistory","jobStatus","setJobStatus","undefined","jobProgress","setJobProgress","isJobActive","setIsJobActive","getData","id","documentId","collectionSlug","localFromContext","collections","collection","find","slug","custom","editorConfig","admin","schema","editorSchema","memoizedValidator","memoizedSchema","validate","value","isValid","success","error","Error","activeSchema","f","fieldType","type","name","schemaJson","Object","keys","length","isLoading","loadingObject","object","stop","objectStop","submit","onError","message","console","onFinish","result","log","requestAnimationFrame","streamObject","action","params","doc","currentInstructionId","options","actionParams","allowedEditorNodes","Array","from","_nodes","locale","code","generateUpload","fetch","body","JSON","stringify","credentials","headers","method","then","uploadResponse","ok","json","job","cancelled","attempts","maxAttempts","poll","res","jobDoc","progress","result_id","status","setTimeout","e","errors","errStr","map","join","catch","generate"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/ui/Compose/hooks/useGenerate.ts"],"sourcesContent":["import { experimental_useObject as useObject } from '@ai-sdk/react'\nimport { useEditorConfigContext } from '@payloadcms/richtext-lexical/client'\nimport { toast, useConfig, useDocumentInfo, useField, useForm, useLocale } from '@payloadcms/ui'\nimport { jsonSchema } from 'ai'\nimport { useCallback, useMemo, useRef } from 'react'\n\nimport type { ActionMenuItems } from '../../../types.js'\n\nimport { PLUGIN_API_ENDPOINT_GENERATE, PLUGIN_INSTRUCTIONS_TABLE, PLUGIN_NAME } from '../../../defaults.js'\nimport { useFieldProps } from '../../../providers/FieldProvider/useFieldProps.js'\nimport { editorSchemaValidator } from '../../../utilities/editorSchemaValidator.js'\nimport { fieldToJsonSchema } from '../../../utilities/fieldToJsonSchema.js'\nimport { setSafeLexicalState } from '../../../utilities/setSafeLexicalState.js'\nimport { useGenerateUpload } from './useGenerateUpload.js'\nimport { useHistory } from './useHistory.js'\nimport { useStreamingUpdate } from './useStreamingUpdate.js'\n\ntype ActionCallbackParams = { action: ActionMenuItems; params?: unknown }\n\nexport const useGenerate = ({ instructionId }: { instructionId: string }) => {\n const instructionIdRef = useRef(instructionId)\n // Sync ref\n instructionIdRef.current = instructionId\n\n const { field, path: pathFromContext } = useFieldProps()\n const { editor } = useEditorConfigContext()\n\n const { config } = useConfig()\n const { collections } = config\n\n // Use dispatchFields to update values without subscribing to them, avoiding re-renders during streaming\n // dispatchFields is handled inside useStreamingUpdate now, so we don't need it here\n // const { dispatchFields } = useForm()\n\n // Keep setValue for non-streaming updates (one-off), but do NOT destructure 'value' to avoid subscriptions\n const { setValue } = useField<any>({\n path: pathFromContext ?? '',\n })\n\n const { set: setHistory } = useHistory()\n const { getData } = useForm()\n const { id: documentId } = useDocumentInfo()\n const localFromContext = useLocale()\n\n // Editor Schema Setup\n const collection = collections.find((collection) => collection.slug === PLUGIN_INSTRUCTIONS_TABLE)\n const { custom: { [PLUGIN_NAME]: { editorConfig = {} } = {} } = {} } = collection?.admin ?? {}\n const { schema: editorSchema = {} } = editorConfig\n\n const memoizedValidator = useMemo(() => {\n return editorSchemaValidator(editorSchema)\n }, [editorSchema])\n\n const memoizedSchema = useMemo(\n () =>\n jsonSchema(editorSchema, {\n validate: (value) => {\n const isValid = memoizedValidator(value)\n\n if (isValid) {\n return {\n success: true,\n value,\n }\n } else {\n return {\n error: new Error('Invalid schema'),\n success: false,\n }\n }\n },\n }),\n [memoizedValidator],\n )\n\n // Active JSON schema for useObject based on field type\n const activeSchema = useMemo(() => {\n const f = field as any\n const fieldType = f?.type as string | undefined\n if (fieldType === 'richText') {\n return memoizedSchema\n }\n if (f && f.name && fieldType) {\n const schemaJson = fieldToJsonSchema(f)\n if (schemaJson && Object.keys(schemaJson).length > 0) {\n return jsonSchema(schemaJson)\n }\n }\n return undefined\n }, [field, memoizedSchema])\n\n const {\n isLoading: loadingObject,\n object,\n stop: objectStop,\n submit,\n } = useObject({\n api: `/api${PLUGIN_API_ENDPOINT_GENERATE}`,\n onError: (error: any) => {\n toast.error(`Failed to generate: ${error.message}`)\n console.error('Error generating object:', error)\n },\n onFinish: (result) => {\n if (result.object && field) {\n if (field.type === 'richText') {\n // Set state directly to editor first for immediate feedback\n setSafeLexicalState(result.object, editor)\n\n // Update history\n setHistory(result.object)\n\n // Delay Payload's setValue slightly to ensure editor stability\n // and prevent field-level re-renders from interfering with the final state.\n setTimeout(() => {\n setValue(result.object)\n }, 150)\n } else if ('name' in field) {\n setHistory(result.object[field.name])\n setValue(result.object[field.name])\n }\n } else {\n console.log('onFinish: result, field ', result, field)\n }\n },\n schema: activeSchema as any,\n })\n\n // Hook 1: Handle high-frequency streaming updates\n useStreamingUpdate({\n editor,\n isLoading: loadingObject,\n object,\n })\n\n // Hook 2: Handle Upload generation and polling\n const { generateUpload, isJobActive, jobProgress, jobStatus } = useGenerateUpload({\n instructionIdRef,\n setValue,\n })\n\n const streamObject = useCallback(\n ({ action = 'Compose', params }: ActionCallbackParams) => {\n const doc = getData()\n\n const currentInstructionId = instructionIdRef.current\n\n const options = {\n action,\n actionParams: params,\n instructionId: currentInstructionId,\n }\n\n submit({\n allowedEditorNodes: Array.from(editor?._nodes?.keys() || []),\n doc: {\n ...doc,\n id: documentId,\n },\n locale: localFromContext?.code,\n options,\n })\n },\n [localFromContext?.code, instructionIdRef, documentId, getData, submit, editor],\n )\n\n const generate = useCallback(\n async (options?: ActionCallbackParams) => {\n if ((field as any)?.type === 'upload') {\n return generateUpload()\n }\n // All supported types use structured object generation when schema is provided server-side\n return streamObject(options ?? { action: 'Compose' })\n },\n [generateUpload, streamObject, field],\n )\n\n const stop = useCallback(() => {\n console.log('Stopping...')\n objectStop()\n }, [objectStop])\n\n return {\n generate,\n isJobActive,\n isLoading: loadingObject,\n jobProgress,\n jobStatus,\n stop,\n }\n}\n"],"names":["experimental_useObject","useObject","useEditorConfigContext","toast","useConfig","useDocumentInfo","useField","useForm","useLocale","jsonSchema","useCallback","useMemo","useRef","PLUGIN_API_ENDPOINT_GENERATE","PLUGIN_INSTRUCTIONS_TABLE","PLUGIN_NAME","useFieldProps","editorSchemaValidator","fieldToJsonSchema","setSafeLexicalState","useGenerateUpload","useHistory","useStreamingUpdate","useGenerate","instructionId","instructionIdRef","current","field","path","pathFromContext","editor","config","collections","setValue","set","setHistory","getData","id","documentId","localFromContext","collection","find","slug","custom","editorConfig","admin","schema","editorSchema","memoizedValidator","memoizedSchema","validate","value","isValid","success","error","Error","activeSchema","f","fieldType","type","name","schemaJson","Object","keys","length","undefined","isLoading","loadingObject","object","stop","objectStop","submit","api","onError","message","console","onFinish","result","setTimeout","log","generateUpload","isJobActive","jobProgress","jobStatus","streamObject","action","params","doc","currentInstructionId","options","actionParams","allowedEditorNodes","Array","from","_nodes","locale","code","generate"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ type UseGenerateUploadParams = {
2
+ instructionIdRef: React.MutableRefObject<string>;
3
+ setValue: (value: any) => void;
4
+ };
5
+ export declare const useGenerateUpload: ({ instructionIdRef, setValue }: UseGenerateUploadParams) => {
6
+ generateUpload: () => Promise<void | Response>;
7
+ isJobActive: boolean;
8
+ jobProgress: number;
9
+ jobStatus: string | undefined;
10
+ };
11
+ export {};
@@ -0,0 +1,123 @@
1
+ import { toast, useConfig, useDocumentInfo, useForm, useLocale } from '@payloadcms/ui';
2
+ import { useCallback, useState } from 'react';
3
+ import { PLUGIN_AI_JOBS_TABLE, PLUGIN_API_ENDPOINT_GENERATE_UPLOAD } from '../../../defaults.js';
4
+ import { useHistory } from './useHistory.js';
5
+ export const useGenerateUpload = ({ instructionIdRef, setValue })=>{
6
+ const { config } = useConfig();
7
+ const { routes: { api }, serverURL } = config;
8
+ const { id: documentId, collectionSlug } = useDocumentInfo();
9
+ const localFromContext = useLocale();
10
+ const { getData } = useForm();
11
+ const { set: setHistory } = useHistory();
12
+ // Async job UI state
13
+ const [jobStatus, setJobStatus] = useState(undefined);
14
+ const [jobProgress, setJobProgress] = useState(0);
15
+ const [isJobActive, setIsJobActive] = useState(false);
16
+ const generateUpload = useCallback(async ()=>{
17
+ const doc = getData();
18
+ const currentInstructionId = instructionIdRef.current;
19
+ return fetch(`${serverURL}${api}${PLUGIN_API_ENDPOINT_GENERATE_UPLOAD}`, {
20
+ body: JSON.stringify({
21
+ collectionSlug: collectionSlug ?? '',
22
+ doc,
23
+ documentId,
24
+ locale: localFromContext?.code,
25
+ options: {
26
+ instructionId: currentInstructionId
27
+ }
28
+ }),
29
+ credentials: 'include',
30
+ headers: {
31
+ 'Content-Type': 'application/json'
32
+ },
33
+ method: 'POST'
34
+ }).then(async (uploadResponse)=>{
35
+ if (uploadResponse.ok) {
36
+ const json = await uploadResponse.json();
37
+ const { job, result } = json || {};
38
+ if (result) {
39
+ // Set the upload ID
40
+ setValue(result?.id);
41
+ setHistory(result?.id);
42
+ // Show toast to prompt user to save
43
+ toast.success('Image generated successfully! Click Save to see the preview.');
44
+ return uploadResponse;
45
+ }
46
+ // Async job: poll AI Jobs collection for status/progress/result_id
47
+ if (job && job.id) {
48
+ setIsJobActive(true);
49
+ const cancelled = false;
50
+ let attempts = 0;
51
+ const maxAttempts = 600 // up to ~10 minutes @ 1s
52
+ ;
53
+ // Basic in-hook state via closure variables; UI will re-render off fetches below
54
+ const poll = async ()=>{
55
+ if (cancelled) {
56
+ return;
57
+ }
58
+ try {
59
+ const res = await fetch(`${serverURL}${api}/${PLUGIN_AI_JOBS_TABLE}/${job.id}`, {
60
+ credentials: 'include'
61
+ });
62
+ if (res.ok) {
63
+ const jobDoc = await res.json();
64
+ const { progress, result_id, status } = jobDoc || {};
65
+ setJobStatus(status);
66
+ setJobProgress(progress ?? 0);
67
+ // When result present, set field and finish
68
+ if (status === 'completed' && result_id) {
69
+ // Force upload field to refetch by clearing then setting the ID
70
+ setValue(null);
71
+ setTimeout(()=>{
72
+ setValue(result_id);
73
+ }, 0);
74
+ setHistory(result_id);
75
+ setIsJobActive(false);
76
+ return;
77
+ }
78
+ if (status === 'failed') {
79
+ setIsJobActive(false);
80
+ throw new Error('Video generation failed');
81
+ }
82
+ }
83
+ } catch (e) {
84
+ // silent retry
85
+ }
86
+ attempts += 1;
87
+ if (!cancelled && attempts < maxAttempts) {
88
+ setTimeout(poll, 1000);
89
+ }
90
+ };
91
+ setTimeout(poll, 1000);
92
+ return uploadResponse;
93
+ }
94
+ throw new Error('generateUpload: Unexpected response');
95
+ } else {
96
+ const { errors = [] } = await uploadResponse.json();
97
+ const errStr = errors.map((error)=>error.message).join(', ');
98
+ throw new Error(errStr);
99
+ }
100
+ }).catch((error)=>{
101
+ toast.error(`Failed to generate: ${error.message}`);
102
+ console.error('Error generating or setting your upload, please set it manually if its saved in your media files.', error);
103
+ });
104
+ }, [
105
+ getData,
106
+ localFromContext?.code,
107
+ instructionIdRef,
108
+ setValue,
109
+ documentId,
110
+ collectionSlug,
111
+ serverURL,
112
+ api,
113
+ setHistory
114
+ ]);
115
+ return {
116
+ generateUpload,
117
+ isJobActive,
118
+ jobProgress,
119
+ jobStatus
120
+ };
121
+ };
122
+
123
+ //# sourceMappingURL=useGenerateUpload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/ui/Compose/hooks/useGenerateUpload.ts"],"sourcesContent":["import { toast, useConfig, useDocumentInfo, useForm, useLocale } from '@payloadcms/ui'\nimport { useCallback, useState } from 'react'\n\nimport type { GenerateTextarea } from '../../../types.js'\n\nimport { PLUGIN_AI_JOBS_TABLE, PLUGIN_API_ENDPOINT_GENERATE_UPLOAD } from '../../../defaults.js'\nimport { useHistory } from './useHistory.js'\n\ntype UseGenerateUploadParams = {\n instructionIdRef: React.MutableRefObject<string>\n setValue: (value: any) => void\n}\n\nexport const useGenerateUpload = ({ instructionIdRef, setValue }: UseGenerateUploadParams) => {\n const { config } = useConfig()\n const {\n routes: { api },\n serverURL,\n } = config\n const { id: documentId, collectionSlug } = useDocumentInfo()\n const localFromContext = useLocale()\n const { getData } = useForm()\n const { set: setHistory } = useHistory()\n\n // Async job UI state\n const [jobStatus, setJobStatus] = useState<string | undefined>(undefined)\n const [jobProgress, setJobProgress] = useState<number>(0)\n const [isJobActive, setIsJobActive] = useState<boolean>(false)\n\n const generateUpload = useCallback(async () => {\n const doc = getData()\n const currentInstructionId = instructionIdRef.current\n\n return fetch(`${serverURL}${api}${PLUGIN_API_ENDPOINT_GENERATE_UPLOAD}`, {\n body: JSON.stringify({\n collectionSlug: collectionSlug ?? '',\n doc,\n documentId,\n locale: localFromContext?.code,\n options: {\n instructionId: currentInstructionId,\n },\n } satisfies Parameters<GenerateTextarea>[0]),\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n .then(async (uploadResponse) => {\n if (uploadResponse.ok) {\n const json = await uploadResponse.json()\n const { job, result } = json || {}\n if (result) {\n // Set the upload ID\n setValue(result?.id)\n setHistory(result?.id)\n\n // Show toast to prompt user to save\n toast.success('Image generated successfully! Click Save to see the preview.')\n\n return uploadResponse\n }\n\n // Async job: poll AI Jobs collection for status/progress/result_id\n if (job && job.id) {\n setIsJobActive(true)\n const cancelled = false\n let attempts = 0\n const maxAttempts = 600 // up to ~10 minutes @ 1s\n\n // Basic in-hook state via closure variables; UI will re-render off fetches below\n const poll = async (): Promise<void> => {\n if (cancelled) {\n return\n }\n try {\n const res = await fetch(`${serverURL}${api}/${PLUGIN_AI_JOBS_TABLE}/${job.id}`, {\n credentials: 'include',\n })\n if (res.ok) {\n const jobDoc = await res.json()\n const { progress, result_id, status } = jobDoc || {}\n setJobStatus(status)\n setJobProgress(progress ?? 0)\n // When result present, set field and finish\n if (status === 'completed' && result_id) {\n // Force upload field to refetch by clearing then setting the ID\n setValue(null)\n setTimeout(() => {\n setValue(result_id)\n }, 0)\n setHistory(result_id)\n setIsJobActive(false)\n return\n }\n if (status === 'failed') {\n setIsJobActive(false)\n throw new Error('Video generation failed')\n }\n }\n } catch (e) {\n // silent retry\n }\n\n attempts += 1\n if (!cancelled && attempts < maxAttempts) {\n setTimeout(poll, 1000)\n }\n }\n setTimeout(poll, 1000)\n return uploadResponse\n }\n\n throw new Error('generateUpload: Unexpected response')\n } else {\n const { errors = [] } = await uploadResponse.json()\n const errStr = errors.map((error: any) => error.message).join(', ')\n throw new Error(errStr)\n }\n })\n .catch((error) => {\n toast.error(`Failed to generate: ${error.message}`)\n console.error(\n 'Error generating or setting your upload, please set it manually if its saved in your media files.',\n error,\n )\n })\n }, [\n getData,\n localFromContext?.code,\n instructionIdRef,\n setValue,\n documentId,\n collectionSlug,\n serverURL,\n api,\n setHistory,\n ])\n\n return {\n generateUpload,\n isJobActive,\n jobProgress,\n jobStatus,\n }\n}\n"],"names":["toast","useConfig","useDocumentInfo","useForm","useLocale","useCallback","useState","PLUGIN_AI_JOBS_TABLE","PLUGIN_API_ENDPOINT_GENERATE_UPLOAD","useHistory","useGenerateUpload","instructionIdRef","setValue","config","routes","api","serverURL","id","documentId","collectionSlug","localFromContext","getData","set","setHistory","jobStatus","setJobStatus","undefined","jobProgress","setJobProgress","isJobActive","setIsJobActive","generateUpload","doc","currentInstructionId","current","fetch","body","JSON","stringify","locale","code","options","instructionId","credentials","headers","method","then","uploadResponse","ok","json","job","result","success","cancelled","attempts","maxAttempts","poll","res","jobDoc","progress","result_id","status","setTimeout","Error","e","errors","errStr","map","error","message","join","catch","console"],"mappings":"AAAA,SAASA,KAAK,EAAEC,SAAS,EAAEC,eAAe,EAAEC,OAAO,EAAEC,SAAS,QAAQ,iBAAgB;AACtF,SAASC,WAAW,EAAEC,QAAQ,QAAQ,QAAO;AAI7C,SAASC,oBAAoB,EAAEC,mCAAmC,QAAQ,uBAAsB;AAChG,SAASC,UAAU,QAAQ,kBAAiB;AAO5C,OAAO,MAAMC,oBAAoB,CAAC,EAAEC,gBAAgB,EAAEC,QAAQ,EAA2B;IACvF,MAAM,EAAEC,MAAM,EAAE,GAAGZ;IACnB,MAAM,EACJa,QAAQ,EAAEC,GAAG,EAAE,EACfC,SAAS,EACV,GAAGH;IACJ,MAAM,EAAEI,IAAIC,UAAU,EAAEC,cAAc,EAAE,GAAGjB;IAC3C,MAAMkB,mBAAmBhB;IACzB,MAAM,EAAEiB,OAAO,EAAE,GAAGlB;IACpB,MAAM,EAAEmB,KAAKC,UAAU,EAAE,GAAGd;IAE5B,qBAAqB;IACrB,MAAM,CAACe,WAAWC,aAAa,GAAGnB,SAA6BoB;IAC/D,MAAM,CAACC,aAAaC,eAAe,GAAGtB,SAAiB;IACvD,MAAM,CAACuB,aAAaC,eAAe,GAAGxB,SAAkB;IAExD,MAAMyB,iBAAiB1B,YAAY;QACjC,MAAM2B,MAAMX;QACZ,MAAMY,uBAAuBtB,iBAAiBuB,OAAO;QAErD,OAAOC,MAAM,CAAC,EAAEnB,UAAU,EAAED,IAAI,EAAEP,oCAAoC,CAAC,EAAE;YACvE4B,MAAMC,KAAKC,SAAS,CAAC;gBACnBnB,gBAAgBA,kBAAkB;gBAClCa;gBACAd;gBACAqB,QAAQnB,kBAAkBoB;gBAC1BC,SAAS;oBACPC,eAAeT;gBACjB;YACF;YACAU,aAAa;YACbC,SAAS;gBACP,gBAAgB;YAClB;YACAC,QAAQ;QACV,GACGC,IAAI,CAAC,OAAOC;YACX,IAAIA,eAAeC,EAAE,EAAE;gBACrB,MAAMC,OAAO,MAAMF,eAAeE,IAAI;gBACtC,MAAM,EAAEC,GAAG,EAAEC,MAAM,EAAE,GAAGF,QAAQ,CAAC;gBACjC,IAAIE,QAAQ;oBACV,oBAAoB;oBACpBvC,SAASuC,QAAQlC;oBACjBM,WAAW4B,QAAQlC;oBAEnB,oCAAoC;oBACpCjB,MAAMoD,OAAO,CAAC;oBAEd,OAAOL;gBACT;gBAEA,mEAAmE;gBACnE,IAAIG,OAAOA,IAAIjC,EAAE,EAAE;oBACjBa,eAAe;oBACf,MAAMuB,YAAY;oBAClB,IAAIC,WAAW;oBACf,MAAMC,cAAc,IAAI,yBAAyB;;oBAEjD,iFAAiF;oBACjF,MAAMC,OAAO;wBACX,IAAIH,WAAW;4BACb;wBACF;wBACA,IAAI;4BACF,MAAMI,MAAM,MAAMtB,MAAM,CAAC,EAAEnB,UAAU,EAAED,IAAI,CAAC,EAAER,qBAAqB,CAAC,EAAE2C,IAAIjC,EAAE,CAAC,CAAC,EAAE;gCAC9E0B,aAAa;4BACf;4BACA,IAAIc,IAAIT,EAAE,EAAE;gCACV,MAAMU,SAAS,MAAMD,IAAIR,IAAI;gCAC7B,MAAM,EAAEU,QAAQ,EAAEC,SAAS,EAAEC,MAAM,EAAE,GAAGH,UAAU,CAAC;gCACnDjC,aAAaoC;gCACbjC,eAAe+B,YAAY;gCAC3B,4CAA4C;gCAC5C,IAAIE,WAAW,eAAeD,WAAW;oCACvC,gEAAgE;oCAChEhD,SAAS;oCACTkD,WAAW;wCACTlD,SAASgD;oCACX,GAAG;oCACHrC,WAAWqC;oCACX9B,eAAe;oCACf;gCACF;gCACA,IAAI+B,WAAW,UAAU;oCACvB/B,eAAe;oCACf,MAAM,IAAIiC,MAAM;gCAClB;4BACF;wBACF,EAAE,OAAOC,GAAG;wBACV,eAAe;wBACjB;wBAEAV,YAAY;wBACZ,IAAI,CAACD,aAAaC,WAAWC,aAAa;4BACxCO,WAAWN,MAAM;wBACnB;oBACF;oBACAM,WAAWN,MAAM;oBACjB,OAAOT;gBACT;gBAEA,MAAM,IAAIgB,MAAM;YAClB,OAAO;gBACL,MAAM,EAAEE,SAAS,EAAE,EAAE,GAAG,MAAMlB,eAAeE,IAAI;gBACjD,MAAMiB,SAASD,OAAOE,GAAG,CAAC,CAACC,QAAeA,MAAMC,OAAO,EAAEC,IAAI,CAAC;gBAC9D,MAAM,IAAIP,MAAMG;YAClB;QACF,GACCK,KAAK,CAAC,CAACH;YACNpE,MAAMoE,KAAK,CAAC,CAAC,oBAAoB,EAAEA,MAAMC,OAAO,CAAC,CAAC;YAClDG,QAAQJ,KAAK,CACX,qGACAA;QAEJ;IACJ,GAAG;QACD/C;QACAD,kBAAkBoB;QAClB7B;QACAC;QACAM;QACAC;QACAH;QACAD;QACAQ;KACD;IAED,OAAO;QACLQ;QACAF;QACAF;QACAH;IACF;AACF,EAAC"}
@@ -1,7 +1,6 @@
1
1
  export declare const useHistory: () => {
2
2
  canRedo: boolean;
3
3
  canUndo: boolean;
4
- currentValue: any;
5
4
  redo: () => any;
6
5
  set: (data: any) => any;
7
6
  undo: () => any;