@ai-stack/payloadcms
Version:
<p align="center"> <img alt="Payload AI Plugin" src="assets/payload-ai-intro.gif" width="100%" /> </p>
174 lines (173 loc) • 8.47 kB
JavaScript
import { deepMerge } from 'payload/shared';
import { defaultGenerationModels } from './ai/models/index.js';
import { lexicalJsonSchema } from './ai/schemas/lexicalJsonSchema.js';
import { instructionsCollection } from './collections/Instructions.js';
import { PLUGIN_NAME } from './defaults.js';
import { fetchFields } from './endpoints/fetchFields.js';
import { endpoints } from './endpoints/index.js';
import { init } from './init.js';
import { translations } from './translations/index.js';
import { getGenerationModels } from './utilities/getGenerationModels.js';
import { isPluginActivated } from './utilities/isPluginActivated.js';
import { updateFieldsConfig } from './utilities/updateFieldsConfig.js';
const defaultPluginConfig = {
access: {
generate: ({ req })=>!!req.user,
settings: ({ req })=>!!req.user
},
collections: {},
disableSponsorMessage: false,
generatePromptOnInit: true,
generationModels: defaultGenerationModels
};
const sponsorMessage = `
╔═══════════════════════════════════════════════════════════════╗
║ THANK YOU FOR USING THE PAYLOAD AI PLUGIN! ║
║ ║
║ If this plugin makes your life easier, please ║
║ consider supporting its development and maintenance: ║
║ ║
║ • Buy me a coffee: https://buymeacoffee.com/ashbuilds ║
║ • Sponsor on GitHub: https://github.com/sponsors/ashbuilds ║
║ ║
║ Your support fuels continued improvements, ║
║ new features, and more caffeinated coding sessions! ☕ ║
║ ║
║ Got feedback or need help? Submit an issue here: ║
║ • https://github.com/ashbuilds/payload-ai/issues/new ║
║ ║
║ Thank you again, and happy building! ║
╚═══════════════════════════════════════════════════════════════╝
`;
const securityMessage = `
╔═══════════════════════════════════════════════════════════════╗
║ SECURITY NOTICE ║
║ ║
║ The AI Plugin now requires authentication by default. ║
║ All AI features are restricted to authenticated users. ║
║ ║
║ To customize access control, configure the 'access' option ║
║ in your plugin settings. See documentation for details. ║
║ ║
║ If you need different access patterns, please configure ║
║ them explicitly in your plugin configuration. ║
╚═══════════════════════════════════════════════════════════════╝
`;
const payloadAiPlugin = (pluginConfig)=>(incomingConfig)=>{
pluginConfig = {
...defaultPluginConfig,
...pluginConfig,
access: {
...defaultPluginConfig.access,
...pluginConfig.access
}
};
pluginConfig.generationModels = getGenerationModels(pluginConfig);
const isActivated = isPluginActivated(pluginConfig);
let updatedConfig = {
...incomingConfig
};
let collectionsFieldPathMap = {};
if (isActivated) {
const Instructions = instructionsCollection(pluginConfig);
// Inject editor schema to config, so that it can be accessed when /textarea endpoint will hit
const lexicalSchema = lexicalJsonSchema(pluginConfig.editorConfig?.nodes);
Instructions.admin = {
...Instructions.admin
};
if (pluginConfig.debugging) {
Instructions.admin.hidden = false;
}
Instructions.admin.custom = {
...Instructions.admin.custom || {},
[PLUGIN_NAME]: {
editorConfig: {
// Used in admin client for useObject hook
schema: lexicalSchema
}
}
};
const collections = [
...incomingConfig.collections ?? [],
Instructions
];
const globals = [
...incomingConfig.globals ?? []
];
const { collections: collectionSlugs, globals: globalsSlugs } = pluginConfig;
const { components: { providers = [] } = {} } = incomingConfig.admin || {};
const updatedProviders = [
...providers ?? [],
{
path: '@ai-stack/payloadcms/client#InstructionsProvider'
}
];
incomingConfig.admin = {
...incomingConfig.admin || {},
components: {
...incomingConfig.admin?.components ?? {},
providers: updatedProviders
}
};
const pluginEndpoints = endpoints(pluginConfig);
updatedConfig = {
...incomingConfig,
collections: collections.map((collection)=>{
if (collectionSlugs[collection.slug]) {
const { schemaPathMap, updatedCollectionConfig } = updateFieldsConfig(collection);
collectionsFieldPathMap = {
...collectionsFieldPathMap,
...schemaPathMap
};
return updatedCollectionConfig;
}
return collection;
}),
endpoints: [
...incomingConfig.endpoints ?? [],
pluginEndpoints.textarea,
pluginEndpoints.upload,
fetchFields(pluginConfig)
],
globals: globals.map((global)=>{
if (globalsSlugs && globalsSlugs[global.slug]) {
const { schemaPathMap, updatedCollectionConfig } = updateFieldsConfig(global);
collectionsFieldPathMap = {
...collectionsFieldPathMap,
...schemaPathMap
};
return updatedCollectionConfig;
}
return global;
}),
i18n: {
...incomingConfig.i18n || {},
translations: {
...deepMerge(translations, incomingConfig.i18n?.translations ?? {})
}
}
};
}
updatedConfig.onInit = async (payload)=>{
if (incomingConfig.onInit) await incomingConfig.onInit(payload);
if (!isActivated) {
payload.logger.warn(`— AI Plugin: Not activated. Please verify your environment keys.`);
return;
}
await init(payload, collectionsFieldPathMap, pluginConfig).catch((error)=>{
payload.logger.error(error, `— AI Plugin: Initialization Error`);
}).finally(()=>{
if (!pluginConfig.disableSponsorMessage) {
setTimeout(()=>{
payload.logger.info(securityMessage);
}, 1000);
setTimeout(()=>{
payload.logger.info(sponsorMessage);
}, 3000);
}
});
};
return updatedConfig;
};
export { payloadAiPlugin };
//# sourceMappingURL=plugin.js.map