@ai-stack/payloadcms 3.68.0-beta.3 → 3.68.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/core/streamObject.js +3 -0
- package/dist/ai/core/streamObject.js.map +1 -1
- package/dist/ai/core/types.d.ts +3 -0
- package/dist/ai/core/types.js.map +1 -1
- package/dist/ai/prompts.d.ts +1 -2
- package/dist/ai/prompts.js +0 -110
- package/dist/ai/prompts.js.map +1 -1
- package/dist/ai/providers/registry.js +0 -1
- package/dist/ai/providers/registry.js.map +1 -1
- package/dist/ai/utils/filterEditorSchemaByNodes.d.ts +9 -0
- package/dist/ai/utils/filterEditorSchemaByNodes.js +30 -3
- package/dist/ai/utils/filterEditorSchemaByNodes.js.map +1 -1
- package/dist/ai/utils/nodeToSchemaMap.d.ts +22 -0
- package/dist/ai/utils/nodeToSchemaMap.js +72 -0
- package/dist/ai/utils/nodeToSchemaMap.js.map +1 -0
- package/dist/collections/AIJobs.js +1 -1
- package/dist/collections/AIJobs.js.map +1 -1
- package/dist/collections/AISettings.js +3 -3
- package/dist/collections/AISettings.js.map +1 -1
- package/dist/endpoints/fetchVoices.js +41 -24
- package/dist/endpoints/fetchVoices.js.map +1 -1
- package/dist/endpoints/index.js +108 -6
- package/dist/endpoints/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/payload-ai.d.ts +7 -4
- package/dist/plugin.js +1 -1
- package/dist/plugin.js.map +1 -1
- package/dist/types.d.ts +34 -2
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/dist/ui/Compose/Compose.js +23 -6
- package/dist/ui/Compose/Compose.js.map +1 -1
- package/dist/ui/Compose/Compose.jsx +23 -4
- package/dist/ui/Compose/hooks/useGenerate.js +21 -72
- package/dist/ui/Compose/hooks/useGenerate.js.map +1 -1
- package/dist/ui/Compose/hooks/useGenerateUpload.d.ts +3 -3
- package/dist/ui/Compose/hooks/useGenerateUpload.js +37 -10
- package/dist/ui/Compose/hooks/useGenerateUpload.js.map +1 -1
- package/dist/ui/Compose/hooks/useStreamingUpdate.js.map +1 -1
- package/dist/ui/VoicesFetcher/index.js +33 -61
- package/dist/ui/VoicesFetcher/index.js.map +1 -1
- package/dist/ui/VoicesFetcher/index.jsx +31 -37
- package/dist/utilities/buildSmartPrompt.js +4 -6
- package/dist/utilities/buildSmartPrompt.js.map +1 -1
- package/dist/utilities/encryption.js +2 -1
- package/dist/utilities/encryption.js.map +1 -1
- package/dist/utilities/seedProperties.js +7 -24
- package/dist/utilities/seedProperties.js.map +1 -1
- package/dist/utilities/setSafeLexicalState.js +1 -2
- package/dist/utilities/setSafeLexicalState.js.map +1 -1
- package/package.json +1 -1
package/dist/payload-ai.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ interface PayloadGenerationBaseArgs {
|
|
|
30
30
|
interface PayloadGenerateObjectArgs extends PayloadGenerationBaseArgs {
|
|
31
31
|
images?: ImagePart[]
|
|
32
32
|
mode?: 'auto' | 'json' | 'tool'
|
|
33
|
+
onFinish?: (event: { object?: unknown }) => Promise<void> | void
|
|
33
34
|
schema?: Record<string, unknown> | z.ZodTypeAny
|
|
34
35
|
}
|
|
35
36
|
|
|
@@ -119,7 +120,11 @@ declare module 'payload' {
|
|
|
119
120
|
* @param type - Model type ('text', 'image', or 'tts')
|
|
120
121
|
* @returns Promise resolving to the model instance
|
|
121
122
|
*/
|
|
122
|
-
getModel: (
|
|
123
|
+
getModel: (
|
|
124
|
+
provider: string,
|
|
125
|
+
modelId: string,
|
|
126
|
+
type?: 'image' | 'text' | 'tts',
|
|
127
|
+
) => Promise<unknown>
|
|
123
128
|
|
|
124
129
|
/**
|
|
125
130
|
* Get the provider registry
|
|
@@ -132,9 +137,7 @@ declare module 'payload' {
|
|
|
132
137
|
* @param args - Generation arguments including provider, model, prompt, and schema
|
|
133
138
|
* @returns Response stream
|
|
134
139
|
*/
|
|
135
|
-
streamObject: <T = unknown>(
|
|
136
|
-
args: PayloadGenerateObjectArgs,
|
|
137
|
-
) => Promise<Response>
|
|
140
|
+
streamObject: <T = unknown>(args: PayloadGenerateObjectArgs) => Promise<Response>
|
|
138
141
|
|
|
139
142
|
/**
|
|
140
143
|
* Stream text output
|
package/dist/plugin.js
CHANGED
|
@@ -156,7 +156,7 @@ const payloadAiPlugin = (pluginConfig)=>(incomingConfig)=>{
|
|
|
156
156
|
payload.logger.info(sponsorMessage);
|
|
157
157
|
}, 3000);
|
|
158
158
|
}
|
|
159
|
-
// Inject AI capabilities with
|
|
159
|
+
// Inject AI capabilities with the abstraction layer
|
|
160
160
|
;
|
|
161
161
|
payload.ai = {
|
|
162
162
|
// Core generation methods
|
package/dist/plugin.js.map
CHANGED
|
@@ -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 { 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":"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,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,uBAAuB;AACzB;AAEA,MAAMC,iBAAiB,CAAC;;;;;;;;;;;;;;;;;;AAkBxB,CAAC;AAED,MAAMC,kBAAkB,CAAC;;;;;;;;;;;;;AAazB,CAAC;AAED,MAAMC,kBACJ,CAACC,eACD,CAACC;QACCD,eAAe;YACb,GAAGV,mBAAmB;YACtB,GAAGU,YAAY;YACfT,QAAQ;gBACN,GAAGD,oBAAoBC,MAAM;gBAC7B,GAAGS,aAAaT,MAAM;YACxB;QACF;QAEA,MAAMW,cAAcd,kBAAkBY;QACtC,IAAIG,gBAAwB;YAAE,GAAGF,cAAc;QAAC;QAEhD,IAAIC,aAAa;YACf,MAAME,eAAetB,uBAAuBkB;YAC5C,MAAMK,SAASzB;YACf,8FAA8F;YAC9F,MAAM0B,gBAAgB3B,kBAAkBqB,aAAaO,YAAY,EAAEC;YAEnEJ,aAAaK,KAAK,GAAG;gBACnB,GAAGL,aAAaK,KAAK;YACvB;YAEA,IAAIT,aAAaU,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,CAAC7B,YAAY,EAAE;oBACbwB,cAAc;wBACZ,0CAA0C;wBAC1CM,QAAQP;oBACV;gBACF;YACF;YAEA,MAAMQ,cAAc;mBAAKb,eAAea,WAAW,IAAI,EAAE;gBAAGV;gBAAcC;aAAO;YACjF,MAAMU,UAAU;mBAAKd,eAAec,OAAO,IAAI,EAAE;gBAAGlC;aAAiB;YACrE,MAAM,EAAEkC,SAASC,YAAY,EAAE,GAAGhB;YAElC,MAAM,EAAEiB,YAAY,EAAEC,YAAY,EAAE,EAAE,GAAG,CAAC,CAAC,EAAE,GAAGjB,eAAeQ,KAAK,IAAI,CAAC;YACzE,MAAMU,mBAAmB;mBACnBD,aAAa,EAAE;gBACnB;oBACEE,MAAM;gBACR;aACD;YAEDnB,eAAeQ,KAAK,GAAG;gBACrB,GAAIR,eAAeQ,KAAK,IAAI,CAAC,CAAC;gBAC9BQ,YAAY;oBACV,GAAIhB,eAAeQ,KAAK,EAAEQ,cAAc,CAAC,CAAC;oBAC1CC,WAAWC;gBACb;YACF;YAEA,MAAME,kBAAkBnC,UAAUc;YAClCG,gBAAgB;gBACd,GAAGF,cAAc;gBACjBa,aAAaA,YAAYQ,GAAG,CAAC,CAACC;oBAC5B,kGAAkG;oBAClG,MAAM,EAAEC,uBAAuB,EAAE,GAAGnC,mBAAmBkC;oBACvD,OAAOC;gBACT;gBACAtC,WAAW;uBACLe,eAAef,SAAS,IAAI,EAAE;oBAClCmC,gBAAgBI,QAAQ;oBACxBJ,gBAAgBK,MAAM;uBAClBL,gBAAgBM,eAAe,GAAG;wBAACN,gBAAgBM,eAAe;qBAAC,GAAG,EAAE;oBAC5E3C,YAAYgB;oBACZf;iBACD;gBACD8B,SAASA,QAAQO,GAAG,CAAC,CAACM;oBACpB,IAAIZ,gBAAgBA,YAAY,CAACY,OAAOC,IAAI,CAAC,EAAE;wBAC7C,MAAM,EAAEL,uBAAuB,EAAE,GAAGnC,mBAAmBuC;wBACvD,OAAOJ;oBACT;oBAEA,OAAOI;gBACT;gBACAE,MAAM;oBACJ,GAAI7B,eAAe6B,IAAI,IAAI,CAAC,CAAC;oBAC7B3C,cAAc;wBACZ,GAAGT,UAAUS,cAAcc,eAAe6B,IAAI,EAAE3C,gBAAgB,CAAC,EAAE;oBACrE;gBACF;YACF;QACF;QAEAgB,cAAc4B,MAAM,GAAG,OAAOC;YAC5B,IAAI/B,eAAe8B,MAAM,EAAE;gBACzB,MAAM9B,eAAe8B,MAAM,CAACC;YAC9B;YAEA,IAAI,CAAC9B,aAAa;gBAChB8B,QAAQC,MAAM,CAACC,IAAI,CAAC,CAAC,gEAAgE,CAAC;gBACtF;YACF;YAEA,IAAI,CAAClC,aAAaJ,qBAAqB,EAAE;gBACvCuC,WAAW;oBACTH,QAAQC,MAAM,CAACG,IAAI,CAACtC;gBACtB,GAAG;gBACHqC,WAAW;oBACTH,QAAQC,MAAM,CAACG,IAAI,CAACvC;gBACtB,GAAG;YACL;YAEA,yDAAyD;;YACvDmC,QAAgBK,EAAE,GAAG;gBACrB,0BAA0B;gBAC1BC,gBAAgB,OAAOC;oBACrB,MAAM,EAAED,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC;oBACxC,OAAOA,eAAe;wBAAE,GAAGC,IAAI;wBAAEP;oBAAQ;gBAC3C;gBAEAQ,cAAc,OAAOD;oBACnB,MAAM,EAAEC,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC;oBACtC,OAAOA,aAAa;wBAAE,GAAGD,IAAI;wBAAEP;oBAAQ;gBACzC;gBAEAS,eAAe,OAAOF;oBACpB,MAAM,EAAEE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC;oBACvC,OAAOA,cAAc;wBAAE,GAAGF,IAAI;wBAAEP;oBAAQ;gBAC1C;gBAEA,qBAAqB;gBACrBU,cAAc,OAAOH;oBACnB,MAAM,EAAEG,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC;oBACtC,MAAMC,SAAS,MAAMD,aAAa;wBAAE,GAAGH,IAAI;wBAAEP;oBAAQ;oBACrD,OAAOW,OAAOC,oBAAoB;gBACpC;gBAEAC,YAAY,OAAON;oBACjB,MAAM,EAAEM,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC;oBACpC,OAAOA,WAAW;wBAAE,GAAGN,IAAI;wBAAEP;oBAAQ;gBACvC;gBAEA,mBAAmB;gBACnBc,UAAU,OAAOC,UAAkBC,SAAiBC;oBAClD,MAAM,EAAEC,aAAa,EAAEC,gBAAgB,EAAEC,WAAW,EAAE,GAAG,MAAM,MAAM,CACnE;oBAEF,IAAIH,SAAS,SAAS;wBACpB,OAAOC,cAAclB,SAASe,UAAUC;oBAC1C;oBACA,IAAIC,SAAS,OAAO;wBAClB,OAAOG,YAAYpB,SAASe,UAAUC;oBACxC;oBACA,OAAOG,iBAAiBnB,SAASe,UAAUC;gBAC7C;gBAEAK,aAAa;oBACX,MAAM,EAAEC,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC;oBAC7C,OAAOA,oBAAoBtB;gBAC7B;gBAEA,2CAA2C;gBAC3C,2DAA2D,GAC3DxC,UAAU,OAAO+C;oBACf,MAAM,EAAE/C,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC;oBAClC,OAAOA,SAAS;wBAAE,GAAG+C,IAAI;wBAAEP;oBAAQ;gBACrC;YACF;QACF;QAEA,OAAO7B;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 the 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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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { JSONSchema } from 'openai/lib/jsonschema';
|
|
|
2
2
|
import type { ImageGenerateParams } from 'openai/resources/images';
|
|
3
3
|
import type { CollectionConfig, CollectionSlug, DataFromCollectionSlug, Endpoint, Field, File, GlobalConfig, GroupField, PayloadRequest, TypedCollection } from 'payload';
|
|
4
4
|
import type { CSSProperties, MouseEventHandler } from 'react';
|
|
5
|
+
import type { GenerateObjectResult, ModelMessage } from 'ai';
|
|
5
6
|
import type { MediaResult } from './ai/core/index.js';
|
|
6
7
|
import type { PLUGIN_INSTRUCTIONS_TABLE } from "./defaults.js";
|
|
7
8
|
export interface PluginConfigAccess {
|
|
@@ -63,8 +64,7 @@ export interface PluginConfig {
|
|
|
63
64
|
prompts?: ActionPrompt[];
|
|
64
65
|
/**
|
|
65
66
|
* Custom seed prompt function for generating field-specific prompts
|
|
66
|
-
* If not provided,
|
|
67
|
-
* You can access default seed prompts by importing { defaultSeedPrompts } from '@ai-stack/payloadcms'
|
|
67
|
+
* If not provided, fields will have empty prompts by default
|
|
68
68
|
*/
|
|
69
69
|
seedPrompts?: SeedPromptFunction;
|
|
70
70
|
uploadCollectionSlug?: CollectionSlug;
|
|
@@ -166,3 +166,35 @@ export type PromptFieldGetterContext = {
|
|
|
166
166
|
export type PromptField = {
|
|
167
167
|
getter?: (data: object, ctx: PromptFieldGetterContext) => Promise<string> | string;
|
|
168
168
|
} & SerializedPromptField;
|
|
169
|
+
export interface BeforeGenerateArgs<T = any> {
|
|
170
|
+
doc: T;
|
|
171
|
+
field: Field;
|
|
172
|
+
headers: Record<string, string>;
|
|
173
|
+
instructions: Record<string, unknown>;
|
|
174
|
+
messages?: ModelMessage[];
|
|
175
|
+
payload: PayloadRequest['payload'];
|
|
176
|
+
prompt: string;
|
|
177
|
+
req: PayloadRequest;
|
|
178
|
+
system: string;
|
|
179
|
+
}
|
|
180
|
+
export type BeforeGenerateResult = {
|
|
181
|
+
messages?: ModelMessage[];
|
|
182
|
+
prompt?: string;
|
|
183
|
+
system?: string;
|
|
184
|
+
} | void;
|
|
185
|
+
export type BeforeGenerateHook<T = any> = (args: BeforeGenerateArgs<T>) => BeforeGenerateResult | Promise<BeforeGenerateResult>;
|
|
186
|
+
export interface AfterGenerateArgs<T = any> {
|
|
187
|
+
doc: T;
|
|
188
|
+
field: Field;
|
|
189
|
+
headers: Record<string, string>;
|
|
190
|
+
instructions: Record<string, unknown>;
|
|
191
|
+
payload: PayloadRequest['payload'];
|
|
192
|
+
req: PayloadRequest;
|
|
193
|
+
result: GenerateObjectResult<any> | MediaResult | string;
|
|
194
|
+
}
|
|
195
|
+
export type AfterGenerateHook<T = any> = (args: AfterGenerateArgs<T>) => Promise<void> | void;
|
|
196
|
+
export interface AIFieldConfig {
|
|
197
|
+
afterGenerate?: AfterGenerateHook[];
|
|
198
|
+
beforeGenerate?: BeforeGenerateHook[];
|
|
199
|
+
[key: string]: unknown;
|
|
200
|
+
}
|
package/dist/types.js
CHANGED
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { JSONSchema } from 'openai/lib/jsonschema'\nimport type { ImageGenerateParams } from 'openai/resources/images'\nimport type {\n CollectionConfig,\n CollectionSlug,\n DataFromCollectionSlug,\n Endpoint,\n Field,\n File,\n GlobalConfig,\n GroupField,\n PayloadRequest,\n TypedCollection,\n} from 'payload'\nimport type { CSSProperties, MouseEventHandler } from 'react'\n\nimport type { MediaResult } from './ai/core/index.js'\nimport type {PLUGIN_INSTRUCTIONS_TABLE} from \"./defaults.js\";\n\nexport interface PluginConfigAccess {\n /**\n * Control access to AI generation features (generate text, images, audio)\n * @default () => !!req.user (requires authentication)\n */\n generate?: ({ req }: { req: PayloadRequest }) => boolean | Promise<boolean>\n /**\n * Control access to AI settings/configuration\n * @default () => !!req.user (requires authentication)\n */\n settings?: ({ req }: { req: PayloadRequest }) => boolean | Promise<boolean>\n}\n\nexport interface PluginOptions {\n /**\n * Provide local tags to filter language options from the Translate Menu\n * Check for the available local tags,\n * visit: https://www.npmjs.com/package/locale-codes\n * Example: [\"en-US\", \"zh-SG\", \"zh-CN\", \"en\"]\n */\n enabledLanguages?: string[]\n}\n\nexport type PluginConfigMediaUploadFunction = (\n result: MediaResult,\n {\n collection,\n request,\n }: {\n collection: CollectionSlug\n request: PayloadRequest\n },\n) => Promise<DataFromCollectionSlug<CollectionSlug>>\n\nexport interface PluginConfig {\n /**\n * Access control configuration for AI features\n * By default, all AI features require authentication\n */\n access?: PluginConfigAccess\n debugging?: boolean\n disableSponsorMessage?: boolean\n editorConfig?: { nodes: JSONSchema[] }\n fields?: Field[]\n generatePromptOnInit?: boolean\n generationModels?: ((defaultModels: GenerationModel[]) => GenerationModel[]) | GenerationModel[]\n globals?: {\n [key: GlobalConfig['slug']]: boolean\n }\n interfaceName?: string\n mediaUpload?: PluginConfigMediaUploadFunction\n options?: PluginOptions\n // Override the instructions collection config\n overrideInstructions?: Partial<CollectionConfig>\n promptFields?: PromptField[]\n /**\n * Custom action prompts for AI text generation\n * If not provided, uses default prompts\n * You can access default prompts by importing { defaultPrompts } from '@ai-stack/payloadcms'\n */\n prompts?: ActionPrompt[]\n /**\n * Custom seed prompt function for generating field-specific prompts\n * If not provided,
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { JSONSchema } from 'openai/lib/jsonschema'\nimport type { ImageGenerateParams } from 'openai/resources/images'\nimport type {\n CollectionConfig,\n CollectionSlug,\n DataFromCollectionSlug,\n Endpoint,\n Field,\n File,\n GlobalConfig,\n GroupField,\n PayloadRequest,\n TypedCollection,\n} from 'payload'\nimport type { CSSProperties, MouseEventHandler } from 'react'\n\nimport type { GenerateObjectResult, ModelMessage } from 'ai'\nimport type { MediaResult } from './ai/core/index.js'\nimport type {PLUGIN_INSTRUCTIONS_TABLE} from \"./defaults.js\";\n\nexport interface PluginConfigAccess {\n /**\n * Control access to AI generation features (generate text, images, audio)\n * @default () => !!req.user (requires authentication)\n */\n generate?: ({ req }: { req: PayloadRequest }) => boolean | Promise<boolean>\n /**\n * Control access to AI settings/configuration\n * @default () => !!req.user (requires authentication)\n */\n settings?: ({ req }: { req: PayloadRequest }) => boolean | Promise<boolean>\n}\n\nexport interface PluginOptions {\n /**\n * Provide local tags to filter language options from the Translate Menu\n * Check for the available local tags,\n * visit: https://www.npmjs.com/package/locale-codes\n * Example: [\"en-US\", \"zh-SG\", \"zh-CN\", \"en\"]\n */\n enabledLanguages?: string[]\n}\n\nexport type PluginConfigMediaUploadFunction = (\n result: MediaResult,\n {\n collection,\n request,\n }: {\n collection: CollectionSlug\n request: PayloadRequest\n },\n) => Promise<DataFromCollectionSlug<CollectionSlug>>\n\nexport interface PluginConfig {\n /**\n * Access control configuration for AI features\n * By default, all AI features require authentication\n */\n access?: PluginConfigAccess\n debugging?: boolean\n disableSponsorMessage?: boolean\n editorConfig?: { nodes: JSONSchema[] }\n fields?: Field[]\n generatePromptOnInit?: boolean\n generationModels?: ((defaultModels: GenerationModel[]) => GenerationModel[]) | GenerationModel[]\n globals?: {\n [key: GlobalConfig['slug']]: boolean\n }\n interfaceName?: string\n mediaUpload?: PluginConfigMediaUploadFunction\n options?: PluginOptions\n // Override the instructions collection config\n overrideInstructions?: Partial<CollectionConfig>\n promptFields?: PromptField[]\n /**\n * Custom action prompts for AI text generation\n * If not provided, uses default prompts\n * You can access default prompts by importing { defaultPrompts } from '@ai-stack/payloadcms'\n */\n prompts?: ActionPrompt[]\n /**\n * Custom seed prompt function for generating field-specific prompts\n * If not provided, fields will have empty prompts by default\n */\n seedPrompts?: SeedPromptFunction\n uploadCollectionSlug?: CollectionSlug\n}\n\nexport interface GenerationModel {\n fields: string[]\n generateText?: (prompt: string, system: string) => Promise<string>\n handler?: (prompt: string, options: any) => File | Promise<any> | Response\n id: string\n name: string\n output: 'audio' | 'file' | 'image' | 'json' | 'text' | 'video'\n settings?: GroupField\n supportsPromptOptimization?: boolean\n}\n\nexport interface GenerationConfig {\n models: GenerationModel[]\n provider: string\n}\n\nexport type GenerateTextarea<T = any> = (args: {\n collectionSlug: CollectionSlug\n doc: T\n documentId?: number | string\n locale?: string\n options?: any\n}) => Promise<string> | string\n\nexport interface Endpoints {\n fetchVoices?: Omit<Endpoint, 'root'>\n textarea: Omit<Endpoint, 'root'>\n upload: Omit<Endpoint, 'root'>\n videogenWebhook?: Omit<Endpoint, 'root'>\n}\n\nexport type ActionMenuItems =\n | 'Compose'\n | 'Expand'\n | 'Proofread'\n | 'Rephrase'\n | 'Settings'\n | 'Simplify'\n | 'Summarize'\n | 'Tone'\n | 'Translate'\n\nexport type ActionPromptOptions = {\n layout?: string\n locale?: string\n prompt?: string\n systemPrompt?: string\n}\n\nexport type ActionPrompt = {\n layout?: (options?: ActionPromptOptions) => string\n name: ActionMenuItems\n system: (options: ActionPromptOptions) => string\n}\n\nexport type SeedPromptOptions = {\n fieldLabel: string\n fieldSchemaPaths: Record<string, any>\n fieldType: string\n path: string\n}\n\nexport type SeedPromptData = Omit<\n TypedCollection[typeof PLUGIN_INSTRUCTIONS_TABLE],\n 'createdAt' | 'id' | 'updatedAt'\n>\n\nexport type SeedPromptResult =\n | {\n data?: SeedPromptData\n }\n | {\n data?: SeedPromptData\n prompt: string\n system: string\n }\n | false\n | undefined\n | void\n\nexport type SeedPromptFunction = (\n options: SeedPromptOptions,\n) => Promise<SeedPromptResult> | SeedPromptResult\n\nexport type ActionMenuEvents =\n | 'onCompose'\n | 'onExpand'\n | 'onProofread'\n | 'onRephrase'\n | 'onSettings'\n | 'onSimplify'\n | 'onSummarize'\n | 'onTone'\n | 'onTranslate'\n\nexport type UseMenuEvents = {\n [key in ActionMenuEvents]?: (data?: unknown) => void\n}\n\nexport type UseMenuOptions = {\n isConfigAllowed: boolean\n}\n\nexport type BaseItemProps<T = any> = {\n children?: React.ReactNode\n disabled?: boolean\n hideIcon?: boolean\n isActive?: boolean\n isMenu?: boolean\n onClick: (data?: unknown) => void\n onMouseEnter?: MouseEventHandler<T> | undefined\n onMouseLeave?: MouseEventHandler<T> | undefined\n style?: CSSProperties | undefined\n title?: string\n}\n\nexport type ImageReference = {\n data: Blob\n name: string\n size: number\n type: string\n url: string\n}\n\nexport type GenerateImageParams = {\n images?: ImageReference[]\n size?: ImageGenerateParams['size']\n style?: ImageGenerateParams['style']\n version?: ImageGenerateParams['model']\n}\n\nexport type SerializedPromptField = {\n collections?: CollectionSlug[]\n name: string\n}\n\nexport type PromptFieldGetterContext = {\n collection: CollectionSlug\n type: string\n}\n\nexport type PromptField = {\n // If not provided, the value will be returned from the data object as-is\n getter?: (data: object, ctx: PromptFieldGetterContext) => Promise<string> | string\n} & SerializedPromptField\n\nexport interface BeforeGenerateArgs<T = any> {\n doc: T\n field: Field\n headers: Record<string, string>\n instructions: Record<string, unknown> // The instruction document\n messages?: ModelMessage[]\n payload: PayloadRequest['payload']\n prompt: string\n req: PayloadRequest\n system: string\n}\n\nexport type BeforeGenerateResult =\n | {\n messages?: ModelMessage[]\n prompt?: string\n system?: string\n }\n | void\n\nexport type BeforeGenerateHook<T = any> = (\n args: BeforeGenerateArgs<T>,\n) => BeforeGenerateResult | Promise<BeforeGenerateResult>\n\nexport interface AfterGenerateArgs<T = any> {\n doc: T\n field: Field\n headers: Record<string, string>\n instructions: Record<string, unknown>\n payload: PayloadRequest['payload']\n req: PayloadRequest\n result: GenerateObjectResult<any> | MediaResult | string // depends on context\n}\n\nexport type AfterGenerateHook<T = any> = (args: AfterGenerateArgs<T>) => Promise<void> | void\n\n// Add to PluginConfig or a new interface if accessed via custom.ai\nexport interface AIFieldConfig {\n afterGenerate?: AfterGenerateHook[]\n beforeGenerate?: BeforeGenerateHook[]\n [key: string]: unknown\n}\n"],"names":[],"mappings":"AA+QA,mEAAmE;AACnE,WAIC"}
|
|
@@ -134,13 +134,30 @@ export const Compose = ({ descriptionProps, forceVisible, instructionId, isConfi
|
|
|
134
134
|
path: pathFromContext
|
|
135
135
|
});
|
|
136
136
|
const setIfValueIsLexicalState = useCallback((val)=>{
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
// Prevent setting incomplete states during streaming
|
|
138
|
+
if (!val || typeof val !== 'object' || !('root' in val) || !lexicalEditor) {
|
|
139
|
+
return;
|
|
140
140
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
// Validate that the state is complete before setting
|
|
142
|
+
// Check for common incomplete streaming states
|
|
143
|
+
if (!val.root || typeof val.root !== 'object' || Object.keys(val.root).length === 0) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (val.root.type !== 'root') {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (!val.root.children || !Array.isArray(val.root.children) || val.root.children.length === 0) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
// Check for invalid child types (common streaming issue)
|
|
153
|
+
const hasInvalidChildren = val.root.children.some((child)=>!child || !child.type || child.type === 'undefined' || child.type === '');
|
|
154
|
+
if (hasInvalidChildren) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// State looks valid, proceed
|
|
158
|
+
setSafeLexicalState(JSON.stringify(val), lexicalEditor);
|
|
159
|
+
// DO NOT PROVIDE lexicalEditor as a dependency, it freaks out and does not update the editor after first undo/redo - revisit
|
|
160
|
+
}, []);
|
|
144
161
|
const popupRender = useCallback(({ close })=>{
|
|
145
162
|
return /*#__PURE__*/ _jsx(Menu, {
|
|
146
163
|
isLoading: isProcessing || isLoading,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/ui/Compose/Compose.tsx"],"sourcesContent":["'use client'\n\nimport type { ClientField } from 'payload'\nimport type { FC } from 'react'\n\nimport { useEditorConfigContext } from '@payloadcms/richtext-lexical/client'\nimport { Popup, useField } from '@payloadcms/ui'\nimport React, { useCallback, useMemo, useState } from 'react'\n\nimport { PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js'\nimport { useInstructions } from '../../providers/InstructionsProvider/useInstructions.js'\nimport { setSafeLexicalState } from '../../utilities/setSafeLexicalState.js'\nimport { PluginIcon } from '../Icons/Icons.js'\nimport styles from './compose.module.css'\nimport { useMenu } from './hooks/menu/useMenu.js'\nimport { useActiveFieldTracking } from './hooks/useActiveFieldTracking.js'\nimport { useGenerate } from './hooks/useGenerate.js'\nimport { UndoRedoActions } from './UndoRedoActions.js'\n\nexport type ComposeProps = {\n descriptionProps?: {\n field: ClientField\n path: string\n schemaPath: string\n }\n forceVisible?: boolean\n instructionId: string\n isConfigAllowed: boolean\n}\n\nexport const Compose: FC<ComposeProps> = ({ descriptionProps, forceVisible, instructionId, isConfigAllowed }) => {\n const pathFromContext = descriptionProps?.path\n const { editor: lexicalEditor } = useEditorConfigContext()\n \n // Get global openDrawer from context\n const { openDrawer } = useInstructions()\n\n // Initialize global active-field tracking\n useActiveFieldTracking()\n\n const [isProcessing, setIsProcessing] = useState<boolean>(false)\n const { generate, isJobActive, isLoading, jobProgress, jobStatus, stop } = useGenerate({ instructionId })\n\n // Memoize menu event handlers to prevent recreation on every render\n const onCompose = useCallback(() => {\n console.log('Composing...')\n setIsProcessing(true)\n generate({\n action: 'Compose',\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const onExpand = useCallback(() => {\n console.log('Expanding...')\n generate({\n action: 'Expand',\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const onProofread = useCallback(() => {\n console.log('Proofreading...')\n generate({\n action: 'Proofread',\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const onRephrase = useCallback(() => {\n console.log('Rephrasing...')\n generate({\n action: 'Rephrase',\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const onSimplify = useCallback(() => {\n console.log('Simplifying...')\n generate({\n action: 'Simplify',\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const onSummarize = useCallback(() => {\n console.log('Summarizing...')\n generate({\n action: 'Summarize',\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const onTranslate = useCallback((data: unknown) => {\n console.log('Translating...')\n generate({\n action: 'Translate',\n params: data,\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const handleOpenSettings = useCallback(() => {\n if (isConfigAllowed) {\n openDrawer(instructionId)\n }\n }, [isConfigAllowed, openDrawer, instructionId])\n\n const { ActiveComponent, Menu } = useMenu(\n {\n onCompose,\n onExpand,\n onProofread,\n onRephrase,\n onSettings: isConfigAllowed ? handleOpenSettings : undefined,\n onSimplify,\n onSummarize,\n onTranslate,\n },\n {\n isConfigAllowed,\n },\n )\n\n const { setValue } = useField<string>({\n path: pathFromContext,\n })\n\n const setIfValueIsLexicalState = useCallback(\n (val: any) => {\n if (val && typeof val === 'object' && 'root' in val && lexicalEditor) {\n // Pass the object directly to our safe setter which handles validation\n setSafeLexicalState(val, lexicalEditor)\n }\n },\n [lexicalEditor],\n )\n\n const popupRender = useCallback(\n ({ close }: { close: () => void }) => {\n return <Menu isLoading={isProcessing || isLoading} onClose={close} />\n },\n [isProcessing, isLoading, Menu],\n )\n\n // Combine loading states to reduce re-renders\n const isAnyLoading = isProcessing || isLoading || isJobActive\n\n const memoizedPopup = useMemo(() => {\n return (\n <Popup\n button={<PluginIcon isLoading={isAnyLoading} />}\n render={popupRender}\n verticalAlign=\"bottom\"\n />\n )\n }, [popupRender, isAnyLoading])\n\n return (\n <label\n className={`payloadai-compose__actions ${styles.actions} ${forceVisible ? styles.actionsVisible : ''}`}\n onClick={(e) => e.preventDefault()}\n role=\"presentation\"\n >\n {memoizedPopup}\n <ActiveComponent\n isLoading={isProcessing || isLoading || isJobActive}\n loadingLabel={isJobActive ? (jobStatus === 'running' ? `Video ${Math.max(0, Math.min(100, Math.round(jobProgress ?? 0)))}%` : (jobStatus || 'Queued')) : undefined}\n stop={stop}\n />\n <UndoRedoActions\n onChange={(val) => {\n setValue(val)\n setIfValueIsLexicalState(val)\n }}\n />\n </label>\n )\n}\n"],"names":["useEditorConfigContext","Popup","useField","React","useCallback","useMemo","useState","useInstructions","setSafeLexicalState","PluginIcon","styles","useMenu","useActiveFieldTracking","useGenerate","UndoRedoActions","Compose","descriptionProps","forceVisible","instructionId","isConfigAllowed","pathFromContext","path","editor","lexicalEditor","openDrawer","isProcessing","setIsProcessing","generate","isJobActive","isLoading","jobProgress","jobStatus","stop","onCompose","console","log","action","catch","reason","error","finally","onExpand","onProofread","onRephrase","onSimplify","onSummarize","onTranslate","data","params","handleOpenSettings","ActiveComponent","Menu","onSettings","undefined","setValue","setIfValueIsLexicalState","val","popupRender","close","onClose","isAnyLoading","memoizedPopup","button","render","verticalAlign","label","className","actions","actionsVisible","onClick","e","preventDefault","role","loadingLabel","Math","max","min","round","onChange"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/Compose/Compose.tsx"],"sourcesContent":["'use client'\n\nimport type { ClientField } from 'payload'\nimport type { FC } from 'react'\n\nimport { useEditorConfigContext } from '@payloadcms/richtext-lexical/client'\nimport { Popup, useField } from '@payloadcms/ui'\nimport React, { useCallback, useMemo, useState } from 'react'\n\nimport { PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js'\nimport { useInstructions } from '../../providers/InstructionsProvider/useInstructions.js'\nimport { setSafeLexicalState } from '../../utilities/setSafeLexicalState.js'\nimport { PluginIcon } from '../Icons/Icons.js'\nimport styles from './compose.module.css'\nimport { useMenu } from './hooks/menu/useMenu.js'\nimport { useActiveFieldTracking } from './hooks/useActiveFieldTracking.js'\nimport { useGenerate } from './hooks/useGenerate.js'\nimport { UndoRedoActions } from './UndoRedoActions.js'\n\nexport type ComposeProps = {\n descriptionProps?: {\n field: ClientField\n path: string\n schemaPath: string\n }\n forceVisible?: boolean\n instructionId: string\n isConfigAllowed: boolean\n}\n\nexport const Compose: FC<ComposeProps> = ({ descriptionProps, forceVisible, instructionId, isConfigAllowed }) => {\n const pathFromContext = descriptionProps?.path\n const { editor: lexicalEditor } = useEditorConfigContext()\n \n // Get global openDrawer from context\n const { openDrawer } = useInstructions()\n\n // Initialize global active-field tracking\n useActiveFieldTracking()\n\n const [isProcessing, setIsProcessing] = useState<boolean>(false)\n const { generate, isJobActive, isLoading, jobProgress, jobStatus, stop } = useGenerate({ instructionId })\n\n // Memoize menu event handlers to prevent recreation on every render\n const onCompose = useCallback(() => {\n console.log('Composing...')\n setIsProcessing(true)\n generate({\n action: 'Compose',\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const onExpand = useCallback(() => {\n console.log('Expanding...')\n generate({\n action: 'Expand',\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const onProofread = useCallback(() => {\n console.log('Proofreading...')\n generate({\n action: 'Proofread',\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const onRephrase = useCallback(() => {\n console.log('Rephrasing...')\n generate({\n action: 'Rephrase',\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const onSimplify = useCallback(() => {\n console.log('Simplifying...')\n generate({\n action: 'Simplify',\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const onSummarize = useCallback(() => {\n console.log('Summarizing...')\n generate({\n action: 'Summarize',\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const onTranslate = useCallback((data: unknown) => {\n console.log('Translating...')\n generate({\n action: 'Translate',\n params: data,\n })\n .catch((reason) => {\n console.error('Compose : ', reason)\n })\n .finally(() => {\n setIsProcessing(false)\n })\n }, [generate])\n\n const handleOpenSettings = useCallback(() => {\n if (isConfigAllowed) {\n openDrawer(instructionId)\n }\n }, [isConfigAllowed, openDrawer, instructionId])\n\n const { ActiveComponent, Menu } = useMenu(\n {\n onCompose,\n onExpand,\n onProofread,\n onRephrase,\n onSettings: isConfigAllowed ? handleOpenSettings : undefined,\n onSimplify,\n onSummarize,\n onTranslate,\n },\n {\n isConfigAllowed,\n },\n )\n\n const { setValue } = useField<string>({\n path: pathFromContext,\n })\n\n const setIfValueIsLexicalState = useCallback((val: any) => {\n // Prevent setting incomplete states during streaming\n if (!val || typeof val !== 'object' || !('root' in val) || !lexicalEditor) {\n return\n }\n\n // Validate that the state is complete before setting\n // Check for common incomplete streaming states\n if (!val.root || typeof val.root !== 'object' || Object.keys(val.root).length === 0) {\n return\n }\n\n if (val.root.type !== 'root') {\n return\n }\n\n if (!val.root.children || !Array.isArray(val.root.children) || val.root.children.length === 0) {\n return\n }\n\n // Check for invalid child types (common streaming issue)\n const hasInvalidChildren = val.root.children.some(\n (child: any) => !child || !child.type || child.type === 'undefined' || child.type === '',\n )\n\n if (hasInvalidChildren) {\n return\n }\n\n // State looks valid, proceed\n setSafeLexicalState(JSON.stringify(val), lexicalEditor)\n\n // DO NOT PROVIDE lexicalEditor as a dependency, it freaks out and does not update the editor after first undo/redo - revisit\n }, [])\n\n const popupRender = useCallback(\n ({ close }: { close: () => void }) => {\n return <Menu isLoading={isProcessing || isLoading} onClose={close} />\n },\n [isProcessing, isLoading, Menu],\n )\n\n // Combine loading states to reduce re-renders\n const isAnyLoading = isProcessing || isLoading || isJobActive\n\n const memoizedPopup = useMemo(() => {\n return (\n <Popup\n button={<PluginIcon isLoading={isAnyLoading} />}\n render={popupRender}\n verticalAlign=\"bottom\"\n />\n )\n }, [popupRender, isAnyLoading])\n\n return (\n <label\n className={`payloadai-compose__actions ${styles.actions} ${forceVisible ? styles.actionsVisible : ''}`}\n onClick={(e) => e.preventDefault()}\n role=\"presentation\"\n >\n {memoizedPopup}\n <ActiveComponent\n isLoading={isProcessing || isLoading || isJobActive}\n loadingLabel={isJobActive ? (jobStatus === 'running' ? `Video ${Math.max(0, Math.min(100, Math.round(jobProgress ?? 0)))}%` : (jobStatus || 'Queued')) : undefined}\n stop={stop}\n />\n <UndoRedoActions\n onChange={(val) => {\n setValue(val)\n setIfValueIsLexicalState(val)\n }}\n />\n </label>\n )\n}\n"],"names":["useEditorConfigContext","Popup","useField","React","useCallback","useMemo","useState","useInstructions","setSafeLexicalState","PluginIcon","styles","useMenu","useActiveFieldTracking","useGenerate","UndoRedoActions","Compose","descriptionProps","forceVisible","instructionId","isConfigAllowed","pathFromContext","path","editor","lexicalEditor","openDrawer","isProcessing","setIsProcessing","generate","isJobActive","isLoading","jobProgress","jobStatus","stop","onCompose","console","log","action","catch","reason","error","finally","onExpand","onProofread","onRephrase","onSimplify","onSummarize","onTranslate","data","params","handleOpenSettings","ActiveComponent","Menu","onSettings","undefined","setValue","setIfValueIsLexicalState","val","root","Object","keys","length","type","children","Array","isArray","hasInvalidChildren","some","child","JSON","stringify","popupRender","close","onClose","isAnyLoading","memoizedPopup","button","render","verticalAlign","label","className","actions","actionsVisible","onClick","e","preventDefault","role","loadingLabel","Math","max","min","round","onChange"],"mappings":"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"}
|
|
@@ -127,11 +127,30 @@ export const Compose = ({ descriptionProps, forceVisible, instructionId, isConfi
|
|
|
127
127
|
path: pathFromContext,
|
|
128
128
|
});
|
|
129
129
|
const setIfValueIsLexicalState = useCallback((val) => {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
130
|
+
// Prevent setting incomplete states during streaming
|
|
131
|
+
if (!val || typeof val !== 'object' || !('root' in val) || !lexicalEditor) {
|
|
132
|
+
return;
|
|
133
133
|
}
|
|
134
|
-
|
|
134
|
+
// Validate that the state is complete before setting
|
|
135
|
+
// Check for common incomplete streaming states
|
|
136
|
+
if (!val.root || typeof val.root !== 'object' || Object.keys(val.root).length === 0) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (val.root.type !== 'root') {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (!val.root.children || !Array.isArray(val.root.children) || val.root.children.length === 0) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
// Check for invalid child types (common streaming issue)
|
|
146
|
+
const hasInvalidChildren = val.root.children.some((child) => !child || !child.type || child.type === 'undefined' || child.type === '');
|
|
147
|
+
if (hasInvalidChildren) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// State looks valid, proceed
|
|
151
|
+
setSafeLexicalState(JSON.stringify(val), lexicalEditor);
|
|
152
|
+
// DO NOT PROVIDE lexicalEditor as a dependency, it freaks out and does not update the editor after first undo/redo - revisit
|
|
153
|
+
}, []);
|
|
135
154
|
const popupRender = useCallback(({ close }) => {
|
|
136
155
|
return <Menu isLoading={isProcessing || isLoading} onClose={close}/>;
|
|
137
156
|
}, [isProcessing, isLoading, Menu]);
|
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
import { experimental_useObject as useObject } from '@ai-sdk/react';
|
|
2
2
|
import { useEditorConfigContext } from '@payloadcms/richtext-lexical/client';
|
|
3
|
-
import { toast,
|
|
3
|
+
import { toast, useDocumentInfo, useField, useForm, useLocale } from '@payloadcms/ui';
|
|
4
4
|
import { jsonSchema } from 'ai';
|
|
5
|
-
import { useCallback,
|
|
6
|
-
import { PLUGIN_API_ENDPOINT_GENERATE
|
|
5
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
6
|
+
import { PLUGIN_API_ENDPOINT_GENERATE } from '../../../defaults.js';
|
|
7
7
|
import { useFieldProps } from '../../../providers/FieldProvider/useFieldProps.js';
|
|
8
|
-
import { editorSchemaValidator } from '../../../utilities/editorSchemaValidator.js';
|
|
9
|
-
import { fieldToJsonSchema } from '../../../utilities/fieldToJsonSchema.js';
|
|
10
8
|
import { setSafeLexicalState } from '../../../utilities/setSafeLexicalState.js';
|
|
11
9
|
import { useGenerateUpload } from './useGenerateUpload.js';
|
|
12
10
|
import { useHistory } from './useHistory.js';
|
|
13
11
|
import { useStreamingUpdate } from './useStreamingUpdate.js';
|
|
14
12
|
export const useGenerate = ({ instructionId })=>{
|
|
13
|
+
// Create a ref to hold the current instructionId
|
|
15
14
|
const instructionIdRef = useRef(instructionId);
|
|
16
|
-
//
|
|
17
|
-
|
|
15
|
+
// Update the ref whenever instructionId changes
|
|
16
|
+
useEffect(()=>{
|
|
17
|
+
instructionIdRef.current = instructionId;
|
|
18
|
+
}, [
|
|
19
|
+
instructionId
|
|
20
|
+
]);
|
|
18
21
|
const { field, path: pathFromContext } = useFieldProps();
|
|
19
|
-
const
|
|
20
|
-
const { config } = useConfig();
|
|
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
|
|
22
|
+
const editorConfigContext = useEditorConfigContext();
|
|
26
23
|
const { setValue } = useField({
|
|
27
24
|
path: pathFromContext ?? ''
|
|
28
25
|
});
|
|
@@ -30,51 +27,6 @@ export const useGenerate = ({ instructionId })=>{
|
|
|
30
27
|
const { getData } = useForm();
|
|
31
28
|
const { id: documentId } = useDocumentInfo();
|
|
32
29
|
const localFromContext = useLocale();
|
|
33
|
-
// Editor Schema Setup
|
|
34
|
-
const collection = collections.find((collection)=>collection.slug === PLUGIN_INSTRUCTIONS_TABLE);
|
|
35
|
-
const { custom: { [PLUGIN_NAME]: { editorConfig = {} } = {} } = {} } = collection?.admin ?? {};
|
|
36
|
-
const { schema: editorSchema = {} } = editorConfig;
|
|
37
|
-
const memoizedValidator = useMemo(()=>{
|
|
38
|
-
return editorSchemaValidator(editorSchema);
|
|
39
|
-
}, [
|
|
40
|
-
editorSchema
|
|
41
|
-
]);
|
|
42
|
-
const memoizedSchema = useMemo(()=>jsonSchema(editorSchema, {
|
|
43
|
-
validate: (value)=>{
|
|
44
|
-
const isValid = memoizedValidator(value);
|
|
45
|
-
if (isValid) {
|
|
46
|
-
return {
|
|
47
|
-
success: true,
|
|
48
|
-
value
|
|
49
|
-
};
|
|
50
|
-
} else {
|
|
51
|
-
return {
|
|
52
|
-
error: new Error('Invalid schema'),
|
|
53
|
-
success: false
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}), [
|
|
58
|
-
memoizedValidator
|
|
59
|
-
]);
|
|
60
|
-
// Active JSON schema for useObject based on field type
|
|
61
|
-
const activeSchema = useMemo(()=>{
|
|
62
|
-
const f = field;
|
|
63
|
-
const fieldType = f?.type;
|
|
64
|
-
if (fieldType === 'richText') {
|
|
65
|
-
return memoizedSchema;
|
|
66
|
-
}
|
|
67
|
-
if (f && f.name && fieldType) {
|
|
68
|
-
const schemaJson = fieldToJsonSchema(f);
|
|
69
|
-
if (schemaJson && Object.keys(schemaJson).length > 0) {
|
|
70
|
-
return jsonSchema(schemaJson);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return undefined;
|
|
74
|
-
}, [
|
|
75
|
-
field,
|
|
76
|
-
memoizedSchema
|
|
77
|
-
]);
|
|
78
30
|
const { isLoading: loadingObject, object, stop: objectStop, submit } = useObject({
|
|
79
31
|
api: `/api${PLUGIN_API_ENDPOINT_GENERATE}`,
|
|
80
32
|
onError: (error)=>{
|
|
@@ -84,16 +36,9 @@ export const useGenerate = ({ instructionId })=>{
|
|
|
84
36
|
onFinish: (result)=>{
|
|
85
37
|
if (result.object && field) {
|
|
86
38
|
if (field.type === 'richText') {
|
|
87
|
-
// Set state directly to editor first for immediate feedback
|
|
88
|
-
setSafeLexicalState(result.object, editor);
|
|
89
|
-
// Update history
|
|
90
39
|
setHistory(result.object);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
setTimeout(()=>{
|
|
94
|
-
setValue(result.object);
|
|
95
|
-
}, 150);
|
|
96
|
-
} else if ('name' in field) {
|
|
40
|
+
setSafeLexicalState(result.object, editor);
|
|
41
|
+
} else if ('name' in field && result.object[field.name]) {
|
|
97
42
|
setHistory(result.object[field.name]);
|
|
98
43
|
setValue(result.object[field.name]);
|
|
99
44
|
}
|
|
@@ -101,9 +46,14 @@ export const useGenerate = ({ instructionId })=>{
|
|
|
101
46
|
console.log('onFinish: result, field ', result, field);
|
|
102
47
|
}
|
|
103
48
|
},
|
|
104
|
-
schema:
|
|
49
|
+
schema: jsonSchema({
|
|
50
|
+
type: 'object',
|
|
51
|
+
additionalProperties: true,
|
|
52
|
+
properties: {}
|
|
53
|
+
})
|
|
105
54
|
});
|
|
106
|
-
|
|
55
|
+
const { editor } = editorConfigContext;
|
|
56
|
+
// Hook: Handle high-frequency streaming updates
|
|
107
57
|
useStreamingUpdate({
|
|
108
58
|
editor,
|
|
109
59
|
isLoading: loadingObject,
|
|
@@ -111,8 +61,7 @@ export const useGenerate = ({ instructionId })=>{
|
|
|
111
61
|
});
|
|
112
62
|
// Hook 2: Handle Upload generation and polling
|
|
113
63
|
const { generateUpload, isJobActive, jobProgress, jobStatus } = useGenerateUpload({
|
|
114
|
-
instructionIdRef
|
|
115
|
-
setValue
|
|
64
|
+
instructionIdRef
|
|
116
65
|
});
|
|
117
66
|
const streamObject = useCallback(({ action = 'Compose', params })=>{
|
|
118
67
|
const doc = getData();
|
|
@@ -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, 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":"AAAA,SAASA,0BAA0BC,SAAS,QAAQ,gBAAe;AACnE,SAASC,sBAAsB,QAAQ,sCAAqC;AAC5E,SAASC,KAAK,EAAEC,SAAS,EAAEC,eAAe,EAAEC,QAAQ,EAAEC,OAAO,EAAEC,SAAS,QAAQ,iBAAgB;AAChG,SAASC,UAAU,QAAQ,KAAI;AAC/B,SAASC,WAAW,EAAEC,OAAO,EAAEC,MAAM,QAAQ,QAAO;AAIpD,SAASC,4BAA4B,EAAEC,yBAAyB,EAAEC,WAAW,QAAQ,uBAAsB;AAC3G,SAASC,aAAa,QAAQ,oDAAmD;AACjF,SAASC,qBAAqB,QAAQ,8CAA6C;AACnF,SAASC,iBAAiB,QAAQ,0CAAyC;AAC3E,SAASC,mBAAmB,QAAQ,4CAA2C;AAC/E,SAASC,iBAAiB,QAAQ,yBAAwB;AAC1D,SAASC,UAAU,QAAQ,kBAAiB;AAC5C,SAASC,kBAAkB,QAAQ,0BAAyB;AAI5D,OAAO,MAAMC,cAAc,CAAC,EAAEC,aAAa,EAA6B;IACtE,MAAMC,mBAAmBb,OAAOY;IAChC,WAAW;IACXC,iBAAiBC,OAAO,GAAGF;IAE3B,MAAM,EAAEG,KAAK,EAAEC,MAAMC,eAAe,EAAE,GAAGb;IACzC,MAAM,EAAEc,MAAM,EAAE,GAAG5B;IAEnB,MAAM,EAAE6B,MAAM,EAAE,GAAG3B;IACnB,MAAM,EAAE4B,WAAW,EAAE,GAAGD;IAExB,wGAAwG;IACxG,oFAAoF;IACpF,uCAAuC;IAEvC,2GAA2G;IAC3G,MAAM,EAAEE,QAAQ,EAAE,GAAG3B,SAAc;QACjCsB,MAAMC,mBAAmB;IAC3B;IAEA,MAAM,EAAEK,KAAKC,UAAU,EAAE,GAAGd;IAC5B,MAAM,EAAEe,OAAO,EAAE,GAAG7B;IACpB,MAAM,EAAE8B,IAAIC,UAAU,EAAE,GAAGjC;IAC3B,MAAMkC,mBAAmB/B;IAEzB,sBAAsB;IACtB,MAAMgC,aAAaR,YAAYS,IAAI,CAAC,CAACD,aAAeA,WAAWE,IAAI,KAAK5B;IACxE,MAAM,EAAE6B,QAAQ,EAAE,CAAC5B,YAAY,EAAE,EAAE6B,eAAe,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAGJ,YAAYK,SAAS,CAAC;IAC7F,MAAM,EAAEC,QAAQC,eAAe,CAAC,CAAC,EAAE,GAAGH;IAEtC,MAAMI,oBAAoBrC,QAAQ;QAChC,OAAOM,sBAAsB8B;IAC/B,GAAG;QAACA;KAAa;IAEjB,MAAME,iBAAiBtC,QACrB,IACEF,WAAWsC,cAAc;YACvBG,UAAU,CAACC;gBACT,MAAMC,UAAUJ,kBAAkBG;gBAElC,IAAIC,SAAS;oBACX,OAAO;wBACLC,SAAS;wBACTF;oBACF;gBACF,OAAO;oBACL,OAAO;wBACLG,OAAO,IAAIC,MAAM;wBACjBF,SAAS;oBACX;gBACF;YACF;QACF,IACF;QAACL;KAAkB;IAGrB,uDAAuD;IACvD,MAAMQ,eAAe7C,QAAQ;QAC3B,MAAM8C,IAAI9B;QACV,MAAM+B,YAAYD,GAAGE;QACrB,IAAID,cAAc,YAAY;YAC5B,OAAOT;QACT;QACA,IAAIQ,KAAKA,EAAEG,IAAI,IAAIF,WAAW;YAC5B,MAAMG,aAAa3C,kBAAkBuC;YACrC,IAAII,cAAcC,OAAOC,IAAI,CAACF,YAAYG,MAAM,GAAG,GAAG;gBACpD,OAAOvD,WAAWoD;YACpB;QACF;QACA,OAAOI;IACT,GAAG;QAACtC;QAAOsB;KAAe;IAE1B,MAAM,EACJiB,WAAWC,aAAa,EACxBC,MAAM,EACNC,MAAMC,UAAU,EAChBC,MAAM,EACP,GAAGtE,UAAU;QACZuE,KAAK,CAAC,IAAI,EAAE3D,6BAA6B,CAAC;QAC1C4D,SAAS,CAACnB;YACRnD,MAAMmD,KAAK,CAAC,CAAC,oBAAoB,EAAEA,MAAMoB,OAAO,CAAC,CAAC;YAClDC,QAAQrB,KAAK,CAAC,4BAA4BA;QAC5C;QACAsB,UAAU,CAACC;YACT,IAAIA,OAAOT,MAAM,IAAIzC,OAAO;gBAC1B,IAAIA,MAAMgC,IAAI,KAAK,YAAY;oBAC7B,4DAA4D;oBAC5DxC,oBAAoB0D,OAAOT,MAAM,EAAEtC;oBAEnC,iBAAiB;oBACjBK,WAAW0C,OAAOT,MAAM;oBAExB,+DAA+D;oBAC/D,4EAA4E;oBAC5EU,WAAW;wBACT7C,SAAS4C,OAAOT,MAAM;oBACxB,GAAG;gBACL,OAAO,IAAI,UAAUzC,OAAO;oBAC1BQ,WAAW0C,OAAOT,MAAM,CAACzC,MAAMiC,IAAI,CAAC;oBACpC3B,SAAS4C,OAAOT,MAAM,CAACzC,MAAMiC,IAAI,CAAC;gBACpC;YACF,OAAO;gBACLe,QAAQI,GAAG,CAAC,4BAA4BF,QAAQlD;YAClD;QACF;QACAmB,QAAQU;IACV;IAEA,kDAAkD;IAClDlC,mBAAmB;QACjBQ;QACAoC,WAAWC;QACXC;IACF;IAEA,+CAA+C;IAC/C,MAAM,EAAEY,cAAc,EAAEC,WAAW,EAAEC,WAAW,EAAEC,SAAS,EAAE,GAAG/D,kBAAkB;QAChFK;QACAQ;IACF;IAEA,MAAMmD,eAAe1E,YACnB,CAAC,EAAE2E,SAAS,SAAS,EAAEC,MAAM,EAAwB;QACnD,MAAMC,MAAMnD;QAEZ,MAAMoD,uBAAuB/D,iBAAiBC,OAAO;QAErD,MAAM+D,UAAU;YACdJ;YACAK,cAAcJ;YACd9D,eAAegE;QACjB;QAEAjB,OAAO;YACLoB,oBAAoBC,MAAMC,IAAI,CAAC/D,QAAQgE,QAAQ/B,UAAU,EAAE;YAC3DwB,KAAK;gBACH,GAAGA,GAAG;gBACNlD,IAAIC;YACN;YACAyD,QAAQxD,kBAAkByD;YAC1BP;QACF;IACF,GACA;QAAClD,kBAAkByD;QAAMvE;QAAkBa;QAAYF;QAASmC;QAAQzC;KAAO;IAGjF,MAAMmE,WAAWvF,YACf,OAAO+E;QACL,IAAI,AAAC9D,OAAegC,SAAS,UAAU;YACrC,OAAOqB;QACT;QACA,2FAA2F;QAC3F,OAAOI,aAAaK,WAAW;YAAEJ,QAAQ;QAAU;IACrD,GACA;QAACL;QAAgBI;QAAczD;KAAM;IAGvC,MAAM0C,OAAO3D,YAAY;QACvBiE,QAAQI,GAAG,CAAC;QACZT;IACF,GAAG;QAACA;KAAW;IAEf,OAAO;QACL2B;QACAhB;QACAf,WAAWC;QACXe;QACAC;QACAd;IACF;AACF,EAAC"}
|
|
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, useDocumentInfo, useField, useForm, useLocale } from '@payloadcms/ui'\nimport { jsonSchema } from 'ai'\nimport { useCallback, useEffect, useRef } from 'react'\n\nimport type { ActionMenuItems } from '../../../types.js'\n\nimport { PLUGIN_API_ENDPOINT_GENERATE } from '../../../defaults.js'\nimport { useFieldProps } from '../../../providers/FieldProvider/useFieldProps.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 // 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 const { setValue } = useField<any>({\n path: pathFromContext ?? '',\n })\n const { set: setHistory } = useHistory()\n const { getData } = useForm()\n const { id: documentId } = useDocumentInfo()\n const localFromContext = useLocale()\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 setSafeLexicalState(result.object, editor)\n } else if ('name' in field && result.object[field.name]) {\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: jsonSchema({\n type: 'object',\n additionalProperties: true,\n properties: {},\n }) as any,\n })\n\n const { editor } = editorConfigContext\n\n // Hook: 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 })\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","useDocumentInfo","useField","useForm","useLocale","jsonSchema","useCallback","useEffect","useRef","PLUGIN_API_ENDPOINT_GENERATE","useFieldProps","setSafeLexicalState","useGenerateUpload","useHistory","useStreamingUpdate","useGenerate","instructionId","instructionIdRef","current","field","path","pathFromContext","editorConfigContext","setValue","set","setHistory","getData","id","documentId","localFromContext","isLoading","loadingObject","object","stop","objectStop","submit","api","onError","error","message","console","onFinish","result","type","editor","name","log","schema","additionalProperties","properties","generateUpload","isJobActive","jobProgress","jobStatus","streamObject","action","params","doc","currentInstructionId","options","actionParams","allowedEditorNodes","Array","from","_nodes","keys","locale","code","generate"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
1
2
|
type UseGenerateUploadParams = {
|
|
2
|
-
instructionIdRef:
|
|
3
|
-
setValue: (value: any) => void;
|
|
3
|
+
instructionIdRef: RefObject<string>;
|
|
4
4
|
};
|
|
5
|
-
export declare const useGenerateUpload: ({ instructionIdRef
|
|
5
|
+
export declare const useGenerateUpload: ({ instructionIdRef }: UseGenerateUploadParams) => {
|
|
6
6
|
generateUpload: () => Promise<void | Response>;
|
|
7
7
|
isJobActive: boolean;
|
|
8
8
|
jobProgress: number;
|