@karixi/payload-ai 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,566 @@
1
+ import { n as generateDocuments } from "./content-generator-fPX2DL3g.mjs";
2
+ import { n as createProvider } from "./base-BPwZbeh1.mjs";
3
+ import { n as readCollectionSchema, t as readAllCollectionSchemas } from "./schema-reader-ZkoI6Pwi.mjs";
4
+ import { z } from "zod";
5
+ //#region src/mcp/prompts.ts
6
+ function getAIPrompts() {
7
+ return [{
8
+ name: "generateContentBrief",
9
+ title: "Generate Content Brief",
10
+ description: "Produce a structured brief that guides AI content generation for a given collection and theme.",
11
+ argsSchema: {
12
+ collection: z.string().describe("The collection slug to generate content for"),
13
+ theme: z.string().describe("The overarching theme or topic for the content"),
14
+ count: z.number().describe("Number of documents to generate")
15
+ },
16
+ handler(args) {
17
+ const collection = args.collection;
18
+ const theme = args.theme;
19
+ const count = args.count;
20
+ return { messages: [{
21
+ role: "user",
22
+ content: {
23
+ type: "text",
24
+ text: [
25
+ `You are preparing a content generation brief for the Payload CMS collection: **${collection}**.`,
26
+ "",
27
+ `**Theme**: ${theme}`,
28
+ `**Documents to generate**: ${count}`,
29
+ "",
30
+ "Please produce a structured brief that includes:",
31
+ "1. A short description of the content style and tone that fits the theme.",
32
+ "2. Key topics or sub-themes each document should cover.",
33
+ "3. Any field-level guidance (titles, descriptions, categories, tags) relevant to this collection.",
34
+ "4. Example values for the most important fields.",
35
+ "",
36
+ `Output the brief as a JSON object with keys: style, topics, fieldGuidance, examples.`
37
+ ].join("\n")
38
+ }
39
+ }] };
40
+ }
41
+ }, {
42
+ name: "reviewGeneratedContent",
43
+ title: "Review Generated Content",
44
+ description: "Return a review prompt asking an AI to evaluate and suggest improvements for a generated document.",
45
+ argsSchema: {
46
+ collection: z.string().describe("The collection slug the document belongs to"),
47
+ documentId: z.string().describe("The ID of the document to review")
48
+ },
49
+ handler(args) {
50
+ const collection = args.collection;
51
+ const documentId = args.documentId;
52
+ return { messages: [{
53
+ role: "user",
54
+ content: {
55
+ type: "text",
56
+ text: [
57
+ `Please review the following generated document.`,
58
+ "",
59
+ `**Collection**: ${collection}`,
60
+ `**Document ID**: ${documentId}`,
61
+ "",
62
+ "Evaluate the document on:",
63
+ "1. **Accuracy** — Is the content factually plausible and internally consistent?",
64
+ "2. **Completeness** — Are all important fields populated with meaningful values?",
65
+ "3. **Quality** — Is the writing style appropriate and free of obvious AI artifacts?",
66
+ "4. **Schema compliance** — Do field values match the expected types and constraints?",
67
+ "",
68
+ "Provide a structured review with a score (1–10) for each criterion and specific suggestions for improvement."
69
+ ].join("\n")
70
+ }
71
+ }] };
72
+ }
73
+ }];
74
+ }
75
+ //#endregion
76
+ //#region src/mcp/resources.ts
77
+ function getAIResources() {
78
+ return [{
79
+ name: "schemaOverview",
80
+ title: "Collection Schema Overview",
81
+ description: "A high-level overview of all Payload CMS collections including their slugs, field counts, and populatable status.",
82
+ uri: "schema://collections",
83
+ mimeType: "text/plain",
84
+ handler() {
85
+ return { contents: [{
86
+ uri: "schema://collections",
87
+ text: [
88
+ "This resource provides a schema overview of all registered Payload CMS collections.",
89
+ "",
90
+ "To retrieve the full schema for a specific collection, use the `getCollectionSchema` tool.",
91
+ "To list all collections with field counts and populatable status, use the `listCollections` tool.",
92
+ "To generate documents into a single collection, use the `populateCollection` tool.",
93
+ "To populate multiple collections at once, use the `bulkPopulate` tool.",
94
+ "",
95
+ "All schema information is derived from the live Payload configuration at runtime."
96
+ ].join("\n")
97
+ }] };
98
+ }
99
+ }];
100
+ }
101
+ //#endregion
102
+ //#region src/generate/deletion-log.ts
103
+ /**
104
+ * Tracks created documents for rollback on failure.
105
+ * Uses in-memory journal — no MongoDB transaction dependency.
106
+ * Works on standalone MongoDB, replica sets, and Atlas.
107
+ */
108
+ var DeletionLog = class {
109
+ journal = [];
110
+ /** Record a created document for potential rollback */
111
+ record(collection, id) {
112
+ this.journal.push({
113
+ collection,
114
+ id,
115
+ createdAt: /* @__PURE__ */ new Date()
116
+ });
117
+ }
118
+ /** Get all recorded entries */
119
+ getEntries() {
120
+ return [...this.journal];
121
+ }
122
+ /** Get count of recorded entries */
123
+ get size() {
124
+ return this.journal.length;
125
+ }
126
+ /**
127
+ * Rollback all created documents by deleting them in reverse order.
128
+ * Best-effort: if process crashes, journal is lost.
129
+ */
130
+ async rollback(payload, req) {
131
+ const failed = [];
132
+ let deleted = 0;
133
+ for (const entry of [...this.journal].reverse()) try {
134
+ await payload.delete({
135
+ collection: entry.collection,
136
+ id: entry.id,
137
+ req
138
+ });
139
+ deleted++;
140
+ } catch (err) {
141
+ failed.push({
142
+ collection: entry.collection,
143
+ id: entry.id,
144
+ error: err instanceof Error ? err.message : String(err)
145
+ });
146
+ }
147
+ this.journal = [];
148
+ return {
149
+ deleted,
150
+ failed
151
+ };
152
+ }
153
+ /** Clear the journal without deleting documents */
154
+ clear() {
155
+ this.journal = [];
156
+ }
157
+ };
158
+ //#endregion
159
+ //#region src/generate/relationship-linker.ts
160
+ /**
161
+ * Link relationship fields between generated documents.
162
+ *
163
+ * For each relationship defined in the schema, looks up available IDs
164
+ * from documentIds and updates the documents in that collection.
165
+ */
166
+ async function linkRelationships(payload, req, schema, documentIds) {
167
+ let updated = 0;
168
+ let failed = 0;
169
+ const ownIds = documentIds[schema.slug] ?? [];
170
+ if (ownIds.length === 0) return {
171
+ updated,
172
+ failed
173
+ };
174
+ for (const docId of ownIds) {
175
+ const updateData = {};
176
+ let hasUpdates = false;
177
+ for (const rel of schema.relationships) {
178
+ const targetCollection = Array.isArray(rel.collection) ? rel.collection[0] : rel.collection;
179
+ if (!targetCollection) continue;
180
+ if (rel.isSelfReferential) {
181
+ const siblings = ownIds.filter((id) => id !== docId);
182
+ if (siblings.length === 0) continue;
183
+ const count = Math.min(siblings.length, 2 + Math.floor(Math.random() * 3));
184
+ const shuffled = [...siblings].sort(() => Math.random() - .5).slice(0, count);
185
+ updateData[rel.field] = rel.hasMany ? shuffled : shuffled[0];
186
+ hasUpdates = true;
187
+ continue;
188
+ }
189
+ const targetIds = documentIds[targetCollection] ?? [];
190
+ if (targetIds.length === 0) continue;
191
+ if (rel.hasMany) {
192
+ const count = Math.min(targetIds.length, 1 + Math.floor(Math.random() * 3));
193
+ const shuffled = [...targetIds].sort(() => Math.random() - .5).slice(0, count);
194
+ updateData[rel.field] = shuffled;
195
+ } else {
196
+ const randomIndex = Math.floor(Math.random() * targetIds.length);
197
+ updateData[rel.field] = targetIds[randomIndex];
198
+ }
199
+ hasUpdates = true;
200
+ }
201
+ if (!hasUpdates) continue;
202
+ try {
203
+ await payload.update({
204
+ collection: schema.slug,
205
+ id: docId,
206
+ data: updateData,
207
+ overrideAccess: true,
208
+ req
209
+ });
210
+ updated++;
211
+ } catch (err) {
212
+ console.error(`[relationship-linker] Failed to update ${schema.slug}/${docId}:`, err instanceof Error ? err.message : String(err));
213
+ failed++;
214
+ }
215
+ }
216
+ return {
217
+ updated,
218
+ failed
219
+ };
220
+ }
221
+ //#endregion
222
+ //#region src/orchestrate/progress-tracker.ts
223
+ /** Emit a progress event on the emitter */
224
+ function emitProgress(emitter, event) {
225
+ emitter.emit("progress", event);
226
+ }
227
+ //#endregion
228
+ //#region src/orchestrate/bulk-runner.ts
229
+ /**
230
+ * Run bulk population of Payload collections in dependency order.
231
+ *
232
+ * Flow:
233
+ * 1. Resolve creation order from schemas
234
+ * 2. Filter to collections requested in config.counts
235
+ * 3. For each collection: generate documents, create them, record in deletion log
236
+ * 4. After all: link deferred relationships
237
+ * 5. On error + rollbackOnError: rollback all created documents
238
+ */
239
+ async function runBulkPopulation(payload, req, schemas, config, emitter) {
240
+ const startTime = Date.now();
241
+ const { resolveCreationOrder } = await import("./dependency-resolver-BgsUvfRJ.mjs");
242
+ const { generateDocuments } = await import("./content-generator-fPX2DL3g.mjs").then((n) => n.t);
243
+ const created = {};
244
+ const failed = {};
245
+ const documentIds = {};
246
+ const deletionLog = new DeletionLog();
247
+ let rolledBack = false;
248
+ const slugsToProcess = resolveCreationOrder(schemas).filter((slug) => slug in config.counts && config.counts[slug] > 0);
249
+ const schemaMap = new Map(schemas.map((s) => [s.slug, s]));
250
+ try {
251
+ for (const slug of slugsToProcess) {
252
+ const schema = schemaMap.get(slug);
253
+ if (!schema) continue;
254
+ const count = config.counts[slug] ?? 0;
255
+ created[slug] = 0;
256
+ failed[slug] = 0;
257
+ documentIds[slug] = [];
258
+ let generatedDocs;
259
+ try {
260
+ generatedDocs = (await generateDocuments(config.provider, schema, {
261
+ count,
262
+ theme: config.theme,
263
+ existingIds: documentIds
264
+ })).documents;
265
+ } catch (err) {
266
+ console.error(`[bulk-runner] Failed to generate documents for "${slug}":`, err instanceof Error ? err.message : String(err));
267
+ failed[slug] = count;
268
+ continue;
269
+ }
270
+ for (const doc of generatedDocs) {
271
+ try {
272
+ const record = await payload.create({
273
+ collection: slug,
274
+ data: doc,
275
+ overrideAccess: true,
276
+ req
277
+ });
278
+ const id = String(record.id);
279
+ deletionLog.record(slug, id);
280
+ documentIds[slug].push(id);
281
+ created[slug]++;
282
+ } catch (err) {
283
+ console.error(`[bulk-runner] Failed to create document in "${slug}":`, err instanceof Error ? err.message : String(err));
284
+ failed[slug]++;
285
+ }
286
+ if (emitter) emitProgress(emitter, {
287
+ phase: "create",
288
+ collection: slug,
289
+ created: created[slug],
290
+ failed: failed[slug],
291
+ total: count,
292
+ elapsed: Date.now() - startTime
293
+ });
294
+ }
295
+ }
296
+ for (const slug of slugsToProcess) {
297
+ const schema = schemaMap.get(slug);
298
+ if (!schema || schema.relationships.length === 0) continue;
299
+ try {
300
+ await linkRelationships(payload, req, schema, documentIds);
301
+ } catch (err) {
302
+ console.error(`[bulk-runner] Failed to link relationships for "${slug}":`, err instanceof Error ? err.message : String(err));
303
+ }
304
+ }
305
+ } catch (err) {
306
+ console.error("[bulk-runner] Unexpected error during bulk population:", err instanceof Error ? err.message : String(err));
307
+ if (config.rollbackOnError) {
308
+ console.log("[bulk-runner] Rolling back created documents...");
309
+ await deletionLog.rollback(payload, req);
310
+ rolledBack = true;
311
+ }
312
+ }
313
+ return {
314
+ created,
315
+ failed,
316
+ documentIds,
317
+ rolledBack,
318
+ elapsed: Date.now() - startTime
319
+ };
320
+ }
321
+ //#endregion
322
+ //#region src/mcp/tools.ts
323
+ function getAITools(pluginConfig) {
324
+ return [
325
+ {
326
+ name: "populateCollection",
327
+ description: "Generate and insert AI-created documents into a Payload CMS collection.",
328
+ parameters: {
329
+ collection: z.string().describe("The collection slug to populate"),
330
+ count: z.number().min(1).max(100).describe("Number of documents to generate"),
331
+ theme: z.string().optional().describe("Optional theme or topic to guide content generation")
332
+ },
333
+ async handler(args, req) {
334
+ const collection = args.collection;
335
+ const count = args.count;
336
+ const theme = args.theme ?? "general";
337
+ try {
338
+ const result = await generateDocuments(createProvider({
339
+ provider: pluginConfig.provider,
340
+ apiKey: process.env[pluginConfig.apiKeyEnvVar] ?? ""
341
+ }), readCollectionSchema(req.payload, collection), {
342
+ count,
343
+ theme
344
+ });
345
+ let created = 0;
346
+ let failed = 0;
347
+ for (const doc of result.documents) try {
348
+ await req.payload.create({
349
+ collection,
350
+ data: doc,
351
+ overrideAccess: true,
352
+ req
353
+ });
354
+ created++;
355
+ } catch {
356
+ failed++;
357
+ }
358
+ return { content: [{
359
+ type: "text",
360
+ text: `Populated "${collection}": ${created} created, ${failed} failed (requested ${count}).`
361
+ }] };
362
+ } catch (err) {
363
+ return { content: [{
364
+ type: "text",
365
+ text: `Error populating "${collection}": ${err instanceof Error ? err.message : String(err)}`
366
+ }] };
367
+ }
368
+ }
369
+ },
370
+ {
371
+ name: "bulkPopulate",
372
+ description: "Generate and insert AI-created documents across multiple Payload CMS collections at once.",
373
+ parameters: {
374
+ theme: z.string().describe("Theme or topic to guide content generation across all collections"),
375
+ counts: z.string().describe("JSON map of collection slug to count, e.g. {\"posts\":5,\"categories\":3}")
376
+ },
377
+ async handler(args, req) {
378
+ const theme = args.theme;
379
+ const countsRaw = args.counts;
380
+ let counts;
381
+ try {
382
+ counts = JSON.parse(countsRaw);
383
+ } catch {
384
+ return { content: [{
385
+ type: "text",
386
+ text: "Error: \"counts\" must be valid JSON, e.g. {\"posts\":5,\"categories\":3}"
387
+ }] };
388
+ }
389
+ try {
390
+ const provider = createProvider({
391
+ provider: pluginConfig.provider,
392
+ apiKey: process.env[pluginConfig.apiKeyEnvVar] ?? ""
393
+ });
394
+ const schemas = readAllCollectionSchemas(req.payload);
395
+ const result = await runBulkPopulation(req.payload, req, schemas, {
396
+ theme,
397
+ counts,
398
+ provider,
399
+ rollbackOnError: pluginConfig.rollbackOnError
400
+ });
401
+ const summary = Object.entries(result.created).map(([slug, n]) => `${slug}: ${n} created, ${result.failed[slug] ?? 0} failed`).join("\n");
402
+ return { content: [{
403
+ type: "text",
404
+ text: `Bulk population complete in ${result.elapsed}ms${result.rolledBack ? " (rolled back)" : ""}:\n${summary}`
405
+ }] };
406
+ } catch (err) {
407
+ return { content: [{
408
+ type: "text",
409
+ text: `Error during bulk population: ${err instanceof Error ? err.message : String(err)}`
410
+ }] };
411
+ }
412
+ }
413
+ },
414
+ {
415
+ name: "getCollectionSchema",
416
+ description: "Return the analyzed schema for a single Payload CMS collection as JSON.",
417
+ parameters: { collection: z.string().describe("The collection slug to inspect") },
418
+ async handler(args, req) {
419
+ const collection = args.collection;
420
+ try {
421
+ const schema = readCollectionSchema(req.payload, collection);
422
+ return { content: [{
423
+ type: "text",
424
+ text: JSON.stringify(schema, null, 2)
425
+ }] };
426
+ } catch (err) {
427
+ return { content: [{
428
+ type: "text",
429
+ text: `Error reading schema for "${collection}": ${err instanceof Error ? err.message : String(err)}`
430
+ }] };
431
+ }
432
+ }
433
+ },
434
+ {
435
+ name: "listCollections",
436
+ description: "List all Payload CMS collections with their field counts and whether they can be auto-populated.",
437
+ parameters: {},
438
+ async handler(_args, req) {
439
+ try {
440
+ const schemas = readAllCollectionSchemas(req.payload);
441
+ const lines = schemas.map((s) => `- ${s.slug}: ${s.fields.length} fields, populatable=${s.populatable}`);
442
+ return { content: [{
443
+ type: "text",
444
+ text: `Collections (${schemas.length}):\n${lines.join("\n")}`
445
+ }] };
446
+ } catch (err) {
447
+ return { content: [{
448
+ type: "text",
449
+ text: `Error listing collections: ${err instanceof Error ? err.message : String(err)}`
450
+ }] };
451
+ }
452
+ }
453
+ }
454
+ ];
455
+ }
456
+ //#endregion
457
+ //#region src/admin/hooks/afterUpload.ts
458
+ /**
459
+ * Creates an afterChange hook for the media collection that auto-generates alt text.
460
+ * Only runs on 'create' operations where alt text is empty.
461
+ */
462
+ function createAltTextHook(pluginConfig) {
463
+ return async ({ doc, operation, req }) => {
464
+ if (operation !== "create") return doc;
465
+ if (doc.alt && String(doc.alt).trim() !== "") return doc;
466
+ if (!process.env[pluginConfig.apiKeyEnvVar]) return doc;
467
+ if (!(doc.url || doc.filename)) return doc;
468
+ try {
469
+ const filename = doc.filename || "image";
470
+ const altText = `${String(filename).replace(/[-_]/g, " ").replace(/\.[^.]+$/, "")} - uploaded media`;
471
+ await req.payload.update({
472
+ collection: "media",
473
+ id: doc.id,
474
+ data: { alt: altText },
475
+ req
476
+ });
477
+ return {
478
+ ...doc,
479
+ alt: altText
480
+ };
481
+ } catch (err) {
482
+ console.warn("[@karixi/payload-ai] Alt text generation failed:", err);
483
+ return doc;
484
+ }
485
+ };
486
+ }
487
+ //#endregion
488
+ //#region src/admin/hooks/beforeChange.ts
489
+ /**
490
+ * Creates a beforeChange hook that auto-fills empty fields with AI content.
491
+ * Only runs on 'create' operations. Only fills fields configured in AIPluginConfig.
492
+ */
493
+ function createSmartDefaultsHook(pluginConfig, collectionSlug) {
494
+ return async ({ data, operation, req }) => {
495
+ if (operation !== "create") return data;
496
+ const collectionConfig = pluginConfig.collections?.[collectionSlug];
497
+ if (!collectionConfig?.fields) return data;
498
+ const apiKey = process.env[pluginConfig.apiKeyEnvVar];
499
+ if (!apiKey) return data;
500
+ const { createProvider } = await import("./base-BPwZbeh1.mjs").then((n) => n.t);
501
+ const { readCollectionSchema } = await import("./schema-reader-ZkoI6Pwi.mjs").then((n) => n.r);
502
+ const { generateDocuments } = await import("./content-generator-fPX2DL3g.mjs").then((n) => n.t);
503
+ const provider = createProvider({
504
+ provider: pluginConfig.provider,
505
+ apiKey
506
+ });
507
+ for (const [fieldName, fieldConfig] of Object.entries(collectionConfig.fields)) {
508
+ if (!fieldConfig.enabled) continue;
509
+ const currentValue = data[fieldName];
510
+ if (currentValue !== void 0 && currentValue !== null && currentValue !== "") continue;
511
+ try {
512
+ const schema = readCollectionSchema(req.payload, collectionSlug);
513
+ const fieldSchema = schema.fields.find((f) => f.name === fieldName);
514
+ if (!fieldSchema) continue;
515
+ const generated = (await generateDocuments(provider, {
516
+ ...schema,
517
+ fields: [fieldSchema],
518
+ requiredFields: [fieldName]
519
+ }, {
520
+ count: 1,
521
+ theme: fieldConfig.prompt
522
+ })).documents[0];
523
+ if (generated?.[fieldName] !== void 0) data[fieldName] = generated[fieldName];
524
+ } catch (err) {
525
+ console.warn(`[@karixi/payload-ai] Smart default failed for ${fieldName}:`, err);
526
+ }
527
+ }
528
+ return data;
529
+ };
530
+ }
531
+ //#endregion
532
+ //#region src/plugin.ts
533
+ /**
534
+ * Payload AI Plugin — adds AI-powered data generation and admin features.
535
+ * Auto-injects MCP custom tools if @payloadcms/plugin-mcp is present.
536
+ */
537
+ function aiPlugin(config) {
538
+ return (incomingConfig) => {
539
+ if (!process.env[config.apiKeyEnvVar]) console.warn(`[@karixi/payload-ai] Warning: ${config.apiKeyEnvVar} environment variable is not set. AI features will not work.`);
540
+ const existingOnInit = incomingConfig.onInit;
541
+ let collections = incomingConfig.collections;
542
+ if (config.features?.adminUI && collections) collections = collections.map((collection) => {
543
+ const slug = collection.slug;
544
+ const updatedHooks = { ...collection.hooks };
545
+ if (config.collections?.[slug]) updatedHooks.beforeChange = [...updatedHooks.beforeChange ?? [], createSmartDefaultsHook(config, slug)];
546
+ if (slug === "media") updatedHooks.afterChange = [...updatedHooks.afterChange ?? [], createAltTextHook(config)];
547
+ if (updatedHooks.beforeChange !== collection.hooks?.beforeChange || updatedHooks.afterChange !== collection.hooks?.afterChange) return {
548
+ ...collection,
549
+ hooks: updatedHooks
550
+ };
551
+ return collection;
552
+ });
553
+ return {
554
+ ...incomingConfig,
555
+ collections,
556
+ onInit: async (payload) => {
557
+ if (existingOnInit) await existingOnInit(payload);
558
+ console.log(`[@karixi/payload-ai] Plugin initialized. Provider: ${config.provider}`);
559
+ }
560
+ };
561
+ };
562
+ }
563
+ //#endregion
564
+ export { aiPlugin, getAIPrompts, getAIResources, getAITools };
565
+
566
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/mcp/prompts.ts","../src/mcp/resources.ts","../src/generate/deletion-log.ts","../src/generate/relationship-linker.ts","../src/orchestrate/progress-tracker.ts","../src/orchestrate/bulk-runner.ts","../src/mcp/tools.ts","../src/admin/hooks/afterUpload.ts","../src/admin/hooks/beforeChange.ts","../src/plugin.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\nimport { z } from 'zod'\n\nexport type MCPPrompt = {\n name: string\n title: string\n description: string\n argsSchema: Record<string, z.ZodTypeAny>\n handler: (\n args: Record<string, unknown>,\n req: PayloadRequest,\n extra: unknown,\n ) => { messages: Array<{ content: { text: string; type: 'text' }; role: 'user' | 'assistant' }> }\n}\n\nexport function getAIPrompts(): MCPPrompt[] {\n return [\n {\n name: 'generateContentBrief',\n title: 'Generate Content Brief',\n description:\n 'Produce a structured brief that guides AI content generation for a given collection and theme.',\n argsSchema: {\n collection: z.string().describe('The collection slug to generate content for'),\n theme: z.string().describe('The overarching theme or topic for the content'),\n count: z.number().describe('Number of documents to generate'),\n },\n handler(args) {\n const collection = args.collection as string\n const theme = args.theme as string\n const count = args.count as number\n\n const text = [\n `You are preparing a content generation brief for the Payload CMS collection: **${collection}**.`,\n '',\n `**Theme**: ${theme}`,\n `**Documents to generate**: ${count}`,\n '',\n 'Please produce a structured brief that includes:',\n '1. A short description of the content style and tone that fits the theme.',\n '2. Key topics or sub-themes each document should cover.',\n '3. Any field-level guidance (titles, descriptions, categories, tags) relevant to this collection.',\n '4. Example values for the most important fields.',\n '',\n `Output the brief as a JSON object with keys: style, topics, fieldGuidance, examples.`,\n ].join('\\n')\n\n return {\n messages: [\n {\n role: 'user',\n content: { type: 'text', text },\n },\n ],\n }\n },\n },\n\n {\n name: 'reviewGeneratedContent',\n title: 'Review Generated Content',\n description:\n 'Return a review prompt asking an AI to evaluate and suggest improvements for a generated document.',\n argsSchema: {\n collection: z.string().describe('The collection slug the document belongs to'),\n documentId: z.string().describe('The ID of the document to review'),\n },\n handler(args) {\n const collection = args.collection as string\n const documentId = args.documentId as string\n\n const text = [\n `Please review the following generated document.`,\n '',\n `**Collection**: ${collection}`,\n `**Document ID**: ${documentId}`,\n '',\n 'Evaluate the document on:',\n '1. **Accuracy** — Is the content factually plausible and internally consistent?',\n '2. **Completeness** — Are all important fields populated with meaningful values?',\n '3. **Quality** — Is the writing style appropriate and free of obvious AI artifacts?',\n '4. **Schema compliance** — Do field values match the expected types and constraints?',\n '',\n 'Provide a structured review with a score (1–10) for each criterion and specific suggestions for improvement.',\n ].join('\\n')\n\n return {\n messages: [\n {\n role: 'user',\n content: { type: 'text', text },\n },\n ],\n }\n },\n },\n ]\n}\n","export type MCPResource = {\n name: string\n title: string\n description: string\n uri: string\n mimeType: string\n handler: (...args: unknown[]) => { contents: Array<{ text: string; uri: string }> }\n}\n\nexport function getAIResources(): MCPResource[] {\n return [\n {\n name: 'schemaOverview',\n title: 'Collection Schema Overview',\n description:\n 'A high-level overview of all Payload CMS collections including their slugs, field counts, and populatable status.',\n uri: 'schema://collections',\n mimeType: 'text/plain',\n handler() {\n const text = [\n 'This resource provides a schema overview of all registered Payload CMS collections.',\n '',\n 'To retrieve the full schema for a specific collection, use the `getCollectionSchema` tool.',\n 'To list all collections with field counts and populatable status, use the `listCollections` tool.',\n 'To generate documents into a single collection, use the `populateCollection` tool.',\n 'To populate multiple collections at once, use the `bulkPopulate` tool.',\n '',\n 'All schema information is derived from the live Payload configuration at runtime.',\n ].join('\\n')\n\n return {\n contents: [\n {\n uri: 'schema://collections',\n text,\n },\n ],\n }\n },\n },\n ]\n}\n","import type { Payload, PayloadRequest } from 'payload'\nimport type { DeletionLogEntry } from '../types.js'\n\n/**\n * Tracks created documents for rollback on failure.\n * Uses in-memory journal — no MongoDB transaction dependency.\n * Works on standalone MongoDB, replica sets, and Atlas.\n */\nexport class DeletionLog {\n private journal: DeletionLogEntry[] = []\n\n /** Record a created document for potential rollback */\n record(collection: string, id: string): void {\n this.journal.push({ collection, id, createdAt: new Date() })\n }\n\n /** Get all recorded entries */\n getEntries(): readonly DeletionLogEntry[] {\n return [...this.journal]\n }\n\n /** Get count of recorded entries */\n get size(): number {\n return this.journal.length\n }\n\n /**\n * Rollback all created documents by deleting them in reverse order.\n * Best-effort: if process crashes, journal is lost.\n */\n async rollback(\n payload: Payload,\n req: PayloadRequest,\n ): Promise<{\n deleted: number\n failed: Array<{ collection: string; id: string; error: string }>\n }> {\n const failed: Array<{ collection: string; id: string; error: string }> = []\n let deleted = 0\n\n // Delete in reverse order (most recent first)\n for (const entry of [...this.journal].reverse()) {\n try {\n await payload.delete({\n collection: entry.collection as Parameters<Payload['delete']>[0]['collection'],\n id: entry.id,\n req,\n })\n deleted++\n } catch (err) {\n failed.push({\n collection: entry.collection,\n id: entry.id,\n error: err instanceof Error ? err.message : String(err),\n })\n }\n }\n\n this.journal = []\n return { deleted, failed }\n }\n\n /** Clear the journal without deleting documents */\n clear(): void {\n this.journal = []\n }\n}\n","import type { Payload, PayloadRequest } from 'payload'\nimport type { CollectionSchema } from '../types.js'\n\n/**\n * Link relationship fields between generated documents.\n *\n * For each relationship defined in the schema, looks up available IDs\n * from documentIds and updates the documents in that collection.\n */\nexport async function linkRelationships(\n payload: Payload,\n req: PayloadRequest,\n schema: CollectionSchema,\n documentIds: Record<string, string[]>,\n): Promise<{ updated: number; failed: number }> {\n let updated = 0\n let failed = 0\n\n const ownIds = documentIds[schema.slug] ?? []\n if (ownIds.length === 0) return { updated, failed }\n\n for (const docId of ownIds) {\n const updateData: Record<string, unknown> = {}\n let hasUpdates = false\n\n for (const rel of schema.relationships) {\n const targetCollection = Array.isArray(rel.collection) ? rel.collection[0] : rel.collection\n\n if (!targetCollection) continue\n\n // Self-referential: assign 2–4 random sibling IDs (excluding self)\n if (rel.isSelfReferential) {\n const siblings = ownIds.filter((id) => id !== docId)\n if (siblings.length === 0) continue\n\n const count = Math.min(siblings.length, 2 + Math.floor(Math.random() * 3))\n const shuffled = [...siblings].sort(() => Math.random() - 0.5).slice(0, count)\n\n updateData[rel.field] = rel.hasMany ? shuffled : shuffled[0]\n hasUpdates = true\n continue\n }\n\n const targetIds = documentIds[targetCollection] ?? []\n if (targetIds.length === 0) continue\n\n if (rel.hasMany) {\n // Pick up to 3 random IDs\n const count = Math.min(targetIds.length, 1 + Math.floor(Math.random() * 3))\n const shuffled = [...targetIds].sort(() => Math.random() - 0.5).slice(0, count)\n updateData[rel.field] = shuffled\n } else {\n // Pick a single random ID\n const randomIndex = Math.floor(Math.random() * targetIds.length)\n updateData[rel.field] = targetIds[randomIndex]\n }\n\n hasUpdates = true\n }\n\n if (!hasUpdates) continue\n\n try {\n await payload.update({\n collection: schema.slug as Parameters<Payload['update']>[0]['collection'],\n id: docId,\n data: updateData,\n overrideAccess: true,\n req,\n })\n updated++\n } catch (err) {\n console.error(\n `[relationship-linker] Failed to update ${schema.slug}/${docId}:`,\n err instanceof Error ? err.message : String(err),\n )\n failed++\n }\n }\n\n return { updated, failed }\n}\n","import { EventEmitter } from 'node:events'\nimport type { ProgressEvent } from '../types.js'\n\n/** Create a typed EventEmitter for progress events */\nexport function createProgressEmitter(): EventEmitter {\n return new EventEmitter()\n}\n\n/** Emit a progress event on the emitter */\nexport function emitProgress(emitter: EventEmitter, event: ProgressEvent): void {\n emitter.emit('progress', event)\n}\n","import type { EventEmitter } from 'node:events'\nimport type { Payload, PayloadRequest } from 'payload'\nimport { DeletionLog } from '../generate/deletion-log.js'\nimport { linkRelationships } from '../generate/relationship-linker.js'\nimport type { AIProvider, CollectionSchema, ProgressEvent } from '../types.js'\nimport { emitProgress } from './progress-tracker.js'\n\nexport type BulkRunConfig = {\n theme: string\n counts: Record<string, number>\n provider: AIProvider\n rollbackOnError?: boolean\n mediaSource?: 'unsplash' | 'placeholder'\n}\n\nexport type BulkRunResult = {\n created: Record<string, number>\n failed: Record<string, number>\n documentIds: Record<string, string[]>\n rolledBack: boolean\n elapsed: number\n}\n\n/**\n * Run bulk population of Payload collections in dependency order.\n *\n * Flow:\n * 1. Resolve creation order from schemas\n * 2. Filter to collections requested in config.counts\n * 3. For each collection: generate documents, create them, record in deletion log\n * 4. After all: link deferred relationships\n * 5. On error + rollbackOnError: rollback all created documents\n */\nexport async function runBulkPopulation(\n payload: Payload,\n req: PayloadRequest,\n schemas: CollectionSchema[],\n config: BulkRunConfig,\n emitter?: EventEmitter,\n): Promise<BulkRunResult> {\n const startTime = Date.now()\n\n // Lazy imports to avoid circular dependency issues at module load time\n const { resolveCreationOrder } = await import('../core/dependency-resolver.js')\n const { generateDocuments } = await import('../core/content-generator.js')\n\n const created: Record<string, number> = {}\n const failed: Record<string, number> = {}\n const documentIds: Record<string, string[]> = {}\n const deletionLog = new DeletionLog()\n let rolledBack = false\n\n // Determine ordered list of slugs to process\n const orderedSlugs = resolveCreationOrder(schemas)\n const slugsToProcess = orderedSlugs.filter(\n (slug) => slug in config.counts && config.counts[slug] > 0,\n )\n\n const schemaMap = new Map(schemas.map((s) => [s.slug, s]))\n\n try {\n for (const slug of slugsToProcess) {\n const schema = schemaMap.get(slug)\n if (!schema) continue\n\n const count = config.counts[slug] ?? 0\n created[slug] = 0\n failed[slug] = 0\n documentIds[slug] = []\n\n let generatedDocs: Record<string, unknown>[]\n try {\n const result = await generateDocuments(config.provider, schema, {\n count,\n theme: config.theme,\n existingIds: documentIds,\n })\n generatedDocs = result.documents\n } catch (err) {\n console.error(\n `[bulk-runner] Failed to generate documents for \"${slug}\":`,\n err instanceof Error ? err.message : String(err),\n )\n failed[slug] = count\n continue\n }\n\n for (const doc of generatedDocs) {\n try {\n const record = await payload.create({\n collection: slug as Parameters<Payload['create']>[0]['collection'],\n data: doc as Record<string, unknown>,\n overrideAccess: true,\n req,\n })\n\n const id = String(record.id)\n deletionLog.record(slug, id)\n documentIds[slug].push(id)\n created[slug]++\n } catch (err) {\n console.error(\n `[bulk-runner] Failed to create document in \"${slug}\":`,\n err instanceof Error ? err.message : String(err),\n )\n failed[slug]++\n }\n\n if (emitter) {\n const event: ProgressEvent = {\n phase: 'create',\n collection: slug,\n created: created[slug],\n failed: failed[slug],\n total: count,\n elapsed: Date.now() - startTime,\n }\n emitProgress(emitter, event)\n }\n }\n }\n\n // Deferred: link relationships across all processed collections\n for (const slug of slugsToProcess) {\n const schema = schemaMap.get(slug)\n if (!schema || schema.relationships.length === 0) continue\n\n try {\n await linkRelationships(payload, req, schema, documentIds)\n } catch (err) {\n console.error(\n `[bulk-runner] Failed to link relationships for \"${slug}\":`,\n err instanceof Error ? err.message : String(err),\n )\n }\n }\n } catch (err) {\n console.error(\n '[bulk-runner] Unexpected error during bulk population:',\n err instanceof Error ? err.message : String(err),\n )\n\n if (config.rollbackOnError) {\n console.log('[bulk-runner] Rolling back created documents...')\n await deletionLog.rollback(payload, req)\n rolledBack = true\n }\n }\n\n return {\n created,\n failed,\n documentIds,\n rolledBack,\n elapsed: Date.now() - startTime,\n }\n}\n","import type { PayloadRequest } from 'payload'\nimport { z } from 'zod'\nimport { generateDocuments } from '../core/content-generator.js'\nimport { createProvider } from '../core/providers/base.js'\nimport { readAllCollectionSchemas, readCollectionSchema } from '../core/schema-reader.js'\nimport { runBulkPopulation } from '../orchestrate/bulk-runner.js'\nimport type { AIPluginConfig } from '../types.js'\n\nexport type MCPTool = {\n name: string\n description: string\n parameters: Record<string, z.ZodTypeAny>\n handler: (\n args: Record<string, unknown>,\n req: PayloadRequest,\n extra: unknown,\n ) => Promise<{ content: Array<{ text: string; type: 'text' }> }>\n}\n\nexport function getAITools(pluginConfig: AIPluginConfig): MCPTool[] {\n return [\n {\n name: 'populateCollection',\n description: 'Generate and insert AI-created documents into a Payload CMS collection.',\n parameters: {\n collection: z.string().describe('The collection slug to populate'),\n count: z.number().min(1).max(100).describe('Number of documents to generate'),\n theme: z\n .string()\n .optional()\n .describe('Optional theme or topic to guide content generation'),\n },\n async handler(args, req) {\n const collection = args.collection as string\n const count = args.count as number\n const theme = (args.theme as string | undefined) ?? 'general'\n\n try {\n const provider = createProvider({\n provider: pluginConfig.provider,\n apiKey: process.env[pluginConfig.apiKeyEnvVar] ?? '',\n })\n\n const schema = readCollectionSchema(req.payload, collection)\n const result = await generateDocuments(provider, schema, { count, theme })\n\n let created = 0\n let failed = 0\n\n for (const doc of result.documents) {\n try {\n await req.payload.create({\n collection: collection as Parameters<typeof req.payload.create>[0]['collection'],\n data: doc as Record<string, unknown>,\n overrideAccess: true,\n req,\n })\n created++\n } catch {\n failed++\n }\n }\n\n const text = `Populated \"${collection}\": ${created} created, ${failed} failed (requested ${count}).`\n return { content: [{ type: 'text', text }] }\n } catch (err) {\n const text = `Error populating \"${collection}\": ${err instanceof Error ? err.message : String(err)}`\n return { content: [{ type: 'text', text }] }\n }\n },\n },\n\n {\n name: 'bulkPopulate',\n description:\n 'Generate and insert AI-created documents across multiple Payload CMS collections at once.',\n parameters: {\n theme: z\n .string()\n .describe('Theme or topic to guide content generation across all collections'),\n counts: z\n .string()\n .describe('JSON map of collection slug to count, e.g. {\"posts\":5,\"categories\":3}'),\n },\n async handler(args, req) {\n const theme = args.theme as string\n const countsRaw = args.counts as string\n\n let counts: Record<string, number>\n try {\n counts = JSON.parse(countsRaw) as Record<string, number>\n } catch {\n return {\n content: [\n {\n type: 'text',\n text: 'Error: \"counts\" must be valid JSON, e.g. {\"posts\":5,\"categories\":3}',\n },\n ],\n }\n }\n\n try {\n const provider = createProvider({\n provider: pluginConfig.provider,\n apiKey: process.env[pluginConfig.apiKeyEnvVar] ?? '',\n })\n\n const schemas = readAllCollectionSchemas(req.payload)\n const result = await runBulkPopulation(req.payload, req, schemas, {\n theme,\n counts,\n provider,\n rollbackOnError: pluginConfig.rollbackOnError,\n })\n\n const summary = Object.entries(result.created)\n .map(([slug, n]) => `${slug}: ${n} created, ${result.failed[slug] ?? 0} failed`)\n .join('\\n')\n\n const text = `Bulk population complete in ${result.elapsed}ms${result.rolledBack ? ' (rolled back)' : ''}:\\n${summary}`\n return { content: [{ type: 'text', text }] }\n } catch (err) {\n const text = `Error during bulk population: ${err instanceof Error ? err.message : String(err)}`\n return { content: [{ type: 'text', text }] }\n }\n },\n },\n\n {\n name: 'getCollectionSchema',\n description: 'Return the analyzed schema for a single Payload CMS collection as JSON.',\n parameters: {\n collection: z.string().describe('The collection slug to inspect'),\n },\n async handler(args, req) {\n const collection = args.collection as string\n\n try {\n const schema = readCollectionSchema(req.payload, collection)\n const text = JSON.stringify(schema, null, 2)\n return { content: [{ type: 'text', text }] }\n } catch (err) {\n const text = `Error reading schema for \"${collection}\": ${err instanceof Error ? err.message : String(err)}`\n return { content: [{ type: 'text', text }] }\n }\n },\n },\n\n {\n name: 'listCollections',\n description:\n 'List all Payload CMS collections with their field counts and whether they can be auto-populated.',\n parameters: {},\n async handler(_args, req) {\n try {\n const schemas = readAllCollectionSchemas(req.payload)\n const lines = schemas.map(\n (s) => `- ${s.slug}: ${s.fields.length} fields, populatable=${s.populatable}`,\n )\n const text = `Collections (${schemas.length}):\\n${lines.join('\\n')}`\n return { content: [{ type: 'text', text }] }\n } catch (err) {\n const text = `Error listing collections: ${err instanceof Error ? err.message : String(err)}`\n return { content: [{ type: 'text', text }] }\n }\n },\n },\n ]\n}\n","import type { CollectionAfterChangeHook } from 'payload'\nimport type { AIPluginConfig } from '../../types.js'\n\n/**\n * Creates an afterChange hook for the media collection that auto-generates alt text.\n * Only runs on 'create' operations where alt text is empty.\n */\nexport function createAltTextHook(pluginConfig: AIPluginConfig): CollectionAfterChangeHook {\n return async ({ doc, operation, req }) => {\n if (operation !== 'create') return doc\n\n // Only process if alt is empty\n if (doc.alt && String(doc.alt).trim() !== '') return doc\n\n const apiKey = process.env[pluginConfig.apiKeyEnvVar]\n if (!apiKey) return doc\n\n // Check if there's an uploaded file URL to analyze\n const imageUrl = doc.url || doc.filename\n if (!imageUrl) return doc\n\n try {\n // TODO: Use AI vision API (provider.analyzeImage) to analyze actual image content.\n // For now, generate descriptive alt text from the filename.\n const filename = doc.filename || 'image'\n const cleanName = String(filename)\n .replace(/[-_]/g, ' ')\n .replace(/\\.[^.]+$/, '')\n\n const altText = `${cleanName} - uploaded media`\n\n // Update the document with generated alt text\n await req.payload.update({\n collection: 'media',\n id: doc.id as string,\n data: { alt: altText },\n req,\n })\n\n return { ...doc, alt: altText }\n } catch (err) {\n console.warn('[@karixi/payload-ai] Alt text generation failed:', err)\n return doc\n }\n }\n}\n","import type { CollectionBeforeChangeHook } from 'payload'\nimport type { AIPluginConfig } from '../../types.js'\n\n/**\n * Creates a beforeChange hook that auto-fills empty fields with AI content.\n * Only runs on 'create' operations. Only fills fields configured in AIPluginConfig.\n */\nexport function createSmartDefaultsHook(\n pluginConfig: AIPluginConfig,\n collectionSlug: string,\n): CollectionBeforeChangeHook {\n return async ({ data, operation, req }) => {\n if (operation !== 'create') return data\n\n const collectionConfig = pluginConfig.collections?.[collectionSlug]\n if (!collectionConfig?.fields) return data\n\n const apiKey = process.env[pluginConfig.apiKeyEnvVar]\n if (!apiKey) return data\n\n // Import dynamically to avoid circular deps\n const { createProvider } = await import('../../core/providers/base.js')\n const { readCollectionSchema } = await import('../../core/schema-reader.js')\n const { generateDocuments } = await import('../../core/content-generator.js')\n\n const provider = createProvider({ provider: pluginConfig.provider, apiKey })\n\n // For each configured field that is empty in the data, generate a value\n for (const [fieldName, fieldConfig] of Object.entries(collectionConfig.fields)) {\n if (!fieldConfig.enabled) continue\n const currentValue = (data as Record<string, unknown>)[fieldName]\n if (currentValue !== undefined && currentValue !== null && currentValue !== '') continue\n\n try {\n const schema = readCollectionSchema(req.payload, collectionSlug)\n const fieldSchema = schema.fields.find((f) => f.name === fieldName)\n if (!fieldSchema) continue\n\n const result = await generateDocuments(\n provider,\n {\n ...schema,\n fields: [fieldSchema],\n requiredFields: [fieldName],\n },\n { count: 1, theme: fieldConfig.prompt },\n )\n\n const generated = result.documents[0]\n if (generated?.[fieldName] !== undefined) {\n ;(data as Record<string, unknown>)[fieldName] = generated[fieldName]\n }\n } catch (err) {\n console.warn(`[@karixi/payload-ai] Smart default failed for ${fieldName}:`, err)\n }\n }\n\n return data\n }\n}\n","import type { CollectionConfig, Config, Payload } from 'payload'\nimport { createAltTextHook } from './admin/hooks/afterUpload.js'\nimport { createSmartDefaultsHook } from './admin/hooks/beforeChange.js'\nimport type { AIPluginConfig } from './types.js'\n\n/**\n * Payload AI Plugin — adds AI-powered data generation and admin features.\n * Auto-injects MCP custom tools if @payloadcms/plugin-mcp is present.\n */\nexport function aiPlugin(config: AIPluginConfig) {\n return (incomingConfig: Config): Config => {\n // Validate API key env var exists at init time\n const apiKey = process.env[config.apiKeyEnvVar]\n if (!apiKey) {\n console.warn(\n `[@karixi/payload-ai] Warning: ${config.apiKeyEnvVar} environment variable is not set. AI features will not work.`,\n )\n }\n\n const existingOnInit = incomingConfig.onInit\n\n // TODO Phase 2: Inject schema introspection + AI generation\n // TODO Phase 3: Register MCP custom tools (auto-detect mcpPlugin)\n\n let collections = incomingConfig.collections\n\n if (config.features?.adminUI && collections) {\n collections = collections.map((collection: CollectionConfig) => {\n const slug = collection.slug\n const updatedHooks = { ...collection.hooks }\n\n // Add beforeChange smart defaults hook for configured collections\n if (config.collections?.[slug]) {\n updatedHooks.beforeChange = [\n ...(updatedHooks.beforeChange ?? []),\n createSmartDefaultsHook(config, slug),\n ]\n }\n\n // Add afterChange alt text hook for media collection\n if (slug === 'media') {\n updatedHooks.afterChange = [\n ...(updatedHooks.afterChange ?? []),\n createAltTextHook(config),\n ]\n }\n\n if (\n updatedHooks.beforeChange !== collection.hooks?.beforeChange ||\n updatedHooks.afterChange !== collection.hooks?.afterChange\n ) {\n return { ...collection, hooks: updatedHooks }\n }\n\n return collection\n })\n }\n\n return {\n ...incomingConfig,\n collections,\n onInit: async (payload: Payload) => {\n if (existingOnInit) await existingOnInit(payload)\n console.log(`[@karixi/payload-ai] Plugin initialized. Provider: ${config.provider}`)\n // TODO Phase 4: Initialize admin UI components\n // TODO Phase 5: Initialize dev tools\n },\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
+ return target;
11
+ };
12
+ //#endregion
13
+ export { __exportAll as t };