payload-forgeai 0.2.0 → 0.4.0

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.
@@ -16,7 +16,7 @@ export const ForgeAIField = (props)=>{
16
16
  const endpoint = useMemo(()=>{
17
17
  if (!collectionSlug) return null;
18
18
  const base = config?.serverURL || '';
19
- return `${base}/api/forge-ai/${collectionSlug}/${path}`;
19
+ return `${base}/api/forgeai/${collectionSlug}/${path}`;
20
20
  }, [
21
21
  collectionSlug,
22
22
  config?.serverURL,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/ForgeAIField.tsx"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useMemo, useState } from 'react'\nimport { type TextFieldClientComponent } from 'payload'\nimport { useConfig, useDocumentInfo, useField, FieldLabel, useFormFields } from '@payloadcms/ui'\n\nexport const ForgeAIField: TextFieldClientComponent = (props) => {\n const { path, field, readOnly } = props\n\n const { setValue, value, errorMessage, showError, formProcessing } = useField<string>({ path })\n const { collectionSlug, id: docId } = useDocumentInfo()\n const { config } = useConfig()\n \n // Access all form fields for context\n const allFields = useFormFields(([fields]) => fields)\n\n const [isGenerating, setIsGenerating] = useState(false)\n const [genError, setGenError] = useState<string | null>(null)\n\n const endpoint = useMemo(() => {\n if (!collectionSlug) return null\n const base = config?.serverURL || ''\n return `${base}/api/forge-ai/${collectionSlug}/${path}`\n }, [collectionSlug, config?.serverURL, path])\n\n const generate = useCallback(async () => {\n if (!endpoint) return\n setIsGenerating(true)\n setGenError(null)\n try {\n // Gather context from form fields\n const contextData: Record<string, any> = {}\n if (allFields) {\n Object.entries(allFields).forEach(([fieldPath, fieldState]) => {\n contextData[fieldPath] = fieldState.value\n })\n }\n\n const res = await fetch(endpoint, {\n method: 'POST',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n context: contextData,\n documentId: docId,\n currentValue: value, // Include current value so AI can generate something different\n }),\n })\n\n if (!res.ok) throw new Error(await res.text())\n\n const generated = await res.json()\n setValue(generated)\n } catch (e) {\n setGenError(e instanceof Error ? e.message : String(e))\n } finally {\n setIsGenerating(false)\n }\n }, [endpoint, setValue, allFields, docId])\n\n return (\n <div className=\"field-type\">\n <FieldLabel htmlFor={path} label={field.label ?? field.name} required={field.required} />\n\n <div>\n <input\n id={path}\n style={{ width: '100%' }}\n disabled={readOnly || formProcessing}\n value={value ?? ''}\n onChange={(e) => setValue(e.target.value)}\n />\n\n <button\n type=\"button\"\n onClick={generate}\n disabled={readOnly || formProcessing || isGenerating || !endpoint}\n style={{\n marginTop: 8,\n padding: '6px 12px',\n border: '1px solid var(--theme-elevation-400)',\n borderRadius: 4,\n background: 'var(--theme-elevation-50)',\n cursor: readOnly || formProcessing || isGenerating || !endpoint ? 'not-allowed' : 'pointer',\n display: 'inline-flex',\n alignItems: 'center',\n gap: 6,\n fontSize: 13,\n color: 'var(--theme-elevation-800)',\n transition: 'all 0.2s ease',\n opacity: readOnly || formProcessing || !endpoint ? 0.5 : 1,\n }}\n onMouseEnter={(e) => {\n if (!readOnly && !formProcessing && !isGenerating && endpoint) {\n e.currentTarget.style.background = 'var(--theme-elevation-100)'\n e.currentTarget.style.borderColor = 'var(--theme-elevation-500)'\n }\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'var(--theme-elevation-50)'\n e.currentTarget.style.borderColor = 'var(--theme-elevation-400)'\n }}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{\n animation: isGenerating ? 'spin 1s linear infinite' : 'none',\n }}\n >\n <path d=\"M21.5 2v6h-6M2.5 22v-6h6M2 11.5a10 10 0 0 1 18.8-4.3M22 12.5a10 10 0 0 1-18.8 4.2\" />\n </svg>\n {isGenerating ? 'Generating…' : 'Generate with AI'}\n </button>\n\n <style>{`\n @keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n `}</style>\n </div>\n\n {genError ? (\n <div style={{ marginTop: 6, color: 'var(--theme-error-500)' }}>{genError}</div>\n ) : null}\n {showError && errorMessage ? (\n <div style={{ marginTop: 6, color: 'var(--theme-error-500)' }}>{errorMessage}</div>\n ) : null}\n </div>\n )\n}\n"],"names":["React","useCallback","useMemo","useState","useConfig","useDocumentInfo","useField","FieldLabel","useFormFields","ForgeAIField","props","path","field","readOnly","setValue","value","errorMessage","showError","formProcessing","collectionSlug","id","docId","config","allFields","fields","isGenerating","setIsGenerating","genError","setGenError","endpoint","base","serverURL","generate","contextData","Object","entries","forEach","fieldPath","fieldState","res","fetch","method","credentials","headers","body","JSON","stringify","context","documentId","currentValue","ok","Error","text","generated","json","e","message","String","div","className","htmlFor","label","name","required","input","style","width","disabled","onChange","target","button","type","onClick","marginTop","padding","border","borderRadius","background","cursor","display","alignItems","gap","fontSize","color","transition","opacity","onMouseEnter","currentTarget","borderColor","onMouseLeave","svg","xmlns","height","viewBox","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","animation","d"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/components/ForgeAIField.tsx"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useMemo, useState } from 'react'\nimport { type TextFieldClientComponent } from 'payload'\nimport { useConfig, useDocumentInfo, useField, FieldLabel, useFormFields } from '@payloadcms/ui'\n\nexport const ForgeAIField: TextFieldClientComponent = (props) => {\n const { path, field, readOnly } = props\n\n const { setValue, value, errorMessage, showError, formProcessing } = useField<string>({ path })\n const { collectionSlug, id: docId } = useDocumentInfo()\n const { config } = useConfig()\n\n // Access all form fields for context\n const allFields = useFormFields(([fields]) => fields)\n\n const [isGenerating, setIsGenerating] = useState(false)\n const [genError, setGenError] = useState<string | null>(null)\n\n const endpoint = useMemo(() => {\n if (!collectionSlug) return null\n const base = config?.serverURL || ''\n return `${base}/api/forgeai/${collectionSlug}/${path}`\n }, [collectionSlug, config?.serverURL, path])\n\n const generate = useCallback(async () => {\n if (!endpoint) return\n setIsGenerating(true)\n setGenError(null)\n try {\n // Gather context from form fields\n const contextData: Record<string, any> = {}\n if (allFields) {\n Object.entries(allFields).forEach(([fieldPath, fieldState]) => {\n contextData[fieldPath] = fieldState.value\n })\n }\n\n const res = await fetch(endpoint, {\n method: 'POST',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n context: contextData,\n documentId: docId,\n currentValue: value, // Include current value so AI can generate something different\n }),\n })\n\n if (!res.ok) throw new Error(await res.text())\n\n const generated = await res.json()\n setValue(generated)\n } catch (e) {\n setGenError(e instanceof Error ? e.message : String(e))\n } finally {\n setIsGenerating(false)\n }\n }, [endpoint, setValue, allFields, docId])\n\n return (\n <div className=\"field-type\">\n <FieldLabel htmlFor={path} label={field.label ?? field.name} required={field.required} />\n\n <div>\n <input\n id={path}\n style={{ width: '100%' }}\n disabled={readOnly || formProcessing}\n value={value ?? ''}\n onChange={(e) => setValue(e.target.value)}\n />\n\n <button\n type=\"button\"\n onClick={generate}\n disabled={readOnly || formProcessing || isGenerating || !endpoint}\n style={{\n marginTop: 8,\n padding: '6px 12px',\n border: '1px solid var(--theme-elevation-400)',\n borderRadius: 4,\n background: 'var(--theme-elevation-50)',\n cursor:\n readOnly || formProcessing || isGenerating || !endpoint ? 'not-allowed' : 'pointer',\n display: 'inline-flex',\n alignItems: 'center',\n gap: 6,\n fontSize: 13,\n color: 'var(--theme-elevation-800)',\n transition: 'all 0.2s ease',\n opacity: readOnly || formProcessing || !endpoint ? 0.5 : 1,\n }}\n onMouseEnter={(e) => {\n if (!readOnly && !formProcessing && !isGenerating && endpoint) {\n e.currentTarget.style.background = 'var(--theme-elevation-100)'\n e.currentTarget.style.borderColor = 'var(--theme-elevation-500)'\n }\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'var(--theme-elevation-50)'\n e.currentTarget.style.borderColor = 'var(--theme-elevation-400)'\n }}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{\n animation: isGenerating ? 'spin 1s linear infinite' : 'none',\n }}\n >\n <path d=\"M21.5 2v6h-6M2.5 22v-6h6M2 11.5a10 10 0 0 1 18.8-4.3M22 12.5a10 10 0 0 1-18.8 4.2\" />\n </svg>\n {isGenerating ? 'Generating…' : 'Generate with AI'}\n </button>\n\n <style>{`\n @keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n }\n `}</style>\n </div>\n\n {genError ? (\n <div style={{ marginTop: 6, color: 'var(--theme-error-500)' }}>{genError}</div>\n ) : null}\n {showError && errorMessage ? (\n <div style={{ marginTop: 6, color: 'var(--theme-error-500)' }}>{errorMessage}</div>\n ) : null}\n </div>\n )\n}\n"],"names":["React","useCallback","useMemo","useState","useConfig","useDocumentInfo","useField","FieldLabel","useFormFields","ForgeAIField","props","path","field","readOnly","setValue","value","errorMessage","showError","formProcessing","collectionSlug","id","docId","config","allFields","fields","isGenerating","setIsGenerating","genError","setGenError","endpoint","base","serverURL","generate","contextData","Object","entries","forEach","fieldPath","fieldState","res","fetch","method","credentials","headers","body","JSON","stringify","context","documentId","currentValue","ok","Error","text","generated","json","e","message","String","div","className","htmlFor","label","name","required","input","style","width","disabled","onChange","target","button","type","onClick","marginTop","padding","border","borderRadius","background","cursor","display","alignItems","gap","fontSize","color","transition","opacity","onMouseEnter","currentTarget","borderColor","onMouseLeave","svg","xmlns","height","viewBox","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","animation","d"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -264,7 +264,7 @@ Custom instructions: ${field.prompt}${contextPrompt}${currentValuePrompt}
264
264
  if (!fieldData) {
265
265
  throw new InvalidConfiguration(`payload-forge-ai: Collection "${collectionSlug}" does not have field "${field.name}".`);
266
266
  }
267
- return setAdminFieldComponent(fieldData, 'payload-forge-ai/ForgeAIField#ForgeAIField');
267
+ return setAdminFieldComponent(fieldData, 'payload-forgeai/ForgeAIField#ForgeAIField');
268
268
  }) ?? []
269
269
  ]
270
270
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionConfig, CollectionSlug, Config, Field, PayloadRequest } from 'payload'\n\nimport { createOpenAI } from '@ai-sdk/openai'\nimport { generateText, type ModelMessage } from 'ai'\nimport { flattenTopLevelFields, InvalidConfiguration } from 'payload'\n\nexport type PayloadForgeAiContextField =\n | string\n | {\n field: string\n prompt?: string\n /**\n * For relationship fields, specify which fields to extract from the related document.\n * For other fields, specify which nested properties to extract.\n * If not specified, the entire value will be used.\n * Can be nested for complex object structures.\n */\n fields?: PayloadForgeAiContextField[]\n }\n\nexport type PayloadForgeAiFieldConfig = {\n context?: PayloadForgeAiContextField[]\n /**\n * If true, tells the AI to generate something different from the current value.\n * Defaults to true.\n */\n generateDifferent?: boolean\n name: string\n prompt: string\n}\n\nexport type PayloadForgeAiCollectionConfig = {\n fields: PayloadForgeAiFieldConfig[]\n}\n\nexport type PayloadForgeAiConfig = {\n apiKey: string\n collections?: Partial<Record<CollectionSlug, PayloadForgeAiCollectionConfig>>\n disabled?: boolean\n}\n\nfunction getValidFieldNames(collection: CollectionConfig): Set<string> {\n const flattened = flattenTopLevelFields(collection.fields)\n return new Set(flattened.map((f) => f.name).filter((name): name is string => name != null))\n}\n\nfunction validateCollectionFields(\n collectionSlug: string,\n collection: CollectionConfig,\n allowedFields: string[],\n): void {\n const validNames = getValidFieldNames(collection)\n const invalid = allowedFields.filter((name) => !validNames.has(name))\n if (invalid.length > 0) {\n throw new InvalidConfiguration(\n `payload-forge-ai: Collection \"${collectionSlug}\" does not have these fields: ${invalid.join(', ')}. ` +\n `Valid top-level fields: ${[...validNames].sort().join(', ')}.`,\n )\n }\n}\n\n/**\n * Recursively extract fields from an object based on field configuration\n */\nfunction extractFields(data: any, fieldConfigs: PayloadForgeAiContextField[]): Record<string, any> {\n if (!data || typeof data !== 'object') {\n return data\n }\n\n const result: Record<string, any> = {}\n\n for (const config of fieldConfigs) {\n const fieldName = typeof config === 'string' ? config : config.field\n const nestedFields = typeof config === 'string' ? undefined : config.fields\n\n if (data[fieldName] !== undefined) {\n if (nestedFields && nestedFields.length > 0) {\n // Recursively extract nested fields\n result[fieldName] = extractFields(data[fieldName], nestedFields)\n } else {\n // Just include the field value\n result[fieldName] = data[fieldName]\n }\n }\n }\n\n return result\n}\n\n/**\n * Recursively build context parts with prompts for nested fields\n */\nfunction buildContextParts(\n data: any,\n fieldConfigs: PayloadForgeAiContextField[],\n indent: string = ' ',\n): string[] {\n if (!data || typeof data !== 'object') {\n return []\n }\n\n const parts: string[] = []\n\n for (const config of fieldConfigs) {\n const fieldName = typeof config === 'string' ? config : config.field\n const customPrompt = typeof config === 'string' ? undefined : config.prompt\n const nestedFields = typeof config === 'string' ? undefined : config.fields\n const fieldValue = data[fieldName]\n\n if (fieldValue !== undefined && fieldValue !== null && fieldValue !== '') {\n if (nestedFields && nestedFields.length > 0 && typeof fieldValue === 'object') {\n // Handle nested fields with their own prompts\n // Add the current field's prompt as a header if it exists\n if (customPrompt) {\n parts.push(`${indent}${customPrompt}:`)\n }\n const nestedParts = buildContextParts(fieldValue, nestedFields, indent + ' ')\n parts.push(...nestedParts)\n } else {\n // Leaf value - format with prompt\n let valueStr: string\n if (typeof fieldValue === 'object') {\n valueStr = JSON.stringify(fieldValue, null, 2)\n } else {\n valueStr = String(fieldValue)\n }\n\n if (customPrompt) {\n parts.push(`${indent}${customPrompt}: ${valueStr}`)\n } else {\n parts.push(`${indent}${fieldName}: ${valueStr}`)\n }\n }\n }\n }\n\n return parts\n}\n\nexport const payloadForgeAi =\n (pluginOptions: PayloadForgeAiConfig) =>\n (config: Config): Config => {\n if (!config.collections) {\n config.collections = []\n }\n\n if (pluginOptions.disabled) {\n return config\n }\n\n const openAi = createOpenAI({\n apiKey: pluginOptions.apiKey,\n })\n\n const model = openAi('gpt-5')\n\n const systemMessages: ModelMessage[] = [\n {\n content: `\n You are a helpful assistant that can help with the creation of content in payloadCMS fields. You must return only the content and not any other questions or comments!\n The content must be in the same language as the prompt.\n The content must be in the same format as the field type.\n The content must be in the same length as the field type.\n The content must be in the same style as the field type.\n The content must be in the same tone as the field type.\n The content must be in the same voice as the field type.\n You may vary the content to make it more interesting and engaging, but you must always return the content in the same language as the prompt.\n `,\n role: 'system',\n },\n ]\n const endpoints = config.endpoints ?? []\n\n if (pluginOptions.collections) {\n for (const collectionSlug in pluginOptions.collections) {\n const entry = pluginOptions.collections[collectionSlug]\n if (!entry?.fields?.length) {\n continue\n }\n\n const collection = config.collections.find(\n (c: CollectionConfig) => c.slug === collectionSlug,\n )\n if (!collection) {\n throw new InvalidConfiguration(\n `payload-forge-ai: Collection \"${collectionSlug}\" is not defined in config.collections.`,\n )\n }\n\n const fieldNames = entry.fields.map((f) => f.name)\n\n validateCollectionFields(collectionSlug, collection, fieldNames)\n\n entry.fields.forEach((field) => {\n // Validate context fields\n if (field.context && field.context.length > 0) {\n const contextFieldNames = field.context.map((ctx) =>\n typeof ctx === 'string' ? ctx : ctx.field,\n )\n validateCollectionFields(collectionSlug, collection, contextFieldNames)\n }\n\n endpoints.push({\n handler: async (req: PayloadRequest) => {\n const payload = req.payload\n const flattened = flattenTopLevelFields(collection.fields)\n\n const fieldData = flattened.find((f) => f.name === field.name)\n if (!fieldData) {\n throw new InvalidConfiguration(\n `payload-forge-ai: Collection \"${collectionSlug}\" does not have field \"${field.name}\".`,\n )\n }\n\n // Parse request body for context\n let contextData: Record<string, any> = {}\n let documentId: string | undefined\n let currentValue: any = undefined\n\n try {\n if (req.json) {\n const body = await req.json()\n contextData = body.context || {}\n documentId = body.documentId\n currentValue = body.currentValue\n }\n } catch (e) {\n // If no body or invalid JSON, continue without context\n }\n\n // Build context prompt from configured context fields\n let contextPrompt = ''\n if (field.context && field.context.length > 0) {\n const contextParts: string[] = []\n\n for (const ctx of field.context) {\n const fieldName = typeof ctx === 'string' ? ctx : ctx.field\n const customPrompt = typeof ctx === 'string' ? undefined : ctx.prompt\n const selectedFields = typeof ctx === 'string' ? undefined : ctx.fields\n let fieldValue = contextData[fieldName]\n\n if (fieldValue !== undefined && fieldValue !== null && fieldValue !== '') {\n const contextField = flattened.find((f) => f.name === fieldName)\n const fieldType = contextField?.type || 'unknown'\n\n // Handle relationship fields - fetch the related document if we only have an ID\n if (contextField?.type === 'relationship' && typeof fieldValue === 'string') {\n try {\n const relationTo = (contextField as any).relationTo\n if (relationTo) {\n const relatedDoc = await payload.findByID({\n collection: relationTo,\n id: fieldValue,\n })\n fieldValue = relatedDoc\n }\n } catch (e) {\n console.error(`Failed to fetch related document for ${fieldName}:`, e)\n // Continue with the ID if fetch fails\n }\n }\n\n // Handle nested fields with recursive prompts\n if (\n selectedFields &&\n selectedFields.length > 0 &&\n typeof fieldValue === 'object'\n ) {\n // Add the outer prompt as a header if it exists\n if (customPrompt) {\n contextParts.push(`${customPrompt}:`)\n }\n console.log(`Building nested parts for field: ${fieldName}`)\n console.log(`Field value keys:`, Object.keys(fieldValue))\n console.log(\n `Selected fields config:`,\n JSON.stringify(selectedFields, null, 2),\n )\n const nestedParts = buildContextParts(fieldValue, selectedFields)\n console.log(`Nested parts result:`, nestedParts)\n contextParts.push(...nestedParts)\n } else {\n // Simple field without nesting\n let valueStr: string\n if (typeof fieldValue === 'object') {\n valueStr = JSON.stringify(fieldValue, null, 2)\n } else {\n valueStr = String(fieldValue)\n }\n\n if (customPrompt) {\n contextParts.push(`${customPrompt}: ${valueStr}`)\n } else {\n contextParts.push(`${fieldName} (${fieldType}): ${valueStr}`)\n }\n }\n }\n }\n\n if (contextParts.length > 0) {\n contextPrompt = '\\n\\nContext from other fields:\\n' + contextParts.join('\\n')\n }\n }\n\n // Add current value info if it exists\n let currentValuePrompt = ''\n const shouldGenerateDifferent = field.generateDifferent ?? true // Default to true\n if (currentValue !== undefined && currentValue !== null && currentValue !== '') {\n if (shouldGenerateDifferent) {\n currentValuePrompt = `\\n\\nCurrent value: ${currentValue}\\nIMPORTANT: Generate something DIFFERENT from the current value above. Do not repeat it.`\n } else {\n currentValuePrompt = `\\n\\nCurrent value: ${currentValue}`\n }\n }\n\n const messages: ModelMessage[] = [\n ...systemMessages,\n {\n content: `\nCollection: ${collectionSlug}\nField name: ${fieldData.name}\nField type: ${fieldData.type}\nCustom instructions: ${field.prompt}${contextPrompt}${currentValuePrompt}\n `,\n role: 'system',\n },\n ]\n\n console.log(messages[messages.length - 1].content)\n\n const response = await generateText({\n messages,\n model,\n })\n\n return Response.json(response.text)\n },\n method: 'post',\n path: `/forge-ai/${collectionSlug}/${field.name}`,\n })\n })\n }\n }\n\n const collectionSlugs = Object.keys(pluginOptions?.collections ?? {})\n\n return {\n ...config,\n collections: [\n ...(config.collections ?? []).filter(\n (c: CollectionConfig) => !collectionSlugs.includes(c.slug),\n ),\n ...collectionSlugs.map((collectionSlug) => {\n const collection = config.collections?.find(\n (c: CollectionConfig) => c.slug === collectionSlug,\n )\n\n if (!collection) {\n throw new InvalidConfiguration(\n `payload-forge-ai: Collection \"${collectionSlug}\" is not defined in config.collections.`,\n )\n }\n return {\n ...collection,\n fields: [\n ...collection.fields\n .filter((f: Field) => {\n if (!hasName(f)) {\n return true\n }\n return (\n pluginOptions.collections?.[collectionSlug]?.fields?.find(\n (field) => field.name === f.name,\n ) === undefined\n )\n })\n .map((f: Field) => {\n return f\n }),\n ...(pluginOptions.collections?.[collectionSlug]?.fields?.map((field) => {\n const fieldData = collection.fields\n .filter(hasName)\n .find((f: NamedField) => f.name === field.name) as Field | undefined\n\n if (!fieldData) {\n throw new InvalidConfiguration(\n `payload-forge-ai: Collection \"${collectionSlug}\" does not have field \"${field.name}\".`,\n )\n }\n\n return setAdminFieldComponent(\n fieldData,\n 'payload-forge-ai/ForgeAIField#ForgeAIField',\n )\n }) ?? []),\n ],\n }\n }),\n ],\n endpoints: [...(config.endpoints || []), ...endpoints],\n }\n\n // messages.push({\n // content:\n // 'You are a helpful assistant that can help with the creation of content for a website.',\n // role: 'system',\n // })\n\n // if (!config.admin) {\n // config.admin = {}\n // }\n\n // if (!config.admin.components) {\n // config.admin.components = {}\n // }\n\n // if (!config.admin.components.beforeDashboard) {\n // config.admin.components.beforeDashboard = []\n // }\n\n // config.admin.components.beforeDashboard.push(`payload-forge-ai/client#BeforeDashboardClient`)\n // config.admin.components.beforeDashboard.push(`payload-forge-ai/rsc#BeforeDashboardServer`)\n }\n\ntype NamedField = { name: string } & Field\n\nconst hasName = (f: Field): f is NamedField => typeof (f as any).name === 'string'\n\nexport function setAdminFieldComponent<T extends Field>(field: T, fieldComponent: string): T {\n return {\n ...field,\n admin: {\n ...(field.admin ?? {}),\n components: {\n ...(field.admin?.components ?? {}),\n Field: fieldComponent,\n },\n } as T['admin'], // <- critical: prevents Admin.position widening to string\n }\n}\n"],"names":["createOpenAI","generateText","flattenTopLevelFields","InvalidConfiguration","getValidFieldNames","collection","flattened","fields","Set","map","f","name","filter","validateCollectionFields","collectionSlug","allowedFields","validNames","invalid","has","length","join","sort","extractFields","data","fieldConfigs","result","config","fieldName","field","nestedFields","undefined","buildContextParts","indent","parts","customPrompt","prompt","fieldValue","push","nestedParts","valueStr","JSON","stringify","String","payloadForgeAi","pluginOptions","collections","disabled","openAi","apiKey","model","systemMessages","content","role","endpoints","entry","find","c","slug","fieldNames","forEach","context","contextFieldNames","ctx","handler","req","payload","fieldData","contextData","documentId","currentValue","json","body","e","contextPrompt","contextParts","selectedFields","contextField","fieldType","type","relationTo","relatedDoc","findByID","id","console","error","log","Object","keys","currentValuePrompt","shouldGenerateDifferent","generateDifferent","messages","response","Response","text","method","path","collectionSlugs","includes","hasName","setAdminFieldComponent","fieldComponent","admin","components","Field"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionConfig, CollectionSlug, Config, Field, PayloadRequest } from 'payload'\n\nimport { createOpenAI } from '@ai-sdk/openai'\nimport { generateText, type ModelMessage } from 'ai'\nimport { flattenTopLevelFields, InvalidConfiguration } from 'payload'\n\nexport type PayloadForgeAiContextField =\n | string\n | {\n field: string\n prompt?: string\n /**\n * For relationship fields, specify which fields to extract from the related document.\n * For other fields, specify which nested properties to extract.\n * If not specified, the entire value will be used.\n * Can be nested for complex object structures.\n */\n fields?: PayloadForgeAiContextField[]\n }\n\nexport type PayloadForgeAiFieldConfig = {\n context?: PayloadForgeAiContextField[]\n /**\n * If true, tells the AI to generate something different from the current value.\n * Defaults to true.\n */\n generateDifferent?: boolean\n name: string\n prompt: string\n}\n\nexport type PayloadForgeAiCollectionConfig = {\n fields: PayloadForgeAiFieldConfig[]\n}\n\nexport type PayloadForgeAiConfig = {\n apiKey: string\n collections?: Partial<Record<CollectionSlug, PayloadForgeAiCollectionConfig>>\n disabled?: boolean\n}\n\nfunction getValidFieldNames(collection: CollectionConfig): Set<string> {\n const flattened = flattenTopLevelFields(collection.fields)\n return new Set(flattened.map((f) => f.name).filter((name): name is string => name != null))\n}\n\nfunction validateCollectionFields(\n collectionSlug: string,\n collection: CollectionConfig,\n allowedFields: string[],\n): void {\n const validNames = getValidFieldNames(collection)\n const invalid = allowedFields.filter((name) => !validNames.has(name))\n if (invalid.length > 0) {\n throw new InvalidConfiguration(\n `payload-forge-ai: Collection \"${collectionSlug}\" does not have these fields: ${invalid.join(', ')}. ` +\n `Valid top-level fields: ${[...validNames].sort().join(', ')}.`,\n )\n }\n}\n\n/**\n * Recursively extract fields from an object based on field configuration\n */\nfunction extractFields(data: any, fieldConfigs: PayloadForgeAiContextField[]): Record<string, any> {\n if (!data || typeof data !== 'object') {\n return data\n }\n\n const result: Record<string, any> = {}\n\n for (const config of fieldConfigs) {\n const fieldName = typeof config === 'string' ? config : config.field\n const nestedFields = typeof config === 'string' ? undefined : config.fields\n\n if (data[fieldName] !== undefined) {\n if (nestedFields && nestedFields.length > 0) {\n // Recursively extract nested fields\n result[fieldName] = extractFields(data[fieldName], nestedFields)\n } else {\n // Just include the field value\n result[fieldName] = data[fieldName]\n }\n }\n }\n\n return result\n}\n\n/**\n * Recursively build context parts with prompts for nested fields\n */\nfunction buildContextParts(\n data: any,\n fieldConfigs: PayloadForgeAiContextField[],\n indent: string = ' ',\n): string[] {\n if (!data || typeof data !== 'object') {\n return []\n }\n\n const parts: string[] = []\n\n for (const config of fieldConfigs) {\n const fieldName = typeof config === 'string' ? config : config.field\n const customPrompt = typeof config === 'string' ? undefined : config.prompt\n const nestedFields = typeof config === 'string' ? undefined : config.fields\n const fieldValue = data[fieldName]\n\n if (fieldValue !== undefined && fieldValue !== null && fieldValue !== '') {\n if (nestedFields && nestedFields.length > 0 && typeof fieldValue === 'object') {\n // Handle nested fields with their own prompts\n // Add the current field's prompt as a header if it exists\n if (customPrompt) {\n parts.push(`${indent}${customPrompt}:`)\n }\n const nestedParts = buildContextParts(fieldValue, nestedFields, indent + ' ')\n parts.push(...nestedParts)\n } else {\n // Leaf value - format with prompt\n let valueStr: string\n if (typeof fieldValue === 'object') {\n valueStr = JSON.stringify(fieldValue, null, 2)\n } else {\n valueStr = String(fieldValue)\n }\n\n if (customPrompt) {\n parts.push(`${indent}${customPrompt}: ${valueStr}`)\n } else {\n parts.push(`${indent}${fieldName}: ${valueStr}`)\n }\n }\n }\n }\n\n return parts\n}\n\nexport const payloadForgeAi =\n (pluginOptions: PayloadForgeAiConfig) =>\n (config: Config): Config => {\n if (!config.collections) {\n config.collections = []\n }\n\n if (pluginOptions.disabled) {\n return config\n }\n\n const openAi = createOpenAI({\n apiKey: pluginOptions.apiKey,\n })\n\n const model = openAi('gpt-5')\n\n const systemMessages: ModelMessage[] = [\n {\n content: `\n You are a helpful assistant that can help with the creation of content in payloadCMS fields. You must return only the content and not any other questions or comments!\n The content must be in the same language as the prompt.\n The content must be in the same format as the field type.\n The content must be in the same length as the field type.\n The content must be in the same style as the field type.\n The content must be in the same tone as the field type.\n The content must be in the same voice as the field type.\n You may vary the content to make it more interesting and engaging, but you must always return the content in the same language as the prompt.\n `,\n role: 'system',\n },\n ]\n const endpoints = config.endpoints ?? []\n\n if (pluginOptions.collections) {\n for (const collectionSlug in pluginOptions.collections) {\n const entry = pluginOptions.collections[collectionSlug]\n if (!entry?.fields?.length) {\n continue\n }\n\n const collection = config.collections.find(\n (c: CollectionConfig) => c.slug === collectionSlug,\n )\n if (!collection) {\n throw new InvalidConfiguration(\n `payload-forge-ai: Collection \"${collectionSlug}\" is not defined in config.collections.`,\n )\n }\n\n const fieldNames = entry.fields.map((f) => f.name)\n\n validateCollectionFields(collectionSlug, collection, fieldNames)\n\n entry.fields.forEach((field) => {\n // Validate context fields\n if (field.context && field.context.length > 0) {\n const contextFieldNames = field.context.map((ctx) =>\n typeof ctx === 'string' ? ctx : ctx.field,\n )\n validateCollectionFields(collectionSlug, collection, contextFieldNames)\n }\n\n endpoints.push({\n handler: async (req: PayloadRequest) => {\n const payload = req.payload\n const flattened = flattenTopLevelFields(collection.fields)\n\n const fieldData = flattened.find((f) => f.name === field.name)\n if (!fieldData) {\n throw new InvalidConfiguration(\n `payload-forge-ai: Collection \"${collectionSlug}\" does not have field \"${field.name}\".`,\n )\n }\n\n // Parse request body for context\n let contextData: Record<string, any> = {}\n let documentId: string | undefined\n let currentValue: any = undefined\n\n try {\n if (req.json) {\n const body = await req.json()\n contextData = body.context || {}\n documentId = body.documentId\n currentValue = body.currentValue\n }\n } catch (e) {\n // If no body or invalid JSON, continue without context\n }\n\n // Build context prompt from configured context fields\n let contextPrompt = ''\n if (field.context && field.context.length > 0) {\n const contextParts: string[] = []\n\n for (const ctx of field.context) {\n const fieldName = typeof ctx === 'string' ? ctx : ctx.field\n const customPrompt = typeof ctx === 'string' ? undefined : ctx.prompt\n const selectedFields = typeof ctx === 'string' ? undefined : ctx.fields\n let fieldValue = contextData[fieldName]\n\n if (fieldValue !== undefined && fieldValue !== null && fieldValue !== '') {\n const contextField = flattened.find((f) => f.name === fieldName)\n const fieldType = contextField?.type || 'unknown'\n\n // Handle relationship fields - fetch the related document if we only have an ID\n if (contextField?.type === 'relationship' && typeof fieldValue === 'string') {\n try {\n const relationTo = (contextField as any).relationTo\n if (relationTo) {\n const relatedDoc = await payload.findByID({\n collection: relationTo,\n id: fieldValue,\n })\n fieldValue = relatedDoc\n }\n } catch (e) {\n console.error(`Failed to fetch related document for ${fieldName}:`, e)\n // Continue with the ID if fetch fails\n }\n }\n\n // Handle nested fields with recursive prompts\n if (\n selectedFields &&\n selectedFields.length > 0 &&\n typeof fieldValue === 'object'\n ) {\n // Add the outer prompt as a header if it exists\n if (customPrompt) {\n contextParts.push(`${customPrompt}:`)\n }\n console.log(`Building nested parts for field: ${fieldName}`)\n console.log(`Field value keys:`, Object.keys(fieldValue))\n console.log(\n `Selected fields config:`,\n JSON.stringify(selectedFields, null, 2),\n )\n const nestedParts = buildContextParts(fieldValue, selectedFields)\n console.log(`Nested parts result:`, nestedParts)\n contextParts.push(...nestedParts)\n } else {\n // Simple field without nesting\n let valueStr: string\n if (typeof fieldValue === 'object') {\n valueStr = JSON.stringify(fieldValue, null, 2)\n } else {\n valueStr = String(fieldValue)\n }\n\n if (customPrompt) {\n contextParts.push(`${customPrompt}: ${valueStr}`)\n } else {\n contextParts.push(`${fieldName} (${fieldType}): ${valueStr}`)\n }\n }\n }\n }\n\n if (contextParts.length > 0) {\n contextPrompt = '\\n\\nContext from other fields:\\n' + contextParts.join('\\n')\n }\n }\n\n // Add current value info if it exists\n let currentValuePrompt = ''\n const shouldGenerateDifferent = field.generateDifferent ?? true // Default to true\n if (currentValue !== undefined && currentValue !== null && currentValue !== '') {\n if (shouldGenerateDifferent) {\n currentValuePrompt = `\\n\\nCurrent value: ${currentValue}\\nIMPORTANT: Generate something DIFFERENT from the current value above. Do not repeat it.`\n } else {\n currentValuePrompt = `\\n\\nCurrent value: ${currentValue}`\n }\n }\n\n const messages: ModelMessage[] = [\n ...systemMessages,\n {\n content: `\nCollection: ${collectionSlug}\nField name: ${fieldData.name}\nField type: ${fieldData.type}\nCustom instructions: ${field.prompt}${contextPrompt}${currentValuePrompt}\n `,\n role: 'system',\n },\n ]\n\n console.log(messages[messages.length - 1].content)\n\n const response = await generateText({\n messages,\n model,\n })\n\n return Response.json(response.text)\n },\n method: 'post',\n path: `/forge-ai/${collectionSlug}/${field.name}`,\n })\n })\n }\n }\n\n const collectionSlugs = Object.keys(pluginOptions?.collections ?? {})\n\n return {\n ...config,\n collections: [\n ...(config.collections ?? []).filter(\n (c: CollectionConfig) => !collectionSlugs.includes(c.slug),\n ),\n ...collectionSlugs.map((collectionSlug) => {\n const collection = config.collections?.find(\n (c: CollectionConfig) => c.slug === collectionSlug,\n )\n\n if (!collection) {\n throw new InvalidConfiguration(\n `payload-forge-ai: Collection \"${collectionSlug}\" is not defined in config.collections.`,\n )\n }\n return {\n ...collection,\n fields: [\n ...collection.fields\n .filter((f: Field) => {\n if (!hasName(f)) {\n return true\n }\n return (\n pluginOptions.collections?.[collectionSlug]?.fields?.find(\n (field) => field.name === f.name,\n ) === undefined\n )\n })\n .map((f: Field) => {\n return f\n }),\n ...(pluginOptions.collections?.[collectionSlug]?.fields?.map((field) => {\n const fieldData = collection.fields\n .filter(hasName)\n .find((f: NamedField) => f.name === field.name) as Field | undefined\n\n if (!fieldData) {\n throw new InvalidConfiguration(\n `payload-forge-ai: Collection \"${collectionSlug}\" does not have field \"${field.name}\".`,\n )\n }\n\n return setAdminFieldComponent(\n fieldData,\n 'payload-forgeai/ForgeAIField#ForgeAIField',\n )\n }) ?? []),\n ],\n }\n }),\n ],\n endpoints: [...(config.endpoints || []), ...endpoints],\n }\n\n // messages.push({\n // content:\n // 'You are a helpful assistant that can help with the creation of content for a website.',\n // role: 'system',\n // })\n\n // if (!config.admin) {\n // config.admin = {}\n // }\n\n // if (!config.admin.components) {\n // config.admin.components = {}\n // }\n\n // if (!config.admin.components.beforeDashboard) {\n // config.admin.components.beforeDashboard = []\n // }\n\n // config.admin.components.beforeDashboard.push(`payload-forge-ai/client#BeforeDashboardClient`)\n // config.admin.components.beforeDashboard.push(`payload-forge-ai/rsc#BeforeDashboardServer`)\n }\n\ntype NamedField = { name: string } & Field\n\nconst hasName = (f: Field): f is NamedField => typeof (f as any).name === 'string'\n\nexport function setAdminFieldComponent<T extends Field>(field: T, fieldComponent: string): T {\n return {\n ...field,\n admin: {\n ...(field.admin ?? {}),\n components: {\n ...(field.admin?.components ?? {}),\n Field: fieldComponent,\n },\n } as T['admin'], // <- critical: prevents Admin.position widening to string\n }\n}\n"],"names":["createOpenAI","generateText","flattenTopLevelFields","InvalidConfiguration","getValidFieldNames","collection","flattened","fields","Set","map","f","name","filter","validateCollectionFields","collectionSlug","allowedFields","validNames","invalid","has","length","join","sort","extractFields","data","fieldConfigs","result","config","fieldName","field","nestedFields","undefined","buildContextParts","indent","parts","customPrompt","prompt","fieldValue","push","nestedParts","valueStr","JSON","stringify","String","payloadForgeAi","pluginOptions","collections","disabled","openAi","apiKey","model","systemMessages","content","role","endpoints","entry","find","c","slug","fieldNames","forEach","context","contextFieldNames","ctx","handler","req","payload","fieldData","contextData","documentId","currentValue","json","body","e","contextPrompt","contextParts","selectedFields","contextField","fieldType","type","relationTo","relatedDoc","findByID","id","console","error","log","Object","keys","currentValuePrompt","shouldGenerateDifferent","generateDifferent","messages","response","Response","text","method","path","collectionSlugs","includes","hasName","setAdminFieldComponent","fieldComponent","admin","components","Field"],"mappings":"AAEA,SAASA,YAAY,QAAQ,iBAAgB;AAC7C,SAASC,YAAY,QAA2B,KAAI;AACpD,SAASC,qBAAqB,EAAEC,oBAAoB,QAAQ,UAAS;AAqCrE,SAASC,mBAAmBC,UAA4B;IACtD,MAAMC,YAAYJ,sBAAsBG,WAAWE,MAAM;IACzD,OAAO,IAAIC,IAAIF,UAAUG,GAAG,CAAC,CAACC,IAAMA,EAAEC,IAAI,EAAEC,MAAM,CAAC,CAACD,OAAyBA,QAAQ;AACvF;AAEA,SAASE,yBACPC,cAAsB,EACtBT,UAA4B,EAC5BU,aAAuB;IAEvB,MAAMC,aAAaZ,mBAAmBC;IACtC,MAAMY,UAAUF,cAAcH,MAAM,CAAC,CAACD,OAAS,CAACK,WAAWE,GAAG,CAACP;IAC/D,IAAIM,QAAQE,MAAM,GAAG,GAAG;QACtB,MAAM,IAAIhB,qBACR,CAAC,8BAA8B,EAAEW,eAAe,8BAA8B,EAAEG,QAAQG,IAAI,CAAC,MAAM,EAAE,CAAC,GACpG,CAAC,wBAAwB,EAAE;eAAIJ;SAAW,CAACK,IAAI,GAAGD,IAAI,CAAC,MAAM,CAAC,CAAC;IAErE;AACF;AAEA;;CAEC,GACD,SAASE,cAAcC,IAAS,EAAEC,YAA0C;IAC1E,IAAI,CAACD,QAAQ,OAAOA,SAAS,UAAU;QACrC,OAAOA;IACT;IAEA,MAAME,SAA8B,CAAC;IAErC,KAAK,MAAMC,UAAUF,aAAc;QACjC,MAAMG,YAAY,OAAOD,WAAW,WAAWA,SAASA,OAAOE,KAAK;QACpE,MAAMC,eAAe,OAAOH,WAAW,WAAWI,YAAYJ,OAAOnB,MAAM;QAE3E,IAAIgB,IAAI,CAACI,UAAU,KAAKG,WAAW;YACjC,IAAID,gBAAgBA,aAAaV,MAAM,GAAG,GAAG;gBAC3C,oCAAoC;gBACpCM,MAAM,CAACE,UAAU,GAAGL,cAAcC,IAAI,CAACI,UAAU,EAAEE;YACrD,OAAO;gBACL,+BAA+B;gBAC/BJ,MAAM,CAACE,UAAU,GAAGJ,IAAI,CAACI,UAAU;YACrC;QACF;IACF;IAEA,OAAOF;AACT;AAEA;;CAEC,GACD,SAASM,kBACPR,IAAS,EACTC,YAA0C,EAC1CQ,SAAiB,IAAI;IAErB,IAAI,CAACT,QAAQ,OAAOA,SAAS,UAAU;QACrC,OAAO,EAAE;IACX;IAEA,MAAMU,QAAkB,EAAE;IAE1B,KAAK,MAAMP,UAAUF,aAAc;QACjC,MAAMG,YAAY,OAAOD,WAAW,WAAWA,SAASA,OAAOE,KAAK;QACpE,MAAMM,eAAe,OAAOR,WAAW,WAAWI,YAAYJ,OAAOS,MAAM;QAC3E,MAAMN,eAAe,OAAOH,WAAW,WAAWI,YAAYJ,OAAOnB,MAAM;QAC3E,MAAM6B,aAAab,IAAI,CAACI,UAAU;QAElC,IAAIS,eAAeN,aAAaM,eAAe,QAAQA,eAAe,IAAI;YACxE,IAAIP,gBAAgBA,aAAaV,MAAM,GAAG,KAAK,OAAOiB,eAAe,UAAU;gBAC7E,8CAA8C;gBAC9C,0DAA0D;gBAC1D,IAAIF,cAAc;oBAChBD,MAAMI,IAAI,CAAC,GAAGL,SAASE,aAAa,CAAC,CAAC;gBACxC;gBACA,MAAMI,cAAcP,kBAAkBK,YAAYP,cAAcG,SAAS;gBACzEC,MAAMI,IAAI,IAAIC;YAChB,OAAO;gBACL,kCAAkC;gBAClC,IAAIC;gBACJ,IAAI,OAAOH,eAAe,UAAU;oBAClCG,WAAWC,KAAKC,SAAS,CAACL,YAAY,MAAM;gBAC9C,OAAO;oBACLG,WAAWG,OAAON;gBACpB;gBAEA,IAAIF,cAAc;oBAChBD,MAAMI,IAAI,CAAC,GAAGL,SAASE,aAAa,EAAE,EAAEK,UAAU;gBACpD,OAAO;oBACLN,MAAMI,IAAI,CAAC,GAAGL,SAASL,UAAU,EAAE,EAAEY,UAAU;gBACjD;YACF;QACF;IACF;IAEA,OAAON;AACT;AAEA,OAAO,MAAMU,iBACX,CAACC,gBACD,CAAClB;QACC,IAAI,CAACA,OAAOmB,WAAW,EAAE;YACvBnB,OAAOmB,WAAW,GAAG,EAAE;QACzB;QAEA,IAAID,cAAcE,QAAQ,EAAE;YAC1B,OAAOpB;QACT;QAEA,MAAMqB,SAAS/C,aAAa;YAC1BgD,QAAQJ,cAAcI,MAAM;QAC9B;QAEA,MAAMC,QAAQF,OAAO;QAErB,MAAMG,iBAAiC;YACrC;gBACEC,SAAS,CAAC;;;;;;;;;UASR,CAAC;gBACHC,MAAM;YACR;SACD;QACD,MAAMC,YAAY3B,OAAO2B,SAAS,IAAI,EAAE;QAExC,IAAIT,cAAcC,WAAW,EAAE;YAC7B,IAAK,MAAM/B,kBAAkB8B,cAAcC,WAAW,CAAE;gBACtD,MAAMS,QAAQV,cAAcC,WAAW,CAAC/B,eAAe;gBACvD,IAAI,CAACwC,OAAO/C,QAAQY,QAAQ;oBAC1B;gBACF;gBAEA,MAAMd,aAAaqB,OAAOmB,WAAW,CAACU,IAAI,CACxC,CAACC,IAAwBA,EAAEC,IAAI,KAAK3C;gBAEtC,IAAI,CAACT,YAAY;oBACf,MAAM,IAAIF,qBACR,CAAC,8BAA8B,EAAEW,eAAe,uCAAuC,CAAC;gBAE5F;gBAEA,MAAM4C,aAAaJ,MAAM/C,MAAM,CAACE,GAAG,CAAC,CAACC,IAAMA,EAAEC,IAAI;gBAEjDE,yBAAyBC,gBAAgBT,YAAYqD;gBAErDJ,MAAM/C,MAAM,CAACoD,OAAO,CAAC,CAAC/B;oBACpB,0BAA0B;oBAC1B,IAAIA,MAAMgC,OAAO,IAAIhC,MAAMgC,OAAO,CAACzC,MAAM,GAAG,GAAG;wBAC7C,MAAM0C,oBAAoBjC,MAAMgC,OAAO,CAACnD,GAAG,CAAC,CAACqD,MAC3C,OAAOA,QAAQ,WAAWA,MAAMA,IAAIlC,KAAK;wBAE3Cf,yBAAyBC,gBAAgBT,YAAYwD;oBACvD;oBAEAR,UAAUhB,IAAI,CAAC;wBACb0B,SAAS,OAAOC;4BACd,MAAMC,UAAUD,IAAIC,OAAO;4BAC3B,MAAM3D,YAAYJ,sBAAsBG,WAAWE,MAAM;4BAEzD,MAAM2D,YAAY5D,UAAUiD,IAAI,CAAC,CAAC7C,IAAMA,EAAEC,IAAI,KAAKiB,MAAMjB,IAAI;4BAC7D,IAAI,CAACuD,WAAW;gCACd,MAAM,IAAI/D,qBACR,CAAC,8BAA8B,EAAEW,eAAe,uBAAuB,EAAEc,MAAMjB,IAAI,CAAC,EAAE,CAAC;4BAE3F;4BAEA,iCAAiC;4BACjC,IAAIwD,cAAmC,CAAC;4BACxC,IAAIC;4BACJ,IAAIC,eAAoBvC;4BAExB,IAAI;gCACF,IAAIkC,IAAIM,IAAI,EAAE;oCACZ,MAAMC,OAAO,MAAMP,IAAIM,IAAI;oCAC3BH,cAAcI,KAAKX,OAAO,IAAI,CAAC;oCAC/BQ,aAAaG,KAAKH,UAAU;oCAC5BC,eAAeE,KAAKF,YAAY;gCAClC;4BACF,EAAE,OAAOG,GAAG;4BACV,uDAAuD;4BACzD;4BAEA,sDAAsD;4BACtD,IAAIC,gBAAgB;4BACpB,IAAI7C,MAAMgC,OAAO,IAAIhC,MAAMgC,OAAO,CAACzC,MAAM,GAAG,GAAG;gCAC7C,MAAMuD,eAAyB,EAAE;gCAEjC,KAAK,MAAMZ,OAAOlC,MAAMgC,OAAO,CAAE;oCAC/B,MAAMjC,YAAY,OAAOmC,QAAQ,WAAWA,MAAMA,IAAIlC,KAAK;oCAC3D,MAAMM,eAAe,OAAO4B,QAAQ,WAAWhC,YAAYgC,IAAI3B,MAAM;oCACrE,MAAMwC,iBAAiB,OAAOb,QAAQ,WAAWhC,YAAYgC,IAAIvD,MAAM;oCACvE,IAAI6B,aAAa+B,WAAW,CAACxC,UAAU;oCAEvC,IAAIS,eAAeN,aAAaM,eAAe,QAAQA,eAAe,IAAI;wCACxE,MAAMwC,eAAetE,UAAUiD,IAAI,CAAC,CAAC7C,IAAMA,EAAEC,IAAI,KAAKgB;wCACtD,MAAMkD,YAAYD,cAAcE,QAAQ;wCAExC,gFAAgF;wCAChF,IAAIF,cAAcE,SAAS,kBAAkB,OAAO1C,eAAe,UAAU;4CAC3E,IAAI;gDACF,MAAM2C,aAAa,AAACH,aAAqBG,UAAU;gDACnD,IAAIA,YAAY;oDACd,MAAMC,aAAa,MAAMf,QAAQgB,QAAQ,CAAC;wDACxC5E,YAAY0E;wDACZG,IAAI9C;oDACN;oDACAA,aAAa4C;gDACf;4CACF,EAAE,OAAOR,GAAG;gDACVW,QAAQC,KAAK,CAAC,CAAC,qCAAqC,EAAEzD,UAAU,CAAC,CAAC,EAAE6C;4CACpE,sCAAsC;4CACxC;wCACF;wCAEA,8CAA8C;wCAC9C,IACEG,kBACAA,eAAexD,MAAM,GAAG,KACxB,OAAOiB,eAAe,UACtB;4CACA,gDAAgD;4CAChD,IAAIF,cAAc;gDAChBwC,aAAarC,IAAI,CAAC,GAAGH,aAAa,CAAC,CAAC;4CACtC;4CACAiD,QAAQE,GAAG,CAAC,CAAC,iCAAiC,EAAE1D,WAAW;4CAC3DwD,QAAQE,GAAG,CAAC,CAAC,iBAAiB,CAAC,EAAEC,OAAOC,IAAI,CAACnD;4CAC7C+C,QAAQE,GAAG,CACT,CAAC,uBAAuB,CAAC,EACzB7C,KAAKC,SAAS,CAACkC,gBAAgB,MAAM;4CAEvC,MAAMrC,cAAcP,kBAAkBK,YAAYuC;4CAClDQ,QAAQE,GAAG,CAAC,CAAC,oBAAoB,CAAC,EAAE/C;4CACpCoC,aAAarC,IAAI,IAAIC;wCACvB,OAAO;4CACL,+BAA+B;4CAC/B,IAAIC;4CACJ,IAAI,OAAOH,eAAe,UAAU;gDAClCG,WAAWC,KAAKC,SAAS,CAACL,YAAY,MAAM;4CAC9C,OAAO;gDACLG,WAAWG,OAAON;4CACpB;4CAEA,IAAIF,cAAc;gDAChBwC,aAAarC,IAAI,CAAC,GAAGH,aAAa,EAAE,EAAEK,UAAU;4CAClD,OAAO;gDACLmC,aAAarC,IAAI,CAAC,GAAGV,UAAU,EAAE,EAAEkD,UAAU,GAAG,EAAEtC,UAAU;4CAC9D;wCACF;oCACF;gCACF;gCAEA,IAAImC,aAAavD,MAAM,GAAG,GAAG;oCAC3BsD,gBAAgB,qCAAqCC,aAAatD,IAAI,CAAC;gCACzE;4BACF;4BAEA,sCAAsC;4BACtC,IAAIoE,qBAAqB;4BACzB,MAAMC,0BAA0B7D,MAAM8D,iBAAiB,IAAI,KAAK,kBAAkB;;4BAClF,IAAIrB,iBAAiBvC,aAAauC,iBAAiB,QAAQA,iBAAiB,IAAI;gCAC9E,IAAIoB,yBAAyB;oCAC3BD,qBAAqB,CAAC,mBAAmB,EAAEnB,aAAa,yFAAyF,CAAC;gCACpJ,OAAO;oCACLmB,qBAAqB,CAAC,mBAAmB,EAAEnB,cAAc;gCAC3D;4BACF;4BAEA,MAAMsB,WAA2B;mCAC5BzC;gCACH;oCACEC,SAAS,CAAC;YAChB,EAAErC,eAAe;YACjB,EAAEoD,UAAUvD,IAAI,CAAC;YACjB,EAAEuD,UAAUY,IAAI,CAAC;qBACR,EAAElD,MAAMO,MAAM,GAAGsC,gBAAgBe,mBAAmB;kBACvD,CAAC;oCACDpC,MAAM;gCACR;6BACD;4BAED+B,QAAQE,GAAG,CAACM,QAAQ,CAACA,SAASxE,MAAM,GAAG,EAAE,CAACgC,OAAO;4BAEjD,MAAMyC,WAAW,MAAM3F,aAAa;gCAClC0F;gCACA1C;4BACF;4BAEA,OAAO4C,SAASvB,IAAI,CAACsB,SAASE,IAAI;wBACpC;wBACAC,QAAQ;wBACRC,MAAM,CAAC,UAAU,EAAElF,eAAe,CAAC,EAAEc,MAAMjB,IAAI,EAAE;oBACnD;gBACF;YACF;QACF;QAEA,MAAMsF,kBAAkBX,OAAOC,IAAI,CAAC3C,eAAeC,eAAe,CAAC;QAEnE,OAAO;YACL,GAAGnB,MAAM;YACTmB,aAAa;mBACR,AAACnB,CAAAA,OAAOmB,WAAW,IAAI,EAAE,AAAD,EAAGjC,MAAM,CAClC,CAAC4C,IAAwB,CAACyC,gBAAgBC,QAAQ,CAAC1C,EAAEC,IAAI;mBAExDwC,gBAAgBxF,GAAG,CAAC,CAACK;oBACtB,MAAMT,aAAaqB,OAAOmB,WAAW,EAAEU,KACrC,CAACC,IAAwBA,EAAEC,IAAI,KAAK3C;oBAGtC,IAAI,CAACT,YAAY;wBACf,MAAM,IAAIF,qBACR,CAAC,8BAA8B,EAAEW,eAAe,uCAAuC,CAAC;oBAE5F;oBACA,OAAO;wBACL,GAAGT,UAAU;wBACbE,QAAQ;+BACHF,WAAWE,MAAM,CACjBK,MAAM,CAAC,CAACF;gCACP,IAAI,CAACyF,QAAQzF,IAAI;oCACf,OAAO;gCACT;gCACA,OACEkC,cAAcC,WAAW,EAAE,CAAC/B,eAAe,EAAEP,QAAQgD,KACnD,CAAC3B,QAAUA,MAAMjB,IAAI,KAAKD,EAAEC,IAAI,MAC5BmB;4BAEV,GACCrB,GAAG,CAAC,CAACC;gCACJ,OAAOA;4BACT;+BACEkC,cAAcC,WAAW,EAAE,CAAC/B,eAAe,EAAEP,QAAQE,IAAI,CAACmB;gCAC5D,MAAMsC,YAAY7D,WAAWE,MAAM,CAChCK,MAAM,CAACuF,SACP5C,IAAI,CAAC,CAAC7C,IAAkBA,EAAEC,IAAI,KAAKiB,MAAMjB,IAAI;gCAEhD,IAAI,CAACuD,WAAW;oCACd,MAAM,IAAI/D,qBACR,CAAC,8BAA8B,EAAEW,eAAe,uBAAuB,EAAEc,MAAMjB,IAAI,CAAC,EAAE,CAAC;gCAE3F;gCAEA,OAAOyF,uBACLlC,WACA;4BAEJ,MAAM,EAAE;yBACT;oBACH;gBACF;aACD;YACDb,WAAW;mBAAK3B,OAAO2B,SAAS,IAAI,EAAE;mBAAMA;aAAU;QACxD;IAEA,kBAAkB;IAClB,aAAa;IACb,+FAA+F;IAC/F,oBAAoB;IACpB,KAAK;IAEL,uBAAuB;IACvB,sBAAsB;IACtB,IAAI;IAEJ,kCAAkC;IAClC,iCAAiC;IACjC,IAAI;IAEJ,kDAAkD;IAClD,iDAAiD;IACjD,IAAI;IAEJ,gGAAgG;IAChG,6FAA6F;IAC/F,EAAC;AAIH,MAAM8C,UAAU,CAACzF,IAA8B,OAAO,AAACA,EAAUC,IAAI,KAAK;AAE1E,OAAO,SAASyF,uBAAwCxE,KAAQ,EAAEyE,cAAsB;IACtF,OAAO;QACL,GAAGzE,KAAK;QACR0E,OAAO;YACL,GAAI1E,MAAM0E,KAAK,IAAI,CAAC,CAAC;YACrBC,YAAY;gBACV,GAAI3E,MAAM0E,KAAK,EAAEC,cAAc,CAAC,CAAC;gBACjCC,OAAOH;YACT;QACF;IACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payload-forgeai",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "A plugin for Payload CMS to generate content with AI",
5
5
  "license": "MIT",
6
6
  "type": "module",