@mvriu5/payload-ai 1.1.1 → 1.3.2
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 +42 -0
- package/dist/components/Icons.d.ts +0 -8
- package/dist/components/Icons.js +4 -216
- package/dist/components/{ActionToast.d.ts → action-toast/ActionToast.d.ts} +2 -2
- package/dist/components/{ActionToast.js → action-toast/ActionToast.js} +27 -35
- package/dist/components/{ActionToast.module.css → action-toast/ActionToast.module.css} +0 -79
- package/dist/components/ai-input/AIInput.js +433 -0
- package/dist/components/{AIInput.module.css → ai-input/AIInput.module.css} +119 -42
- package/dist/components/ai-input/badge.d.ts +14 -0
- package/dist/components/ai-input/badge.js +85 -0
- package/dist/components/{AuditLogList.d.ts → audit-log-list/AuditLogList.d.ts} +4 -8
- package/dist/components/{AuditLogList.js → audit-log-list/AuditLogList.js} +49 -21
- package/dist/components/{AuditLogList.module.css → audit-log-list/AuditLogList.module.css} +11 -65
- package/dist/components/dashboard/Dashboard.d.ts +2 -0
- package/dist/components/dashboard/Dashboard.js +15 -0
- package/dist/components/dashboard/Dashboard.module.css +13 -0
- package/dist/components/{DiffDialog.d.ts → diff-dialog/DiffDialog.d.ts} +2 -2
- package/dist/components/{DiffDialog.js → diff-dialog/DiffDialog.js} +200 -189
- package/dist/components/{DiffDialog.module.css → diff-dialog/DiffDialog.module.css} +17 -35
- package/dist/components/hooks/useAIChatStream.d.ts +39 -0
- package/dist/components/hooks/useAIChatStream.js +217 -0
- package/dist/components/hooks/useAISettings.js +26 -25
- package/dist/components/hooks/useAuditLog.d.ts +11 -0
- package/dist/components/hooks/useAuditLog.js +41 -0
- package/dist/components/hooks/useDocumentMentionSuggestions.d.ts +1 -1
- package/dist/components/hooks/useDocumentMentionSuggestions.js +31 -27
- package/dist/components/hooks/useMentions.d.ts +58 -0
- package/dist/components/hooks/useMentions.js +276 -0
- package/dist/components/hooks/usePluginConfig.d.ts +52 -0
- package/dist/components/hooks/usePluginConfig.js +20 -0
- package/dist/components/{MentionPopover.d.ts → mention-popover/MentionPopover.d.ts} +2 -4
- package/dist/components/{MentionPopover.js → mention-popover/MentionPopover.js} +1 -8
- package/dist/components/{MentionPopover.module.css → mention-popover/MentionPopover.module.css} +1 -1
- package/dist/exports/client.d.ts +2 -2
- package/dist/exports/client.js +2 -2
- package/dist/handlers/applyActionHandler.js +341 -112
- package/dist/handlers/chatHandler.js +940 -84
- package/dist/handlers/mediaUploadHandler.d.ts +7 -0
- package/dist/handlers/mediaUploadHandler.js +99 -0
- package/dist/handlers/mentionSuggestionHandler.js +16 -14
- package/dist/handlers/proposalDiffHandler.js +117 -50
- package/dist/index.d.ts +6 -0
- package/dist/index.js +39 -7
- package/dist/payload/collectionPermissions.js +3 -1
- package/dist/payload/logging.d.ts +9 -0
- package/dist/payload/logging.js +14 -0
- package/dist/payload/normalizeData.d.ts +16 -12
- package/dist/payload/normalizeData.js +47 -14
- package/dist/payload/proposalData.d.ts +31 -0
- package/dist/payload/proposalData.js +578 -0
- package/dist/payload/schemaContext.d.ts +3 -7
- package/dist/payload/schemaContext.js +147 -66
- package/package.json +6 -6
- package/dist/components/AIInput.js +0 -747
- /package/dist/components/{AIInput.d.ts → ai-input/AIInput.d.ts} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getCollectionPermissions, getCollectionSlugsForAction } from "./collectionPermissions.js";
|
|
2
|
-
import {
|
|
2
|
+
import { getSchemaFields as getNormalizeSchemaFields, hasDrafts, isAuthCollection } from "./normalizeData.js";
|
|
3
3
|
import { getSerializableLabel, isInternalCollection, isRecord } from "./shared.js";
|
|
4
4
|
const getSerializableRelationTo = (relationTo)=>{
|
|
5
5
|
if (typeof relationTo === "string") return relationTo;
|
|
@@ -44,34 +44,32 @@ const getLocaleConfigs = (req)=>{
|
|
|
44
44
|
};
|
|
45
45
|
const getSerializableOptions = (options)=>{
|
|
46
46
|
if (!Array.isArray(options)) return undefined;
|
|
47
|
-
const serializedOptions = options.
|
|
47
|
+
const serializedOptions = options.flatMap((option)=>{
|
|
48
48
|
if (typeof option === "string") {
|
|
49
|
-
return
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
return [
|
|
50
|
+
{
|
|
51
|
+
label: option,
|
|
52
|
+
value: option
|
|
53
|
+
}
|
|
54
|
+
];
|
|
53
55
|
}
|
|
54
|
-
if (!isRecord(option)) return
|
|
56
|
+
if (!isRecord(option)) return [];
|
|
55
57
|
const label = "label" in option ? getSerializableLabel(option.label) : undefined;
|
|
56
58
|
const value = "value" in option && typeof option.value === "string" ? option.value : undefined;
|
|
57
|
-
if (!label && !value) return
|
|
58
|
-
return
|
|
59
|
-
|
|
60
|
-
label
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
value
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
59
|
+
if (!label && !value) return [];
|
|
60
|
+
return [
|
|
61
|
+
{
|
|
62
|
+
...label ? {
|
|
63
|
+
label
|
|
64
|
+
} : {},
|
|
65
|
+
...value ? {
|
|
66
|
+
value
|
|
67
|
+
} : {}
|
|
68
|
+
}
|
|
69
|
+
];
|
|
70
|
+
});
|
|
67
71
|
return serializedOptions.length > 0 ? serializedOptions : undefined;
|
|
68
72
|
};
|
|
69
|
-
const hasDrafts = (config)=>{
|
|
70
|
-
const versions = config?.versions;
|
|
71
|
-
if (!versions || versions === true) return false;
|
|
72
|
-
if (!isRecord(versions)) return false;
|
|
73
|
-
return Boolean(versions.drafts);
|
|
74
|
-
};
|
|
75
73
|
const toNormalizeCollectionConfig = (config)=>{
|
|
76
74
|
if (!config) return undefined;
|
|
77
75
|
return {
|
|
@@ -82,22 +80,7 @@ const toNormalizeCollectionConfig = (config)=>{
|
|
|
82
80
|
};
|
|
83
81
|
const getSchemaFields = (config)=>{
|
|
84
82
|
const normalizedConfig = toNormalizeCollectionConfig(config);
|
|
85
|
-
|
|
86
|
-
...config?.fields || []
|
|
87
|
-
];
|
|
88
|
-
if (hasDrafts(config)) {
|
|
89
|
-
fields.push({
|
|
90
|
-
label: "Status",
|
|
91
|
-
name: "_status",
|
|
92
|
-
options: [
|
|
93
|
-
"draft",
|
|
94
|
-
"published"
|
|
95
|
-
],
|
|
96
|
-
required: true,
|
|
97
|
-
type: "select"
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
return fields;
|
|
83
|
+
return getNormalizeSchemaFields(normalizedConfig);
|
|
101
84
|
};
|
|
102
85
|
const getLocalizedFieldNames = (fields, path = "")=>{
|
|
103
86
|
return fields.flatMap((field)=>{
|
|
@@ -191,6 +174,14 @@ const describeField = (field)=>{
|
|
|
191
174
|
...options ? {
|
|
192
175
|
options
|
|
193
176
|
} : {},
|
|
177
|
+
...field.type === "blocks" && field.blocks ? {
|
|
178
|
+
acceptedBlockTypes: field.blocks.map((block)=>block.slug),
|
|
179
|
+
blockExample: [
|
|
180
|
+
{
|
|
181
|
+
...getBlockExample(field.blocks[0])
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
} : {},
|
|
194
185
|
...field.admin?.condition ? {
|
|
195
186
|
hasCondition: true
|
|
196
187
|
} : {},
|
|
@@ -208,6 +199,8 @@ const describeBlock = (block)=>{
|
|
|
208
199
|
const cached = blockDescriptionCache.get(block);
|
|
209
200
|
if (cached) return cached;
|
|
210
201
|
const description = {
|
|
202
|
+
blockType: block.slug,
|
|
203
|
+
example: getBlockExample(block),
|
|
211
204
|
fields: (block.fields || []).map(describeField),
|
|
212
205
|
label: getSerializableLabel(block.labels?.singular) || block.slug,
|
|
213
206
|
slug: block.slug
|
|
@@ -215,6 +208,43 @@ const describeBlock = (block)=>{
|
|
|
215
208
|
blockDescriptionCache.set(block, description);
|
|
216
209
|
return description;
|
|
217
210
|
};
|
|
211
|
+
const getBlockExample = (block)=>{
|
|
212
|
+
if (!block) return {};
|
|
213
|
+
const example = {
|
|
214
|
+
blockType: block.slug
|
|
215
|
+
};
|
|
216
|
+
for (const field of block.fields || []){
|
|
217
|
+
if (!field.name) continue;
|
|
218
|
+
if (field.type === "array") {
|
|
219
|
+
example[field.name] = field.fields?.length ? [
|
|
220
|
+
Object.fromEntries(field.fields.filter((childField)=>Boolean(childField.name)).slice(0, 2).map((childField)=>[
|
|
221
|
+
childField.name,
|
|
222
|
+
childField.type === "checkbox" ? false : `<${childField.name}>`
|
|
223
|
+
]))
|
|
224
|
+
] : [];
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
if (field.type === "blocks") {
|
|
228
|
+
example[field.name] = field.blocks?.length ? [
|
|
229
|
+
getBlockExample(field.blocks[0])
|
|
230
|
+
] : [];
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (field.type === "group") {
|
|
234
|
+
example[field.name] = Object.fromEntries((field.fields || []).filter((childField)=>Boolean(childField.name)).slice(0, 2).map((childField)=>[
|
|
235
|
+
childField.name,
|
|
236
|
+
childField.type === "checkbox" ? false : `<${childField.name}>`
|
|
237
|
+
]));
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (field.type === "checkbox") {
|
|
241
|
+
example[field.name] = false;
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
example[field.name] = `<${field.name}>`;
|
|
245
|
+
}
|
|
246
|
+
return example;
|
|
247
|
+
};
|
|
218
248
|
export const describeCollectionLikeConfig = ({ config, permissions, type })=>{
|
|
219
249
|
return {
|
|
220
250
|
...describeCollectionLikeSummary({
|
|
@@ -262,8 +292,76 @@ export const getMentionContext = async ({ blockContexts, collectionSlugs, collec
|
|
|
262
292
|
const context = [];
|
|
263
293
|
const seen = new Set();
|
|
264
294
|
const localeConfigs = getLocaleConfigs(req);
|
|
265
|
-
const
|
|
295
|
+
const localeConfigsByCode = new Map(localeConfigs.map((locale)=>[
|
|
296
|
+
locale.code,
|
|
297
|
+
locale
|
|
298
|
+
]));
|
|
299
|
+
const collectionSlugSet = new Set(collectionSlugs);
|
|
300
|
+
const globalSlugSet = new Set(globalSlugs);
|
|
301
|
+
const collectionConfigsBySlug = new Map(req.payload.config.collections.map((collection)=>[
|
|
302
|
+
collection.slug,
|
|
303
|
+
collection
|
|
304
|
+
]));
|
|
305
|
+
const globalConfigsBySlug = new Map(req.payload.config.globals?.map((global)=>[
|
|
306
|
+
global.slug,
|
|
307
|
+
global
|
|
308
|
+
]));
|
|
309
|
+
const blockContextsBySlug = new Map();
|
|
310
|
+
for (const block of blockContexts){
|
|
311
|
+
const blocks = blockContextsBySlug.get(block.slug) || [];
|
|
312
|
+
blocks.push(block);
|
|
313
|
+
blockContextsBySlug.set(block.slug, blocks);
|
|
314
|
+
}
|
|
315
|
+
const selectedLocales = [];
|
|
316
|
+
const selectedLocaleSet = new Set();
|
|
317
|
+
for (const mention of mentions){
|
|
318
|
+
if (mention.type !== "locale" || !mention.slug || selectedLocaleSet.has(mention.slug)) continue;
|
|
319
|
+
selectedLocaleSet.add(mention.slug);
|
|
320
|
+
selectedLocales.push(mention.slug);
|
|
321
|
+
}
|
|
266
322
|
const activeLocale = selectedLocales.at(-1);
|
|
323
|
+
const mentionDocResults = await Promise.all(mentions.slice(0, 8).map(async (mention)=>{
|
|
324
|
+
if (mention.type === "global" && mention.slug) {
|
|
325
|
+
const slug = mention.slug;
|
|
326
|
+
if (!globalSlugSet.has(slug)) return null;
|
|
327
|
+
const globalConfig = globalConfigsBySlug.get(slug);
|
|
328
|
+
if (!globalConfig) return null;
|
|
329
|
+
return {
|
|
330
|
+
doc: await req.payload.findGlobal({
|
|
331
|
+
depth: 2,
|
|
332
|
+
...activeLocale ? {
|
|
333
|
+
locale: activeLocale
|
|
334
|
+
} : {},
|
|
335
|
+
overrideAccess: false,
|
|
336
|
+
req,
|
|
337
|
+
slug: slug
|
|
338
|
+
}).catch(()=>null),
|
|
339
|
+
key: `global:${slug}`
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
if (mention.type === "doc" && mention.collection && mention.id) {
|
|
343
|
+
const slug = mention.collection;
|
|
344
|
+
if (isInternalCollection(slug) || !collectionSlugSet.has(slug)) return null;
|
|
345
|
+
return {
|
|
346
|
+
doc: await req.payload.findByID({
|
|
347
|
+
collection: slug,
|
|
348
|
+
depth: 2,
|
|
349
|
+
id: mention.id,
|
|
350
|
+
...activeLocale ? {
|
|
351
|
+
locale: activeLocale
|
|
352
|
+
} : {},
|
|
353
|
+
overrideAccess: false,
|
|
354
|
+
req
|
|
355
|
+
}).catch(()=>null),
|
|
356
|
+
key: `doc:${slug}:${mention.id}`
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
return null;
|
|
360
|
+
}));
|
|
361
|
+
const docsByMentionKey = new Map();
|
|
362
|
+
for (const result of mentionDocResults){
|
|
363
|
+
if (result) docsByMentionKey.set(result.key, result.doc);
|
|
364
|
+
}
|
|
267
365
|
if (localeConfigs.length > 0) {
|
|
268
366
|
context.push({
|
|
269
367
|
activeLocale,
|
|
@@ -275,7 +373,7 @@ export const getMentionContext = async ({ blockContexts, collectionSlugs, collec
|
|
|
275
373
|
}
|
|
276
374
|
for (const mention of mentions.slice(0, 8)){
|
|
277
375
|
if (mention.type === "locale" && mention.slug) {
|
|
278
|
-
const locale =
|
|
376
|
+
const locale = localeConfigsByCode.get(mention.slug);
|
|
279
377
|
if (!locale) continue;
|
|
280
378
|
const key = `locale:${locale.code}`;
|
|
281
379
|
if (seen.has(key)) continue;
|
|
@@ -288,8 +386,8 @@ export const getMentionContext = async ({ blockContexts, collectionSlugs, collec
|
|
|
288
386
|
if (mention.type === "collection" && mention.slug) {
|
|
289
387
|
const slug = mention.slug;
|
|
290
388
|
const key = `collection:${slug}`;
|
|
291
|
-
if (seen.has(key) || isInternalCollection(slug) || !
|
|
292
|
-
const collectionConfig =
|
|
389
|
+
if (seen.has(key) || isInternalCollection(slug) || !collectionSlugSet.has(slug)) continue;
|
|
390
|
+
const collectionConfig = collectionConfigsBySlug.get(slug);
|
|
293
391
|
if (!collectionConfig) continue;
|
|
294
392
|
seen.add(key);
|
|
295
393
|
context.push(describeCollectionLikeConfig({
|
|
@@ -301,18 +399,10 @@ export const getMentionContext = async ({ blockContexts, collectionSlugs, collec
|
|
|
301
399
|
if (mention.type === "global" && mention.slug) {
|
|
302
400
|
const slug = mention.slug;
|
|
303
401
|
const key = `global:${slug}`;
|
|
304
|
-
if (seen.has(key) || !
|
|
305
|
-
const globalConfig =
|
|
402
|
+
if (seen.has(key) || !globalSlugSet.has(slug)) continue;
|
|
403
|
+
const globalConfig = globalConfigsBySlug.get(slug);
|
|
306
404
|
if (!globalConfig) continue;
|
|
307
|
-
const globalDoc =
|
|
308
|
-
depth: 2,
|
|
309
|
-
...activeLocale ? {
|
|
310
|
-
locale: activeLocale
|
|
311
|
-
} : {},
|
|
312
|
-
overrideAccess: false,
|
|
313
|
-
req,
|
|
314
|
-
slug: slug
|
|
315
|
-
}).catch(()=>null);
|
|
405
|
+
const globalDoc = docsByMentionKey.get(key) ?? null;
|
|
316
406
|
seen.add(key);
|
|
317
407
|
context.push({
|
|
318
408
|
...describeCollectionLikeConfig({
|
|
@@ -323,7 +413,7 @@ export const getMentionContext = async ({ blockContexts, collectionSlugs, collec
|
|
|
323
413
|
});
|
|
324
414
|
}
|
|
325
415
|
if (mention.type === "block" && mention.slug) {
|
|
326
|
-
const matchingBlocks =
|
|
416
|
+
const matchingBlocks = (blockContextsBySlug.get(mention.slug) || []).filter((block)=>!mention.parent || block.parent === mention.parent);
|
|
327
417
|
for (const block of matchingBlocks){
|
|
328
418
|
const key = `block:${block.parent}:${block.slug}`;
|
|
329
419
|
if (seen.has(key)) continue;
|
|
@@ -337,17 +427,8 @@ export const getMentionContext = async ({ blockContexts, collectionSlugs, collec
|
|
|
337
427
|
if (mention.type === "doc" && mention.collection && mention.id) {
|
|
338
428
|
const slug = mention.collection;
|
|
339
429
|
const key = `doc:${slug}:${mention.id}`;
|
|
340
|
-
if (seen.has(key) || isInternalCollection(slug) || !
|
|
341
|
-
const doc =
|
|
342
|
-
collection: slug,
|
|
343
|
-
depth: 2,
|
|
344
|
-
id: mention.id,
|
|
345
|
-
...activeLocale ? {
|
|
346
|
-
locale: activeLocale
|
|
347
|
-
} : {},
|
|
348
|
-
overrideAccess: false,
|
|
349
|
-
req
|
|
350
|
-
}).catch(()=>null);
|
|
430
|
+
if (seen.has(key) || isInternalCollection(slug) || !collectionSlugSet.has(slug)) continue;
|
|
431
|
+
const doc = docsByMentionKey.get(key);
|
|
351
432
|
if (!doc) continue;
|
|
352
433
|
seen.add(key);
|
|
353
434
|
context.push({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mvriu5/payload-ai",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "AI assistant plugin for Payload CMS with provider selection, CMS mentions, and signed action proposals.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"payload",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"test:e2e:headed": "playwright test --headed",
|
|
64
64
|
"test:handlers": "vitest run tests/handlers",
|
|
65
65
|
"test:unit": "vitest run tests/unit",
|
|
66
|
-
"
|
|
66
|
+
"knip": "knip"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@ai-sdk/anthropic": "^3.0.81",
|
|
@@ -71,21 +71,21 @@
|
|
|
71
71
|
"@ai-sdk/mistral": "^3.0.37",
|
|
72
72
|
"@ai-sdk/openai": "^3.0.67",
|
|
73
73
|
"@openrouter/ai-sdk-provider": "^2.9.1",
|
|
74
|
-
"@playwright/test": "^1.56.1",
|
|
75
74
|
"@payloadcms/db-postgres": "3.84.1",
|
|
76
75
|
"@payloadcms/next": "3.84.1",
|
|
77
76
|
"@payloadcms/richtext-lexical": "3.84.1",
|
|
78
77
|
"@payloadcms/ui": "3.84.1",
|
|
78
|
+
"@playwright/test": "^1.56.1",
|
|
79
79
|
"@swc/cli": "0.8.1",
|
|
80
80
|
"@types/node": "25.9.3",
|
|
81
81
|
"@types/react": "19.2.17",
|
|
82
82
|
"@types/react-dom": "19.2.3",
|
|
83
83
|
"copyfiles": "2.4.1",
|
|
84
|
-
"cross-env": "^
|
|
84
|
+
"cross-env": "^10.1.0",
|
|
85
85
|
"eslint": "^10.5.0",
|
|
86
|
-
"graphql": "^
|
|
86
|
+
"graphql": "^17.0.1",
|
|
87
87
|
"jsdom": "^29.1.1",
|
|
88
|
-
"knip": "^6.
|
|
88
|
+
"knip": "^6.18.0",
|
|
89
89
|
"next": "16.2.9",
|
|
90
90
|
"payload": "3.84.1",
|
|
91
91
|
"prettier": "^3.8.4",
|