@ai-stack/payloadcms 3.2.24 → 3.2.26

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.
@@ -43,7 +43,9 @@ const defaultAdminConfig = {
43
43
  group: 'Plugins',
44
44
  hidden: true
45
45
  };
46
- export const instructionsCollection = (pluginConfig)=>({
46
+ export const instructionsCollection = (pluginConfig)=>{
47
+ const isLocalized = pluginConfig._localization?.enabled && pluginConfig._localization.locales.length > 0;
48
+ return {
47
49
  labels: {
48
50
  plural: 'Compose Settings',
49
51
  singular: 'Compose Setting'
@@ -58,6 +60,9 @@ export const instructionsCollection = (pluginConfig)=>({
58
60
  ...defaultAdminConfig,
59
61
  ...pluginConfig.overrideInstructions?.admin
60
62
  },
63
+ ...isLocalized ? {
64
+ localization: true
65
+ } : {},
61
66
  fields: [
62
67
  {
63
68
  name: 'schema-path',
@@ -145,6 +150,10 @@ export const instructionsCollection = (pluginConfig)=>({
145
150
  {
146
151
  name: 'prompt',
147
152
  type: 'textarea',
153
+ // Make prompt localized if localization is enabled
154
+ ...isLocalized ? {
155
+ localized: true
156
+ } : {},
148
157
  admin: {
149
158
  components: {
150
159
  Field: '@ai-stack/payloadcms/fields#PromptEditorField'
@@ -192,6 +201,9 @@ export const instructionsCollection = (pluginConfig)=>({
192
201
  {
193
202
  name: 'system',
194
203
  type: 'textarea',
204
+ ...isLocalized ? {
205
+ localized: true
206
+ } : {},
195
207
  defaultValue: `INSTRUCTIONS:
196
208
  You are a highly skilled and professional blog writer,
197
209
  renowned for crafting engaging and well-organized articles.
@@ -216,13 +228,11 @@ informative and accurate but also captivating and beautifully structured.`,
216
228
  * - User can add their own layout to collections and use it later for generate specific rich text
217
229
  * - User can select previously added layout
218
230
  * - IMP: Remove layout from default, this seem to affect other functions like rephrase etc.
219
- */ /** TODO:
220
- * - Layouts can be saved in as an array
221
- * - User can add their own layout to collections and use it later for generate specific rich text
222
- * - User can select previously added layout
223
- * - IMP: Remove layout from default, this seem to affect other functions like rephrase etc.
224
231
  */ name: 'layout',
225
232
  type: 'textarea',
233
+ ...isLocalized ? {
234
+ localized: true
235
+ } : {},
226
236
  admin: {
227
237
  condition: (_, current)=>{
228
238
  return current['field-type'] === 'richText';
@@ -245,6 +255,7 @@ informative and accurate but also captivating and beautifully structured.`,
245
255
  },
246
256
  ...groupSettings(pluginConfig)
247
257
  ]
248
- });
258
+ };
259
+ };
249
260
 
250
261
  //# sourceMappingURL=Instructions.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/collections/Instructions.ts"],"sourcesContent":["import type { CollectionConfig, GroupField } from 'payload'\nimport type { PluginConfig } from 'src/types.js'\n\nimport { PLUGIN_INSTRUCTIONS_TABLE } from '../defaults.js'\nimport { getGenerationModels } from '../utilities/getGenerationModels.js'\n\nconst groupSettings = (pluginConfig: PluginConfig) =>\n (getGenerationModels(pluginConfig) ?? []).reduce((fields, model) => {\n if (model.settings) {\n fields.push(model.settings)\n }\n return fields\n }, [] as GroupField[])\n\nconst modelOptions = (pluginConfig: PluginConfig) =>\n (getGenerationModels(pluginConfig) ?? []).map((model) => {\n return {\n fields: model.fields,\n label: model.name,\n value: model.id,\n }\n })\n\nconst defaultAccessConfig = {\n create: ({ req }: { req: { user?: any } }) => {\n if (!req.user) {\n return false\n }\n return true\n },\n delete: ({ req }: { req: { user?: any } }) => {\n if (!req.user) {\n return false\n }\n return true\n },\n read: ({ req }: { req: { user?: any } }) => {\n if (!req.user) {\n return false\n }\n return true\n },\n update: ({ req }: { req: { user?: any } }) => {\n if (!req.user) {\n return false\n }\n return true\n },\n}\n\nconst defaultAdminConfig = {\n group: 'Plugins',\n hidden: true,\n}\n\nexport const instructionsCollection = (pluginConfig: PluginConfig) =>\n <CollectionConfig>{\n labels: {\n plural: 'Compose Settings',\n singular: 'Compose Setting',\n },\n ...pluginConfig.overrideInstructions,\n slug: PLUGIN_INSTRUCTIONS_TABLE,\n access: {\n ...defaultAccessConfig,\n ...pluginConfig.overrideInstructions?.access,\n },\n admin: {\n ...defaultAdminConfig,\n ...pluginConfig.overrideInstructions?.admin,\n },\n fields: [\n {\n name: 'schema-path',\n type: 'text',\n admin: {\n description: \"Please don't change this unless you're sure of what you're doing\",\n },\n unique: true,\n },\n {\n name: 'field-type',\n type: 'select',\n admin: {\n description: \"Please don't change this unless you're sure of what you're doing\",\n },\n defaultValue: 'text',\n label: 'Field type',\n options: [\n {\n label: 'text',\n value: 'text',\n },\n {\n label: 'textarea',\n value: 'textarea',\n },\n {\n label: 'upload',\n value: 'upload',\n },\n {\n label: 'richText',\n value: 'richText',\n },\n ],\n },\n {\n name: 'relation-to',\n type: 'text',\n admin: {\n condition: (_, current) => {\n return current['field-type'] === 'upload'\n },\n },\n label: 'Relation to',\n },\n {\n name: 'model-id',\n type: 'select',\n admin: {\n components: {\n Field: {\n clientProps: {\n filterByField: 'field-type',\n options: modelOptions(pluginConfig),\n },\n path: '@ai-stack/payloadcms/fields#SelectField',\n },\n },\n },\n label: 'Model',\n options: modelOptions(pluginConfig).map((option) => {\n return {\n label: option.label,\n value: option.value,\n }\n }),\n },\n {\n name: 'disabled',\n type: 'checkbox',\n admin: {\n description: 'Please reload your collection after applying the changes',\n },\n defaultValue: false,\n label: 'Hide Compose button for this field',\n },\n {\n id: 'ai-prompts-tabs',\n type: 'tabs',\n tabs: [\n {\n description:\n 'Define dynamic templates using {{ fieldName }}. Type { to see available field suggestions.',\n fields: [\n {\n name: 'prompt',\n type: 'textarea',\n admin: {\n components: {\n Field: '@ai-stack/payloadcms/fields#PromptEditorField',\n },\n description: \"Click 'Compose' to run this custom prompt and generate content\",\n },\n label: '',\n },\n ],\n label: 'Prompt',\n },\n {\n admin: {\n condition: (_, current) => {\n return current['field-type'] === 'upload' && current['model-id'] === 'gpt-image-1'\n },\n },\n description:\n 'These images will be used to generate new visuals in a similar style, layout, or content. You can combine multiple references for more controlled results.',\n fields: [\n {\n name: 'images',\n type: 'array',\n fields: [\n {\n name: 'image',\n type: 'upload',\n admin: {\n description: 'Please make sure the image is publicly accessible.',\n },\n relationTo: pluginConfig.uploadCollectionSlug\n ? pluginConfig.uploadCollectionSlug\n : 'media',\n },\n ],\n },\n ],\n label: 'Sample Images',\n },\n {\n admin: {\n condition: (_, current) => {\n return current['field-type'] === 'richText'\n },\n },\n description: '',\n fields: [\n {\n name: 'system',\n type: 'textarea',\n defaultValue: `INSTRUCTIONS:\nYou are a highly skilled and professional blog writer,\nrenowned for crafting engaging and well-organized articles.\nWhen given a title, you meticulously create blogs that are not only\ninformative and accurate but also captivating and beautifully structured.`,\n label: '',\n },\n ],\n label: 'System prompt',\n },\n {\n admin: {\n condition: (_, current) => {\n return current['field-type'] === 'richText'\n },\n },\n description: '',\n fields: [\n {\n /** TODO:\n * - Layouts can be saved in as an array\n * - User can add their own layout to collections and use it later for generate specific rich text\n * - User can select previously added layout\n * - IMP: Remove layout from default, this seem to affect other functions like rephrase etc.\n */\n name: 'layout',\n type: 'textarea',\n admin: {\n condition: (_, current) => {\n return current['field-type'] === 'richText'\n },\n },\n defaultValue: `[paragraph] - Write a concise introduction (2-3 sentences) that outlines the main topic.\n[horizontalrule] - Insert a horizontal rule to separate the introduction from the main content.\n[list] - Create a list with 3-5 items. Each list item should contain:\n a. [heading] - A brief, descriptive heading (up to 5 words)\n b. [paragraph] - A short explanation or elaboration (1-2 sentences)\n[horizontalrule] - Insert another horizontal rule to separate the main content from the conclusion.\n[paragraph] - Compose a brief conclusion (2-3 sentences) summarizing the key points.\n[quote] - Include a relevant quote from a famous person, directly related to the topic. Format: \"Quote text.\" - Author Name`,\n label: '',\n },\n ],\n label: 'Layout',\n },\n ],\n },\n ...groupSettings(pluginConfig),\n ],\n }\n"],"names":["PLUGIN_INSTRUCTIONS_TABLE","getGenerationModels","groupSettings","pluginConfig","reduce","fields","model","settings","push","modelOptions","map","label","name","value","id","defaultAccessConfig","create","req","user","delete","read","update","defaultAdminConfig","group","hidden","instructionsCollection","labels","plural","singular","overrideInstructions","slug","access","admin","type","description","unique","defaultValue","options","condition","_","current","components","Field","clientProps","filterByField","path","option","tabs","relationTo","uploadCollectionSlug"],"mappings":"AAGA,SAASA,yBAAyB,QAAQ,iBAAgB;AAC1D,SAASC,mBAAmB,QAAQ,sCAAqC;AAEzE,MAAMC,gBAAgB,CAACC,eACrB,AAACF,CAAAA,oBAAoBE,iBAAiB,EAAE,AAAD,EAAGC,MAAM,CAAC,CAACC,QAAQC;QACxD,IAAIA,MAAMC,QAAQ,EAAE;YAClBF,OAAOG,IAAI,CAACF,MAAMC,QAAQ;QAC5B;QACA,OAAOF;IACT,GAAG,EAAE;AAEP,MAAMI,eAAe,CAACN,eACpB,AAACF,CAAAA,oBAAoBE,iBAAiB,EAAE,AAAD,EAAGO,GAAG,CAAC,CAACJ;QAC7C,OAAO;YACLD,QAAQC,MAAMD,MAAM;YACpBM,OAAOL,MAAMM,IAAI;YACjBC,OAAOP,MAAMQ,EAAE;QACjB;IACF;AAEF,MAAMC,sBAAsB;IAC1BC,QAAQ,CAAC,EAAEC,GAAG,EAA2B;QACvC,IAAI,CAACA,IAAIC,IAAI,EAAE;YACb,OAAO;QACT;QACA,OAAO;IACT;IACAC,QAAQ,CAAC,EAAEF,GAAG,EAA2B;QACvC,IAAI,CAACA,IAAIC,IAAI,EAAE;YACb,OAAO;QACT;QACA,OAAO;IACT;IACAE,MAAM,CAAC,EAAEH,GAAG,EAA2B;QACrC,IAAI,CAACA,IAAIC,IAAI,EAAE;YACb,OAAO;QACT;QACA,OAAO;IACT;IACAG,QAAQ,CAAC,EAAEJ,GAAG,EAA2B;QACvC,IAAI,CAACA,IAAIC,IAAI,EAAE;YACb,OAAO;QACT;QACA,OAAO;IACT;AACF;AAEA,MAAMI,qBAAqB;IACzBC,OAAO;IACPC,QAAQ;AACV;AAEA,OAAO,MAAMC,yBAAyB,CAACtB,eACnB,CAAA;QAChBuB,QAAQ;YACNC,QAAQ;YACRC,UAAU;QACZ;QACA,GAAGzB,aAAa0B,oBAAoB;QACpCC,MAAM9B;QACN+B,QAAQ;YACN,GAAGhB,mBAAmB;YACtB,GAAGZ,aAAa0B,oBAAoB,EAAEE,MAAM;QAC9C;QACAC,OAAO;YACL,GAAGV,kBAAkB;YACrB,GAAGnB,aAAa0B,oBAAoB,EAAEG,KAAK;QAC7C;QACA3B,QAAQ;YACN;gBACEO,MAAM;gBACNqB,MAAM;gBACND,OAAO;oBACLE,aAAa;gBACf;gBACAC,QAAQ;YACV;YACA;gBACEvB,MAAM;gBACNqB,MAAM;gBACND,OAAO;oBACLE,aAAa;gBACf;gBACAE,cAAc;gBACdzB,OAAO;gBACP0B,SAAS;oBACP;wBACE1B,OAAO;wBACPE,OAAO;oBACT;oBACA;wBACEF,OAAO;wBACPE,OAAO;oBACT;oBACA;wBACEF,OAAO;wBACPE,OAAO;oBACT;oBACA;wBACEF,OAAO;wBACPE,OAAO;oBACT;iBACD;YACH;YACA;gBACED,MAAM;gBACNqB,MAAM;gBACND,OAAO;oBACLM,WAAW,CAACC,GAAGC;wBACb,OAAOA,OAAO,CAAC,aAAa,KAAK;oBACnC;gBACF;gBACA7B,OAAO;YACT;YACA;gBACEC,MAAM;gBACNqB,MAAM;gBACND,OAAO;oBACLS,YAAY;wBACVC,OAAO;4BACLC,aAAa;gCACXC,eAAe;gCACfP,SAAS5B,aAAaN;4BACxB;4BACA0C,MAAM;wBACR;oBACF;gBACF;gBACAlC,OAAO;gBACP0B,SAAS5B,aAAaN,cAAcO,GAAG,CAAC,CAACoC;oBACvC,OAAO;wBACLnC,OAAOmC,OAAOnC,KAAK;wBACnBE,OAAOiC,OAAOjC,KAAK;oBACrB;gBACF;YACF;YACA;gBACED,MAAM;gBACNqB,MAAM;gBACND,OAAO;oBACLE,aAAa;gBACf;gBACAE,cAAc;gBACdzB,OAAO;YACT;YACA;gBACEG,IAAI;gBACJmB,MAAM;gBACNc,MAAM;oBACJ;wBACEb,aACE;wBACF7B,QAAQ;4BACN;gCACEO,MAAM;gCACNqB,MAAM;gCACND,OAAO;oCACLS,YAAY;wCACVC,OAAO;oCACT;oCACAR,aAAa;gCACf;gCACAvB,OAAO;4BACT;yBACD;wBACDA,OAAO;oBACT;oBACA;wBACEqB,OAAO;4BACLM,WAAW,CAACC,GAAGC;gCACb,OAAOA,OAAO,CAAC,aAAa,KAAK,YAAYA,OAAO,CAAC,WAAW,KAAK;4BACvE;wBACF;wBACAN,aACE;wBACF7B,QAAQ;4BACN;gCACEO,MAAM;gCACNqB,MAAM;gCACN5B,QAAQ;oCACN;wCACEO,MAAM;wCACNqB,MAAM;wCACND,OAAO;4CACLE,aAAa;wCACf;wCACAc,YAAY7C,aAAa8C,oBAAoB,GACzC9C,aAAa8C,oBAAoB,GACjC;oCACN;iCACD;4BACH;yBACD;wBACDtC,OAAO;oBACT;oBACA;wBACEqB,OAAO;4BACLM,WAAW,CAACC,GAAGC;gCACb,OAAOA,OAAO,CAAC,aAAa,KAAK;4BACnC;wBACF;wBACAN,aAAa;wBACb7B,QAAQ;4BACN;gCACEO,MAAM;gCACNqB,MAAM;gCACNG,cAAc,CAAC;;;;yEAI0C,CAAC;gCAC1DzB,OAAO;4BACT;yBACD;wBACDA,OAAO;oBACT;oBACA;wBACEqB,OAAO;4BACLM,WAAW,CAACC,GAAGC;gCACb,OAAOA,OAAO,CAAC,aAAa,KAAK;4BACnC;wBACF;wBACAN,aAAa;wBACb7B,QAAQ;4BACN;gCACE;;;;;iBAKC,GALD;;;;;iBAKC,GACDO,MAAM;gCACNqB,MAAM;gCACND,OAAO;oCACLM,WAAW,CAACC,GAAGC;wCACb,OAAOA,OAAO,CAAC,aAAa,KAAK;oCACnC;gCACF;gCACAJ,cAAc,CAAC;;;;;;;2HAO4F,CAAC;gCAC5GzB,OAAO;4BACT;yBACD;wBACDA,OAAO;oBACT;iBACD;YACH;eACGT,cAAcC;SAClB;IACH,CAAA,EAAC"}
1
+ {"version":3,"sources":["../../src/collections/Instructions.ts"],"sourcesContent":["import type { CollectionConfig, GroupField } from 'payload'\nimport type { PluginConfig } from 'src/types.js'\n\nimport { PLUGIN_INSTRUCTIONS_TABLE } from '../defaults.js'\nimport { getGenerationModels } from '../utilities/getGenerationModels.js'\n\nconst groupSettings = (pluginConfig: PluginConfig) =>\n (getGenerationModels(pluginConfig) ?? []).reduce((fields, model) => {\n if (model.settings) {\n fields.push(model.settings)\n }\n return fields\n }, [] as GroupField[])\n\nconst modelOptions = (pluginConfig: PluginConfig) =>\n (getGenerationModels(pluginConfig) ?? []).map((model) => {\n return {\n fields: model.fields,\n label: model.name,\n value: model.id,\n }\n })\n\nconst defaultAccessConfig = {\n create: ({ req }: { req: { user?: unknown } }) => {\n if (!req.user) {\n return false\n }\n return true\n },\n delete: ({ req }: { req: { user?: unknown } }) => {\n if (!req.user) {\n return false\n }\n return true\n },\n read: ({ req }: { req: { user?: unknown } }) => {\n if (!req.user) {\n return false\n }\n return true\n },\n update: ({ req }: { req: { user?: unknown } }) => {\n if (!req.user) {\n return false\n }\n return true\n },\n}\n\nconst defaultAdminConfig = {\n group: 'Plugins',\n hidden: true,\n}\n\nexport const instructionsCollection = (pluginConfig: PluginConfig) => {\n const isLocalized =\n pluginConfig._localization?.enabled && pluginConfig._localization.locales.length > 0\n\n return <CollectionConfig>{\n labels: {\n plural: 'Compose Settings',\n singular: 'Compose Setting',\n },\n ...pluginConfig.overrideInstructions,\n slug: PLUGIN_INSTRUCTIONS_TABLE,\n access: {\n ...defaultAccessConfig,\n ...pluginConfig.overrideInstructions?.access,\n },\n admin: {\n ...defaultAdminConfig,\n ...pluginConfig.overrideInstructions?.admin,\n },\n ...(isLocalized ? { localization: true } : {}),\n fields: [\n {\n name: 'schema-path',\n type: 'text',\n admin: {\n description: \"Please don't change this unless you're sure of what you're doing\",\n },\n unique: true,\n },\n {\n name: 'field-type',\n type: 'select',\n admin: {\n description: \"Please don't change this unless you're sure of what you're doing\",\n },\n defaultValue: 'text',\n label: 'Field type',\n options: [\n {\n label: 'text',\n value: 'text',\n },\n {\n label: 'textarea',\n value: 'textarea',\n },\n {\n label: 'upload',\n value: 'upload',\n },\n {\n label: 'richText',\n value: 'richText',\n },\n ],\n },\n {\n name: 'relation-to',\n type: 'text',\n admin: {\n condition: (_: unknown, current: Record<string, unknown>) => {\n return current['field-type'] === 'upload'\n },\n },\n label: 'Relation to',\n },\n {\n name: 'model-id',\n type: 'select',\n admin: {\n components: {\n Field: {\n clientProps: {\n filterByField: 'field-type',\n options: modelOptions(pluginConfig),\n },\n path: '@ai-stack/payloadcms/fields#SelectField',\n },\n },\n },\n label: 'Model',\n options: modelOptions(pluginConfig).map((option) => {\n return {\n label: option.label,\n value: option.value,\n }\n }),\n },\n {\n name: 'disabled',\n type: 'checkbox',\n admin: {\n description: 'Please reload your collection after applying the changes',\n },\n defaultValue: false,\n label: 'Hide Compose button for this field',\n },\n {\n id: 'ai-prompts-tabs',\n type: 'tabs',\n tabs: [\n {\n description:\n 'Define dynamic templates using {{ fieldName }}. Type { to see available field suggestions.',\n fields: [\n {\n name: 'prompt',\n type: 'textarea',\n // Make prompt localized if localization is enabled\n ...(isLocalized ? { localized: true } : {}),\n admin: {\n components: {\n Field: '@ai-stack/payloadcms/fields#PromptEditorField',\n },\n description: \"Click 'Compose' to run this custom prompt and generate content\",\n },\n label: '',\n },\n ],\n label: 'Prompt',\n },\n {\n admin: {\n condition: (_: unknown, current: Record<string, unknown>) => {\n return current['field-type'] === 'upload' && current['model-id'] === 'gpt-image-1'\n },\n },\n description:\n 'These images will be used to generate new visuals in a similar style, layout, or content. You can combine multiple references for more controlled results.',\n fields: [\n {\n name: 'images',\n type: 'array',\n fields: [\n {\n name: 'image',\n type: 'upload',\n admin: {\n description: 'Please make sure the image is publicly accessible.',\n },\n relationTo: pluginConfig.uploadCollectionSlug\n ? pluginConfig.uploadCollectionSlug\n : 'media',\n },\n ],\n },\n ],\n label: 'Sample Images',\n },\n {\n admin: {\n condition: (_: unknown, current: Record<string, unknown>) => {\n return current['field-type'] === 'richText'\n },\n },\n description: '',\n fields: [\n {\n name: 'system',\n type: 'textarea',\n ...(isLocalized ? { localized: true } : {}),\n defaultValue: `INSTRUCTIONS:\nYou are a highly skilled and professional blog writer,\nrenowned for crafting engaging and well-organized articles.\nWhen given a title, you meticulously create blogs that are not only\ninformative and accurate but also captivating and beautifully structured.`,\n label: '',\n },\n ],\n label: 'System prompt',\n },\n {\n admin: {\n condition: (_: unknown, current: Record<string, unknown>) => {\n return current['field-type'] === 'richText'\n },\n },\n description: '',\n fields: [\n {\n /** TODO:\n * - Layouts can be saved in as an array\n * - User can add their own layout to collections and use it later for generate specific rich text\n * - User can select previously added layout\n * - IMP: Remove layout from default, this seem to affect other functions like rephrase etc.\n */\n name: 'layout',\n type: 'textarea',\n ...(isLocalized ? { localized: true } : {}),\n admin: {\n condition: (_: unknown, current: Record<string, unknown>) => {\n return current['field-type'] === 'richText'\n },\n },\n defaultValue: `[paragraph] - Write a concise introduction (2-3 sentences) that outlines the main topic.\n[horizontalrule] - Insert a horizontal rule to separate the introduction from the main content.\n[list] - Create a list with 3-5 items. Each list item should contain:\n a. [heading] - A brief, descriptive heading (up to 5 words)\n b. [paragraph] - A short explanation or elaboration (1-2 sentences)\n[horizontalrule] - Insert another horizontal rule to separate the main content from the conclusion.\n[paragraph] - Compose a brief conclusion (2-3 sentences) summarizing the key points.\n[quote] - Include a relevant quote from a famous person, directly related to the topic. Format: \"Quote text.\" - Author Name`,\n label: '',\n },\n ],\n label: 'Layout',\n },\n ],\n },\n ...groupSettings(pluginConfig),\n ],\n }\n}\n"],"names":["PLUGIN_INSTRUCTIONS_TABLE","getGenerationModels","groupSettings","pluginConfig","reduce","fields","model","settings","push","modelOptions","map","label","name","value","id","defaultAccessConfig","create","req","user","delete","read","update","defaultAdminConfig","group","hidden","instructionsCollection","isLocalized","_localization","enabled","locales","length","labels","plural","singular","overrideInstructions","slug","access","admin","localization","type","description","unique","defaultValue","options","condition","_","current","components","Field","clientProps","filterByField","path","option","tabs","localized","relationTo","uploadCollectionSlug"],"mappings":"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"}
@@ -3,8 +3,15 @@ export const fetchFields = (config)=>{
3
3
  const { access, options = {}, promptFields = [] } = config;
4
4
  return {
5
5
  handler: async (req)=>{
6
+ // Check if localization is enabled
7
+ const { locales = [] } = req.payload.config.localization || {};
8
+ const isLocalized = locales.length > 0;
9
+ // Get locale from request if available (from query params or headers)
10
+ const locale = req.query?.locale;
11
+ // Fetch instructions - if localized, fetch for the requested locale or default
6
12
  const { docs = [] } = await req.payload.find({
7
13
  collection: PLUGIN_INSTRUCTIONS_TABLE,
14
+ locale: isLocalized && locale ? locale : undefined,
8
15
  pagination: false
9
16
  });
10
17
  let isConfigAllowed = true // Users allowed to update prompts by default
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/endpoints/fetchFields.ts"],"sourcesContent":["import type { Endpoint, PayloadRequest } from 'payload'\n\nimport type { PluginConfig, SerializedPromptField } from '../types.js'\n\nimport { PLUGIN_FETCH_FIELDS_ENDPOINT, PLUGIN_INSTRUCTIONS_TABLE } from '../defaults.js'\n\nexport const fetchFields: (config: PluginConfig) => Endpoint = (config) => {\n const { access, options = {}, promptFields = [] } = config\n return {\n handler: async (req: PayloadRequest) => {\n const { docs = [] } = await req.payload.find({\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n pagination: false,\n })\n\n let isConfigAllowed = true // Users allowed to update prompts by default\n\n if (access?.settings) {\n try {\n isConfigAllowed = await access.settings({ req })\n } catch (e) {\n req.payload.logger.error(req, 'Please check your \"access.settings\" for request')\n }\n }\n\n const fieldMap: Record<string, { disabled?: boolean; fieldType: any; id: any }> = {}\n docs.forEach((doc) => {\n fieldMap[doc['schema-path']] = {\n id: doc.id,\n disabled: !!doc['disabled'],\n fieldType: doc['field-type'],\n }\n })\n\n return Response.json({\n ...options,\n debugging: config.debugging,\n fields: fieldMap,\n isConfigAllowed,\n promptFields: promptFields.map(({ getter: _getter, ...field }): SerializedPromptField => {\n return field\n }),\n })\n },\n method: 'get',\n path: PLUGIN_FETCH_FIELDS_ENDPOINT,\n }\n}\n"],"names":["PLUGIN_FETCH_FIELDS_ENDPOINT","PLUGIN_INSTRUCTIONS_TABLE","fetchFields","config","access","options","promptFields","handler","req","docs","payload","find","collection","pagination","isConfigAllowed","settings","e","logger","error","fieldMap","forEach","doc","id","disabled","fieldType","Response","json","debugging","fields","map","getter","_getter","field","method","path"],"mappings":"AAIA,SAASA,4BAA4B,EAAEC,yBAAyB,QAAQ,iBAAgB;AAExF,OAAO,MAAMC,cAAkD,CAACC;IAC9D,MAAM,EAAEC,MAAM,EAAEC,UAAU,CAAC,CAAC,EAAEC,eAAe,EAAE,EAAE,GAAGH;IACpD,OAAO;QACLI,SAAS,OAAOC;YACd,MAAM,EAAEC,OAAO,EAAE,EAAE,GAAG,MAAMD,IAAIE,OAAO,CAACC,IAAI,CAAC;gBAC3CC,YAAYX;gBACZY,YAAY;YACd;YAEA,IAAIC,kBAAkB,KAAK,6CAA6C;;YAExE,IAAIV,QAAQW,UAAU;gBACpB,IAAI;oBACFD,kBAAkB,MAAMV,OAAOW,QAAQ,CAAC;wBAAEP;oBAAI;gBAChD,EAAE,OAAOQ,GAAG;oBACVR,IAAIE,OAAO,CAACO,MAAM,CAACC,KAAK,CAACV,KAAK;gBAChC;YACF;YAEA,MAAMW,WAA4E,CAAC;YACnFV,KAAKW,OAAO,CAAC,CAACC;gBACZF,QAAQ,CAACE,GAAG,CAAC,cAAc,CAAC,GAAG;oBAC7BC,IAAID,IAAIC,EAAE;oBACVC,UAAU,CAAC,CAACF,GAAG,CAAC,WAAW;oBAC3BG,WAAWH,GAAG,CAAC,aAAa;gBAC9B;YACF;YAEA,OAAOI,SAASC,IAAI,CAAC;gBACnB,GAAGrB,OAAO;gBACVsB,WAAWxB,OAAOwB,SAAS;gBAC3BC,QAAQT;gBACRL;gBACAR,cAAcA,aAAauB,GAAG,CAAC,CAAC,EAAEC,QAAQC,OAAO,EAAE,GAAGC,OAAO;oBAC3D,OAAOA;gBACT;YACF;QACF;QACAC,QAAQ;QACRC,MAAMlC;IACR;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/endpoints/fetchFields.ts"],"sourcesContent":["import type { Endpoint, PayloadRequest } from 'payload'\n\nimport type { PluginConfig, SerializedPromptField } from '../types.js'\n\nimport { PLUGIN_FETCH_FIELDS_ENDPOINT, PLUGIN_INSTRUCTIONS_TABLE } from '../defaults.js'\n\nexport const fetchFields: (config: PluginConfig) => Endpoint = (config) => {\n const { access, options = {}, promptFields = [] } = config\n return {\n handler: async (req: PayloadRequest) => {\n // Check if localization is enabled\n const { locales = [] } = req.payload.config.localization || {}\n const isLocalized = locales.length > 0\n \n // Get locale from request if available (from query params or headers)\n const locale = req.query?.locale as string | undefined\n \n // Fetch instructions - if localized, fetch for the requested locale or default\n const { docs = [] } = await req.payload.find({\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n locale: isLocalized && locale ? locale : undefined,\n pagination: false,\n })\n\n let isConfigAllowed = true // Users allowed to update prompts by default\n\n if (access?.settings) {\n try {\n isConfigAllowed = await access.settings({ req })\n } catch (e) {\n req.payload.logger.error(req, 'Please check your \"access.settings\" for request')\n }\n }\n\n const fieldMap: Record<string, { disabled?: boolean; fieldType: any; id: any }> = {}\n docs.forEach((doc) => {\n fieldMap[doc['schema-path']] = {\n id: doc.id,\n disabled: !!doc['disabled'],\n fieldType: doc['field-type'],\n }\n })\n\n return Response.json({\n ...options,\n debugging: config.debugging,\n fields: fieldMap,\n isConfigAllowed,\n promptFields: promptFields.map(({ getter: _getter, ...field }): SerializedPromptField => {\n return field\n }),\n })\n },\n method: 'get',\n path: PLUGIN_FETCH_FIELDS_ENDPOINT,\n }\n}\n"],"names":["PLUGIN_FETCH_FIELDS_ENDPOINT","PLUGIN_INSTRUCTIONS_TABLE","fetchFields","config","access","options","promptFields","handler","req","locales","payload","localization","isLocalized","length","locale","query","docs","find","collection","undefined","pagination","isConfigAllowed","settings","e","logger","error","fieldMap","forEach","doc","id","disabled","fieldType","Response","json","debugging","fields","map","getter","_getter","field","method","path"],"mappings":"AAIA,SAASA,4BAA4B,EAAEC,yBAAyB,QAAQ,iBAAgB;AAExF,OAAO,MAAMC,cAAkD,CAACC;IAC9D,MAAM,EAAEC,MAAM,EAAEC,UAAU,CAAC,CAAC,EAAEC,eAAe,EAAE,EAAE,GAAGH;IACpD,OAAO;QACLI,SAAS,OAAOC;YACd,mCAAmC;YACnC,MAAM,EAAEC,UAAU,EAAE,EAAE,GAAGD,IAAIE,OAAO,CAACP,MAAM,CAACQ,YAAY,IAAI,CAAC;YAC7D,MAAMC,cAAcH,QAAQI,MAAM,GAAG;YAErC,sEAAsE;YACtE,MAAMC,SAASN,IAAIO,KAAK,EAAED;YAE1B,+EAA+E;YAC/E,MAAM,EAAEE,OAAO,EAAE,EAAE,GAAG,MAAMR,IAAIE,OAAO,CAACO,IAAI,CAAC;gBAC3CC,YAAYjB;gBACZa,QAAQF,eAAeE,SAASA,SAASK;gBACzCC,YAAY;YACd;YAEA,IAAIC,kBAAkB,KAAK,6CAA6C;;YAExE,IAAIjB,QAAQkB,UAAU;gBACpB,IAAI;oBACFD,kBAAkB,MAAMjB,OAAOkB,QAAQ,CAAC;wBAAEd;oBAAI;gBAChD,EAAE,OAAOe,GAAG;oBACVf,IAAIE,OAAO,CAACc,MAAM,CAACC,KAAK,CAACjB,KAAK;gBAChC;YACF;YAEA,MAAMkB,WAA4E,CAAC;YACnFV,KAAKW,OAAO,CAAC,CAACC;gBACZF,QAAQ,CAACE,GAAG,CAAC,cAAc,CAAC,GAAG;oBAC7BC,IAAID,IAAIC,EAAE;oBACVC,UAAU,CAAC,CAACF,GAAG,CAAC,WAAW;oBAC3BG,WAAWH,GAAG,CAAC,aAAa;gBAC9B;YACF;YAEA,OAAOI,SAASC,IAAI,CAAC;gBACnB,GAAG5B,OAAO;gBACV6B,WAAW/B,OAAO+B,SAAS;gBAC3BC,QAAQT;gBACRL;gBACAf,cAAcA,aAAa8B,GAAG,CAAC,CAAC,EAAEC,QAAQC,OAAO,EAAE,GAAGC,OAAO;oBAC3D,OAAOA;gBACT;YACF;QACF;QACAC,QAAQ;QACRC,MAAMzC;IACR;AACF,EAAC"}
@@ -42,7 +42,7 @@ const extendContextWithPromptFields = (data, ctx, pluginConfig)=>{
42
42
  return Promise.resolve(value).then((v)=>new asyncHandlebars.SafeString(v));
43
43
  }
44
44
  // {{prop}} escapes content by default. Here we make sure it won't be escaped.
45
- const value = typeof target === "object" ? target[prop] : undefined;
45
+ const value = typeof target === 'object' ? target[prop] : undefined;
46
46
  return typeof value === 'string' ? new asyncHandlebars.SafeString(value) : value;
47
47
  },
48
48
  // It's used by the handlebars library to determine if the property is enumerable
@@ -133,7 +133,7 @@ const assignPrompt = async (action, { type, actionParams, collection, context, f
133
133
  layout: updatedLayout,
134
134
  // TODO: revisit this toLexicalHTML
135
135
  prompt: await replacePlaceholders(`{{${toLexicalHTML} ${field}}}`, extendedContext),
136
- system: type === 'richText' ? buildRichTextSystem(system, updatedLayout) : system
136
+ system
137
137
  };
138
138
  };
139
139
  export const endpoints = (pluginConfig)=>({
@@ -150,10 +150,15 @@ export const endpoints = (pluginConfig)=>({
150
150
  if (!instructionId) {
151
151
  throw new Error(`Instruction ID is required for "${PLUGIN_NAME}" to work, please check your configuration, or try again`);
152
152
  }
153
+ const { defaultLocale, locales = [] } = req.payload.config.localization || {};
154
+ const localeData = locales.find((l)=>{
155
+ return l.code === locale;
156
+ });
153
157
  // Verify user has access to the specific instruction
154
158
  const instructions = await req.payload.findByID({
155
159
  id: instructionId,
156
160
  collection: PLUGIN_INSTRUCTIONS_TABLE,
161
+ locale: locales.length > 0 && locale ? locale : undefined,
157
162
  req
158
163
  });
159
164
  const { collections } = req.payload.config;
@@ -173,10 +178,6 @@ export const endpoints = (pluginConfig)=>({
173
178
  const collectionName = parts[0];
174
179
  const fieldName = parts.length > 1 ? parts[parts.length - 1] : '';
175
180
  registerEditorHelper(req.payload, schemaPath);
176
- const { defaultLocale, locales = [] } = req.payload.config.localization || {};
177
- const localeData = locales.find((l)=>{
178
- return l.code === locale;
179
- });
180
181
  let localeInfo = locale;
181
182
  if (localeData && defaultLocale && localeData.label && typeof localeData.label === 'object' && defaultLocale in localeData.label) {
182
183
  localeInfo = localeData.label[defaultLocale];
@@ -186,7 +187,7 @@ export const endpoints = (pluginConfig)=>({
186
187
  if (!model) {
187
188
  throw new Error('Model not found');
188
189
  }
189
- const settingsName = model.settings && "name" in model.settings ? model.settings.name : undefined;
190
+ const settingsName = model.settings && 'name' in model.settings ? model.settings.name : undefined;
190
191
  if (!settingsName) {
191
192
  req.payload.logger.error('— AI Plugin: Error fetching settings name!');
192
193
  }
@@ -212,8 +213,10 @@ export const endpoints = (pluginConfig)=>({
212
213
  let jsonSchema = allowedEditorSchema;
213
214
  try {
214
215
  const targetCollection = req.payload.config.collections.find((c)=>c.slug === collectionName);
215
- if (targetCollection && fieldName) {
216
- const targetField = getFieldBySchemaPath(targetCollection, schemaPath);
216
+ const targetGlobal = req.payload.config.globals?.find((g)=>g.slug === collectionName);
217
+ const targetConfig = targetCollection || targetGlobal;
218
+ if (targetConfig && fieldName) {
219
+ const targetField = getFieldBySchemaPath(targetConfig, schemaPath);
217
220
  const supported = [
218
221
  'text',
219
222
  'textarea',
@@ -288,10 +291,15 @@ export const endpoints = (pluginConfig)=>({
288
291
  prompt: ''
289
292
  };
290
293
  if (instructionId) {
294
+ // Get locale from request if available
295
+ const { locale: requestLocale } = data;
296
+ const { locales = [] } = req.payload.config.localization || {};
291
297
  // Verify user has access to the specific instruction
298
+ // Pass locale if localization is enabled for the Instructions collection
292
299
  instructions = await req.payload.findByID({
293
300
  id: instructionId,
294
301
  collection: PLUGIN_INSTRUCTIONS_TABLE,
302
+ locale: locales.length > 0 && requestLocale ? requestLocale : undefined,
295
303
  req
296
304
  });
297
305
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/endpoints/index.ts"],"sourcesContent":["import type { CollectionSlug, PayloadRequest } from 'payload'\n\nimport * as process from 'node:process'\n\nimport type {\n ActionMenuItems,\n Endpoints,\n PluginConfig,\n PromptFieldGetterContext,\n} from '../types.js'\n\nimport { defaultPrompts } from '../ai/prompts.js'\nimport { filterEditorSchemaByNodes } from '../ai/utils/filterEditorSchemaByNodes.js'\nimport {\n PLUGIN_API_ENDPOINT_GENERATE,\n PLUGIN_API_ENDPOINT_GENERATE_UPLOAD,\n PLUGIN_INSTRUCTIONS_TABLE,\n PLUGIN_NAME,\n} from '../defaults.js'\nimport { asyncHandlebars } from '../libraries/handlebars/asyncHandlebars.js'\nimport { registerEditorHelper } from '../libraries/handlebars/helpers.js'\nimport { handlebarsHelpersMap } from '../libraries/handlebars/helpersMap.js'\nimport { replacePlaceholders } from '../libraries/handlebars/replacePlaceholders.js'\nimport { extractImageData } from '../utilities/extractImageData.js'\nimport { fieldToJsonSchema } from '../utilities/fieldToJsonSchema.js'\nimport { getFieldBySchemaPath } from '../utilities/getFieldBySchemaPath.js'\nimport { getGenerationModels } from '../utilities/getGenerationModels.js'\n\nconst requireAuthentication = (req: PayloadRequest) => {\n if (!req.user) {\n throw new Error('Authentication required. Please log in to use AI features.')\n }\n return true\n}\n\nconst checkAccess = async (req: PayloadRequest, pluginConfig: PluginConfig) => {\n requireAuthentication(req)\n\n if (pluginConfig.access?.generate) {\n const hasAccess = await pluginConfig.access.generate({ req })\n if (!hasAccess) {\n throw new Error('Insufficient permissions to use AI generation features.')\n }\n }\n\n return true\n}\n\nconst extendContextWithPromptFields = (\n data: object,\n ctx: PromptFieldGetterContext,\n pluginConfig: PluginConfig,\n) => {\n const { promptFields = [] } = pluginConfig\n const fieldsMap = new Map(\n promptFields\n .filter((f) => !f.collections || f.collections.includes(ctx.collection))\n .map((f) => [f.name, f]),\n )\n return new Proxy(data, {\n get: (target, prop: string) => {\n const field = fieldsMap.get(prop)\n if (field?.getter) {\n const value = field.getter(data, ctx)\n return Promise.resolve(value).then((v) => new asyncHandlebars.SafeString(v))\n }\n // {{prop}} escapes content by default. Here we make sure it won't be escaped.\n const value = typeof target === \"object\" ? (target as any)[prop] : undefined\n return typeof value === 'string' ? new asyncHandlebars.SafeString(value) : value\n },\n // It's used by the handlebars library to determine if the property is enumerable\n getOwnPropertyDescriptor: (target, prop) => {\n const field = fieldsMap.get(prop as string)\n if (field) {\n return {\n configurable: true,\n enumerable: true,\n }\n }\n return Object.getOwnPropertyDescriptor(target, prop)\n },\n has: (target, prop) => {\n return fieldsMap.has(prop as string) || (target && prop in target)\n },\n ownKeys: (target) => {\n return [...fieldsMap.keys(), ...Object.keys(target || {})]\n },\n })\n}\n\nconst buildRichTextSystem = (baseSystem: string, layout: string) => {\n return `${baseSystem}\n\nRULES:\n- Generate original and unique content based on the given topic.\n- Strictly adhere to the specified layout and formatting instructions.\n- Utilize the provided rich text editor tools for appropriate formatting.\n- Ensure the output follows the structure of the sample output object.\n- Produce valid JSON with no undefined or null values.\n---\nLAYOUT INSTRUCTIONS:\n${layout}\n\n---\nADDITIONAL GUIDELINES:\n- Ensure coherence and logical flow between all sections.\n- Maintain a consistent tone and style throughout the content.\n- Use clear and concise language appropriate for the target audience.\n`;\n};\n\nconst assignPrompt = async (\n action: ActionMenuItems,\n {\n type,\n actionParams,\n collection,\n context,\n field,\n layout,\n locale,\n pluginConfig,\n systemPrompt = '',\n template,\n }: {\n actionParams: Record<any, any>\n collection: CollectionSlug\n context: object\n field: string\n layout: string\n locale: string\n pluginConfig: PluginConfig\n systemPrompt: string\n template: string\n type: string\n },\n) => {\n const extendedContext = extendContextWithPromptFields(context, { type, collection }, pluginConfig)\n const prompt = await replacePlaceholders(template, extendedContext)\n const toLexicalHTML = type === 'richText' ? handlebarsHelpersMap.toHTML.name : ''\n\n const assignedPrompts = {\n layout: type === 'richText' ? layout : undefined,\n prompt,\n //TODO: Define only once on a collection level\n system: type === 'richText' ? buildRichTextSystem(systemPrompt, layout) : undefined,\n }\n\n if (action === 'Compose') {\n if (locale && locale !== 'en') {\n /**\n * NOTE: Avoid using the \"system prompt\" for setting the output language,\n * as it causes quotation marks to appear in the output (Currently only tested with openai models).\n * Appending the language instruction directly to the prompt resolves this issue.\n **/\n assignedPrompts.prompt += `\n --- \n OUTPUT LANGUAGE: ${locale}\n `\n }\n\n return assignedPrompts\n }\n\n const prompts = [...(pluginConfig.prompts || []), ...defaultPrompts]\n const foundPrompt = prompts.find((p) => p.name === action)\n const getLayout = foundPrompt?.layout\n const getSystemPrompt = foundPrompt?.system\n\n let updatedLayout = layout\n if (getLayout) {\n updatedLayout = getLayout()\n }\n\n const system = getSystemPrompt\n ? getSystemPrompt({\n ...(actionParams || {}),\n prompt,\n systemPrompt,\n })\n : ''\n\n return {\n layout: updatedLayout,\n // TODO: revisit this toLexicalHTML\n prompt: await replacePlaceholders(`{{${toLexicalHTML} ${field}}}`, extendedContext),\n system: type === 'richText' ? buildRichTextSystem(system, updatedLayout) : system,\n }\n}\n\nexport const endpoints: (pluginConfig: PluginConfig) => Endpoints = (pluginConfig) =>\n ({\n textarea: {\n //TODO: This is the main endpoint for generating content - its just needs to be renamed to 'generate' or something.\n handler: async (req: PayloadRequest) => {\n try {\n // Check authentication and authorization first\n await checkAccess(req, pluginConfig)\n\n const data = await req.json?.()\n\n const { allowedEditorNodes = [], locale = 'en', options } = data\n const { action, actionParams, instructionId } = options\n const contextData = data.doc\n\n if (!instructionId) {\n throw new Error(\n `Instruction ID is required for \"${PLUGIN_NAME}\" to work, please check your configuration, or try again`,\n )\n }\n\n // Verify user has access to the specific instruction\n const instructions = await req.payload.findByID({\n id: instructionId,\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n req, // Pass req to ensure access control is applied\n })\n\n const { collections } = req.payload.config\n const collection = collections.find(\n (collection) => collection.slug === PLUGIN_INSTRUCTIONS_TABLE,\n )\n\n if (!collection) {\n throw new Error('Collection not found')\n }\n\n const { custom: { [PLUGIN_NAME]: { editorConfig = {} } = {} } = {} } = collection.admin\n const { schema: editorSchema = {} } = editorConfig\n const { prompt: promptTemplate = '' } = instructions\n\n let allowedEditorSchema = editorSchema\n if (allowedEditorNodes.length) {\n allowedEditorSchema = filterEditorSchemaByNodes(editorSchema, allowedEditorNodes)\n }\n\n const schemaPath = instructions['schema-path'] as string\n const parts = schemaPath?.split('.') || []\n const collectionName = parts[0]\n const fieldName = parts.length > 1 ? parts[parts.length - 1] : ''\n\n registerEditorHelper(req.payload, schemaPath)\n\n const { defaultLocale, locales = [] } = req.payload.config.localization || {}\n const localeData = locales.find((l) => {\n return l.code === locale\n })\n\n let localeInfo = locale\n if (\n localeData &&\n defaultLocale &&\n localeData.label &&\n typeof localeData.label === 'object' &&\n defaultLocale in localeData.label\n ) {\n localeInfo = localeData.label[defaultLocale]\n }\n\n const models = getGenerationModels(pluginConfig)\n const model =\n models && Array.isArray(models)\n ? models.find((model) => model.id === instructions['model-id'])\n : undefined\n\n if (!model) {\n throw new Error('Model not found')\n }\n\n const settingsName = model.settings && \"name\" in model.settings ? model.settings.name : undefined\n if (!settingsName) {\n req.payload.logger.error('— AI Plugin: Error fetching settings name!')\n }\n\n const modelOptions = settingsName ? instructions[settingsName] || {} : {}\n\n const prompts = await assignPrompt(action, {\n type: String(instructions['field-type']),\n actionParams,\n collection: collectionName,\n context: contextData,\n field: fieldName || '',\n layout: instructions.layout,\n locale: localeInfo,\n pluginConfig,\n systemPrompt: instructions.system,\n template: String(promptTemplate),\n })\n\n if (pluginConfig.debugging) {\n req.payload.logger.info(\n { prompts },\n `— AI Plugin: Executing text prompt on ${schemaPath} using ${model.id}`,\n )\n }\n\n // Build per-field JSON schema for structured generation when applicable\n let jsonSchema= allowedEditorSchema\n try {\n const targetCollection = req.payload.config.collections.find(\n (c) => c.slug === collectionName,\n )\n if (targetCollection && fieldName) {\n const targetField = getFieldBySchemaPath(targetCollection, schemaPath)\n const supported = ['text', 'textarea', 'select', 'number', 'date', 'code', 'email', 'json']\n const t = String(targetField?.type || '')\n if (targetField && supported.includes(t)) {\n jsonSchema = fieldToJsonSchema(targetField as any, { nameOverride: fieldName })\n }\n }\n } catch (e) {\n req.payload.logger.error(e, '— AI Plugin: Error building field JSON schema')\n }\n\n return model.handler?.(prompts.prompt, {\n ...modelOptions,\n layout: prompts.layout,\n locale: localeInfo,\n schema: jsonSchema,\n system: prompts.system,\n })\n } catch (error) {\n req.payload.logger.error(error, 'Error generating content: ')\n const message =\n error && typeof error === 'object' && 'message' in error\n ? (error as any).message\n : String(error)\n return new Response(JSON.stringify({ error: message }), {\n headers: { 'Content-Type': 'application/json' },\n status:\n message.includes('Authentication required') ||\n message.includes('Insufficient permissions')\n ? 401\n : 500,\n })\n }\n },\n method: 'post',\n path: PLUGIN_API_ENDPOINT_GENERATE,\n },\n upload: {\n handler: async (req: PayloadRequest) => {\n try {\n // Check authentication and authorization first\n await checkAccess(req, pluginConfig)\n\n const data = await req.json?.()\n\n const { collectionSlug, documentId, options } = data\n const { instructionId } = options\n let docData = {}\n\n if (documentId) {\n try {\n docData = await req.payload.findByID({\n id: documentId,\n collection: collectionSlug,\n draft: true,\n req, // Pass req to ensure access control is applied\n })\n } catch (e) {\n req.payload.logger.error(\n e,\n '— AI Plugin: Error fetching document, you should try again after enabling drafts for this collection',\n )\n }\n }\n\n const contextData = {\n ...data.doc,\n ...docData,\n }\n\n let instructions: Record<string, any> = { images: [], 'model-id': '', prompt: '' }\n\n if (instructionId) {\n // Verify user has access to the specific instruction\n instructions = await req.payload.findByID({\n id: instructionId,\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n req, // Pass req to ensure access control is applied\n })\n }\n\n const { images: sampleImages = [], prompt: promptTemplate = '' } = instructions\n const schemaPath = instructions['schema-path']\n\n registerEditorHelper(req.payload, schemaPath)\n\n const extendedContext = extendContextWithPromptFields(\n contextData,\n { type: instructions['field-type'], collection: collectionSlug },\n pluginConfig,\n )\n const text = await replacePlaceholders(promptTemplate, extendedContext)\n const modelId = instructions['model-id']\n const uploadCollectionSlug = instructions['relation-to']\n\n const images = [...extractImageData(text), ...sampleImages]\n\n const editImages = []\n for (const img of images) {\n const serverURL =\n req.payload.config?.serverURL ||\n process.env.SERVER_URL ||\n process.env.NEXT_PUBLIC_SERVER_URL\n\n let url = img.image.thumbnailURL || img.image.url\n if (!url.startsWith('http')) {\n url = `${serverURL}${url}`\n }\n\n try {\n\n const response = await fetch(url, {\n headers: {\n //TODO: Further testing needed or so find a proper way.\n Authorization: `Bearer ${req.headers.get('Authorization')?.split('Bearer ')[1] || ''}`,\n },\n method: 'GET',\n })\n\n const blob = await response.blob()\n editImages.push({\n name: img.image.name,\n type: img.image.type,\n data: blob,\n size: blob.size,\n url,\n })\n } catch (e) {\n req.payload.logger.error(e, `Error fetching reference image ${url}`)\n throw Error(\n \"We couldn't fetch the images. Please ensure the images are accessible and hosted publicly.\",\n )\n }\n }\n\n const modelsUpload = getGenerationModels(pluginConfig)\n const model =\n modelsUpload && Array.isArray(modelsUpload)\n ? modelsUpload.find((model) => model.id === modelId)\n : undefined\n\n if (!model) {\n throw new Error('Model not found')\n }\n\n // @ts-ignore\n const settingsName = model && model.settings ? model.settings.name : undefined\n if (!settingsName) {\n req.payload.logger.error('— AI Plugin: Error fetching settings name!')\n }\n\n let modelOptions = settingsName ? instructions[settingsName] || {} : {}\n modelOptions = {\n ...modelOptions,\n images: editImages,\n }\n\n if (pluginConfig.debugging) {\n req.payload.logger.info(\n { text },\n `— AI Plugin: Executing image prompt using ${model.id}`,\n )\n }\n\n const result = await model.handler?.(text, modelOptions)\n let assetData: { alt?: string; id: number | string }\n\n if (typeof pluginConfig.mediaUpload === 'function') {\n assetData = await pluginConfig.mediaUpload(result, {\n collection: uploadCollectionSlug,\n request: req,\n })\n } else {\n assetData = await req.payload.create({\n collection: uploadCollectionSlug,\n data: result.data,\n file: result.file,\n req, // Pass req to ensure access control is applied\n })\n }\n\n if (!assetData.id) {\n req.payload.logger.error(\n 'Error uploading generated media, is your media upload function correct?',\n )\n throw new Error('Error uploading generated media!')\n }\n\n return new Response(\n JSON.stringify({\n result: {\n id: assetData.id,\n alt: assetData.alt,\n },\n }),\n )\n } catch (error) {\n req.payload.logger.error(error, 'Error generating upload: ')\n const message =\n error && typeof error === 'object' && 'message' in error\n ? (error as any).message\n : String(error)\n return new Response(JSON.stringify({ error: message }), {\n headers: { 'Content-Type': 'application/json' },\n status:\n message.includes('Authentication required') ||\n message.includes('Insufficient permissions')\n ? 401\n : 500,\n })\n }\n },\n method: 'post',\n path: PLUGIN_API_ENDPOINT_GENERATE_UPLOAD,\n },\n }) satisfies Endpoints\n"],"names":["process","defaultPrompts","filterEditorSchemaByNodes","PLUGIN_API_ENDPOINT_GENERATE","PLUGIN_API_ENDPOINT_GENERATE_UPLOAD","PLUGIN_INSTRUCTIONS_TABLE","PLUGIN_NAME","asyncHandlebars","registerEditorHelper","handlebarsHelpersMap","replacePlaceholders","extractImageData","fieldToJsonSchema","getFieldBySchemaPath","getGenerationModels","requireAuthentication","req","user","Error","checkAccess","pluginConfig","access","generate","hasAccess","extendContextWithPromptFields","data","ctx","promptFields","fieldsMap","Map","filter","f","collections","includes","collection","map","name","Proxy","get","target","prop","field","getter","value","Promise","resolve","then","v","SafeString","undefined","getOwnPropertyDescriptor","configurable","enumerable","Object","has","ownKeys","keys","buildRichTextSystem","baseSystem","layout","assignPrompt","action","type","actionParams","context","locale","systemPrompt","template","extendedContext","prompt","toLexicalHTML","toHTML","assignedPrompts","system","prompts","foundPrompt","find","p","getLayout","getSystemPrompt","updatedLayout","endpoints","textarea","handler","json","allowedEditorNodes","options","instructionId","contextData","doc","instructions","payload","findByID","id","config","slug","custom","editorConfig","admin","schema","editorSchema","promptTemplate","allowedEditorSchema","length","schemaPath","parts","split","collectionName","fieldName","defaultLocale","locales","localization","localeData","l","code","localeInfo","label","models","model","Array","isArray","settingsName","settings","logger","error","modelOptions","String","debugging","info","jsonSchema","targetCollection","c","targetField","supported","t","nameOverride","e","message","Response","JSON","stringify","headers","status","method","path","upload","collectionSlug","documentId","docData","draft","images","sampleImages","text","modelId","uploadCollectionSlug","editImages","img","serverURL","env","SERVER_URL","NEXT_PUBLIC_SERVER_URL","url","image","thumbnailURL","startsWith","response","fetch","Authorization","blob","push","size","modelsUpload","result","assetData","mediaUpload","request","create","file","alt"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/endpoints/index.ts"],"sourcesContent":["import type { CollectionSlug, PayloadRequest } from 'payload'\n\nimport * as process from 'node:process'\n\nimport type {\n ActionMenuItems,\n Endpoints,\n PluginConfig,\n PromptFieldGetterContext,\n} from '../types.js'\n\nimport { defaultPrompts } from '../ai/prompts.js'\nimport { filterEditorSchemaByNodes } from '../ai/utils/filterEditorSchemaByNodes.js'\nimport {\n PLUGIN_API_ENDPOINT_GENERATE,\n PLUGIN_API_ENDPOINT_GENERATE_UPLOAD,\n PLUGIN_INSTRUCTIONS_TABLE,\n PLUGIN_NAME,\n} from '../defaults.js'\nimport { asyncHandlebars } from '../libraries/handlebars/asyncHandlebars.js'\nimport { registerEditorHelper } from '../libraries/handlebars/helpers.js'\nimport { handlebarsHelpersMap } from '../libraries/handlebars/helpersMap.js'\nimport { replacePlaceholders } from '../libraries/handlebars/replacePlaceholders.js'\nimport { extractImageData } from '../utilities/extractImageData.js'\nimport { fieldToJsonSchema } from '../utilities/fieldToJsonSchema.js'\nimport { getFieldBySchemaPath } from '../utilities/getFieldBySchemaPath.js'\nimport { getGenerationModels } from '../utilities/getGenerationModels.js'\n\nconst requireAuthentication = (req: PayloadRequest) => {\n if (!req.user) {\n throw new Error('Authentication required. Please log in to use AI features.')\n }\n return true\n}\n\nconst checkAccess = async (req: PayloadRequest, pluginConfig: PluginConfig) => {\n requireAuthentication(req)\n\n if (pluginConfig.access?.generate) {\n const hasAccess = await pluginConfig.access.generate({ req })\n if (!hasAccess) {\n throw new Error('Insufficient permissions to use AI generation features.')\n }\n }\n\n return true\n}\n\nconst extendContextWithPromptFields = (\n data: object,\n ctx: PromptFieldGetterContext,\n pluginConfig: PluginConfig,\n) => {\n const { promptFields = [] } = pluginConfig\n const fieldsMap = new Map(\n promptFields\n .filter((f) => !f.collections || f.collections.includes(ctx.collection))\n .map((f) => [f.name, f]),\n )\n return new Proxy(data, {\n get: (target, prop: string) => {\n const field = fieldsMap.get(prop)\n if (field?.getter) {\n const value = field.getter(data, ctx)\n return Promise.resolve(value).then((v) => new asyncHandlebars.SafeString(v))\n }\n // {{prop}} escapes content by default. Here we make sure it won't be escaped.\n const value = typeof target === 'object' ? (target as any)[prop] : undefined\n return typeof value === 'string' ? new asyncHandlebars.SafeString(value) : value\n },\n // It's used by the handlebars library to determine if the property is enumerable\n getOwnPropertyDescriptor: (target, prop) => {\n const field = fieldsMap.get(prop as string)\n if (field) {\n return {\n configurable: true,\n enumerable: true,\n }\n }\n return Object.getOwnPropertyDescriptor(target, prop)\n },\n has: (target, prop) => {\n return fieldsMap.has(prop as string) || (target && prop in target)\n },\n ownKeys: (target) => {\n return [...fieldsMap.keys(), ...Object.keys(target || {})]\n },\n })\n}\n\nconst buildRichTextSystem = (baseSystem: string, layout: string) => {\n return `${baseSystem}\n\nRULES:\n- Generate original and unique content based on the given topic.\n- Strictly adhere to the specified layout and formatting instructions.\n- Utilize the provided rich text editor tools for appropriate formatting.\n- Ensure the output follows the structure of the sample output object.\n- Produce valid JSON with no undefined or null values.\n---\nLAYOUT INSTRUCTIONS:\n${layout}\n\n---\nADDITIONAL GUIDELINES:\n- Ensure coherence and logical flow between all sections.\n- Maintain a consistent tone and style throughout the content.\n- Use clear and concise language appropriate for the target audience.\n`\n}\n\nconst assignPrompt = async (\n action: ActionMenuItems,\n {\n type,\n actionParams,\n collection,\n context,\n field,\n layout,\n locale,\n pluginConfig,\n systemPrompt = '',\n template,\n }: {\n actionParams: Record<any, any>\n collection: CollectionSlug\n context: object\n field: string\n layout: string\n locale: string\n pluginConfig: PluginConfig\n systemPrompt: string\n template: string\n type: string\n },\n) => {\n const extendedContext = extendContextWithPromptFields(context, { type, collection }, pluginConfig)\n const prompt = await replacePlaceholders(template, extendedContext)\n const toLexicalHTML = type === 'richText' ? handlebarsHelpersMap.toHTML.name : ''\n\n const assignedPrompts = {\n layout: type === 'richText' ? layout : undefined,\n prompt,\n //TODO: Define only once on a collection level\n system: type === 'richText' ? buildRichTextSystem(systemPrompt, layout) : undefined,\n }\n\n if (action === 'Compose') {\n if (locale && locale !== 'en') {\n /**\n * NOTE: Avoid using the \"system prompt\" for setting the output language,\n * as it causes quotation marks to appear in the output (Currently only tested with openai models).\n * Appending the language instruction directly to the prompt resolves this issue.\n **/\n assignedPrompts.prompt += `\n --- \n OUTPUT LANGUAGE: ${locale}\n `\n }\n\n return assignedPrompts\n }\n\n const prompts = [...(pluginConfig.prompts || []), ...defaultPrompts]\n const foundPrompt = prompts.find((p) => p.name === action)\n const getLayout = foundPrompt?.layout\n const getSystemPrompt = foundPrompt?.system\n\n let updatedLayout = layout\n if (getLayout) {\n updatedLayout = getLayout()\n }\n\n const system = getSystemPrompt\n ? getSystemPrompt({\n ...(actionParams || {}),\n prompt,\n systemPrompt,\n })\n : ''\n\n return {\n layout: updatedLayout,\n // TODO: revisit this toLexicalHTML\n prompt: await replacePlaceholders(`{{${toLexicalHTML} ${field}}}`, extendedContext),\n system,\n }\n}\n\nexport const endpoints: (pluginConfig: PluginConfig) => Endpoints = (pluginConfig) =>\n ({\n textarea: {\n //TODO: This is the main endpoint for generating content - its just needs to be renamed to 'generate' or something.\n handler: async (req: PayloadRequest) => {\n try {\n // Check authentication and authorization first\n await checkAccess(req, pluginConfig)\n\n const data = await req.json?.()\n\n const { allowedEditorNodes = [], locale = 'en', options } = data\n const { action, actionParams, instructionId } = options\n const contextData = data.doc\n\n if (!instructionId) {\n throw new Error(\n `Instruction ID is required for \"${PLUGIN_NAME}\" to work, please check your configuration, or try again`,\n )\n }\n\n const { defaultLocale, locales = [] } = req.payload.config.localization || {}\n const localeData = locales.find((l) => {\n return l.code === locale\n })\n\n // Verify user has access to the specific instruction\n const instructions = await req.payload.findByID({\n id: instructionId,\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n locale: locales.length > 0 && locale ? locale : undefined,\n req, // Pass req to ensure access control is applied\n })\n\n const { collections } = req.payload.config\n const collection = collections.find(\n (collection) => collection.slug === PLUGIN_INSTRUCTIONS_TABLE,\n )\n\n if (!collection) {\n throw new Error('Collection not found')\n }\n\n const { custom: { [PLUGIN_NAME]: { editorConfig = {} } = {} } = {} } = collection.admin\n const { schema: editorSchema = {} } = editorConfig\n const { prompt: promptTemplate = '' } = instructions\n\n let allowedEditorSchema = editorSchema\n if (allowedEditorNodes.length) {\n allowedEditorSchema = filterEditorSchemaByNodes(editorSchema, allowedEditorNodes)\n }\n\n const schemaPath = instructions['schema-path'] as string\n const parts = schemaPath?.split('.') || []\n const collectionName = parts[0]\n const fieldName = parts.length > 1 ? parts[parts.length - 1] : ''\n\n registerEditorHelper(req.payload, schemaPath)\n\n let localeInfo = locale\n if (\n localeData &&\n defaultLocale &&\n localeData.label &&\n typeof localeData.label === 'object' &&\n defaultLocale in localeData.label\n ) {\n localeInfo = localeData.label[defaultLocale]\n }\n\n const models = getGenerationModels(pluginConfig)\n const model =\n models && Array.isArray(models)\n ? models.find((model) => model.id === instructions['model-id'])\n : undefined\n\n if (!model) {\n throw new Error('Model not found')\n }\n\n const settingsName =\n model.settings && 'name' in model.settings ? model.settings.name : undefined\n if (!settingsName) {\n req.payload.logger.error('— AI Plugin: Error fetching settings name!')\n }\n\n const modelOptions = settingsName ? instructions[settingsName] || {} : {}\n\n const prompts = await assignPrompt(action, {\n type: String(instructions['field-type']),\n actionParams,\n collection: collectionName,\n context: contextData,\n field: fieldName || '',\n layout: instructions.layout,\n locale: localeInfo,\n pluginConfig,\n systemPrompt: instructions.system,\n template: String(promptTemplate),\n })\n\n if (pluginConfig.debugging) {\n req.payload.logger.info(\n { prompts },\n `— AI Plugin: Executing text prompt on ${schemaPath} using ${model.id}`,\n )\n }\n\n // Build per-field JSON schema for structured generation when applicable\n let jsonSchema = allowedEditorSchema\n try {\n \n const targetCollection = req.payload.config.collections.find(\n (c) => c.slug === collectionName,\n )\n\n const targetGlobal = req.payload.config.globals?.find(\n (g) => g.slug === collectionName,\n )\n\n const targetConfig = targetCollection || targetGlobal\n\n if (targetConfig && fieldName) {\n const targetField = getFieldBySchemaPath(targetConfig, schemaPath)\n const supported = [\n 'text',\n 'textarea',\n 'select',\n 'number',\n 'date',\n 'code',\n 'email',\n 'json',\n ]\n\n const t = String(targetField?.type || '')\n if (targetField && supported.includes(t)) {\n jsonSchema = fieldToJsonSchema(targetField as any, { nameOverride: fieldName })\n }\n }\n } catch (e) {\n req.payload.logger.error(e, '— AI Plugin: Error building field JSON schema')\n }\n\n return model.handler?.(prompts.prompt, {\n ...modelOptions,\n layout: prompts.layout,\n locale: localeInfo,\n schema: jsonSchema,\n system: prompts.system,\n })\n } catch (error) {\n req.payload.logger.error(error, 'Error generating content: ')\n const message =\n error && typeof error === 'object' && 'message' in error\n ? (error as any).message\n : String(error)\n return new Response(JSON.stringify({ error: message }), {\n headers: { 'Content-Type': 'application/json' },\n status:\n message.includes('Authentication required') ||\n message.includes('Insufficient permissions')\n ? 401\n : 500,\n })\n }\n },\n method: 'post',\n path: PLUGIN_API_ENDPOINT_GENERATE,\n },\n upload: {\n handler: async (req: PayloadRequest) => {\n try {\n // Check authentication and authorization first\n await checkAccess(req, pluginConfig)\n\n const data = await req.json?.()\n\n const { collectionSlug, documentId, options } = data\n const { instructionId } = options\n let docData = {}\n\n if (documentId) {\n try {\n docData = await req.payload.findByID({\n id: documentId,\n collection: collectionSlug,\n draft: true,\n req, // Pass req to ensure access control is applied\n })\n } catch (e) {\n req.payload.logger.error(\n e,\n '— AI Plugin: Error fetching document, you should try again after enabling drafts for this collection',\n )\n }\n }\n\n const contextData = {\n ...data.doc,\n ...docData,\n }\n\n let instructions: Record<string, any> = { images: [], 'model-id': '', prompt: '' }\n\n if (instructionId) {\n // Get locale from request if available\n const { locale: requestLocale } = data\n const { locales = [] } = req.payload.config.localization || {}\n\n // Verify user has access to the specific instruction\n // Pass locale if localization is enabled for the Instructions collection\n instructions = await req.payload.findByID({\n id: instructionId,\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n locale: locales.length > 0 && requestLocale ? requestLocale : undefined,\n req, // Pass req to ensure access control is applied\n })\n }\n\n const { images: sampleImages = [], prompt: promptTemplate = '' } = instructions\n const schemaPath = instructions['schema-path']\n\n registerEditorHelper(req.payload, schemaPath)\n\n const extendedContext = extendContextWithPromptFields(\n contextData,\n { type: instructions['field-type'], collection: collectionSlug },\n pluginConfig,\n )\n const text = await replacePlaceholders(promptTemplate, extendedContext)\n const modelId = instructions['model-id']\n const uploadCollectionSlug = instructions['relation-to']\n\n const images = [...extractImageData(text), ...sampleImages]\n\n const editImages = []\n for (const img of images) {\n const serverURL =\n req.payload.config?.serverURL ||\n process.env.SERVER_URL ||\n process.env.NEXT_PUBLIC_SERVER_URL\n\n let url = img.image.thumbnailURL || img.image.url\n if (!url.startsWith('http')) {\n url = `${serverURL}${url}`\n }\n\n try {\n const response = await fetch(url, {\n headers: {\n //TODO: Further testing needed or so find a proper way.\n Authorization: `Bearer ${req.headers.get('Authorization')?.split('Bearer ')[1] || ''}`,\n },\n method: 'GET',\n })\n\n const blob = await response.blob()\n editImages.push({\n name: img.image.name,\n type: img.image.type,\n data: blob,\n size: blob.size,\n url,\n })\n } catch (e) {\n req.payload.logger.error(e, `Error fetching reference image ${url}`)\n throw Error(\n \"We couldn't fetch the images. Please ensure the images are accessible and hosted publicly.\",\n )\n }\n }\n\n const modelsUpload = getGenerationModels(pluginConfig)\n const model =\n modelsUpload && Array.isArray(modelsUpload)\n ? modelsUpload.find((model) => model.id === modelId)\n : undefined\n\n if (!model) {\n throw new Error('Model not found')\n }\n\n // @ts-ignore\n const settingsName = model && model.settings ? model.settings.name : undefined\n if (!settingsName) {\n req.payload.logger.error('— AI Plugin: Error fetching settings name!')\n }\n\n let modelOptions = settingsName ? instructions[settingsName] || {} : {}\n modelOptions = {\n ...modelOptions,\n images: editImages,\n }\n\n if (pluginConfig.debugging) {\n req.payload.logger.info(\n { text },\n `— AI Plugin: Executing image prompt using ${model.id}`,\n )\n }\n\n const result = await model.handler?.(text, modelOptions)\n let assetData: { alt?: string; id: number | string }\n\n if (typeof pluginConfig.mediaUpload === 'function') {\n assetData = await pluginConfig.mediaUpload(result, {\n collection: uploadCollectionSlug,\n request: req,\n })\n } else {\n assetData = await req.payload.create({\n collection: uploadCollectionSlug,\n data: result.data,\n file: result.file,\n req, // Pass req to ensure access control is applied\n })\n }\n\n if (!assetData.id) {\n req.payload.logger.error(\n 'Error uploading generated media, is your media upload function correct?',\n )\n throw new Error('Error uploading generated media!')\n }\n\n return new Response(\n JSON.stringify({\n result: {\n id: assetData.id,\n alt: assetData.alt,\n },\n }),\n )\n } catch (error) {\n req.payload.logger.error(error, 'Error generating upload: ')\n const message =\n error && typeof error === 'object' && 'message' in error\n ? (error as any).message\n : String(error)\n return new Response(JSON.stringify({ error: message }), {\n headers: { 'Content-Type': 'application/json' },\n status:\n message.includes('Authentication required') ||\n message.includes('Insufficient permissions')\n ? 401\n : 500,\n })\n }\n },\n method: 'post',\n path: PLUGIN_API_ENDPOINT_GENERATE_UPLOAD,\n },\n }) satisfies Endpoints\n"],"names":["process","defaultPrompts","filterEditorSchemaByNodes","PLUGIN_API_ENDPOINT_GENERATE","PLUGIN_API_ENDPOINT_GENERATE_UPLOAD","PLUGIN_INSTRUCTIONS_TABLE","PLUGIN_NAME","asyncHandlebars","registerEditorHelper","handlebarsHelpersMap","replacePlaceholders","extractImageData","fieldToJsonSchema","getFieldBySchemaPath","getGenerationModels","requireAuthentication","req","user","Error","checkAccess","pluginConfig","access","generate","hasAccess","extendContextWithPromptFields","data","ctx","promptFields","fieldsMap","Map","filter","f","collections","includes","collection","map","name","Proxy","get","target","prop","field","getter","value","Promise","resolve","then","v","SafeString","undefined","getOwnPropertyDescriptor","configurable","enumerable","Object","has","ownKeys","keys","buildRichTextSystem","baseSystem","layout","assignPrompt","action","type","actionParams","context","locale","systemPrompt","template","extendedContext","prompt","toLexicalHTML","toHTML","assignedPrompts","system","prompts","foundPrompt","find","p","getLayout","getSystemPrompt","updatedLayout","endpoints","textarea","handler","json","allowedEditorNodes","options","instructionId","contextData","doc","defaultLocale","locales","payload","config","localization","localeData","l","code","instructions","findByID","id","length","slug","custom","editorConfig","admin","schema","editorSchema","promptTemplate","allowedEditorSchema","schemaPath","parts","split","collectionName","fieldName","localeInfo","label","models","model","Array","isArray","settingsName","settings","logger","error","modelOptions","String","debugging","info","jsonSchema","targetCollection","c","targetGlobal","globals","g","targetConfig","targetField","supported","t","nameOverride","e","message","Response","JSON","stringify","headers","status","method","path","upload","collectionSlug","documentId","docData","draft","images","requestLocale","sampleImages","text","modelId","uploadCollectionSlug","editImages","img","serverURL","env","SERVER_URL","NEXT_PUBLIC_SERVER_URL","url","image","thumbnailURL","startsWith","response","fetch","Authorization","blob","push","size","modelsUpload","result","assetData","mediaUpload","request","create","file","alt"],"mappings":"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"}
package/dist/init.js CHANGED
@@ -10,12 +10,19 @@ export const init = async (payload, fieldSchemaPaths, pluginConfig)=>{
10
10
  payload.logger.info(`— AI Plugin: Initializing...`);
11
11
  }
12
12
  const paths = Object.keys(fieldSchemaPaths);
13
+ // Note: schema-path is globally unique, so we create one entry per path regardless of localization
14
+ // Localization info is kept for potential future use or debugging
15
+ const _isLocalized = pluginConfig._localization?.enabled && pluginConfig._localization.locales.length > 0;
16
+ const _locales = pluginConfig._localization?.locales || [];
13
17
  // Get all instructions for faster initialization
18
+ // Query with locale: 'all' to get entries from all locales when localization is enabled
14
19
  const { docs: allInstructions } = await payload.find({
15
20
  collection: PLUGIN_INSTRUCTIONS_TABLE,
16
21
  depth: 0,
22
+ locale: 'all',
17
23
  pagination: false,
18
24
  select: {
25
+ id: true,
19
26
  'field-type': true,
20
27
  'schema-path': true
21
28
  }
@@ -24,6 +31,7 @@ export const init = async (payload, fieldSchemaPaths, pluginConfig)=>{
24
31
  for(let i = 0; i < paths.length; i++){
25
32
  const path = paths[i];
26
33
  const { type: fieldType, label: fieldLabel, relationTo } = fieldSchemaPaths[path];
34
+ // Find existing entry for this path (schema-path is globally unique, not per locale)
27
35
  let instructions = allInstructions.find((entry)=>entry['schema-path'] === path);
28
36
  if (!instructions) {
29
37
  let seed;
@@ -71,12 +79,44 @@ export const init = async (payload, fieldSchemaPaths, pluginConfig)=>{
71
79
  prompt: generatedPrompt,
72
80
  ...seed.data
73
81
  }, `Prompt seeded for "${path}" field`);
74
- instructions = await payload.create({
75
- collection: PLUGIN_INSTRUCTIONS_TABLE,
76
- data
77
- }).catch((err)=>{
78
- payload.logger.error(err, '— AI Plugin: Error creating Compose settings-');
79
- });
82
+ try {
83
+ instructions = await payload.create({
84
+ collection: PLUGIN_INSTRUCTIONS_TABLE,
85
+ data
86
+ });
87
+ } catch (err) {
88
+ // Handle unique constraint violation - entry might already exist for another locale
89
+ const error = err;
90
+ if (error?.name === 'ValidationError' && error?.data?.errors?.some((e)=>e.path === 'schema-path')) {
91
+ // Try to find the existing entry across all locales
92
+ const { docs } = await payload.find({
93
+ collection: PLUGIN_INSTRUCTIONS_TABLE,
94
+ limit: 1,
95
+ locale: 'all',
96
+ select: {
97
+ id: true,
98
+ 'field-type': true,
99
+ 'schema-path': true
100
+ },
101
+ where: {
102
+ 'schema-path': {
103
+ equals: path
104
+ }
105
+ }
106
+ });
107
+ const existingEntry = docs[0];
108
+ if (existingEntry) {
109
+ instructions = existingEntry;
110
+ if (pluginConfig.debugging) {
111
+ payload.logger.info(`— AI Plugin: Entry already exists for ${path}, using existing entry`);
112
+ }
113
+ } else {
114
+ payload.logger.error(err, `— AI Plugin: Error creating Compose settings for ${path}`);
115
+ }
116
+ } else {
117
+ payload.logger.error(err, `— AI Plugin: Error creating Compose settings for ${path}`);
118
+ }
119
+ }
80
120
  if (instructions?.id) {
81
121
  fieldInstructionsMap[path] = {
82
122
  id: instructions.id,
@@ -85,7 +125,8 @@ export const init = async (payload, fieldSchemaPaths, pluginConfig)=>{
85
125
  }
86
126
  } else {
87
127
  if (instructions['field-type'] !== fieldType) {
88
- payload.logger.warn(`— AI Plugin: Field type mismatch for ${path}! Was "${fieldType}", it is "${instructions['field-type']}" now. Updating...`);
128
+ const currentFieldType = instructions['field-type'];
129
+ payload.logger.warn(`— AI Plugin: Field type mismatch for ${path}! Was "${fieldType}", it is "${currentFieldType}" now. Updating...`);
89
130
  await payload.update({
90
131
  id: instructions.id,
91
132
  collection: PLUGIN_INSTRUCTIONS_TABLE,
package/dist/init.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/init.ts"],"sourcesContent":["import type { Payload } from 'payload'\n\nimport type { PluginConfig } from './types.js'\n\nimport { defaultSeedPrompts } from './ai/prompts.js'\nimport { systemGenerate } from './ai/utils/systemGenerate.js'\nimport { PLUGIN_INSTRUCTIONS_TABLE } from './defaults.js'\nimport { getGenerationModels } from './utilities/getGenerationModels.js'\n\nexport const init = async (\n payload: Payload,\n fieldSchemaPaths: Record<string, { label: string; relationTo?: string; type: string }>,\n pluginConfig: PluginConfig,\n) => {\n if (!pluginConfig.generatePromptOnInit) {\n return\n }\n\n if (pluginConfig.debugging) {\n payload.logger.info(`— AI Plugin: Initializing...`)\n }\n\n const paths = Object.keys(fieldSchemaPaths)\n\n // Get all instructions for faster initialization\n const { docs: allInstructions } = await payload.find({\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n depth: 0,\n pagination: false,\n select: {\n 'field-type': true,\n 'schema-path': true,\n },\n })\n\n const fieldInstructionsMap: Record<string, { fieldType: any; id: any }> = {}\n\n for (let i = 0; i < paths.length; i++) {\n const path = paths[i]\n const { type: fieldType, label: fieldLabel, relationTo } = fieldSchemaPaths[path]\n let instructions = allInstructions.find((entry) => entry['schema-path'] === path)\n\n if (!instructions) {\n let seed\n const seedOptions = {\n fieldLabel,\n fieldSchemaPaths,\n fieldType,\n path,\n }\n\n if (pluginConfig.seedPrompts) {seed = await pluginConfig.seedPrompts(seedOptions)}\n if (seed === undefined) {seed = await defaultSeedPrompts(seedOptions)}\n // Field should be ignored\n if (!seed) {\n if (pluginConfig.debugging) {\n payload.logger.info(`— AI Plugin: No seed prompt for ${path}, ignoring...`)\n }\n continue\n }\n\n let generatedPrompt = '{{ title }}'\n if ('prompt' in seed) {\n // find the model that has the generateText function\n const models = getGenerationModels(pluginConfig)\n const model =\n models && Array.isArray(models) ? models.find((model) => model.generateText) : undefined\n generatedPrompt = await systemGenerate(\n {\n prompt: seed.prompt,\n system: seed.system,\n },\n model?.generateText,\n )\n }\n\n const modelsForId = getGenerationModels(pluginConfig)\n const modelForId =\n modelsForId && Array.isArray(modelsForId)\n ? modelsForId.find((a) => a.fields.includes(fieldType))\n : undefined\n\n const data = {\n 'model-id': modelForId?.id,\n prompt: generatedPrompt,\n ...seed.data, // allow to override data, but not the one below\n 'field-type': fieldType,\n 'relation-to': relationTo,\n 'schema-path': path,\n }\n\n payload.logger.info(\n {\n 'model-id': data['model-id'],\n prompt: generatedPrompt,\n ...seed.data,\n },\n `Prompt seeded for \"${path}\" field`,\n )\n\n instructions = (await payload\n .create({\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n data,\n })\n .catch((err) => {\n payload.logger.error(err, '— AI Plugin: Error creating Compose settings-')\n })) as (typeof allInstructions)[0]\n\n if (instructions?.id) {\n fieldInstructionsMap[path] = {\n id: instructions.id,\n fieldType,\n }\n }\n } else {\n if (instructions['field-type'] !== fieldType) {\n payload.logger.warn(\n `— AI Plugin: Field type mismatch for ${path}! Was \"${fieldType}\", it is \"${instructions['field-type']}\" now. Updating...`,\n )\n await payload.update({\n id: instructions.id,\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n data: {\n 'field-type': fieldType,\n },\n })\n instructions['field-type'] = fieldType\n }\n\n fieldInstructionsMap[path] = {\n id: instructions.id,\n fieldType,\n }\n }\n }\n\n if (pluginConfig.debugging) {\n payload.logger.info(\n `— AI Plugin: Enabled fields map: ${JSON.stringify(fieldInstructionsMap, null, 2)}`,\n )\n payload.logger.info(`— AI Plugin: Initialized!`)\n }\n\n if (pluginConfig.generatePromptOnInit) {\n payload.logger.info(\n '\\n\\n-AI Plugin: Example prompts are added to get you started, Now go break some code 🚀🚀🚀\\n\\n',\n )\n }\n}\n"],"names":["defaultSeedPrompts","systemGenerate","PLUGIN_INSTRUCTIONS_TABLE","getGenerationModels","init","payload","fieldSchemaPaths","pluginConfig","generatePromptOnInit","debugging","logger","info","paths","Object","keys","docs","allInstructions","find","collection","depth","pagination","select","fieldInstructionsMap","i","length","path","type","fieldType","label","fieldLabel","relationTo","instructions","entry","seed","seedOptions","seedPrompts","undefined","generatedPrompt","models","model","Array","isArray","generateText","prompt","system","modelsForId","modelForId","a","fields","includes","data","id","create","catch","err","error","warn","update","JSON","stringify"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/init.ts"],"sourcesContent":["import type { Payload } from 'payload'\n\nimport type { PluginConfig } from './types.js'\n\nimport { defaultSeedPrompts } from './ai/prompts.js'\nimport { systemGenerate } from './ai/utils/systemGenerate.js'\nimport { PLUGIN_INSTRUCTIONS_TABLE } from './defaults.js'\nimport { getGenerationModels } from './utilities/getGenerationModels.js'\n\nexport const init = async (\n payload: Payload,\n fieldSchemaPaths: Record<string, { label: string; relationTo?: string; type: string }>,\n pluginConfig: PluginConfig,\n) => {\n if (!pluginConfig.generatePromptOnInit) {\n return\n }\n\n if (pluginConfig.debugging) {\n payload.logger.info(`— AI Plugin: Initializing...`)\n }\n\n const paths = Object.keys(fieldSchemaPaths)\n\n // Note: schema-path is globally unique, so we create one entry per path regardless of localization\n // Localization info is kept for potential future use or debugging\n const _isLocalized =\n pluginConfig._localization?.enabled && pluginConfig._localization.locales.length > 0\n const _locales = pluginConfig._localization?.locales || []\n\n // Get all instructions for faster initialization\n // Query with locale: 'all' to get entries from all locales when localization is enabled\n const { docs: allInstructions } = await payload.find({\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n depth: 0,\n locale: 'all',\n pagination: false,\n select: {\n id: true,\n 'field-type': true,\n 'schema-path': true,\n },\n })\n\n const fieldInstructionsMap: Record<string, { fieldType: string; id: number | string }> = {}\n\n type InstructionDoc = (typeof allInstructions)[0]\n\n for (let i = 0; i < paths.length; i++) {\n const path = paths[i]\n const { type: fieldType, label: fieldLabel, relationTo } = fieldSchemaPaths[path]\n // Find existing entry for this path (schema-path is globally unique, not per locale)\n let instructions: InstructionDoc | undefined = allInstructions.find(\n (entry) => entry['schema-path'] === path,\n )\n\n if (!instructions) {\n let seed\n const seedOptions = {\n fieldLabel,\n fieldSchemaPaths,\n fieldType,\n path,\n }\n\n if (pluginConfig.seedPrompts) {\n seed = await pluginConfig.seedPrompts(seedOptions)\n }\n if (seed === undefined) {\n seed = await defaultSeedPrompts(seedOptions)\n }\n // Field should be ignored\n if (!seed) {\n if (pluginConfig.debugging) {\n payload.logger.info(`— AI Plugin: No seed prompt for ${path}, ignoring...`)\n }\n continue\n }\n\n let generatedPrompt = '{{ title }}'\n if ('prompt' in seed) {\n // find the model that has the generateText function\n const models = getGenerationModels(pluginConfig)\n const model =\n models && Array.isArray(models) ? models.find((model) => model.generateText) : undefined\n generatedPrompt = await systemGenerate(\n {\n prompt: seed.prompt,\n system: seed.system,\n },\n model?.generateText,\n )\n }\n\n const modelsForId = getGenerationModels(pluginConfig)\n const modelForId =\n modelsForId && Array.isArray(modelsForId)\n ? modelsForId.find((a) => a.fields.includes(fieldType))\n : undefined\n\n const data = {\n 'model-id': modelForId?.id,\n prompt: generatedPrompt,\n ...seed.data, // allow to override data, but not the one below\n 'field-type': fieldType,\n 'relation-to': relationTo,\n 'schema-path': path,\n }\n\n payload.logger.info(\n {\n 'model-id': data['model-id'],\n prompt: generatedPrompt,\n ...seed.data,\n },\n `Prompt seeded for \"${path}\" field`,\n )\n\n try {\n instructions = (await payload.create({\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n data,\n })) as InstructionDoc\n } catch (err: unknown) {\n // Handle unique constraint violation - entry might already exist for another locale\n const error = err as { data?: { errors?: Array<{ path?: string }> }; name?: string }\n if (\n error?.name === 'ValidationError' &&\n error?.data?.errors?.some((e) => e.path === 'schema-path')\n ) {\n // Try to find the existing entry across all locales\n const { docs } = await payload.find({\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n limit: 1,\n locale: 'all',\n select: {\n id: true,\n 'field-type': true,\n 'schema-path': true,\n },\n where: {\n 'schema-path': {\n equals: path,\n },\n },\n })\n\n const existingEntry = docs[0] as InstructionDoc | undefined\n if (existingEntry) {\n instructions = existingEntry\n if (pluginConfig.debugging) {\n payload.logger.info(\n `— AI Plugin: Entry already exists for ${path}, using existing entry`,\n )\n }\n } else {\n payload.logger.error(err, `— AI Plugin: Error creating Compose settings for ${path}`)\n }\n } else {\n payload.logger.error(err, `— AI Plugin: Error creating Compose settings for ${path}`)\n }\n }\n\n if (instructions?.id) {\n fieldInstructionsMap[path] = {\n id: instructions.id,\n fieldType,\n }\n }\n } else {\n if (instructions['field-type'] !== fieldType) {\n const currentFieldType = instructions['field-type'] as string\n payload.logger.warn(\n `— AI Plugin: Field type mismatch for ${path}! Was \"${fieldType}\", it is \"${currentFieldType}\" now. Updating...`,\n )\n await payload.update({\n id: instructions.id,\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n data: {\n 'field-type': fieldType,\n },\n })\n instructions['field-type'] = fieldType\n }\n\n fieldInstructionsMap[path] = {\n id: instructions.id,\n fieldType,\n }\n }\n }\n\n if (pluginConfig.debugging) {\n payload.logger.info(\n `— AI Plugin: Enabled fields map: ${JSON.stringify(fieldInstructionsMap, null, 2)}`,\n )\n payload.logger.info(`— AI Plugin: Initialized!`)\n }\n\n if (pluginConfig.generatePromptOnInit) {\n payload.logger.info(\n '\\n\\n-AI Plugin: Example prompts are added to get you started, Now go break some code 🚀🚀🚀\\n\\n',\n )\n }\n}\n"],"names":["defaultSeedPrompts","systemGenerate","PLUGIN_INSTRUCTIONS_TABLE","getGenerationModels","init","payload","fieldSchemaPaths","pluginConfig","generatePromptOnInit","debugging","logger","info","paths","Object","keys","_isLocalized","_localization","enabled","locales","length","_locales","docs","allInstructions","find","collection","depth","locale","pagination","select","id","fieldInstructionsMap","i","path","type","fieldType","label","fieldLabel","relationTo","instructions","entry","seed","seedOptions","seedPrompts","undefined","generatedPrompt","models","model","Array","isArray","generateText","prompt","system","modelsForId","modelForId","a","fields","includes","data","create","err","error","name","errors","some","e","limit","where","equals","existingEntry","currentFieldType","warn","update","JSON","stringify"],"mappings":"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"}
package/dist/plugin.js CHANGED
@@ -53,10 +53,36 @@ const securityMessage = `
53
53
  ║ them explicitly in your plugin configuration. ║
54
54
  ╚═══════════════════════════════════════════════════════════════╝
55
55
  `;
56
+ const isLocalizationEnabled = (config)=>{
57
+ return config !== false && typeof config === 'object' && config !== null && 'locales' in config && Array.isArray(config.locales) && config.locales.length > 0;
58
+ };
59
+ const extractLocales = (config)=>{
60
+ if (config && typeof config === 'object' && 'locales' in config && Array.isArray(config.locales)) {
61
+ return {
62
+ defaultLocale: 'defaultLocale' in config && typeof config.defaultLocale === 'string' ? config.defaultLocale : undefined,
63
+ locales: config.locales.map((locale)=>typeof locale === 'string' ? locale : locale.code)
64
+ };
65
+ }
66
+ return {
67
+ locales: []
68
+ };
69
+ };
56
70
  const payloadAiPlugin = (pluginConfig)=>(incomingConfig)=>{
71
+ const localizationConfig = incomingConfig.localization;
72
+ const hasLocalization = isLocalizationEnabled(localizationConfig);
73
+ const localizationData = hasLocalization ? extractLocales(localizationConfig) : {
74
+ locales: []
75
+ };
57
76
  pluginConfig = {
58
77
  ...defaultPluginConfig,
59
78
  ...pluginConfig,
79
+ _localization: hasLocalization ? {
80
+ enabled: true,
81
+ ...localizationData
82
+ } : {
83
+ enabled: false,
84
+ locales: []
85
+ },
60
86
  access: {
61
87
  ...defaultPluginConfig.access,
62
88
  ...pluginConfig.access
@@ -67,7 +93,7 @@ const payloadAiPlugin = (pluginConfig)=>(incomingConfig)=>{
67
93
  let updatedConfig = {
68
94
  ...incomingConfig
69
95
  };
70
- let collectionsFieldPathMap = {};
96
+ const collectionsFieldPathMap = {};
71
97
  if (isActivated) {
72
98
  const Instructions = instructionsCollection(pluginConfig);
73
99
  // Inject editor schema to config, so that it can be accessed when /textarea endpoint will hit
@@ -110,19 +136,17 @@ const payloadAiPlugin = (pluginConfig)=>(incomingConfig)=>{
110
136
  }
111
137
  };
112
138
  const pluginEndpoints = endpoints(pluginConfig);
139
+ const processedCollections = collections.map((collection)=>{
140
+ if (collectionSlugs[collection.slug]) {
141
+ const { schemaPathMap, updatedCollectionConfig } = updateFieldsConfig(collection);
142
+ Object.assign(collectionsFieldPathMap, schemaPathMap);
143
+ return updatedCollectionConfig;
144
+ }
145
+ return collection;
146
+ });
113
147
  updatedConfig = {
114
148
  ...incomingConfig,
115
- collections: collections.map((collection)=>{
116
- if (collectionSlugs[collection.slug]) {
117
- const { schemaPathMap, updatedCollectionConfig } = updateFieldsConfig(collection);
118
- collectionsFieldPathMap = {
119
- ...collectionsFieldPathMap,
120
- ...schemaPathMap
121
- };
122
- return updatedCollectionConfig;
123
- }
124
- return collection;
125
- }),
149
+ collections: processedCollections,
126
150
  endpoints: [
127
151
  ...incomingConfig.endpoints ?? [],
128
152
  pluginEndpoints.textarea,
@@ -130,12 +154,9 @@ const payloadAiPlugin = (pluginConfig)=>(incomingConfig)=>{
130
154
  fetchFields(pluginConfig)
131
155
  ],
132
156
  globals: globals.map((global)=>{
133
- if (globalsSlugs && globalsSlugs[global.slug]) {
157
+ if (globalsSlugs?.[global.slug]) {
134
158
  const { schemaPathMap, updatedCollectionConfig } = updateFieldsConfig(global);
135
- collectionsFieldPathMap = {
136
- ...collectionsFieldPathMap,
137
- ...schemaPathMap
138
- };
159
+ Object.assign(collectionsFieldPathMap, schemaPathMap);
139
160
  return updatedCollectionConfig;
140
161
  }
141
162
  return global;
@@ -149,7 +170,9 @@ const payloadAiPlugin = (pluginConfig)=>(incomingConfig)=>{
149
170
  };
150
171
  }
151
172
  updatedConfig.onInit = async (payload)=>{
152
- if (incomingConfig.onInit) await incomingConfig.onInit(payload);
173
+ if (incomingConfig.onInit) {
174
+ await incomingConfig.onInit(payload);
175
+ }
153
176
  if (!isActivated) {
154
177
  payload.logger.warn(`— AI Plugin: Not activated. Please verify your environment keys.`);
155
178
  return;
@@ -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 { defaultGenerationModels } from './ai/models/index.js'\nimport { lexicalJsonSchema } from './ai/schemas/lexicalJsonSchema.js'\nimport { instructionsCollection } from './collections/Instructions.js'\nimport { PLUGIN_NAME } from './defaults.js'\nimport { fetchFields } from './endpoints/fetchFields.js'\nimport { endpoints } from './endpoints/index.js'\nimport { init } from './init.js'\nimport { translations } from './translations/index.js'\nimport { getGenerationModels } from './utilities/getGenerationModels.js'\nimport { isPluginActivated } from './utilities/isPluginActivated.js'\nimport { updateFieldsConfig } from './utilities/updateFieldsConfig.js'\n\nconst defaultPluginConfig: PluginConfig = {\n access: {\n generate: ({ req }) => !!req.user,\n settings: ({ req }) => !!req.user,\n },\n collections: {},\n disableSponsorMessage: false,\n generatePromptOnInit: true,\n generationModels: defaultGenerationModels,\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 pluginConfig.generationModels = getGenerationModels(pluginConfig)\n\n const isActivated = isPluginActivated(pluginConfig)\n let updatedConfig: Config = { ...incomingConfig }\n let collectionsFieldPathMap = {}\n\n if (isActivated) {\n const Instructions = instructionsCollection(pluginConfig)\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]\n const globals = [...(incomingConfig.globals ?? [])]\n const { collections: collectionSlugs, globals: globalsSlugs } = pluginConfig\n\n const { components: { providers = [] } = {} } = incomingConfig.admin || {}\n const updatedProviders = [\n ...(providers ?? []),\n {\n path: '@ai-stack/payloadcms/client#InstructionsProvider',\n },\n ]\n\n incomingConfig.admin = {\n ...(incomingConfig.admin || {}),\n components: {\n ...(incomingConfig.admin?.components ?? {}),\n providers: updatedProviders,\n },\n }\n\n const pluginEndpoints = endpoints(pluginConfig)\n updatedConfig = {\n ...incomingConfig,\n collections: collections.map((collection) => {\n if (collectionSlugs[collection.slug]) {\n const { schemaPathMap, updatedCollectionConfig } = updateFieldsConfig(collection)\n collectionsFieldPathMap = {\n ...collectionsFieldPathMap,\n ...schemaPathMap,\n }\n return updatedCollectionConfig as CollectionConfig\n }\n\n return collection\n }),\n endpoints: [\n ...(incomingConfig.endpoints ?? []),\n pluginEndpoints.textarea,\n pluginEndpoints.upload,\n fetchFields(pluginConfig),\n ],\n globals: globals.map((global) => {\n if (globalsSlugs && globalsSlugs[global.slug]) {\n const { schemaPathMap, updatedCollectionConfig } = updateFieldsConfig(global)\n collectionsFieldPathMap = {\n ...collectionsFieldPathMap,\n ...schemaPathMap,\n }\n return updatedCollectionConfig as GlobalConfig\n }\n\n return global\n }),\n i18n: {\n ...(incomingConfig.i18n || {}),\n translations: {\n ...deepMerge(translations, incomingConfig.i18n?.translations ?? {}),\n },\n },\n }\n }\n\n updatedConfig.onInit = async (payload) => {\n if (incomingConfig.onInit) await incomingConfig.onInit(payload)\n\n if (!isActivated) {\n payload.logger.warn(`— AI Plugin: Not activated. Please verify your environment keys.`)\n return\n }\n\n await init(payload, collectionsFieldPathMap, pluginConfig)\n .catch((error) => {\n payload.logger.error(error, `— AI Plugin: Initialization Error`)\n })\n .finally(() => {\n if (!pluginConfig.disableSponsorMessage) {\n setTimeout(() => {\n payload.logger.info(securityMessage)\n }, 1000)\n setTimeout(() => {\n payload.logger.info(sponsorMessage)\n }, 3000)\n }\n })\n }\n\n return updatedConfig\n }\n\nexport { payloadAiPlugin }\n"],"names":["deepMerge","defaultGenerationModels","lexicalJsonSchema","instructionsCollection","PLUGIN_NAME","fetchFields","endpoints","init","translations","getGenerationModels","isPluginActivated","updateFieldsConfig","defaultPluginConfig","access","generate","req","user","settings","collections","disableSponsorMessage","generatePromptOnInit","generationModels","sponsorMessage","securityMessage","payloadAiPlugin","pluginConfig","incomingConfig","isActivated","updatedConfig","collectionsFieldPathMap","Instructions","lexicalSchema","editorConfig","nodes","admin","debugging","hidden","custom","schema","globals","collectionSlugs","globalsSlugs","components","providers","updatedProviders","path","pluginEndpoints","map","collection","slug","schemaPathMap","updatedCollectionConfig","textarea","upload","global","i18n","onInit","payload","logger","warn","catch","error","finally","setTimeout","info"],"mappings":"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"}
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 { defaultGenerationModels } from './ai/models/index.js'\nimport { lexicalJsonSchema } from './ai/schemas/lexicalJsonSchema.js'\nimport { instructionsCollection } from './collections/Instructions.js'\nimport { PLUGIN_NAME } from './defaults.js'\nimport { fetchFields } from './endpoints/fetchFields.js'\nimport { endpoints } from './endpoints/index.js'\nimport { init } from './init.js'\nimport { translations } from './translations/index.js'\nimport { getGenerationModels } from './utilities/getGenerationModels.js'\nimport { isPluginActivated } from './utilities/isPluginActivated.js'\nimport { updateFieldsConfig } from './utilities/updateFieldsConfig.js'\n\nconst defaultPluginConfig: PluginConfig = {\n access: {\n generate: ({ req }) => !!req.user,\n settings: ({ req }) => !!req.user,\n },\n collections: {},\n disableSponsorMessage: false,\n generatePromptOnInit: true,\n generationModels: defaultGenerationModels,\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 isLocalizationEnabled = (config: Config['localization']) => {\n return (\n config !== false &&\n typeof config === 'object' &&\n config !== null &&\n 'locales' in config &&\n Array.isArray(config.locales) &&\n config.locales.length > 0\n )\n}\n\nconst extractLocales = (\n config: Config['localization'],\n): { defaultLocale?: string; locales: string[] } => {\n if (\n config &&\n typeof config === 'object' &&\n 'locales' in config &&\n Array.isArray(config.locales)\n ) {\n return {\n defaultLocale:\n 'defaultLocale' in config && typeof config.defaultLocale === 'string'\n ? config.defaultLocale\n : undefined,\n locales: config.locales.map((locale) =>\n typeof locale === 'string' ? locale : (locale as { code: string }).code,\n ),\n }\n }\n return { locales: [] }\n}\n\nconst payloadAiPlugin =\n (pluginConfig: PluginConfig) =>\n (incomingConfig: Config): Config => {\n const localizationConfig = incomingConfig.localization\n const hasLocalization = isLocalizationEnabled(localizationConfig)\n const localizationData = hasLocalization ? extractLocales(localizationConfig) : { locales: [] }\n\n pluginConfig = {\n ...defaultPluginConfig,\n ...pluginConfig,\n _localization: hasLocalization\n ? {\n enabled: true,\n ...localizationData,\n }\n : {\n enabled: false,\n locales: [],\n },\n access: {\n ...defaultPluginConfig.access,\n ...pluginConfig.access,\n },\n }\n\n pluginConfig.generationModels = getGenerationModels(pluginConfig)\n\n const isActivated = isPluginActivated(pluginConfig)\n let updatedConfig: Config = { ...incomingConfig }\n const collectionsFieldPathMap: Record<\n string,\n { label: string; relationTo?: string; type: string }\n > = {}\n\n if (isActivated) {\n const Instructions = instructionsCollection(pluginConfig)\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]\n const globals = [...(incomingConfig.globals ?? [])]\n const { collections: collectionSlugs, globals: globalsSlugs } = pluginConfig\n\n const { components: { providers = [] } = {} } = incomingConfig.admin || {}\n const updatedProviders = [\n ...(providers ?? []),\n {\n path: '@ai-stack/payloadcms/client#InstructionsProvider',\n },\n ]\n\n incomingConfig.admin = {\n ...(incomingConfig.admin || {}),\n components: {\n ...(incomingConfig.admin?.components ?? {}),\n providers: updatedProviders,\n },\n }\n\n const pluginEndpoints = endpoints(pluginConfig)\n\n const processedCollections = collections.map((collection) => {\n if (collectionSlugs[collection.slug]) {\n const { schemaPathMap, updatedCollectionConfig } = updateFieldsConfig(collection)\n Object.assign(collectionsFieldPathMap, schemaPathMap)\n return updatedCollectionConfig as CollectionConfig\n }\n return collection\n })\n\n updatedConfig = {\n ...incomingConfig,\n collections: processedCollections,\n endpoints: [\n ...(incomingConfig.endpoints ?? []),\n pluginEndpoints.textarea,\n pluginEndpoints.upload,\n fetchFields(pluginConfig),\n ],\n globals: globals.map((global) => {\n if (globalsSlugs?.[global.slug]) {\n const { schemaPathMap, updatedCollectionConfig } = updateFieldsConfig(global)\n Object.assign(collectionsFieldPathMap, schemaPathMap)\n return updatedCollectionConfig as GlobalConfig\n }\n return global\n }),\n i18n: {\n ...(incomingConfig.i18n || {}),\n translations: {\n ...deepMerge(translations, incomingConfig.i18n?.translations ?? {}),\n },\n },\n }\n }\n\n updatedConfig.onInit = async (payload) => {\n if (incomingConfig.onInit) {\n await incomingConfig.onInit(payload)\n }\n\n if (!isActivated) {\n payload.logger.warn(`— AI Plugin: Not activated. Please verify your environment keys.`)\n return\n }\n\n await init(payload, collectionsFieldPathMap, pluginConfig)\n .catch((error) => {\n payload.logger.error(error, `— AI Plugin: Initialization Error`)\n })\n .finally(() => {\n if (!pluginConfig.disableSponsorMessage) {\n setTimeout(() => {\n payload.logger.info(securityMessage)\n }, 1000)\n setTimeout(() => {\n payload.logger.info(sponsorMessage)\n }, 3000)\n }\n })\n }\n\n return updatedConfig\n }\n\nexport { payloadAiPlugin }\n"],"names":["deepMerge","defaultGenerationModels","lexicalJsonSchema","instructionsCollection","PLUGIN_NAME","fetchFields","endpoints","init","translations","getGenerationModels","isPluginActivated","updateFieldsConfig","defaultPluginConfig","access","generate","req","user","settings","collections","disableSponsorMessage","generatePromptOnInit","generationModels","sponsorMessage","securityMessage","isLocalizationEnabled","config","Array","isArray","locales","length","extractLocales","defaultLocale","undefined","map","locale","code","payloadAiPlugin","pluginConfig","incomingConfig","localizationConfig","localization","hasLocalization","localizationData","_localization","enabled","isActivated","updatedConfig","collectionsFieldPathMap","Instructions","lexicalSchema","editorConfig","nodes","admin","debugging","hidden","custom","schema","globals","collectionSlugs","globalsSlugs","components","providers","updatedProviders","path","pluginEndpoints","processedCollections","collection","slug","schemaPathMap","updatedCollectionConfig","Object","assign","textarea","upload","global","i18n","onInit","payload","logger","warn","catch","error","finally","setTimeout","info"],"mappings":"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"}
@@ -4,6 +4,9 @@ import { useContext, useEffect, useMemo, useState } from 'react';
4
4
  import { PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js';
5
5
  import { handlebarsHelpers, handlebarsHelpersMap } from '../../libraries/handlebars/helpersMap.js';
6
6
  const warnedOnceOnNoInstructionId = new Set();
7
+ const normalizePath = (path)=>{
8
+ return path.replace(/\._index-\d+-\d+/g, '');
9
+ };
7
10
  const warnOnceOnMissingInstructions = (path)=>{
8
11
  if (!warnedOnceOnNoInstructionId.has(path)) {
9
12
  warnedOnceOnNoInstructionId.add(path);
@@ -14,7 +17,7 @@ const warnOnceOnMissingInstructions = (path)=>{
14
17
  export const useInstructions = (update = {})=>{
15
18
  const context = useContext(InstructionsContext);
16
19
  const { collectionSlug } = useDocumentInfo();
17
- const { activeCollection, hasInstructions, instructions, promptFields, setActiveCollection, debugging } = context;
20
+ const { activeCollection, debugging, hasInstructions, instructions, promptFields, setActiveCollection } = context;
18
21
  const [schemaPath, setSchemaPath] = useState(update.schemaPath);
19
22
  useEffect(()=>{
20
23
  if (update.schemaPath !== schemaPath) {
@@ -84,7 +87,8 @@ export const useInstructions = (update = {})=>{
84
87
  instructions,
85
88
  promptFields
86
89
  ]);
87
- const pathInstructions = instructions[schemaPath];
90
+ const normalizedPath = schemaPath ? normalizePath(schemaPath) : '';
91
+ const pathInstructions = instructions[normalizedPath];
88
92
  if (debugging && !pathInstructions && schemaPath && hasInstructions) {
89
93
  warnOnceOnMissingInstructions(schemaPath);
90
94
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/providers/InstructionsProvider/useInstructions.ts"],"sourcesContent":["import { InstructionsContext } from '@ai-stack/payloadcms/client'\nimport { useDocumentInfo } from '@payloadcms/ui'\nimport { useContext, useEffect, useMemo, useState } from 'react'\n\nimport { PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js'\nimport { handlebarsHelpers, handlebarsHelpersMap } from '../../libraries/handlebars/helpersMap.js'\n\n\nconst warnedOnceOnNoInstructionId = new Set<string>()\nconst warnOnceOnMissingInstructions = (path: string) => {\n if (!warnedOnceOnNoInstructionId.has(path)) {\n warnedOnceOnNoInstructionId.add(path)\n // eslint-disable-next-line no-console\n console.info(`[AI Plugin] There are no AI instructions for this field: ${path}. Enable \"generatePromptOnInit\" option to enable them.`)\n }\n}\n\nexport const useInstructions = (\n update: {\n schemaPath?: unknown\n } = {},\n) => {\n const context = useContext(InstructionsContext)\n const { collectionSlug } = useDocumentInfo()\n const { activeCollection, hasInstructions, instructions, promptFields, setActiveCollection, debugging } = context\n\n const [schemaPath, setSchemaPath] = useState(update.schemaPath as string)\n\n useEffect(() => {\n if (update.schemaPath !== schemaPath) {\n setSchemaPath((update.schemaPath as string) ?? '')\n }\n }, [update.schemaPath])\n\n useEffect(() => {\n if (\n activeCollection !== collectionSlug &&\n collectionSlug !== PLUGIN_INSTRUCTIONS_TABLE &&\n typeof setActiveCollection === 'function'\n ) {\n setActiveCollection(collectionSlug ?? '')\n }\n }, [activeCollection, collectionSlug, setActiveCollection])\n\n const groupedFields = useMemo(() => {\n const result: Record<string, string[]> = {}\n\n for (const fullKey of Object.keys(instructions || {})) {\n const [collection, ...pathParts] = fullKey.split('.')\n const path = pathParts.join('.')\n if (!result[collection]) {\n result[collection] = []\n }\n result[collection].push(path)\n }\n\n return result\n }, [instructions])\n\n // Suggestions for prompt editor\n const promptEditorSuggestions = useMemo(() => {\n const activeFields = groupedFields[activeCollection as string] || []\n\n const suggestions: string[] = []\n\n activeFields.forEach((f) => {\n const fieldKey = Object.keys(instructions).find((k) => k.endsWith(f))\n const fieldInfo = fieldKey ? instructions[fieldKey] : undefined\n\n if (!fieldInfo) {return}\n\n if (fieldInfo.fieldType === 'upload') {\n suggestions.push(`${f}.url`)\n return\n }\n\n const helpers = handlebarsHelpers.filter(\n (h) => (handlebarsHelpersMap as Record<string, any>)[h]?.field === fieldInfo.fieldType,\n )\n\n if (helpers.length) {\n for (const helper of helpers) {\n suggestions.push(`${helper} ${f}`)\n }\n } else {\n suggestions.push(f)\n }\n }, [])\n\n promptFields.forEach(({ name, collections }) => {\n if (!activeCollection) {return}\n\n if (!collections || collections.includes(activeCollection)) {\n suggestions.push(name)\n }\n })\n\n return suggestions\n }, [groupedFields, activeCollection, instructions, promptFields])\n\n const pathInstructions = instructions[schemaPath]\n\n if (debugging && !pathInstructions && schemaPath && hasInstructions) {\n warnOnceOnMissingInstructions(schemaPath)\n }\n \n return {\n ...context,\n ...(pathInstructions || {}),\n promptEditorSuggestions,\n }\n}\n"],"names":["InstructionsContext","useDocumentInfo","useContext","useEffect","useMemo","useState","PLUGIN_INSTRUCTIONS_TABLE","handlebarsHelpers","handlebarsHelpersMap","warnedOnceOnNoInstructionId","Set","warnOnceOnMissingInstructions","path","has","add","console","info","useInstructions","update","context","collectionSlug","activeCollection","hasInstructions","instructions","promptFields","setActiveCollection","debugging","schemaPath","setSchemaPath","groupedFields","result","fullKey","Object","keys","collection","pathParts","split","join","push","promptEditorSuggestions","activeFields","suggestions","forEach","f","fieldKey","find","k","endsWith","fieldInfo","undefined","fieldType","helpers","filter","h","field","length","helper","name","collections","includes","pathInstructions"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/providers/InstructionsProvider/useInstructions.ts"],"sourcesContent":["import { InstructionsContext } from '@ai-stack/payloadcms/client'\nimport { useDocumentInfo } from '@payloadcms/ui'\nimport { useContext, useEffect, useMemo, useState } from 'react'\n\nimport { PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js'\nimport { handlebarsHelpers, handlebarsHelpersMap } from '../../libraries/handlebars/helpersMap.js'\n\nconst warnedOnceOnNoInstructionId = new Set<string>()\n\nconst normalizePath = (path: string): string => {\n return path.replace(/\\._index-\\d+-\\d+/g, '')\n}\n\nconst warnOnceOnMissingInstructions = (path: string) => {\n if (!warnedOnceOnNoInstructionId.has(path)) {\n warnedOnceOnNoInstructionId.add(path)\n // eslint-disable-next-line no-console\n console.info(`[AI Plugin] There are no AI instructions for this field: ${path}. Enable \"generatePromptOnInit\" option to enable them.`)\n }\n}\n\nexport const useInstructions = (\n update: {\n schemaPath?: unknown\n } = {},\n) => {\n const context = useContext(InstructionsContext)\n const { collectionSlug } = useDocumentInfo()\n const { activeCollection, debugging, hasInstructions, instructions, promptFields, setActiveCollection } = context\n\n const [schemaPath, setSchemaPath] = useState(update.schemaPath as string)\n\n useEffect(() => {\n if (update.schemaPath !== schemaPath) {\n setSchemaPath((update.schemaPath as string) ?? '')\n }\n }, [update.schemaPath])\n\n useEffect(() => {\n if (\n activeCollection !== collectionSlug &&\n collectionSlug !== PLUGIN_INSTRUCTIONS_TABLE &&\n typeof setActiveCollection === 'function'\n ) {\n setActiveCollection(collectionSlug ?? '')\n }\n }, [activeCollection, collectionSlug, setActiveCollection])\n\n const groupedFields = useMemo(() => {\n const result: Record<string, string[]> = {}\n for (const fullKey of Object.keys(instructions || {})) {\n const [collection, ...pathParts] = fullKey.split('.')\n const path = pathParts.join('.')\n if (!result[collection]) {\n result[collection] = []\n }\n result[collection].push(path)\n }\n return result\n }, [instructions])\n\n // Suggestions for prompt editor\n const promptEditorSuggestions = useMemo(() => {\n const activeFields = groupedFields[activeCollection as string] || []\n const suggestions: string[] = []\n\n activeFields.forEach((f) => {\n const fieldKey = Object.keys(instructions).find((k) => k.endsWith(f))\n const fieldInfo = fieldKey ? instructions[fieldKey] : undefined\n if (!fieldInfo) { return }\n\n if (fieldInfo.fieldType === 'upload') {\n suggestions.push(`${f}.url`)\n return\n }\n\n const helpers = handlebarsHelpers.filter(\n (h) => (handlebarsHelpersMap as Record<string, any>)[h]?.field === fieldInfo.fieldType,\n )\n\n if (helpers.length) {\n for (const helper of helpers) {\n suggestions.push(`${helper} ${f}`)\n }\n } else {\n suggestions.push(f)\n }\n }, [])\n\n promptFields.forEach(({ name, collections }) => {\n if (!activeCollection) { return }\n if (!collections || collections.includes(activeCollection)) {\n suggestions.push(name)\n }\n })\n\n return suggestions\n }, [groupedFields, activeCollection, instructions, promptFields])\n\n const normalizedPath = schemaPath ? normalizePath(schemaPath) : ''\n const pathInstructions = instructions[normalizedPath]\n\n if (debugging && !pathInstructions && schemaPath && hasInstructions) {\n warnOnceOnMissingInstructions(schemaPath)\n }\n\n return {\n ...context,\n ...(pathInstructions || {}),\n promptEditorSuggestions,\n }\n}"],"names":["InstructionsContext","useDocumentInfo","useContext","useEffect","useMemo","useState","PLUGIN_INSTRUCTIONS_TABLE","handlebarsHelpers","handlebarsHelpersMap","warnedOnceOnNoInstructionId","Set","normalizePath","path","replace","warnOnceOnMissingInstructions","has","add","console","info","useInstructions","update","context","collectionSlug","activeCollection","debugging","hasInstructions","instructions","promptFields","setActiveCollection","schemaPath","setSchemaPath","groupedFields","result","fullKey","Object","keys","collection","pathParts","split","join","push","promptEditorSuggestions","activeFields","suggestions","forEach","f","fieldKey","find","k","endsWith","fieldInfo","undefined","fieldType","helpers","filter","h","field","length","helper","name","collections","includes","normalizedPath","pathInstructions"],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -2,7 +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 { PLUGIN_INSTRUCTIONS_TABLE } from "./defaults.js";
5
+ import type { PLUGIN_INSTRUCTIONS_TABLE } from './defaults.js';
6
6
  export interface PluginConfigAccess {
7
7
  /**
8
8
  * Control access to AI generation features (generate text, images, audio)
@@ -36,6 +36,16 @@ export type PluginConfigMediaUploadFunction = (result: {
36
36
  request: PayloadRequest;
37
37
  }) => Promise<DataFromCollectionSlug<CollectionSlug>>;
38
38
  export interface PluginConfig {
39
+ /**
40
+ * Localization configuration for Instructions collection
41
+ * Automatically populated from Payload config if localization is enabled
42
+ * @internal
43
+ */
44
+ _localization?: {
45
+ defaultLocale?: string;
46
+ enabled: boolean;
47
+ locales: string[];
48
+ };
39
49
  /**
40
50
  * Access control configuration for AI features
41
51
  * By default, all AI features require authentication
@@ -70,7 +80,7 @@ export interface PluginConfig {
70
80
  * Custom seed prompt function for generating field-specific prompts
71
81
  * If not provided, uses default seed prompt function
72
82
  * You can access default seed prompts by importing { defaultSeedPrompts } from '@ai-stack/payloadcms'
73
- */
83
+ */
74
84
  seedPrompts?: SeedPromptFunction;
75
85
  uploadCollectionSlug?: CollectionSlug;
76
86
  }
@@ -159,7 +169,7 @@ export type GenerateImageParams = {
159
169
  version?: ImageGenerateParams['model'];
160
170
  };
161
171
  export type SerializedPromptField = {
162
- collections?: (CollectionSlug)[];
172
+ collections?: CollectionSlug[];
163
173
  name: string;
164
174
  };
165
175
  export type PromptFieldGetterContext = {
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 {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: { data: Record<any, any>; file: File },\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 collections: {\n [key: CollectionSlug]: boolean\n }\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, uses default seed prompt function\n * You can access default seed prompts by importing { defaultSeedPrompts } from '@ai-stack/payloadcms'\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) => 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 textarea: Omit<Endpoint, 'root'>\n upload: 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<TypedCollection[typeof PLUGIN_INSTRUCTIONS_TABLE], 'createdAt' | 'id' | 'updatedAt'>\n\nexport type SeedPromptResult = {\n data?: SeedPromptData\n} | {\n data?: SeedPromptData\n prompt: string\n system: string\n} | false | undefined | void\n\nexport type SeedPromptFunction = (options: SeedPromptOptions) => 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"],"names":[],"mappings":"AA4NA,WAGyB"}
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 { 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: { data: Record<any, any>; file: File },\n {\n collection,\n request,\n }: {\n collection: CollectionSlug\n request: PayloadRequest\n },\n) => Promise<DataFromCollectionSlug<CollectionSlug>>\n\nexport interface PluginConfig {\n /**\n * Localization configuration for Instructions collection\n * Automatically populated from Payload config if localization is enabled\n * @internal\n */\n _localization?: {\n defaultLocale?: string\n enabled: boolean\n locales: string[]\n }\n /**\n * Access control configuration for AI features\n * By default, all AI features require authentication\n */\n access?: PluginConfigAccess\n collections: {\n [key: CollectionSlug]: boolean\n }\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, uses default seed prompt function\n * You can access default seed prompts by importing { defaultSeedPrompts } from '@ai-stack/payloadcms'\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) => 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 textarea: Omit<Endpoint, 'root'>\n upload: 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"],"names":[],"mappings":"AAgPA,WAGyB"}
@@ -1,5 +1,5 @@
1
- import type { ClientCollectionConfig, CollectionConfig, Field } from 'payload';
2
- type AnyCollectionConfig = ClientCollectionConfig | CollectionConfig;
1
+ import type { Field, GlobalConfig, CollectionConfig, ClientGlobalConfig, ClientCollectionConfig } from 'payload';
2
+ type AnyCollectionConfig = GlobalConfig | CollectionConfig | ClientGlobalConfig | ClientCollectionConfig;
3
3
  /**
4
4
  * Resolve a Payload field definition by a full schemaPath like:
5
5
  * "{collectionSlug}.fieldA.subFieldB.blockSlug.innerField"
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/getFieldBySchemaPath.ts"],"sourcesContent":["import type { ClientCollectionConfig, CollectionConfig, Field } from 'payload'\n\ntype AnyCollectionConfig = ClientCollectionConfig | CollectionConfig\n\n/**\n * Resolve a Payload field definition by a full schemaPath like:\n * \"{collectionSlug}.fieldA.subFieldB.blockSlug.innerField\"\n *\n * Notes:\n * - Tabs are a UI construct and are not part of schemaPath (fields inside tabs are at the same level).\n * - Blocks include the block slug as part of the path (we must consume it between the block field and its inner fields).\n * - Rows are skipped by this plugin&#39;s schema path mapping; support added defensively.\n */\nexport const getFieldBySchemaPath = (\n collectionConfig: AnyCollectionConfig,\n schemaPath: string,\n): Field | null => {\n if (!collectionConfig || !schemaPath) {\n return null\n }\n\n const parts = schemaPath.split('.')\n if (!parts.length) {\n return null\n }\n\n // Strip the collection slug prefix if present\n const [collectionSlug, ...rest] = parts\n const pathParts =\n collectionSlug === collectionConfig.slug ? rest.filter(Boolean) : parts.filter(Boolean)\n\n if (!pathParts.length) {\n return null\n }\n\n const findInFields = (fields: Field[], segments: string[]): Field | null => {\n if (!segments.length) {\n return null\n }\n\n const [current, ...remaining] = segments\n\n // First, try to match a field by name\n for (const field of fields) {\n // Tabs do not contribute to path segments; search inside all tabs with the same segments\n if ((field as any).tabs) {\n const tabs = (field as any).tabs as Array<{ fields?: Field[] }>\n for (const tab of tabs) {\n const foundInTab =\n tab.fields && tab.fields.length ? findInFields(tab.fields, segments) : null\n if (foundInTab) {\n return foundInTab\n }\n }\n }\n\n if ((field as any).name === current) {\n // If this is the last segment, we found the target field\n if (remaining.length === 0) {\n return field\n }\n\n // Recurse into composite field types\n if ((field as any).fields && Array.isArray((field as any).fields)) {\n const found = findInFields((field as any).fields, remaining)\n if (found) {\n return found\n }\n }\n\n if ((field as any).blocks && Array.isArray((field as any).blocks)) {\n // Next segment should be a block slug, then continue into block fields\n if (!remaining.length) {\n return field\n } // path stops at block container (unlikely for our mapping)\n const [blockSlug, ...afterBlock] = remaining\n const blocks = (field as any).blocks as Array<{ fields: Field[]; slug: string }>\n const block = blocks.find((b) => b.slug === blockSlug)\n if (block) {\n const found = findInFields(block.fields, afterBlock)\n if (found) {\n return found\n }\n }\n }\n }\n }\n\n // Not found at this level\n return null\n }\n\n const rootFields = (collectionConfig as any).fields as Field[] | undefined\n if (!rootFields || !Array.isArray(rootFields)) {\n return null\n }\n\n return findInFields(rootFields, pathParts)\n}\n"],"names":["getFieldBySchemaPath","collectionConfig","schemaPath","parts","split","length","collectionSlug","rest","pathParts","slug","filter","Boolean","findInFields","fields","segments","current","remaining","field","tabs","tab","foundInTab","name","Array","isArray","found","blocks","blockSlug","afterBlock","block","find","b","rootFields"],"mappings":"AAIA;;;;;;;;CAQC,GACD,OAAO,MAAMA,uBAAuB,CAClCC,kBACAC;IAEA,IAAI,CAACD,oBAAoB,CAACC,YAAY;QACpC,OAAO;IACT;IAEA,MAAMC,QAAQD,WAAWE,KAAK,CAAC;IAC/B,IAAI,CAACD,MAAME,MAAM,EAAE;QACjB,OAAO;IACT;IAEA,8CAA8C;IAC9C,MAAM,CAACC,gBAAgB,GAAGC,KAAK,GAAGJ;IAClC,MAAMK,YACJF,mBAAmBL,iBAAiBQ,IAAI,GAAGF,KAAKG,MAAM,CAACC,WAAWR,MAAMO,MAAM,CAACC;IAEjF,IAAI,CAACH,UAAUH,MAAM,EAAE;QACrB,OAAO;IACT;IAEA,MAAMO,eAAe,CAACC,QAAiBC;QACrC,IAAI,CAACA,SAAST,MAAM,EAAE;YACpB,OAAO;QACT;QAEA,MAAM,CAACU,SAAS,GAAGC,UAAU,GAAGF;QAEhC,sCAAsC;QACtC,KAAK,MAAMG,SAASJ,OAAQ;YAC1B,yFAAyF;YACzF,IAAI,AAACI,MAAcC,IAAI,EAAE;gBACvB,MAAMA,OAAO,AAACD,MAAcC,IAAI;gBAChC,KAAK,MAAMC,OAAOD,KAAM;oBACtB,MAAME,aACJD,IAAIN,MAAM,IAAIM,IAAIN,MAAM,CAACR,MAAM,GAAGO,aAAaO,IAAIN,MAAM,EAAEC,YAAY;oBACzE,IAAIM,YAAY;wBACd,OAAOA;oBACT;gBACF;YACF;YAEA,IAAI,AAACH,MAAcI,IAAI,KAAKN,SAAS;gBACnC,yDAAyD;gBACzD,IAAIC,UAAUX,MAAM,KAAK,GAAG;oBAC1B,OAAOY;gBACT;gBAEA,qCAAqC;gBACrC,IAAI,AAACA,MAAcJ,MAAM,IAAIS,MAAMC,OAAO,CAAC,AAACN,MAAcJ,MAAM,GAAG;oBACjE,MAAMW,QAAQZ,aAAa,AAACK,MAAcJ,MAAM,EAAEG;oBAClD,IAAIQ,OAAO;wBACT,OAAOA;oBACT;gBACF;gBAEA,IAAI,AAACP,MAAcQ,MAAM,IAAIH,MAAMC,OAAO,CAAC,AAACN,MAAcQ,MAAM,GAAG;oBACjE,uEAAuE;oBACvE,IAAI,CAACT,UAAUX,MAAM,EAAE;wBACrB,OAAOY;oBACT,EAAE,2DAA2D;oBAC7D,MAAM,CAACS,WAAW,GAAGC,WAAW,GAAGX;oBACnC,MAAMS,SAAS,AAACR,MAAcQ,MAAM;oBACpC,MAAMG,QAAQH,OAAOI,IAAI,CAAC,CAACC,IAAMA,EAAErB,IAAI,KAAKiB;oBAC5C,IAAIE,OAAO;wBACT,MAAMJ,QAAQZ,aAAagB,MAAMf,MAAM,EAAEc;wBACzC,IAAIH,OAAO;4BACT,OAAOA;wBACT;oBACF;gBACF;YACF;QACF;QAEA,0BAA0B;QAC1B,OAAO;IACT;IAEA,MAAMO,aAAa,AAAC9B,iBAAyBY,MAAM;IACnD,IAAI,CAACkB,cAAc,CAACT,MAAMC,OAAO,CAACQ,aAAa;QAC7C,OAAO;IACT;IAEA,OAAOnB,aAAamB,YAAYvB;AAClC,EAAC"}
1
+ {"version":3,"sources":["../../src/utilities/getFieldBySchemaPath.ts"],"sourcesContent":["import type {\n Field,\n GlobalConfig,\n CollectionConfig,\n ClientGlobalConfig,\n ClientCollectionConfig,\n} from 'payload'\n\ntype AnyCollectionConfig =\n | GlobalConfig\n | CollectionConfig\n | ClientGlobalConfig\n | ClientCollectionConfig\n\n/**\n * Resolve a Payload field definition by a full schemaPath like:\n * \"{collectionSlug}.fieldA.subFieldB.blockSlug.innerField\"\n *\n * Notes:\n * - Tabs are a UI construct and are not part of schemaPath (fields inside tabs are at the same level).\n * - Blocks include the block slug as part of the path (we must consume it between the block field and its inner fields).\n * - Rows are skipped by this plugin&#39;s schema path mapping; support added defensively.\n */\nexport const getFieldBySchemaPath = (\n collectionConfig: AnyCollectionConfig,\n schemaPath: string,\n): Field | null => {\n if (!collectionConfig || !schemaPath) {\n return null\n }\n\n const parts = schemaPath.split('.')\n if (!parts.length) {\n return null\n }\n\n // Strip the collection slug prefix if present\n const [collectionSlug, ...rest] = parts\n const pathParts =\n collectionSlug === collectionConfig.slug ? rest.filter(Boolean) : parts.filter(Boolean)\n\n if (!pathParts.length) {\n return null\n }\n\n const findInFields = (fields: Field[], segments: string[]): Field | null => {\n if (!segments.length) {\n return null\n }\n\n const [current, ...remaining] = segments\n\n // First, try to match a field by name\n for (const field of fields) {\n // Tabs do not contribute to path segments; search inside all tabs with the same segments\n if ((field as any).tabs) {\n const tabs = (field as any).tabs as Array<{ fields?: Field[] }>\n for (const tab of tabs) {\n const foundInTab =\n tab.fields && tab.fields.length ? findInFields(tab.fields, segments) : null\n if (foundInTab) {\n return foundInTab\n }\n }\n }\n\n if ((field as any).name === current) {\n // If this is the last segment, we found the target field\n if (remaining.length === 0) {\n return field\n }\n\n // Recurse into composite field types\n if ((field as any).fields && Array.isArray((field as any).fields)) {\n const found = findInFields((field as any).fields, remaining)\n if (found) {\n return found\n }\n }\n\n if ((field as any).blocks && Array.isArray((field as any).blocks)) {\n // Next segment should be a block slug, then continue into block fields\n if (!remaining.length) {\n return field\n } // path stops at block container (unlikely for our mapping)\n const [blockSlug, ...afterBlock] = remaining\n const blocks = (field as any).blocks as Array<{ fields: Field[]; slug: string }>\n const block = blocks.find((b) => b.slug === blockSlug)\n if (block) {\n const found = findInFields(block.fields, afterBlock)\n if (found) {\n return found\n }\n }\n }\n }\n }\n\n // Not found at this level\n return null\n }\n\n const rootFields = (collectionConfig as any).fields as Field[] | undefined\n if (!rootFields || !Array.isArray(rootFields)) {\n return null\n }\n\n return findInFields(rootFields, pathParts)\n}\n"],"names":["getFieldBySchemaPath","collectionConfig","schemaPath","parts","split","length","collectionSlug","rest","pathParts","slug","filter","Boolean","findInFields","fields","segments","current","remaining","field","tabs","tab","foundInTab","name","Array","isArray","found","blocks","blockSlug","afterBlock","block","find","b","rootFields"],"mappings":"AAcA;;;;;;;;CAQC,GACD,OAAO,MAAMA,uBAAuB,CAClCC,kBACAC;IAEA,IAAI,CAACD,oBAAoB,CAACC,YAAY;QACpC,OAAO;IACT;IAEA,MAAMC,QAAQD,WAAWE,KAAK,CAAC;IAC/B,IAAI,CAACD,MAAME,MAAM,EAAE;QACjB,OAAO;IACT;IAEA,8CAA8C;IAC9C,MAAM,CAACC,gBAAgB,GAAGC,KAAK,GAAGJ;IAClC,MAAMK,YACJF,mBAAmBL,iBAAiBQ,IAAI,GAAGF,KAAKG,MAAM,CAACC,WAAWR,MAAMO,MAAM,CAACC;IAEjF,IAAI,CAACH,UAAUH,MAAM,EAAE;QACrB,OAAO;IACT;IAEA,MAAMO,eAAe,CAACC,QAAiBC;QACrC,IAAI,CAACA,SAAST,MAAM,EAAE;YACpB,OAAO;QACT;QAEA,MAAM,CAACU,SAAS,GAAGC,UAAU,GAAGF;QAEhC,sCAAsC;QACtC,KAAK,MAAMG,SAASJ,OAAQ;YAC1B,yFAAyF;YACzF,IAAI,AAACI,MAAcC,IAAI,EAAE;gBACvB,MAAMA,OAAO,AAACD,MAAcC,IAAI;gBAChC,KAAK,MAAMC,OAAOD,KAAM;oBACtB,MAAME,aACJD,IAAIN,MAAM,IAAIM,IAAIN,MAAM,CAACR,MAAM,GAAGO,aAAaO,IAAIN,MAAM,EAAEC,YAAY;oBACzE,IAAIM,YAAY;wBACd,OAAOA;oBACT;gBACF;YACF;YAEA,IAAI,AAACH,MAAcI,IAAI,KAAKN,SAAS;gBACnC,yDAAyD;gBACzD,IAAIC,UAAUX,MAAM,KAAK,GAAG;oBAC1B,OAAOY;gBACT;gBAEA,qCAAqC;gBACrC,IAAI,AAACA,MAAcJ,MAAM,IAAIS,MAAMC,OAAO,CAAC,AAACN,MAAcJ,MAAM,GAAG;oBACjE,MAAMW,QAAQZ,aAAa,AAACK,MAAcJ,MAAM,EAAEG;oBAClD,IAAIQ,OAAO;wBACT,OAAOA;oBACT;gBACF;gBAEA,IAAI,AAACP,MAAcQ,MAAM,IAAIH,MAAMC,OAAO,CAAC,AAACN,MAAcQ,MAAM,GAAG;oBACjE,uEAAuE;oBACvE,IAAI,CAACT,UAAUX,MAAM,EAAE;wBACrB,OAAOY;oBACT,EAAE,2DAA2D;oBAC7D,MAAM,CAACS,WAAW,GAAGC,WAAW,GAAGX;oBACnC,MAAMS,SAAS,AAACR,MAAcQ,MAAM;oBACpC,MAAMG,QAAQH,OAAOI,IAAI,CAAC,CAACC,IAAMA,EAAErB,IAAI,KAAKiB;oBAC5C,IAAIE,OAAO;wBACT,MAAMJ,QAAQZ,aAAagB,MAAMf,MAAM,EAAEc;wBACzC,IAAIH,OAAO;4BACT,OAAOA;wBACT;oBACF;gBACF;YACF;QACF;QAEA,0BAA0B;QAC1B,OAAO;IACT;IAEA,MAAMO,aAAa,AAAC9B,iBAAyBY,MAAM;IACnD,IAAI,CAACkB,cAAc,CAACT,MAAMC,OAAO,CAACQ,aAAa;QAC7C,OAAO;IACT;IAEA,OAAOnB,aAAamB,YAAYvB;AAClC,EAAC"}
@@ -1,50 +1,66 @@
1
1
  export const updateFieldsConfig = (collectionConfig)=>{
2
2
  let schemaPathMap = {};
3
- function updateField(field, parentPath = '') {
4
- const currentPath = parentPath ? `${parentPath}.${field.name}` : field.name;
3
+ /**
4
+ * Recursively updates field configuration to inject AI components
5
+ * @param field - Payload field to process
6
+ * @param parentPath - Schema path from parent (for nested fields)
7
+ */ function updateField(field, parentPath = '') {
8
+ const fieldWithName = field;
9
+ const currentPath = parentPath ? `${parentPath}.${fieldWithName.name}` : fieldWithName.name;
5
10
  const currentSchemaPath = `${collectionConfig.slug}.${currentPath}`;
6
- // Disabled fields/ field types
7
- if (field.admin?.disabled || field.admin?.readOnly || field.admin?.hidden || field.type === 'row') {
11
+ // Disabled fields/ field types - skip processing
12
+ const admin = field.admin;
13
+ if (admin?.disabled || admin?.readOnly || admin?.hidden) {
8
14
  return field;
9
15
  }
16
+ // Rows are layout-only constructs and should not add to the schema path (like tabs)
17
+ // Process their nested fields but use parentPath to maintain correct path structure
18
+ if (field.type === 'row' && 'fields' in field) {
19
+ const fieldWithFields = field;
20
+ return {
21
+ ...field,
22
+ fields: fieldWithFields.fields.map((subField)=>updateField(subField, parentPath))
23
+ };
24
+ }
10
25
  // Map field path for global fieldInstructionsMap to load related instructions
11
26
  // This is done due to save extra API call to get instructions when Field components are loaded in admin
12
27
  // Doing is will only call instructions data when user clicks on settings
13
- if ([
28
+ if (field.type && [
14
29
  'richText',
15
30
  'text',
16
31
  'textarea',
17
32
  'upload'
18
33
  ].includes(field.type)) {
34
+ const fieldAny = field;
19
35
  schemaPathMap = {
20
36
  ...schemaPathMap,
21
37
  [currentSchemaPath]: {
22
38
  type: field.type,
23
- label: field.label || field.name,
24
- relationTo: field.relationTo
39
+ label: fieldAny.label || fieldWithName.name,
40
+ relationTo: fieldAny.relationTo
25
41
  }
26
42
  };
27
43
  }
28
44
  // Inject AI actions, richText is not included here as it has to be explicitly defined by user
29
- if ([
45
+ if (field.type && [
30
46
  'text',
31
47
  'textarea',
32
48
  'upload'
33
49
  ].includes(field.type)) {
34
- let customField = {};
50
+ const customField = {};
35
51
  // Custom fields don't fully adhere to the Payload schema, making it difficult to
36
52
  // determine which components support injecting ComposeField as a Description.
37
- if (field.admin?.components?.Field || field.admin?.components?.Description) {
38
- // TODO: If a field already provides its own Description, we still inject our ComposeField
39
- // by overriding Description. If you need both, consider composing your own wrapper.
40
- customField = {};
53
+ if (admin?.components) {
54
+ // TODO: If a field already provides its own Description, we still inject our ComposeField
55
+ // by overriding Description. If you need both, consider composing your own wrapper.
56
+ // customField would be used here if needed
41
57
  }
42
58
  return {
43
59
  ...field,
44
60
  admin: {
45
61
  ...field.admin,
46
62
  components: {
47
- ...field.admin?.components || {},
63
+ ...admin?.components || {},
48
64
  Description: {
49
65
  clientProps: {
50
66
  schemaPath: currentSchemaPath
@@ -56,16 +72,20 @@ export const updateFieldsConfig = (collectionConfig)=>{
56
72
  }
57
73
  };
58
74
  }
59
- if (field.fields) {
75
+ // Handle fields with nested fields (group, collapsible, etc.)
76
+ if ('fields' in field && Array.isArray(field.fields)) {
77
+ const fieldWithFields = field;
60
78
  return {
61
79
  ...field,
62
- fields: field.fields.map((subField)=>updateField(subField, currentPath))
80
+ fields: fieldWithFields.fields.map((subField)=>updateField(subField, currentPath))
63
81
  };
64
82
  }
65
- if (field.tabs) {
83
+ // Handle fields with tabs
84
+ if ('tabs' in field && Array.isArray(field.tabs)) {
85
+ const fieldWithTabs = field;
66
86
  return {
67
87
  ...field,
68
- tabs: field.tabs.map((tab)=>{
88
+ tabs: fieldWithTabs.tabs.map((tab)=>{
69
89
  return {
70
90
  ...tab,
71
91
  // Tabs are a UI construct and should not add to the schema path
@@ -74,10 +94,12 @@ export const updateFieldsConfig = (collectionConfig)=>{
74
94
  })
75
95
  };
76
96
  }
77
- if (field.blocks) {
97
+ // Handle fields with blocks
98
+ if ('blocks' in field && Array.isArray(field.blocks)) {
99
+ const fieldWithBlocks = field;
78
100
  return {
79
101
  ...field,
80
- blocks: field.blocks.map((block)=>({
102
+ blocks: fieldWithBlocks.blocks.map((block)=>({
81
103
  ...block,
82
104
  fields: block.fields.map((subField)=>updateField(subField, `${currentPath}.${block.slug}`))
83
105
  }))
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/updateFieldsConfig.ts"],"sourcesContent":["import type { CollectionConfig, GlobalConfig } from 'payload'\n\ninterface UpdateFieldsConfig {\n schemaPathMap: Record<string, string>\n updatedCollectionConfig: CollectionConfig | GlobalConfig\n}\n\nexport const updateFieldsConfig = (collectionConfig: CollectionConfig | GlobalConfig): UpdateFieldsConfig => {\n let schemaPathMap = {}\n\n function updateField(field: any, parentPath = ''): any {\n const currentPath = parentPath ? `${parentPath}.${field.name}` : field.name\n const currentSchemaPath = `${collectionConfig.slug}.${currentPath}`\n\n // Disabled fields/ field types\n if (\n field.admin?.disabled ||\n field.admin?.readOnly ||\n field.admin?.hidden ||\n field.type === 'row'\n ) {\n return field\n }\n\n // Map field path for global fieldInstructionsMap to load related instructions\n // This is done due to save extra API call to get instructions when Field components are loaded in admin\n // Doing is will only call instructions data when user clicks on settings\n if (['richText', 'text', 'textarea', 'upload'].includes(field.type)) {\n schemaPathMap = {\n ...schemaPathMap,\n [currentSchemaPath]: {\n type: field.type,\n label: field.label || field.name,\n relationTo: field.relationTo,\n },\n }\n }\n\n // Inject AI actions, richText is not included here as it has to be explicitly defined by user\n if (['text', 'textarea', 'upload'].includes(field.type)) {\n let customField = {}\n\n // Custom fields don't fully adhere to the Payload schema, making it difficult to\n // determine which components support injecting ComposeField as a Description.\n if (field.admin?.components?.Field || field.admin?.components?.Description) {\n // TODO: If a field already provides its own Description, we still inject our ComposeField\n // by overriding Description. If you need both, consider composing your own wrapper.\n customField = {}\n }\n\n return {\n ...field,\n admin: {\n ...field.admin,\n components: {\n ...(field.admin?.components || {}),\n Description: {\n clientProps: {\n schemaPath: currentSchemaPath,\n },\n path: '@ai-stack/payloadcms/fields#ComposeField',\n },\n ...customField,\n },\n },\n }\n }\n\n if (field.fields) {\n return {\n ...field,\n fields: field.fields.map((subField: any) => updateField(subField, currentPath)),\n }\n }\n\n if (field.tabs) {\n return {\n ...field,\n tabs: field.tabs.map((tab: any) => {\n return {\n ...tab,\n // Tabs are a UI construct and should not add to the schema path\n fields: (tab.fields || []).map((subField: any) => updateField(subField, parentPath)),\n }\n }),\n }\n }\n\n if (field.blocks) {\n return {\n ...field,\n blocks: field.blocks.map((block: any) => ({\n ...block,\n fields: block.fields.map((subField: any) =>\n updateField(subField, `${currentPath}.${block.slug}`),\n ),\n })),\n }\n }\n\n return field\n }\n\n const updatedCollectionConfig = {\n ...collectionConfig,\n fields: collectionConfig.fields.map((field) => updateField(field)),\n }\n\n return {\n schemaPathMap,\n updatedCollectionConfig,\n }\n}\n"],"names":["updateFieldsConfig","collectionConfig","schemaPathMap","updateField","field","parentPath","currentPath","name","currentSchemaPath","slug","admin","disabled","readOnly","hidden","type","includes","label","relationTo","customField","components","Field","Description","clientProps","schemaPath","path","fields","map","subField","tabs","tab","blocks","block","updatedCollectionConfig"],"mappings":"AAOA,OAAO,MAAMA,qBAAqB,CAACC;IACjC,IAAIC,gBAAgB,CAAC;IAErB,SAASC,YAAYC,KAAU,EAAEC,aAAa,EAAE;QAC9C,MAAMC,cAAcD,aAAa,CAAC,EAAEA,WAAW,CAAC,EAAED,MAAMG,IAAI,CAAC,CAAC,GAAGH,MAAMG,IAAI;QAC3E,MAAMC,oBAAoB,CAAC,EAAEP,iBAAiBQ,IAAI,CAAC,CAAC,EAAEH,YAAY,CAAC;QAEnE,+BAA+B;QAC/B,IACEF,MAAMM,KAAK,EAAEC,YACbP,MAAMM,KAAK,EAAEE,YACbR,MAAMM,KAAK,EAAEG,UACbT,MAAMU,IAAI,KAAK,OACf;YACA,OAAOV;QACT;QAEA,8EAA8E;QAC9E,wGAAwG;QACxG,yEAAyE;QACzE,IAAI;YAAC;YAAY;YAAQ;YAAY;SAAS,CAACW,QAAQ,CAACX,MAAMU,IAAI,GAAG;YACnEZ,gBAAgB;gBACd,GAAGA,aAAa;gBAChB,CAACM,kBAAkB,EAAE;oBACnBM,MAAMV,MAAMU,IAAI;oBAChBE,OAAOZ,MAAMY,KAAK,IAAIZ,MAAMG,IAAI;oBAChCU,YAAYb,MAAMa,UAAU;gBAC9B;YACF;QACF;QAEA,8FAA8F;QAC9F,IAAI;YAAC;YAAQ;YAAY;SAAS,CAACF,QAAQ,CAACX,MAAMU,IAAI,GAAG;YACvD,IAAII,cAAc,CAAC;YAEnB,iFAAiF;YACjF,8EAA8E;YAC9E,IAAId,MAAMM,KAAK,EAAES,YAAYC,SAAShB,MAAMM,KAAK,EAAES,YAAYE,aAAa;gBAC1E,0FAA0F;gBAC1F,oFAAoF;gBACpFH,cAAc,CAAC;YACjB;YAEA,OAAO;gBACL,GAAGd,KAAK;gBACRM,OAAO;oBACL,GAAGN,MAAMM,KAAK;oBACdS,YAAY;wBACV,GAAIf,MAAMM,KAAK,EAAES,cAAc,CAAC,CAAC;wBACjCE,aAAa;4BACXC,aAAa;gCACXC,YAAYf;4BACd;4BACAgB,MAAM;wBACR;wBACA,GAAGN,WAAW;oBAChB;gBACF;YACF;QACF;QAEA,IAAId,MAAMqB,MAAM,EAAE;YAChB,OAAO;gBACL,GAAGrB,KAAK;gBACRqB,QAAQrB,MAAMqB,MAAM,CAACC,GAAG,CAAC,CAACC,WAAkBxB,YAAYwB,UAAUrB;YACpE;QACF;QAEA,IAAIF,MAAMwB,IAAI,EAAE;YACd,OAAO;gBACL,GAAGxB,KAAK;gBACRwB,MAAMxB,MAAMwB,IAAI,CAACF,GAAG,CAAC,CAACG;oBACpB,OAAO;wBACL,GAAGA,GAAG;wBACN,gEAAgE;wBAChEJ,QAAQ,AAACI,CAAAA,IAAIJ,MAAM,IAAI,EAAE,AAAD,EAAGC,GAAG,CAAC,CAACC,WAAkBxB,YAAYwB,UAAUtB;oBAC1E;gBACF;YACF;QACF;QAEA,IAAID,MAAM0B,MAAM,EAAE;YAChB,OAAO;gBACL,GAAG1B,KAAK;gBACR0B,QAAQ1B,MAAM0B,MAAM,CAACJ,GAAG,CAAC,CAACK,QAAgB,CAAA;wBACxC,GAAGA,KAAK;wBACRN,QAAQM,MAAMN,MAAM,CAACC,GAAG,CAAC,CAACC,WACxBxB,YAAYwB,UAAU,CAAC,EAAErB,YAAY,CAAC,EAAEyB,MAAMtB,IAAI,CAAC,CAAC;oBAExD,CAAA;YACF;QACF;QAEA,OAAOL;IACT;IAEA,MAAM4B,0BAA0B;QAC9B,GAAG/B,gBAAgB;QACnBwB,QAAQxB,iBAAiBwB,MAAM,CAACC,GAAG,CAAC,CAACtB,QAAUD,YAAYC;IAC7D;IAEA,OAAO;QACLF;QACA8B;IACF;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/utilities/updateFieldsConfig.ts"],"sourcesContent":["import type { CollectionConfig, Field, GlobalConfig } from 'payload'\n\ninterface UpdateFieldsConfig {\n schemaPathMap: Record<string, string>\n updatedCollectionConfig: CollectionConfig | GlobalConfig\n}\n\ntype FieldWithName = { name: string }\ntype FieldWithFields = { fields: Field[] }\ntype FieldWithTabs = { tabs: Array<{ fields?: Field[] }> }\ntype FieldWithBlocks = { blocks: Array<{ fields: Field[]; slug: string }> }\n\nexport const updateFieldsConfig = (\n collectionConfig: CollectionConfig | GlobalConfig,\n): UpdateFieldsConfig => {\n let schemaPathMap = {}\n\n /**\n * Recursively updates field configuration to inject AI components\n * @param field - Payload field to process\n * @param parentPath - Schema path from parent (for nested fields)\n */\n function updateField(field: Field, parentPath = ''): Field {\n const fieldWithName = field as Field & FieldWithName\n const currentPath = parentPath ? `${parentPath}.${fieldWithName.name}` : fieldWithName.name\n const currentSchemaPath = `${collectionConfig.slug}.${currentPath}`\n\n // Disabled fields/ field types - skip processing\n const admin = field.admin as Record<string, unknown> | undefined\n if (admin?.disabled || admin?.readOnly || admin?.hidden) {\n return field\n }\n\n // Rows are layout-only constructs and should not add to the schema path (like tabs)\n // Process their nested fields but use parentPath to maintain correct path structure\n if (field.type === 'row' && 'fields' in field) {\n const fieldWithFields = field as Field & FieldWithFields\n return {\n ...field,\n fields: fieldWithFields.fields.map((subField) => updateField(subField, parentPath)),\n } as Field\n }\n\n // Map field path for global fieldInstructionsMap to load related instructions\n // This is done due to save extra API call to get instructions when Field components are loaded in admin\n // Doing is will only call instructions data when user clicks on settings\n if (field.type && ['richText', 'text', 'textarea', 'upload'].includes(field.type)) {\n const fieldAny = field as Record<string, unknown>\n schemaPathMap = {\n ...schemaPathMap,\n [currentSchemaPath]: {\n type: field.type,\n label: fieldAny.label || fieldWithName.name,\n relationTo: fieldAny.relationTo,\n },\n }\n }\n\n // Inject AI actions, richText is not included here as it has to be explicitly defined by user\n if (field.type && ['text', 'textarea', 'upload'].includes(field.type)) {\n const customField: Record<string, never> = {}\n\n // Custom fields don't fully adhere to the Payload schema, making it difficult to\n // determine which components support injecting ComposeField as a Description.\n if (admin?.components) {\n // TODO: If a field already provides its own Description, we still inject our ComposeField\n // by overriding Description. If you need both, consider composing your own wrapper.\n // customField would be used here if needed\n }\n\n return {\n ...field,\n admin: {\n ...(field.admin as Record<string, unknown>),\n components: {\n ...((admin?.components as Record<string, unknown>) || {}),\n Description: {\n clientProps: {\n schemaPath: currentSchemaPath,\n },\n path: '@ai-stack/payloadcms/fields#ComposeField',\n },\n ...customField,\n },\n },\n } as Field\n }\n\n // Handle fields with nested fields (group, collapsible, etc.)\n if ('fields' in field && Array.isArray(field.fields)) {\n const fieldWithFields = field as Field & FieldWithFields\n return {\n ...field,\n fields: fieldWithFields.fields.map((subField) => updateField(subField, currentPath)),\n } as Field\n }\n\n // Handle fields with tabs\n if ('tabs' in field && Array.isArray(field.tabs)) {\n const fieldWithTabs = field as Field & FieldWithTabs\n return {\n ...field,\n tabs: fieldWithTabs.tabs.map((tab) => {\n return {\n ...tab,\n // Tabs are a UI construct and should not add to the schema path\n fields: (tab.fields || []).map((subField) => updateField(subField, parentPath)),\n }\n }),\n } as Field\n }\n\n // Handle fields with blocks\n if ('blocks' in field && Array.isArray(field.blocks)) {\n const fieldWithBlocks = field as Field & FieldWithBlocks\n return {\n ...field,\n blocks: fieldWithBlocks.blocks.map((block) => ({\n ...block,\n fields: block.fields.map((subField) =>\n updateField(subField, `${currentPath}.${block.slug}`),\n ),\n })),\n } as Field\n }\n\n return field\n }\n\n const updatedCollectionConfig = {\n ...collectionConfig,\n fields: collectionConfig.fields.map((field) => updateField(field)),\n }\n\n return {\n schemaPathMap,\n updatedCollectionConfig,\n }\n}\n"],"names":["updateFieldsConfig","collectionConfig","schemaPathMap","updateField","field","parentPath","fieldWithName","currentPath","name","currentSchemaPath","slug","admin","disabled","readOnly","hidden","type","fieldWithFields","fields","map","subField","includes","fieldAny","label","relationTo","customField","components","Description","clientProps","schemaPath","path","Array","isArray","tabs","fieldWithTabs","tab","blocks","fieldWithBlocks","block","updatedCollectionConfig"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-stack/payloadcms",
3
- "version": "3.2.24",
3
+ "version": "3.2.26",
4
4
  "private": false,
5
5
  "bugs": "https://github.com/ashbuilds/payload-ai/issues",
6
6
  "repository": "https://github.com/ashbuilds/payload-ai",
@@ -25,41 +25,41 @@
25
25
  ],
26
26
  "exports": {
27
27
  ".": {
28
- "import": "./src/index.ts",
29
- "types": "./src/index.ts",
30
- "default": "./src/index.ts"
28
+ "import": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
30
+ "default": "./dist/index.js"
31
31
  },
32
32
  "./client": {
33
- "import": "./src/exports/client.ts",
34
- "types": "./src/exports/client.ts",
35
- "default": "./src/exports/client.ts"
33
+ "import": "./dist/exports/client.js",
34
+ "types": "./dist/exports/client.d.ts",
35
+ "default": "./dist/exports/client.js"
36
36
  },
37
37
  "./types": {
38
- "import": "./src/exports/types.ts",
39
- "types": "./src/exports/types.ts",
40
- "default": "./src/exports/types.ts"
38
+ "import": "./dist/exports/types.js",
39
+ "types": "./dist/exports/types.d.ts",
40
+ "default": "./dist/exports/types.js"
41
41
  },
42
42
  "./fields": {
43
- "import": "./src/exports/fields.ts",
44
- "types": "./src/exports/fields.ts",
45
- "default": "./src/exports/fields.ts"
43
+ "import": "./dist/exports/fields.js",
44
+ "types": "./dist/exports/fields.d.ts",
45
+ "default": "./dist/exports/fields.js"
46
46
  }
47
47
  },
48
- "main": "./src/index.ts",
49
- "types": "./src/index.ts",
48
+ "main": "./dist/index.js",
49
+ "types": "./dist/index.d.ts",
50
50
  "typesVersions": {
51
51
  "*": {
52
52
  "client": [
53
- "src/exports/client.ts"
53
+ "dist/exports/client.d.ts"
54
54
  ],
55
55
  "types": [
56
- "src/exports/types.ts"
56
+ "dist/exports/types.d.ts"
57
57
  ],
58
58
  "fields": [
59
- "src/exports/fields.ts"
59
+ "dist/exports/fields.d.ts"
60
60
  ],
61
61
  "*": [
62
- "src/*"
62
+ "dist/*"
63
63
  ]
64
64
  }
65
65
  },
package/dist/types.d.js DELETED
@@ -1,3 +0,0 @@
1
- export { };
2
-
3
- //# sourceMappingURL=types.d.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/types.d.ts"],"sourcesContent":["import type { Field } from 'payload'\n\nexport interface AIGenerateArgs {\n prompt: string\n system?: string\n schema?: Field[]\n provider?: string\n model?: string\n mode?: 'auto' | 'json' | 'tool'\n}\n\ndeclare module 'payload' {\n export interface Payload {\n ai: {\n generate: (args: AIGenerateArgs) => Promise<any>\n }\n }\n}\n"],"names":[],"mappings":"AAEA,WAOC"}