@ai-stack/payloadcms 3.2.9-beta → 3.2.11-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -21
- package/dist/ai/models/anthropic/generateRichText.d.ts +1 -1
- package/dist/ai/models/anthropic/generateRichText.d.ts.map +1 -1
- package/dist/ai/models/anthropic/generateRichText.js +5 -6
- package/dist/ai/models/anthropic/generateRichText.js.map +1 -1
- package/dist/ai/models/anthropic/index.js +15 -12
- package/dist/ai/models/anthropic/index.js.map +1 -1
- package/dist/ai/models/openai/generateImage.d.ts +2 -6
- package/dist/ai/models/openai/generateImage.d.ts.map +1 -1
- package/dist/ai/models/openai/generateImage.js +19 -9
- package/dist/ai/models/openai/generateImage.js.map +1 -1
- package/dist/ai/models/openai/generateRichText.d.ts +1 -1
- package/dist/ai/models/openai/generateRichText.d.ts.map +1 -1
- package/dist/ai/models/openai/generateRichText.js +5 -6
- package/dist/ai/models/openai/generateRichText.js.map +1 -1
- package/dist/ai/models/openai/index.d.ts.map +1 -1
- package/dist/ai/models/openai/index.js +133 -4
- package/dist/ai/models/openai/index.js.map +1 -1
- package/dist/ai/prompts.js +6 -6
- package/dist/ai/prompts.js.map +1 -1
- package/dist/ai/schemas/lexicalJsonSchema.d.ts +19 -741
- package/dist/ai/schemas/lexicalJsonSchema.d.ts.map +1 -1
- package/dist/ai/schemas/lexicalJsonSchema.js +72 -4
- package/dist/ai/schemas/lexicalJsonSchema.js.map +1 -1
- package/dist/ai/utils/editImagesWithOpenAI.d.ts +11 -0
- package/dist/ai/utils/editImagesWithOpenAI.d.ts.map +1 -0
- package/dist/ai/utils/editImagesWithOpenAI.js +37 -0
- package/dist/ai/utils/editImagesWithOpenAI.js.map +1 -0
- package/dist/ai/utils/filterEditorSchemaByNodes.d.ts +72 -0
- package/dist/ai/utils/filterEditorSchemaByNodes.d.ts.map +1 -0
- package/dist/ai/utils/filterEditorSchemaByNodes.js +43 -0
- package/dist/ai/utils/filterEditorSchemaByNodes.js.map +1 -0
- package/dist/ai/utils/isObjectSchema.d.ts +3 -0
- package/dist/ai/utils/isObjectSchema.d.ts.map +1 -0
- package/dist/ai/utils/isObjectSchema.js +5 -0
- package/dist/ai/utils/isObjectSchema.js.map +1 -0
- package/dist/collections/Instructions.d.ts.map +1 -1
- package/dist/collections/Instructions.js +26 -1
- package/dist/collections/Instructions.js.map +1 -1
- package/dist/defaults.d.ts +1 -1
- package/dist/defaults.js +1 -1
- package/dist/defaults.js.map +1 -1
- package/dist/endpoints/index.d.ts.map +1 -1
- package/dist/endpoints/index.js +65 -15
- package/dist/endpoints/index.js.map +1 -1
- package/dist/fields/PromptEditorField/PromptEditorField.d.ts.map +1 -1
- package/dist/fields/PromptEditorField/PromptEditorField.js +46 -16
- package/dist/fields/PromptEditorField/PromptEditorField.js.map +1 -1
- package/dist/fields/PromptEditorField/defaultStyle.d.ts +50 -0
- package/dist/fields/PromptEditorField/defaultStyle.d.ts.map +1 -0
- package/dist/fields/PromptEditorField/defaultStyle.js +51 -0
- package/dist/fields/PromptEditorField/defaultStyle.js.map +1 -0
- package/dist/providers/InstructionsProvider/InstructionsProvider.d.ts +2 -0
- package/dist/providers/InstructionsProvider/InstructionsProvider.d.ts.map +1 -1
- package/dist/providers/InstructionsProvider/InstructionsProvider.js +4 -1
- package/dist/providers/InstructionsProvider/InstructionsProvider.js.map +1 -1
- package/dist/providers/InstructionsProvider/useInstructions.d.ts.map +1 -1
- package/dist/providers/InstructionsProvider/useInstructions.js +54 -29
- package/dist/providers/InstructionsProvider/useInstructions.js.map +1 -1
- package/dist/types.d.ts +18 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/ui/Compose/Compose.js +2 -2
- package/dist/ui/Compose/Compose.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/useMenu.d.ts +1 -1
- package/dist/ui/Compose/hooks/menu/useMenu.d.ts.map +1 -1
- package/dist/ui/Compose/hooks/menu/useMenu.js +2 -1
- package/dist/ui/Compose/hooks/menu/useMenu.js.map +1 -1
- package/dist/ui/Compose/hooks/useGenerate.d.ts.map +1 -1
- package/dist/ui/Compose/hooks/useGenerate.js +11 -4
- package/dist/ui/Compose/hooks/useGenerate.js.map +1 -1
- package/dist/utilities/extractImageData.d.ts +10 -0
- package/dist/utilities/extractImageData.d.ts.map +1 -0
- package/dist/utilities/extractImageData.js +22 -0
- package/dist/utilities/extractImageData.js.map +1 -0
- package/dist/utilities/setSafeLexicalState.js +5 -2
- package/dist/utilities/setSafeLexicalState.js.map +1 -1
- package/package.json +14 -9
- package/dist/ai/models/example-prompt-rich-text.md +0 -47
- package/dist/ai/models/example.d.ts +0 -73
- package/dist/ai/models/example.d.ts.map +0 -1
- package/dist/ai/models/example.js +0 -126
- package/dist/ai/models/example.js.map +0 -1
- package/dist/libraries/autocomplete/AutocompleteTextArea.d.ts +0 -8
- package/dist/libraries/autocomplete/AutocompleteTextArea.d.ts.map +0 -1
- package/dist/libraries/autocomplete/AutocompleteTextArea.js +0 -437
- package/dist/libraries/autocomplete/AutocompleteTextArea.js.map +0 -1
- package/dist/libraries/autocomplete/AutocompleteTextArea.module.scss +0 -35
package/dist/endpoints/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import * as process from 'node:process';
|
|
1
2
|
import { defaultPrompts } from '../ai/prompts.js';
|
|
3
|
+
import { filterEditorSchemaByNodes } from '../ai/utils/filterEditorSchemaByNodes.js';
|
|
2
4
|
import { PLUGIN_API_ENDPOINT_GENERATE, PLUGIN_API_ENDPOINT_GENERATE_UPLOAD, PLUGIN_INSTRUCTIONS_TABLE, PLUGIN_NAME } from '../defaults.js';
|
|
3
5
|
import { registerEditorHelper } from '../libraries/handlebars/helpers.js';
|
|
4
6
|
import { handlebarsHelpersMap } from '../libraries/handlebars/helpersMap.js';
|
|
5
7
|
import { replacePlaceholders } from '../libraries/handlebars/replacePlaceholders.js';
|
|
8
|
+
import { extractImageData } from '../utilities/extractImageData.js';
|
|
6
9
|
import { getGenerationModels } from '../utilities/getGenerationModels.js';
|
|
7
10
|
const assignPrompt = async (action, { type, actionParams, context, field, layout, systemPrompt = '', template })=>{
|
|
8
11
|
const prompt = await replacePlaceholders(template, context);
|
|
@@ -38,7 +41,7 @@ export const endpoints = (pluginConfig)=>({
|
|
|
38
41
|
//TODO: This is the main endpoint for generating content - its just needs to be renamed to 'generate' or something.
|
|
39
42
|
handler: async (req)=>{
|
|
40
43
|
const data = await req.json?.();
|
|
41
|
-
const { locale = 'en', options } = data;
|
|
44
|
+
const { allowedEditorNodes = [], locale = 'en', options } = data;
|
|
42
45
|
const { action, actionParams, instructionId } = options;
|
|
43
46
|
const contextData = data.doc;
|
|
44
47
|
if (!instructionId) {
|
|
@@ -53,6 +56,10 @@ export const endpoints = (pluginConfig)=>({
|
|
|
53
56
|
const { custom: { [PLUGIN_NAME]: { editorConfig = {} } = {} } = {} } = collection.admin;
|
|
54
57
|
const { schema: editorSchema = {} } = editorConfig;
|
|
55
58
|
const { prompt: promptTemplate = '' } = instructions;
|
|
59
|
+
let allowedEditorSchema = editorSchema;
|
|
60
|
+
if (allowedEditorNodes.length) {
|
|
61
|
+
allowedEditorSchema = filterEditorSchemaByNodes(editorSchema, allowedEditorNodes);
|
|
62
|
+
}
|
|
56
63
|
const schemaPath = instructions['schema-path'];
|
|
57
64
|
const fieldName = schemaPath?.split('.').pop();
|
|
58
65
|
registerEditorHelper(req.payload, schemaPath);
|
|
@@ -73,19 +80,20 @@ export const endpoints = (pluginConfig)=>({
|
|
|
73
80
|
systemPrompt: instructions.system,
|
|
74
81
|
template: promptTemplate
|
|
75
82
|
});
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
try {
|
|
84
|
+
return model.handler?.(prompts.prompt, {
|
|
85
|
+
...modelOptions,
|
|
86
|
+
editorSchema: allowedEditorSchema,
|
|
87
|
+
layout: prompts.layout,
|
|
88
|
+
locale: localeInfo,
|
|
89
|
+
system: prompts.system
|
|
90
|
+
});
|
|
91
|
+
} catch (error) {
|
|
92
|
+
req.payload.logger.error('Error generating content: ', error);
|
|
85
93
|
return new Response(JSON.stringify(error.message), {
|
|
86
94
|
status: 500
|
|
87
95
|
});
|
|
88
|
-
}
|
|
96
|
+
}
|
|
89
97
|
},
|
|
90
98
|
method: 'post',
|
|
91
99
|
path: PLUGIN_API_ENDPOINT_GENERATE
|
|
@@ -93,10 +101,19 @@ export const endpoints = (pluginConfig)=>({
|
|
|
93
101
|
upload: {
|
|
94
102
|
handler: async (req)=>{
|
|
95
103
|
const data = await req.json?.();
|
|
96
|
-
const { options } = data;
|
|
104
|
+
const { collectionSlug, documentId, options } = data;
|
|
97
105
|
const { instructionId } = options;
|
|
98
|
-
const
|
|
106
|
+
const docData = await req.payload.findByID({
|
|
107
|
+
id: documentId,
|
|
108
|
+
collection: collectionSlug,
|
|
109
|
+
draft: true
|
|
110
|
+
});
|
|
111
|
+
const contextData = {
|
|
112
|
+
...data.doc,
|
|
113
|
+
...docData
|
|
114
|
+
};
|
|
99
115
|
let instructions = {
|
|
116
|
+
images: [],
|
|
100
117
|
'model-id': '',
|
|
101
118
|
prompt: ''
|
|
102
119
|
};
|
|
@@ -107,15 +124,48 @@ export const endpoints = (pluginConfig)=>({
|
|
|
107
124
|
collection: PLUGIN_INSTRUCTIONS_TABLE
|
|
108
125
|
});
|
|
109
126
|
}
|
|
110
|
-
const { prompt: promptTemplate = '' } = instructions;
|
|
127
|
+
const { images: sampleImages = [], prompt: promptTemplate = '' } = instructions;
|
|
111
128
|
const schemaPath = instructions['schema-path'];
|
|
112
129
|
registerEditorHelper(req.payload, schemaPath);
|
|
113
130
|
const text = await replacePlaceholders(promptTemplate, contextData);
|
|
114
131
|
const modelId = instructions['model-id'];
|
|
115
132
|
const uploadCollectionSlug = instructions['relation-to'];
|
|
133
|
+
const images = [
|
|
134
|
+
...extractImageData(text),
|
|
135
|
+
...sampleImages
|
|
136
|
+
];
|
|
137
|
+
const editImages = [];
|
|
138
|
+
for (const img of images){
|
|
139
|
+
try {
|
|
140
|
+
const serverURL = req.payload.config?.serverURL || process.env.SERVER_URL || process.env.NEXT_PUBLIC_SERVER_URL;
|
|
141
|
+
const response = await fetch(`${serverURL}${img.image.url}`, {
|
|
142
|
+
headers: {
|
|
143
|
+
//TODO: Further testing needed or so find a proper way.
|
|
144
|
+
Authorization: `Bearer ${req.headers.get('Authorization')?.split('Bearer ')[1] || ''}`
|
|
145
|
+
},
|
|
146
|
+
method: 'GET'
|
|
147
|
+
});
|
|
148
|
+
const blob = await response.blob();
|
|
149
|
+
editImages.push({
|
|
150
|
+
name: img.image.name,
|
|
151
|
+
type: img.image.type,
|
|
152
|
+
data: blob,
|
|
153
|
+
size: blob.size,
|
|
154
|
+
url: `${serverURL}${img.image.url}`
|
|
155
|
+
});
|
|
156
|
+
} catch (e) {
|
|
157
|
+
req.payload.logger.error('Error fetching reference images!');
|
|
158
|
+
console.error(e);
|
|
159
|
+
throw Error("We couldn't fetch the images. Please ensure the images are accessible and hosted publicly.");
|
|
160
|
+
}
|
|
161
|
+
}
|
|
116
162
|
const model = getGenerationModels(pluginConfig).find((model)=>model.id === modelId);
|
|
117
163
|
const settingsName = model.settings?.name;
|
|
118
|
-
|
|
164
|
+
let modelOptions = instructions[settingsName] || {};
|
|
165
|
+
modelOptions = {
|
|
166
|
+
...modelOptions,
|
|
167
|
+
images: editImages
|
|
168
|
+
};
|
|
119
169
|
const result = await model.handler?.(text, modelOptions);
|
|
120
170
|
const assetData = await req.payload.create({
|
|
121
171
|
collection: uploadCollectionSlug,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/endpoints/index.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\nimport type { ActionMenuItems, Endpoints, PluginConfig } from '../types.js'\n\nimport { defaultPrompts } from '../ai/prompts.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 { registerEditorHelper } from '../libraries/handlebars/helpers.js'\nimport { handlebarsHelpersMap } from '../libraries/handlebars/helpersMap.js'\nimport { replacePlaceholders } from '../libraries/handlebars/replacePlaceholders.js'\nimport { getGenerationModels } from '../utilities/getGenerationModels.js'\n\nconst assignPrompt = async (\n action: ActionMenuItems,\n {\n type,\n actionParams,\n context,\n field,\n layout,\n systemPrompt = '',\n template,\n }: {\n actionParams: Record<any, any>\n context: object\n field: string\n layout: string\n systemPrompt: string\n template: string\n type: string\n },\n) => {\n const prompt = await replacePlaceholders(template, context)\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' ? systemPrompt : undefined,\n }\n\n if (action === 'Compose') {\n return assignedPrompts\n }\n\n const { layout: getLayout, system: getSystemPrompt } = defaultPrompts.find(\n (p) => p.name === action,\n )\n\n let updatedLayout = layout\n if (getLayout) {\n updatedLayout = getLayout()\n }\n\n const system = getSystemPrompt({\n ...(actionParams || {}),\n prompt,\n systemPrompt,\n })\n\n return {\n layout: updatedLayout,\n // TODO: revisit this toLexicalHTML\n prompt: await replacePlaceholders(`{{${toLexicalHTML} ${field}}}`, context),\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 const data = await req.json?.()\n\n const { 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`,\n )\n }\n\n const instructions = await req.payload.findByID({\n id: instructionId,\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n })\n\n const { collections } = req.payload.config\n const collection = collections.find(\n (collection) => collection.slug === PLUGIN_INSTRUCTIONS_TABLE,\n )\n\n const { custom: { [PLUGIN_NAME]: { editorConfig = {} } = {} } = {} } = collection.admin\n const { schema: editorSchema = {} } = editorConfig\n const { prompt: promptTemplate = '' } = instructions\n\n const schemaPath = instructions['schema-path'] as string\n const fieldName = schemaPath?.split('.').pop()\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 const localeInfo = localeData?.label[defaultLocale] || locale\n\n const model = getGenerationModels(pluginConfig)\n .find((model) => model.id === instructions['model-id'])\n const settingsName = model.settings?.name\n const modelOptions = instructions[settingsName] || {}\n\n const prompts = await assignPrompt(action, {\n type: instructions['field-type'] as string,\n actionParams,\n context: contextData,\n field: fieldName,\n layout: instructions.layout,\n systemPrompt: instructions.system,\n template: promptTemplate as string,\n })\n\n // console.log('Running handler with prompts:', prompts)\n return model\n .handler?.(prompts.prompt, {\n ...modelOptions,\n editorSchema,\n layout: prompts.layout,\n locale: localeInfo,\n system: prompts.system,\n })\n .catch((error) => {\n console.error('Error: endpoint - generating text:', error)\n return new Response(JSON.stringify(error.message), { status: 500 })\n })\n },\n method: 'post',\n path: PLUGIN_API_ENDPOINT_GENERATE,\n },\n upload: {\n handler: async (req: PayloadRequest) => {\n const data = await req.json?.()\n\n const { options } = data\n const { instructionId } = options\n const contextData = data.doc\n\n let instructions = { 'model-id': '', prompt: '' }\n\n if (instructionId) {\n // @ts-expect-error\n instructions = await req.payload.findByID({\n id: instructionId,\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n })\n }\n\n const { prompt: promptTemplate = '' } = instructions\n const schemaPath = instructions['schema-path']\n\n registerEditorHelper(req.payload, schemaPath)\n\n const text = await replacePlaceholders(promptTemplate, contextData)\n const modelId = instructions['model-id']\n const uploadCollectionSlug = instructions['relation-to']\n\n const model = getGenerationModels(pluginConfig)\n .find((model) => model.id === modelId)\n const settingsName = model.settings?.name\n const modelOptions = instructions[settingsName] || {}\n\n const result = await model.handler?.(text, modelOptions)\n\n const assetData = await req.payload.create({\n collection: uploadCollectionSlug,\n data: result.data,\n file: result.file,\n })\n\n return new Response(\n JSON.stringify({\n result: {\n id: assetData.id,\n alt: assetData.alt,\n },\n }),\n )\n },\n method: 'post',\n path: PLUGIN_API_ENDPOINT_GENERATE_UPLOAD,\n },\n }) satisfies Endpoints\n"],"names":["defaultPrompts","PLUGIN_API_ENDPOINT_GENERATE","PLUGIN_API_ENDPOINT_GENERATE_UPLOAD","PLUGIN_INSTRUCTIONS_TABLE","PLUGIN_NAME","registerEditorHelper","handlebarsHelpersMap","replacePlaceholders","getGenerationModels","assignPrompt","action","type","actionParams","context","field","layout","systemPrompt","template","prompt","toLexicalHTML","toHTML","name","assignedPrompts","undefined","system","getLayout","getSystemPrompt","find","p","updatedLayout","endpoints","pluginConfig","textarea","handler","req","data","json","locale","options","instructionId","contextData","doc","Error","instructions","payload","findByID","id","collection","collections","config","slug","custom","editorConfig","admin","schema","editorSchema","promptTemplate","schemaPath","fieldName","split","pop","defaultLocale","locales","localization","localeData","l","code","localeInfo","label","model","settingsName","settings","modelOptions","prompts","catch","error","console","Response","JSON","stringify","message","status","method","path","upload","text","modelId","uploadCollectionSlug","result","assetData","create","file","alt"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/endpoints/index.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\nimport * as process from 'node:process'\n\nimport type { ActionMenuItems, Endpoints, PluginConfig } 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 { 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 { getGenerationModels } from '../utilities/getGenerationModels.js'\n\nconst assignPrompt = async (\n action: ActionMenuItems,\n {\n type,\n actionParams,\n context,\n field,\n layout,\n systemPrompt = '',\n template,\n }: {\n actionParams: Record<any, any>\n context: object\n field: string\n layout: string\n systemPrompt: string\n template: string\n type: string\n },\n) => {\n const prompt = await replacePlaceholders(template, context)\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' ? systemPrompt : undefined,\n }\n\n if (action === 'Compose') {\n return assignedPrompts\n }\n\n const { layout: getLayout, system: getSystemPrompt } = defaultPrompts.find(\n (p) => p.name === action,\n )\n\n let updatedLayout = layout\n if (getLayout) {\n updatedLayout = getLayout()\n }\n\n const system = getSystemPrompt({\n ...(actionParams || {}),\n prompt,\n systemPrompt,\n })\n\n return {\n layout: updatedLayout,\n // TODO: revisit this toLexicalHTML\n prompt: await replacePlaceholders(`{{${toLexicalHTML} ${field}}}`, context),\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 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`,\n )\n }\n\n const instructions = await req.payload.findByID({\n id: instructionId,\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n })\n\n const { collections } = req.payload.config\n const collection = collections.find(\n (collection) => collection.slug === PLUGIN_INSTRUCTIONS_TABLE,\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 fieldName = schemaPath?.split('.').pop()\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 const localeInfo = localeData?.label[defaultLocale] || locale\n\n const model = getGenerationModels(pluginConfig).find(\n (model) => model.id === instructions['model-id'],\n )\n const settingsName = model.settings?.name\n const modelOptions = instructions[settingsName] || {}\n\n const prompts = await assignPrompt(action, {\n type: instructions['field-type'] as string,\n actionParams,\n context: contextData,\n field: fieldName,\n layout: instructions.layout,\n systemPrompt: instructions.system,\n template: promptTemplate as string,\n })\n\n try {\n return model.handler?.(prompts.prompt, {\n ...modelOptions,\n editorSchema: allowedEditorSchema,\n layout: prompts.layout,\n locale: localeInfo,\n system: prompts.system,\n })\n } catch (error) {\n req.payload.logger.error('Error generating content: ', error)\n return new Response(JSON.stringify(error.message), { status: 500 })\n }\n },\n method: 'post',\n path: PLUGIN_API_ENDPOINT_GENERATE,\n },\n upload: {\n handler: async (req: PayloadRequest) => {\n const data = await req.json?.()\n\n const { collectionSlug, documentId, options } = data\n const { instructionId } = options\n\n const docData = await req.payload.findByID({\n id: documentId,\n collection: collectionSlug,\n draft: true,\n })\n const contextData = {\n ...data.doc,\n ...docData,\n }\n\n let instructions = { images: [], 'model-id': '', prompt: '' }\n\n if (instructionId) {\n // @ts-expect-error\n instructions = await req.payload.findByID({\n id: instructionId,\n collection: PLUGIN_INSTRUCTIONS_TABLE,\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 text = await replacePlaceholders(promptTemplate, contextData)\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 try {\n const serverURL =\n req.payload.config?.serverURL ||\n process.env.SERVER_URL ||\n process.env.NEXT_PUBLIC_SERVER_URL\n\n const response = await fetch(`${serverURL}${img.image.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: `${serverURL}${img.image.url}`,\n })\n } catch (e) {\n req.payload.logger.error('Error fetching reference images!')\n console.error(e)\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 model = getGenerationModels(pluginConfig).find((model) => model.id === modelId)\n const settingsName = model.settings?.name\n let modelOptions = instructions[settingsName] || {}\n modelOptions = {\n ...modelOptions,\n images: editImages,\n }\n\n const result = await model.handler?.(text, modelOptions)\n\n const assetData = await req.payload.create({\n collection: uploadCollectionSlug,\n data: result.data,\n file: result.file,\n })\n\n return new Response(\n JSON.stringify({\n result: {\n id: assetData.id,\n alt: assetData.alt,\n },\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","registerEditorHelper","handlebarsHelpersMap","replacePlaceholders","extractImageData","getGenerationModels","assignPrompt","action","type","actionParams","context","field","layout","systemPrompt","template","prompt","toLexicalHTML","toHTML","name","assignedPrompts","undefined","system","getLayout","getSystemPrompt","find","p","updatedLayout","endpoints","pluginConfig","textarea","handler","req","data","json","allowedEditorNodes","locale","options","instructionId","contextData","doc","Error","instructions","payload","findByID","id","collection","collections","config","slug","custom","editorConfig","admin","schema","editorSchema","promptTemplate","allowedEditorSchema","length","schemaPath","fieldName","split","pop","defaultLocale","locales","localization","localeData","l","code","localeInfo","label","model","settingsName","settings","modelOptions","prompts","error","logger","Response","JSON","stringify","message","status","method","path","upload","collectionSlug","documentId","docData","draft","images","sampleImages","text","modelId","uploadCollectionSlug","editImages","img","serverURL","env","SERVER_URL","NEXT_PUBLIC_SERVER_URL","response","fetch","image","url","headers","Authorization","get","blob","push","size","e","console","result","assetData","create","file","alt"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PromptEditorField.d.ts","sourceRoot":"","sources":["../../../src/fields/PromptEditorField/PromptEditorField.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAA;AAGvD,OAAO,
|
|
1
|
+
{"version":3,"file":"PromptEditorField.d.ts","sourceRoot":"","sources":["../../../src/fields/PromptEditorField/PromptEditorField.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAA;AAGvD,OAAO,KAA4D,MAAM,OAAO,CAAA;AAMhF,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CA6DhE,CAAA"}
|
|
@@ -1,34 +1,64 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { FieldDescription, FieldLabel, useField } from '@payloadcms/ui';
|
|
4
|
-
import React from 'react';
|
|
5
|
-
import {
|
|
4
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
5
|
+
import { Mention, MentionsInput } from 'react-mentions/dist/react-mentions.cjs.js';
|
|
6
6
|
import { useInstructions } from '../../providers/InstructionsProvider/useInstructions.js';
|
|
7
|
-
|
|
7
|
+
import { defaultStyle } from './defaultStyle.js';
|
|
8
8
|
export const PromptEditorField = (props)=>{
|
|
9
9
|
const { field, path: pathFromContext } = props;
|
|
10
|
-
const { setValue, value } = useField({
|
|
10
|
+
const { setValue, value: payloadValue } = useField({
|
|
11
11
|
path: pathFromContext
|
|
12
12
|
});
|
|
13
|
+
const [localValue, setLocalValue] = useState(payloadValue || '');
|
|
14
|
+
const hasInitialized = useRef(false);
|
|
13
15
|
const { promptEditorSuggestions } = useInstructions();
|
|
16
|
+
const suggestions = useMemo(()=>promptEditorSuggestions.map((suggestion)=>({
|
|
17
|
+
id: suggestion,
|
|
18
|
+
display: suggestion
|
|
19
|
+
})), [
|
|
20
|
+
promptEditorSuggestions
|
|
21
|
+
]);
|
|
22
|
+
useEffect(()=>{
|
|
23
|
+
if (!hasInitialized.current || payloadValue === '') {
|
|
24
|
+
setLocalValue(payloadValue || '');
|
|
25
|
+
hasInitialized.current = true;
|
|
26
|
+
}
|
|
27
|
+
}, [
|
|
28
|
+
payloadValue
|
|
29
|
+
]);
|
|
30
|
+
const handleChange = useCallback((e)=>{
|
|
31
|
+
setLocalValue(e.target.value);
|
|
32
|
+
}, []);
|
|
33
|
+
const handleBlur = useCallback(()=>{
|
|
34
|
+
setValue(localValue);
|
|
35
|
+
}, [
|
|
36
|
+
localValue,
|
|
37
|
+
setValue
|
|
38
|
+
]);
|
|
39
|
+
const displayTransform = useCallback((id)=>`{{ ${id} }}`, []);
|
|
14
40
|
return /*#__PURE__*/ _jsxs("div", {
|
|
15
41
|
className: "field-type textarea",
|
|
16
42
|
children: [
|
|
17
43
|
/*#__PURE__*/ _jsx(FieldLabel, {
|
|
18
44
|
label: field.label
|
|
19
45
|
}),
|
|
20
|
-
/*#__PURE__*/ _jsx(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
46
|
+
/*#__PURE__*/ _jsx(MentionsInput, {
|
|
47
|
+
onBlur: handleBlur,
|
|
48
|
+
onChange: handleChange,
|
|
49
|
+
placeholder: "Type your prompt using {{ fieldName }} variables...",
|
|
50
|
+
style: defaultStyle,
|
|
51
|
+
value: localValue,
|
|
52
|
+
children: /*#__PURE__*/ _jsx(Mention, {
|
|
53
|
+
data: suggestions,
|
|
54
|
+
displayTransform: displayTransform,
|
|
55
|
+
markup: "{{__id__}}",
|
|
56
|
+
style: {
|
|
57
|
+
backgroundColor: 'var(--theme-elevation-100)',
|
|
58
|
+
padding: "2px 0"
|
|
59
|
+
},
|
|
60
|
+
trigger: "{"
|
|
61
|
+
})
|
|
32
62
|
}),
|
|
33
63
|
/*#__PURE__*/ _jsx(FieldDescription, {
|
|
34
64
|
description: field?.admin?.description,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/fields/PromptEditorField/PromptEditorField.tsx"],"sourcesContent":["'use client'\n\nimport type { TextareaFieldClientProps } from 'payload'\n\nimport { FieldDescription, FieldLabel, useField } from '@payloadcms/ui'\nimport React from 'react'\
|
|
1
|
+
{"version":3,"sources":["../../../src/fields/PromptEditorField/PromptEditorField.tsx"],"sourcesContent":["'use client'\n\nimport type { TextareaFieldClientProps } from 'payload'\n\nimport { FieldDescription, FieldLabel, useField } from '@payloadcms/ui'\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { Mention, MentionsInput } from 'react-mentions/dist/react-mentions.cjs.js'\n\nimport { useInstructions } from '../../providers/InstructionsProvider/useInstructions.js'\nimport { defaultStyle } from './defaultStyle.js'\n\nexport const PromptEditorField: React.FC<TextareaFieldClientProps> = (props) => {\n const { field, path: pathFromContext } = props\n const { setValue, value: payloadValue } = useField<string>({\n path: pathFromContext,\n })\n\n const [localValue, setLocalValue] = useState(payloadValue || '')\n const hasInitialized = useRef(false)\n\n const { promptEditorSuggestions } = useInstructions()\n\n const suggestions = useMemo(\n () =>\n promptEditorSuggestions.map((suggestion) => ({\n id: suggestion,\n display: suggestion,\n })),\n [promptEditorSuggestions],\n )\n\n useEffect(() => {\n if (!hasInitialized.current || payloadValue === '') {\n setLocalValue(payloadValue || '')\n hasInitialized.current = true\n }\n }, [payloadValue])\n\n const handleChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setLocalValue(e.target.value)\n }, [])\n\n const handleBlur = useCallback(() => {\n setValue(localValue)\n }, [localValue, setValue])\n\n const displayTransform = useCallback((id: string) => `{{ ${id} }}`, [])\n\n return (\n <div className=\"field-type textarea\">\n <FieldLabel label={field.label} />\n <MentionsInput\n onBlur={handleBlur}\n onChange={handleChange}\n placeholder=\"Type your prompt using {{ fieldName }} variables...\"\n style={defaultStyle}\n value={localValue}\n >\n <Mention\n data={suggestions}\n displayTransform={displayTransform}\n markup=\"{{__id__}}\"\n style={{\n backgroundColor: 'var(--theme-elevation-100)',\n padding: \"2px 0\"\n }}\n trigger=\"{\"\n />\n </MentionsInput>\n <FieldDescription description={field?.admin?.description} path=\"\" />\n </div>\n )\n}"],"names":["FieldDescription","FieldLabel","useField","React","useCallback","useEffect","useMemo","useRef","useState","Mention","MentionsInput","useInstructions","defaultStyle","PromptEditorField","props","field","path","pathFromContext","setValue","value","payloadValue","localValue","setLocalValue","hasInitialized","promptEditorSuggestions","suggestions","map","suggestion","id","display","current","handleChange","e","target","handleBlur","displayTransform","div","className","label","onBlur","onChange","placeholder","style","data","markup","backgroundColor","padding","trigger","description","admin"],"mappings":"AAAA;;AAIA,SAASA,gBAAgB,EAAEC,UAAU,EAAEC,QAAQ,QAAQ,iBAAgB;AACvE,OAAOC,SAASC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AAChF,SAASC,OAAO,EAAEC,aAAa,QAAQ,4CAA2C;AAElF,SAASC,eAAe,QAAQ,0DAAyD;AACzF,SAASC,YAAY,QAAQ,oBAAmB;AAEhD,OAAO,MAAMC,oBAAwD,CAACC;IACpE,MAAM,EAAEC,KAAK,EAAEC,MAAMC,eAAe,EAAE,GAAGH;IACzC,MAAM,EAAEI,QAAQ,EAAEC,OAAOC,YAAY,EAAE,GAAGlB,SAAiB;QACzDc,MAAMC;IACR;IAEA,MAAM,CAACI,YAAYC,cAAc,GAAGd,SAASY,gBAAgB;IAC7D,MAAMG,iBAAiBhB,OAAO;IAE9B,MAAM,EAAEiB,uBAAuB,EAAE,GAAGb;IAEpC,MAAMc,cAAcnB,QAClB,IACEkB,wBAAwBE,GAAG,CAAC,CAACC,aAAgB,CAAA;gBAC3CC,IAAID;gBACJE,SAASF;YACX,CAAA,IACF;QAACH;KAAwB;IAG3BnB,UAAU;QACR,IAAI,CAACkB,eAAeO,OAAO,IAAIV,iBAAiB,IAAI;YAClDE,cAAcF,gBAAgB;YAC9BG,eAAeO,OAAO,GAAG;QAC3B;IACF,GAAG;QAACV;KAAa;IAEjB,MAAMW,eAAe3B,YAAY,CAAC4B;QAChCV,cAAcU,EAAEC,MAAM,CAACd,KAAK;IAC9B,GAAG,EAAE;IAEL,MAAMe,aAAa9B,YAAY;QAC7Bc,SAASG;IACX,GAAG;QAACA;QAAYH;KAAS;IAEzB,MAAMiB,mBAAmB/B,YAAY,CAACwB,KAAe,CAAC,GAAG,EAAEA,GAAG,GAAG,CAAC,EAAE,EAAE;IAEtE,qBACE,MAACQ;QAAIC,WAAU;;0BACb,KAACpC;gBAAWqC,OAAOvB,MAAMuB,KAAK;;0BAC9B,KAAC5B;gBACC6B,QAAQL;gBACRM,UAAUT;gBACVU,aAAY;gBACZC,OAAO9B;gBACPO,OAAOE;0BAEP,cAAA,KAACZ;oBACCkC,MAAMlB;oBACNU,kBAAkBA;oBAClBS,QAAO;oBACPF,OAAO;wBACLG,iBAAiB;wBACjBC,SAAS;oBACX;oBACAC,SAAQ;;;0BAGZ,KAAC/C;gBAAiBgD,aAAajC,OAAOkC,OAAOD;gBAAahC,MAAK;;;;AAGrE,EAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export declare const defaultStyle: {
|
|
2
|
+
control: {
|
|
3
|
+
fontSize: number;
|
|
4
|
+
fontWeight: string;
|
|
5
|
+
};
|
|
6
|
+
'&multiLine': {
|
|
7
|
+
control: {
|
|
8
|
+
fontFamily: string;
|
|
9
|
+
minHeight: number;
|
|
10
|
+
};
|
|
11
|
+
highlighter: {
|
|
12
|
+
border: string;
|
|
13
|
+
padding: number;
|
|
14
|
+
};
|
|
15
|
+
input: {
|
|
16
|
+
padding: number;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
'&singleLine': {
|
|
20
|
+
display: string;
|
|
21
|
+
width: number;
|
|
22
|
+
highlighter: {
|
|
23
|
+
border: string;
|
|
24
|
+
padding: number;
|
|
25
|
+
};
|
|
26
|
+
input: {
|
|
27
|
+
border: string;
|
|
28
|
+
padding: number;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
suggestions: {
|
|
32
|
+
item: {
|
|
33
|
+
'&focused': {
|
|
34
|
+
backgroundColor: string;
|
|
35
|
+
};
|
|
36
|
+
borderBottom: string;
|
|
37
|
+
padding: string;
|
|
38
|
+
};
|
|
39
|
+
list: {
|
|
40
|
+
backgroundColor: string;
|
|
41
|
+
borderRadius: string;
|
|
42
|
+
bottom: number;
|
|
43
|
+
fontSize: number;
|
|
44
|
+
maxHeight: number;
|
|
45
|
+
overflow: string;
|
|
46
|
+
position: string;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=defaultStyle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaultStyle.d.ts","sourceRoot":"","sources":["../../../src/fields/PromptEditorField/defaultStyle.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoDxB,CAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export const defaultStyle = {
|
|
2
|
+
control: {
|
|
3
|
+
fontSize: 12,
|
|
4
|
+
fontWeight: 'normal'
|
|
5
|
+
},
|
|
6
|
+
'&multiLine': {
|
|
7
|
+
control: {
|
|
8
|
+
fontFamily: 'monospace',
|
|
9
|
+
minHeight: 63
|
|
10
|
+
},
|
|
11
|
+
highlighter: {
|
|
12
|
+
border: '1px solid transparent',
|
|
13
|
+
padding: 9
|
|
14
|
+
},
|
|
15
|
+
input: {
|
|
16
|
+
padding: 9
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
'&singleLine': {
|
|
20
|
+
display: 'inline-block',
|
|
21
|
+
width: 180,
|
|
22
|
+
highlighter: {
|
|
23
|
+
border: '2px inset transparent',
|
|
24
|
+
padding: 1
|
|
25
|
+
},
|
|
26
|
+
input: {
|
|
27
|
+
border: '2px inset',
|
|
28
|
+
padding: 1
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
suggestions: {
|
|
32
|
+
item: {
|
|
33
|
+
'&focused': {
|
|
34
|
+
backgroundColor: 'var(--theme-elevation-100)'
|
|
35
|
+
},
|
|
36
|
+
borderBottom: '1px solid rgba(0,0,0,0.15)',
|
|
37
|
+
padding: '5px 15px'
|
|
38
|
+
},
|
|
39
|
+
list: {
|
|
40
|
+
backgroundColor: 'var(--theme-input-bg)',
|
|
41
|
+
borderRadius: '4px',
|
|
42
|
+
bottom: 14,
|
|
43
|
+
fontSize: 14,
|
|
44
|
+
maxHeight: 160,
|
|
45
|
+
overflow: 'auto',
|
|
46
|
+
position: 'absolute'
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=defaultStyle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/fields/PromptEditorField/defaultStyle.ts"],"sourcesContent":["export const defaultStyle = {\n control: {\n fontSize: 12,\n fontWeight: 'normal',\n },\n\n '&multiLine': {\n control: {\n fontFamily: 'monospace',\n minHeight: 63,\n },\n highlighter: {\n border: '1px solid transparent',\n padding: 9,\n },\n input: {\n padding: 9,\n },\n },\n\n '&singleLine': {\n display: 'inline-block',\n width: 180,\n\n highlighter: {\n border: '2px inset transparent',\n padding: 1,\n },\n input: {\n border: '2px inset',\n padding: 1,\n },\n },\n\n suggestions: {\n item: {\n '&focused': {\n backgroundColor: 'var(--theme-elevation-100)',\n },\n borderBottom: '1px solid rgba(0,0,0,0.15)',\n padding: '5px 15px',\n },\n list: {\n backgroundColor: 'var(--theme-input-bg)',\n borderRadius: '4px',\n bottom: 14,\n fontSize: 14,\n maxHeight: 160,\n overflow: 'auto',\n position: 'absolute',\n },\n },\n}\n"],"names":["defaultStyle","control","fontSize","fontWeight","fontFamily","minHeight","highlighter","border","padding","input","display","width","suggestions","item","backgroundColor","borderBottom","list","borderRadius","bottom","maxHeight","overflow","position"],"mappings":"AAAA,OAAO,MAAMA,eAAe;IAC1BC,SAAS;QACPC,UAAU;QACVC,YAAY;IACd;IAEA,cAAc;QACZF,SAAS;YACPG,YAAY;YACZC,WAAW;QACb;QACAC,aAAa;YACXC,QAAQ;YACRC,SAAS;QACX;QACAC,OAAO;YACLD,SAAS;QACX;IACF;IAEA,eAAe;QACbE,SAAS;QACTC,OAAO;QAEPL,aAAa;YACXC,QAAQ;YACRC,SAAS;QACX;QACAC,OAAO;YACLF,QAAQ;YACRC,SAAS;QACX;IACF;IAEAI,aAAa;QACXC,MAAM;YACJ,YAAY;gBACVC,iBAAiB;YACnB;YACAC,cAAc;YACdP,SAAS;QACX;QACAQ,MAAM;YACJF,iBAAiB;YACjBG,cAAc;YACdC,QAAQ;YACRhB,UAAU;YACViB,WAAW;YACXC,UAAU;YACVC,UAAU;QACZ;IACF;AACF,EAAC"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { Field } from 'payload';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
export declare const InstructionsContext: React.Context<{
|
|
4
|
+
activeCollection?: string;
|
|
4
5
|
field?: Field;
|
|
5
6
|
instructions: Record<string, any>;
|
|
6
7
|
isConfigAllowed: boolean;
|
|
7
8
|
path?: string;
|
|
8
9
|
schemaPath?: unknown;
|
|
10
|
+
setActiveCollection?: (val: unknown) => void;
|
|
9
11
|
}>;
|
|
10
12
|
export declare const InstructionsProvider: React.FC;
|
|
11
13
|
//# sourceMappingURL=InstructionsProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstructionsProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/InstructionsProvider/InstructionsProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAGpC,OAAO,KAA6C,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"InstructionsProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/InstructionsProvider/InstructionsProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAGpC,OAAO,KAA6C,MAAM,OAAO,CAAA;AAoBjE,eAAO,MAAM,mBAAmB;uBAfX,MAAM;YACjB,KAAK;kBACC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;qBAChB,OAAO;WACjB,MAAM;iBACA,OAAO;0BACE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI;EASkB,CAAA;AAEhE,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAkCxC,CAAA"}
|
|
@@ -13,6 +13,7 @@ const initialContext = {
|
|
|
13
13
|
export const InstructionsContext = /*#__PURE__*/ createContext(initialContext);
|
|
14
14
|
export const InstructionsProvider = ({ children })=>{
|
|
15
15
|
const [instructions, setInstructionsState] = useState({});
|
|
16
|
+
const [activeCollection, setActiveCollection] = useState('');
|
|
16
17
|
const [isConfigAllowed, setIsConfigAllowed] = useState(false);
|
|
17
18
|
const { user } = useAuth();
|
|
18
19
|
const { config } = useConfig();
|
|
@@ -33,8 +34,10 @@ export const InstructionsProvider = ({ children })=>{
|
|
|
33
34
|
]);
|
|
34
35
|
return /*#__PURE__*/ _jsx(InstructionsContext.Provider, {
|
|
35
36
|
value: {
|
|
37
|
+
activeCollection,
|
|
36
38
|
instructions,
|
|
37
|
-
isConfigAllowed
|
|
39
|
+
isConfigAllowed,
|
|
40
|
+
setActiveCollection
|
|
38
41
|
},
|
|
39
42
|
children: children
|
|
40
43
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/InstructionsProvider/InstructionsProvider.tsx"],"sourcesContent":["'use client'\n\nimport type { Field } from 'payload'\n\nimport { useAuth, useConfig } from '@payloadcms/ui'\nimport React, { createContext, useEffect, useState } from 'react'\n\nimport { PLUGIN_FETCH_FIELDS_ENDPOINT } from '../../defaults.js'\n\nconst initialContext: {\n field?: Field\n instructions: Record<string, any>\n isConfigAllowed: boolean\n path?: string\n schemaPath?: unknown\n} = {\n field: undefined,\n instructions: undefined,\n isConfigAllowed: true,\n path: '',\n schemaPath: '',\n}\n\nexport const InstructionsContext = createContext(initialContext)\n\nexport const InstructionsProvider: React.FC = ({ children }: { children: React.ReactNode }) => {\n const [instructions, setInstructionsState] = useState({})\n const [isConfigAllowed, setIsConfigAllowed] = useState(false)\n const {
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/InstructionsProvider/InstructionsProvider.tsx"],"sourcesContent":["'use client'\n\nimport type { Field } from 'payload'\n\nimport { useAuth, useConfig } from '@payloadcms/ui'\nimport React, { createContext, useEffect, useState } from 'react'\n\nimport { PLUGIN_FETCH_FIELDS_ENDPOINT } from '../../defaults.js'\n\nconst initialContext: {\n activeCollection?: string\n field?: Field\n instructions: Record<string, any>\n isConfigAllowed: boolean\n path?: string\n schemaPath?: unknown\n setActiveCollection?: (val: unknown) => void\n} = {\n field: undefined,\n instructions: undefined,\n isConfigAllowed: true,\n path: '',\n schemaPath: '',\n}\n\nexport const InstructionsContext = createContext(initialContext)\n\nexport const InstructionsProvider: React.FC = ({ children }: { children: React.ReactNode }) => {\n const [instructions, setInstructionsState] = useState({})\n const [activeCollection, setActiveCollection] = useState('')\n const [isConfigAllowed, setIsConfigAllowed] = useState(false)\n const { user } = useAuth()\n\n const { config } = useConfig()\n const {\n routes: { api },\n serverURL,\n } = config\n\n // This is here because each field have separate instructions and\n // their ID is needed to edit them for Drawer\n useEffect(() => {\n fetch(`${serverURL}${api}${PLUGIN_FETCH_FIELDS_ENDPOINT}`)\n .then(async (res) => {\n await res.json().then((data) => {\n setIsConfigAllowed(data?.isConfigAllowed)\n setInstructionsState(data?.fields)\n })\n })\n .catch((err) => {\n console.error('InstructionsProvider:', err)\n })\n }, [user])\n\n return (\n <InstructionsContext.Provider\n value={{ activeCollection, instructions, isConfigAllowed, setActiveCollection }}\n >\n {children}\n </InstructionsContext.Provider>\n )\n}\n"],"names":["useAuth","useConfig","React","createContext","useEffect","useState","PLUGIN_FETCH_FIELDS_ENDPOINT","initialContext","field","undefined","instructions","isConfigAllowed","path","schemaPath","InstructionsContext","InstructionsProvider","children","setInstructionsState","activeCollection","setActiveCollection","setIsConfigAllowed","user","config","routes","api","serverURL","fetch","then","res","json","data","fields","catch","err","console","error","Provider","value"],"mappings":"AAAA;;AAIA,SAASA,OAAO,EAAEC,SAAS,QAAQ,iBAAgB;AACnD,OAAOC,SAASC,aAAa,EAAEC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAEjE,SAASC,4BAA4B,QAAQ,oBAAmB;AAEhE,MAAMC,iBAQF;IACFC,OAAOC;IACPC,cAAcD;IACdE,iBAAiB;IACjBC,MAAM;IACNC,YAAY;AACd;AAEA,OAAO,MAAMC,oCAAsBX,cAAcI,gBAAe;AAEhE,OAAO,MAAMQ,uBAAiC,CAAC,EAAEC,QAAQ,EAAiC;IACxF,MAAM,CAACN,cAAcO,qBAAqB,GAAGZ,SAAS,CAAC;IACvD,MAAM,CAACa,kBAAkBC,oBAAoB,GAAGd,SAAS;IACzD,MAAM,CAACM,iBAAiBS,mBAAmB,GAAGf,SAAS;IACvD,MAAM,EAAEgB,IAAI,EAAE,GAAGrB;IAEjB,MAAM,EAAEsB,MAAM,EAAE,GAAGrB;IACnB,MAAM,EACJsB,QAAQ,EAAEC,GAAG,EAAE,EACfC,SAAS,EACV,GAAGH;IAEJ,iEAAiE;IACjE,6CAA6C;IAC7ClB,UAAU;QACRsB,MAAM,GAAGD,YAAYD,MAAMlB,8BAA8B,EACtDqB,IAAI,CAAC,OAAOC;YACX,MAAMA,IAAIC,IAAI,GAAGF,IAAI,CAAC,CAACG;gBACrBV,mBAAmBU,MAAMnB;gBACzBM,qBAAqBa,MAAMC;YAC7B;QACF,GACCC,KAAK,CAAC,CAACC;YACNC,QAAQC,KAAK,CAAC,yBAAyBF;QACzC;IACJ,GAAG;QAACZ;KAAK;IAET,qBACE,KAACP,oBAAoBsB,QAAQ;QAC3BC,OAAO;YAAEnB;YAAkBR;YAAcC;YAAiBQ;QAAoB;kBAE7EH;;AAGP,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useInstructions.d.ts","sourceRoot":"","sources":["../../../src/providers/InstructionsProvider/useInstructions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useInstructions.d.ts","sourceRoot":"","sources":["../../../src/providers/InstructionsProvider/useInstructions.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,eAAe,GAC1B,SAAQ;IACN,UAAU,CAAC,EAAE,OAAO,CAAA;CAChB,QAqEP,CAAA"}
|
|
@@ -1,45 +1,70 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useDocumentInfo } from '@payloadcms/ui';
|
|
2
|
+
import { useContext, useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import { PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js';
|
|
2
4
|
import { handlebarsHelpers, handlebarsHelpersMap } from '../../libraries/handlebars/helpersMap.js';
|
|
3
5
|
import { InstructionsContext } from './InstructionsProvider.js';
|
|
4
6
|
export const useInstructions = (update = {})=>{
|
|
5
7
|
const context = useContext(InstructionsContext);
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
return key.split('.').slice(1).join('.');
|
|
9
|
-
});
|
|
10
|
-
const promptEditorSuggestions = [
|
|
11
|
-
...fields
|
|
12
|
-
].reduce((acc, f)=>{
|
|
13
|
-
const fieldKey = Object.keys(context.instructions).find((k)=>k.endsWith(f));
|
|
14
|
-
const fieldInfo = context.instructions[fieldKey];
|
|
15
|
-
// Currently, Upload fields are excluded from suggestions
|
|
16
|
-
if (fieldInfo.fieldType === 'upload') {
|
|
17
|
-
return acc;
|
|
18
|
-
}
|
|
19
|
-
const helpers = handlebarsHelpers.filter((h)=>handlebarsHelpersMap[h]?.field === fieldInfo.fieldType);
|
|
20
|
-
if (helpers.length) {
|
|
21
|
-
for (const helper of helpers){
|
|
22
|
-
acc.push(helper + ` ${f}`);
|
|
23
|
-
}
|
|
24
|
-
return acc;
|
|
25
|
-
}
|
|
26
|
-
acc.push(f);
|
|
27
|
-
return acc;
|
|
28
|
-
}, []);
|
|
8
|
+
const { collectionSlug } = useDocumentInfo();
|
|
9
|
+
const { activeCollection, instructions, setActiveCollection } = context;
|
|
29
10
|
const [schemaPath, setSchemaPath] = useState(update.schemaPath);
|
|
30
11
|
useEffect(()=>{
|
|
31
12
|
if (update.schemaPath !== schemaPath) {
|
|
32
13
|
setSchemaPath(update.schemaPath);
|
|
33
14
|
}
|
|
34
15
|
}, [
|
|
35
|
-
schemaPath
|
|
36
|
-
|
|
16
|
+
update.schemaPath
|
|
17
|
+
]);
|
|
18
|
+
useEffect(()=>{
|
|
19
|
+
if (activeCollection !== collectionSlug && collectionSlug !== PLUGIN_INSTRUCTIONS_TABLE) {
|
|
20
|
+
setActiveCollection(collectionSlug);
|
|
21
|
+
}
|
|
22
|
+
}, [
|
|
23
|
+
activeCollection,
|
|
24
|
+
collectionSlug,
|
|
25
|
+
setActiveCollection
|
|
26
|
+
]);
|
|
27
|
+
const groupedFields = useMemo(()=>{
|
|
28
|
+
const result = {};
|
|
29
|
+
for (const fullKey of Object.keys(instructions)){
|
|
30
|
+
const [collection, ...pathParts] = fullKey.split('.');
|
|
31
|
+
const path = pathParts.join('.');
|
|
32
|
+
if (!result[collection]) result[collection] = [];
|
|
33
|
+
result[collection].push(path);
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}, [
|
|
37
|
+
instructions
|
|
38
|
+
]);
|
|
39
|
+
// Suggestions for prompt editor
|
|
40
|
+
const promptEditorSuggestions = useMemo(()=>{
|
|
41
|
+
const activeFields = groupedFields[activeCollection] || [];
|
|
42
|
+
return activeFields.reduce((acc, f)=>{
|
|
43
|
+
const fieldKey = Object.keys(instructions).find((k)=>k.endsWith(f));
|
|
44
|
+
const fieldInfo = instructions[fieldKey];
|
|
45
|
+
if (!fieldInfo) return acc;
|
|
46
|
+
if (fieldInfo.fieldType === 'upload') {
|
|
47
|
+
acc.push(`${f}.url`);
|
|
48
|
+
return acc;
|
|
49
|
+
}
|
|
50
|
+
const helpers = handlebarsHelpers.filter((h)=>handlebarsHelpersMap[h]?.field === fieldInfo.fieldType);
|
|
51
|
+
if (helpers.length) {
|
|
52
|
+
for (const helper of helpers){
|
|
53
|
+
acc.push(`${helper} ${f}`);
|
|
54
|
+
}
|
|
55
|
+
} else {
|
|
56
|
+
acc.push(f);
|
|
57
|
+
}
|
|
58
|
+
return acc;
|
|
59
|
+
}, []);
|
|
60
|
+
}, [
|
|
61
|
+
groupedFields,
|
|
62
|
+
activeCollection,
|
|
63
|
+
instructions
|
|
37
64
|
]);
|
|
38
65
|
return {
|
|
39
66
|
...context,
|
|
40
|
-
...
|
|
41
|
-
fields,
|
|
42
|
-
map: context.instructions,
|
|
67
|
+
...instructions[schemaPath] || {},
|
|
43
68
|
promptEditorSuggestions
|
|
44
69
|
};
|
|
45
70
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/InstructionsProvider/useInstructions.ts"],"sourcesContent":["import { useContext, useEffect, useState } from 'react'\n\nimport { handlebarsHelpers, handlebarsHelpersMap } from '../../libraries/handlebars/helpersMap.js'\nimport { InstructionsContext } from './InstructionsProvider.js'\n\nexport const useInstructions = (\n update: {\n schemaPath?: unknown\n } = {},\n) => {\n const context = useContext(InstructionsContext)\n\n
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/InstructionsProvider/useInstructions.ts"],"sourcesContent":["import { 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'\nimport { InstructionsContext } from './InstructionsProvider.js'\n\nexport const useInstructions = (\n update: {\n schemaPath?: unknown\n } = {},\n) => {\n const context = useContext(InstructionsContext)\n const { collectionSlug } = useDocumentInfo()\n const { activeCollection, instructions, 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 (activeCollection !== collectionSlug && collectionSlug !== PLUGIN_INSTRUCTIONS_TABLE) {\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]) result[collection] = []\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] || []\n\n return activeFields.reduce<string[]>((acc, f) => {\n const fieldKey = Object.keys(instructions).find((k) => k.endsWith(f))\n const fieldInfo = instructions[fieldKey]\n\n if (!fieldInfo) return acc\n\n if (fieldInfo.fieldType === 'upload') {\n acc.push(`${f}.url`)\n return acc\n }\n\n const helpers = handlebarsHelpers.filter(\n (h) => handlebarsHelpersMap[h]?.field === fieldInfo.fieldType,\n )\n\n if (helpers.length) {\n for (const helper of helpers) {\n acc.push(`${helper} ${f}`)\n }\n } else {\n acc.push(f)\n }\n\n return acc\n }, [])\n }, [groupedFields, activeCollection, instructions])\n\n return {\n ...context,\n ...(instructions[schemaPath] || {}),\n promptEditorSuggestions,\n }\n}\n"],"names":["useDocumentInfo","useContext","useEffect","useMemo","useState","PLUGIN_INSTRUCTIONS_TABLE","handlebarsHelpers","handlebarsHelpersMap","InstructionsContext","useInstructions","update","context","collectionSlug","activeCollection","instructions","setActiveCollection","schemaPath","setSchemaPath","groupedFields","result","fullKey","Object","keys","collection","pathParts","split","path","join","push","promptEditorSuggestions","activeFields","reduce","acc","f","fieldKey","find","k","endsWith","fieldInfo","fieldType","helpers","filter","h","field","length","helper"],"mappings":"AAAA,SAASA,eAAe,QAAQ,iBAAgB;AAChD,SAASC,UAAU,EAAEC,SAAS,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AAEhE,SAASC,yBAAyB,QAAQ,oBAAmB;AAC7D,SAASC,iBAAiB,EAAEC,oBAAoB,QAAQ,2CAA0C;AAClG,SAASC,mBAAmB,QAAQ,4BAA2B;AAE/D,OAAO,MAAMC,kBAAkB,CAC7BC,SAEI,CAAC,CAAC;IAEN,MAAMC,UAAUV,WAAWO;IAC3B,MAAM,EAAEI,cAAc,EAAE,GAAGZ;IAC3B,MAAM,EAAEa,gBAAgB,EAAEC,YAAY,EAAEC,mBAAmB,EAAE,GAAGJ;IAEhE,MAAM,CAACK,YAAYC,cAAc,GAAGb,SAASM,OAAOM,UAAU;IAE9Dd,UAAU;QACR,IAAIQ,OAAOM,UAAU,KAAKA,YAAY;YACpCC,cAAcP,OAAOM,UAAU;QACjC;IACF,GAAG;QAACN,OAAOM,UAAU;KAAC;IAEtBd,UAAU;QACR,IAAIW,qBAAqBD,kBAAkBA,mBAAmBP,2BAA2B;YACvFU,oBAAoBH;QACtB;IACF,GAAG;QAACC;QAAkBD;QAAgBG;KAAoB;IAE1D,MAAMG,gBAAgBf,QAAQ;QAC5B,MAAMgB,SAAmC,CAAC;QAE1C,KAAK,MAAMC,WAAWC,OAAOC,IAAI,CAACR,cAAe;YAC/C,MAAM,CAACS,YAAY,GAAGC,UAAU,GAAGJ,QAAQK,KAAK,CAAC;YACjD,MAAMC,OAAOF,UAAUG,IAAI,CAAC;YAC5B,IAAI,CAACR,MAAM,CAACI,WAAW,EAAEJ,MAAM,CAACI,WAAW,GAAG,EAAE;YAChDJ,MAAM,CAACI,WAAW,CAACK,IAAI,CAACF;QAC1B;QAEA,OAAOP;IACT,GAAG;QAACL;KAAa;IAEjB,gCAAgC;IAChC,MAAMe,0BAA0B1B,QAAQ;QACtC,MAAM2B,eAAeZ,aAAa,CAACL,iBAAiB,IAAI,EAAE;QAE1D,OAAOiB,aAAaC,MAAM,CAAW,CAACC,KAAKC;YACzC,MAAMC,WAAWb,OAAOC,IAAI,CAACR,cAAcqB,IAAI,CAAC,CAACC,IAAMA,EAAEC,QAAQ,CAACJ;YAClE,MAAMK,YAAYxB,YAAY,CAACoB,SAAS;YAExC,IAAI,CAACI,WAAW,OAAON;YAEvB,IAAIM,UAAUC,SAAS,KAAK,UAAU;gBACpCP,IAAIJ,IAAI,CAAC,GAAGK,EAAE,IAAI,CAAC;gBACnB,OAAOD;YACT;YAEA,MAAMQ,UAAUlC,kBAAkBmC,MAAM,CACtC,CAACC,IAAMnC,oBAAoB,CAACmC,EAAE,EAAEC,UAAUL,UAAUC,SAAS;YAG/D,IAAIC,QAAQI,MAAM,EAAE;gBAClB,KAAK,MAAMC,UAAUL,QAAS;oBAC5BR,IAAIJ,IAAI,CAAC,GAAGiB,OAAO,CAAC,EAAEZ,GAAG;gBAC3B;YACF,OAAO;gBACLD,IAAIJ,IAAI,CAACK;YACX;YAEA,OAAOD;QACT,GAAG,EAAE;IACP,GAAG;QAACd;QAAeL;QAAkBC;KAAa;IAElD,OAAO;QACL,GAAGH,OAAO;QACV,GAAIG,YAAY,CAACE,WAAW,IAAI,CAAC,CAAC;QAClCa;IACF;AACF,EAAC"}
|