@mvriu5/payload-ai 0.5.6 → 0.5.9

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.
Files changed (39) hide show
  1. package/README.md +52 -5
  2. package/dist/ai/providerOptions.d.ts +1 -14
  3. package/dist/ai/providerOptions.js +0 -23
  4. package/dist/ai/providerRuntime.d.ts +3 -2
  5. package/dist/ai/providerRuntime.js +6 -15
  6. package/dist/components/AIActionProposalList.d.ts +2 -1
  7. package/dist/components/AIActionProposalList.js +74 -6
  8. package/dist/components/AIActionProposalList.module.css +49 -5
  9. package/dist/components/AIApiKeyField.js +0 -8
  10. package/dist/components/AIInput.d.ts +1 -1
  11. package/dist/components/AIInput.js +156 -23
  12. package/dist/components/AIInput.module.css +185 -147
  13. package/dist/components/CollectionMentionPopover.d.ts +1 -1
  14. package/dist/components/DiffDialog.d.ts +12 -0
  15. package/dist/components/DiffDialog.js +310 -0
  16. package/dist/components/DiffDialog.module.css +249 -0
  17. package/dist/components/Icons.d.ts +9 -0
  18. package/dist/components/Icons.js +266 -0
  19. package/dist/components/RecentChangesList.d.ts +18 -0
  20. package/dist/components/RecentChangesList.js +66 -0
  21. package/dist/components/RecentChangesList.module.css +135 -0
  22. package/dist/components/hooks/useAISettings.d.ts +1 -1
  23. package/dist/endpoints/aiApplyActionEndpointHandler.d.ts +3 -1
  24. package/dist/endpoints/aiApplyActionEndpointHandler.js +209 -8
  25. package/dist/endpoints/aiChatEndpointHandler.d.ts +5 -1
  26. package/dist/endpoints/aiChatEndpointHandler.js +106 -21
  27. package/dist/endpoints/aiMentionSuggestionsEndpointHandler.d.ts +2 -1
  28. package/dist/endpoints/aiMentionSuggestionsEndpointHandler.js +7 -7
  29. package/dist/endpoints/aiProposalDiffEndpointHandler.d.ts +7 -0
  30. package/dist/endpoints/aiProposalDiffEndpointHandler.js +138 -0
  31. package/dist/endpoints/aiRecentChangesEndpointHandler.d.ts +6 -0
  32. package/dist/endpoints/aiRecentChangesEndpointHandler.js +35 -0
  33. package/dist/index.d.ts +3 -1
  34. package/dist/index.js +140 -18
  35. package/dist/payload/collectionPermissions.d.ts +22 -0
  36. package/dist/payload/collectionPermissions.js +68 -0
  37. package/dist/payload/schemaContext.d.ts +46 -2
  38. package/dist/payload/schemaContext.js +105 -14
  39. package/package.json +113 -121
@@ -1,3 +1,5 @@
1
+ import { getCollectionPermissions, getCollectionSlugsForAction } from "./collectionPermissions.js";
2
+ import { getCollectionFields, isAuthCollection } from "./normalizeData.js";
1
3
  import { getSerializableLabel, isInternalCollection } from "./shared.js";
2
4
  const getSerializableRelationTo = (relationTo)=>{
3
5
  if (typeof relationTo === "string") {
@@ -8,9 +10,88 @@ const getSerializableRelationTo = (relationTo)=>{
8
10
  }
9
11
  return undefined;
10
12
  };
13
+ const getSerializableOptions = (options)=>{
14
+ if (!Array.isArray(options)) return undefined;
15
+ const serializedOptions = options.map((option)=>{
16
+ if (typeof option === "string") {
17
+ return {
18
+ label: option,
19
+ value: option
20
+ };
21
+ }
22
+ if (!option || typeof option !== "object") return null;
23
+ const label = "label" in option ? getSerializableLabel(option.label) : undefined;
24
+ const value = "value" in option && typeof option.value === "string" ? option.value : undefined;
25
+ if (!label && !value) return null;
26
+ return {
27
+ ...label ? {
28
+ label
29
+ } : {},
30
+ ...value ? {
31
+ value
32
+ } : {}
33
+ };
34
+ }).filter(Boolean);
35
+ return serializedOptions.length > 0 ? serializedOptions : undefined;
36
+ };
37
+ const hasDrafts = (config)=>{
38
+ const versions = config?.versions;
39
+ if (!versions || versions === true) return false;
40
+ if (typeof versions !== "object") return false;
41
+ return Boolean(versions.drafts);
42
+ };
43
+ const toNormalizeCollectionConfig = (config)=>{
44
+ if (!config) return undefined;
45
+ return {
46
+ auth: config.auth,
47
+ fields: config.fields || [],
48
+ slug: config.slug
49
+ };
50
+ };
51
+ const getSchemaFields = (config)=>{
52
+ const normalizedConfig = toNormalizeCollectionConfig(config);
53
+ const fields = isAuthCollection(normalizedConfig) ? getCollectionFields(normalizedConfig) : [
54
+ ...config?.fields || []
55
+ ];
56
+ if (hasDrafts(config)) {
57
+ fields.push({
58
+ label: "Status",
59
+ name: "_status",
60
+ options: [
61
+ "draft",
62
+ "published"
63
+ ],
64
+ required: true,
65
+ type: "select"
66
+ });
67
+ }
68
+ return fields;
69
+ };
70
+ export const describeCollectionLikeConfig = ({ config, permissions, type })=>{
71
+ const slug = config.slug;
72
+ return {
73
+ access: {
74
+ aiPermissions: type === "collection" ? getCollectionPermissions({
75
+ permissions,
76
+ slug
77
+ }) : {
78
+ read: true,
79
+ update: true
80
+ },
81
+ hasPayloadAccessControl: Boolean(config.access)
82
+ },
83
+ fields: getSchemaFields(config).map(describeField),
84
+ hasAuth: isAuthCollection(toNormalizeCollectionConfig(config)) || undefined,
85
+ hasDrafts: hasDrafts(config) || undefined,
86
+ label: type === "collection" ? config.labels?.plural || config.labels?.singular || slug : getSerializableLabel(config.label) || slug,
87
+ slug,
88
+ type
89
+ };
90
+ };
11
91
  export const describeField = (field)=>{
12
92
  const label = getSerializableLabel(field.label);
13
93
  const relationTo = getSerializableRelationTo(field.relationTo);
94
+ const options = getSerializableOptions(field.options);
14
95
  return {
15
96
  ...label ? {
16
97
  label
@@ -27,9 +108,18 @@ export const describeField = (field)=>{
27
108
  ...field.hasMany ? {
28
109
  hasMany: field.hasMany
29
110
  } : {},
111
+ ...field.localized ? {
112
+ localized: field.localized
113
+ } : {},
30
114
  ...relationTo ? {
31
115
  relationTo
32
116
  } : {},
117
+ ...options ? {
118
+ options
119
+ } : {},
120
+ ...field.admin?.condition ? {
121
+ hasCondition: true
122
+ } : {},
33
123
  ...field.fields ? {
34
124
  fields: field.fields.map(describeField)
35
125
  } : {},
@@ -71,11 +161,13 @@ export const collectBlocks = ({ fields, parent })=>{
71
161
  return blocks;
72
162
  };
73
163
  export const getAllowedCollectionSlugs = (req, collections)=>{
74
- const configuredSlugs = req.payload.config.collections.map((collection)=>collection.slug).filter((slug)=>!isInternalCollection(slug));
75
- if (!collections) return configuredSlugs;
76
- return configuredSlugs.filter((slug)=>collections.includes(slug));
164
+ return getCollectionSlugsForAction({
165
+ action: "read",
166
+ permissions: collections,
167
+ req
168
+ });
77
169
  };
78
- export const getMentionContext = async ({ blockContexts, collectionSlugs, globalSlugs, mentions, req })=>{
170
+ export const getMentionContext = async ({ blockContexts, collectionSlugs, collections, globalSlugs, mentions, req })=>{
79
171
  if (!mentions || mentions.length === 0) return [];
80
172
  const context = [];
81
173
  const seen = new Set();
@@ -87,12 +179,11 @@ export const getMentionContext = async ({ blockContexts, collectionSlugs, global
87
179
  const collectionConfig = req.payload.config.collections.find((collection)=>collection.slug === slug);
88
180
  if (!collectionConfig) continue;
89
181
  seen.add(key);
90
- context.push({
91
- fields: collectionConfig.fields.map(describeField),
92
- label: collectionConfig.labels?.plural || collectionConfig.labels?.singular || slug,
93
- slug,
182
+ context.push(describeCollectionLikeConfig({
183
+ config: collectionConfig,
184
+ permissions: collections,
94
185
  type: "collection"
95
- });
186
+ }));
96
187
  }
97
188
  if (mention.type === "global" && mention.slug) {
98
189
  const slug = mention.slug;
@@ -108,11 +199,11 @@ export const getMentionContext = async ({ blockContexts, collectionSlugs, global
108
199
  }).catch(()=>null);
109
200
  seen.add(key);
110
201
  context.push({
111
- doc: globalDoc,
112
- fields: globalConfig.fields.map(describeField),
113
- label: globalConfig.label || slug,
114
- slug,
115
- type: "global"
202
+ ...describeCollectionLikeConfig({
203
+ config: globalConfig,
204
+ type: "global"
205
+ }),
206
+ doc: globalDoc
116
207
  });
117
208
  }
118
209
  if (mention.type === "block" && mention.slug) {
package/package.json CHANGED
@@ -1,125 +1,117 @@
1
1
  {
2
- "name": "@mvriu5/payload-ai",
3
- "version": "0.5.6",
4
- "description": "AI assistant plugin for Payload CMS with provider selection, CMS mentions, and signed action proposals.",
5
- "keywords": [
6
- "payload",
7
- "payloadcms",
8
- "payload-plugin",
9
- "ai",
10
- "cms",
11
- "openai",
12
- "anthropic",
13
- "google-generative-ai",
14
- "groq",
15
- "mistral"
16
- ],
17
- "author": "Marius",
18
- "license": "MIT",
19
- "homepage": "https://github.com/mvriu5/payload-ai-plugin#readme",
20
- "repository": {
21
- "type": "git",
22
- "url": "git+https://github.com/mvriu5/payload-ai-plugin.git"
23
- },
24
- "bugs": {
25
- "url": "https://github.com/mvriu5/payload-ai-plugin/issues"
26
- },
27
- "type": "module",
28
- "exports": {
29
- ".": {
30
- "import": "./dist/index.js",
31
- "types": "./dist/index.d.ts",
32
- "default": "./dist/index.js"
33
- },
34
- "./client": {
35
- "import": "./dist/exports/client.js",
36
- "types": "./dist/exports/client.d.ts",
37
- "default": "./dist/exports/client.js"
38
- }
39
- },
40
- "main": "./dist/index.js",
41
- "types": "./dist/index.d.ts",
42
- "files": [
43
- "dist"
44
- ],
45
- "scripts": {
46
- "build": "pnpm copyfiles && pnpm build:types && pnpm build:swc",
47
- "build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
48
- "build:types": "tsc --outDir dist --rootDir ./src",
49
- "clean": "rimraf {dist,*.tsbuildinfo}",
50
- "copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
51
- "dev": "next dev dev --turbo",
52
- "dev:generate-importmap": "pnpm dev:payload generate:importmap",
53
- "dev:generate-types": "pnpm dev:payload generate:types",
54
- "dev:payload": "cross-env PAYLOAD_CONFIG_PATH=./dev/payload.config.ts payload",
55
- "generate:importmap": "pnpm dev:generate-importmap",
56
- "generate:types": "pnpm dev:generate-types",
57
- "lint": "eslint",
58
- "lint:fix": "eslint ./src --fix",
59
- "prepublishOnly": "pnpm clean && pnpm build"
60
- },
61
- "devDependencies": {
62
- "@payloadcms/db-postgres": "3.84.1",
63
- "@payloadcms/next": "3.84.1",
64
- "@payloadcms/richtext-lexical": "3.84.1",
65
- "@payloadcms/ui": "3.84.1",
66
- "@swc/cli": "0.6.0",
67
- "@types/node": "22.19.9",
68
- "@types/react": "19.2.14",
69
- "@types/react-dom": "19.2.3",
70
- "copyfiles": "2.4.1",
71
- "cross-env": "^7.0.3",
72
- "eslint": "^9.23.0",
73
- "graphql": "^16.8.1",
74
- "knip": "^6.16.1",
75
- "next": "16.2.6",
76
- "payload": "3.84.1",
77
- "react": "19.2.6",
78
- "react-dom": "19.2.6",
79
- "rimraf": "3.0.2",
80
- "sharp": "0.34.2",
81
- "typescript": "5.7.3",
82
- "vite-tsconfig-paths": "6.0.5",
83
- "vitest": "4.0.18"
84
- },
85
- "peerDependencies": {
86
- "payload": "^3.84.1"
87
- },
88
- "engines": {
89
- "node": "^18.20.2 || >=20.9.0",
90
- "pnpm": "^9 || ^10"
91
- },
92
- "publishConfig": {
93
- "access": "public"
94
- },
95
- "pnpm": {
96
- "onlyBuiltDependencies": [
97
- "sharp",
98
- "esbuild",
99
- "unrs-resolver"
100
- ]
101
- },
102
- "knip": {
103
- "entry": [
104
- "dev/payload.config.ts",
105
- "dev/next.config.mjs",
106
- "dev/app/**/*.{ts,tsx}"
2
+ "name": "@mvriu5/payload-ai",
3
+ "version": "0.5.9",
4
+ "description": "AI assistant plugin for Payload CMS with provider selection, CMS mentions, and signed action proposals.",
5
+ "keywords": [
6
+ "payload",
7
+ "payloadcms",
8
+ "payload-plugin",
9
+ "ai",
10
+ "cms",
11
+ "openai",
12
+ "anthropic",
13
+ "google-generative-ai",
14
+ "mistral"
107
15
  ],
108
- "ignore": [
109
- "dev/payload-types.ts"
16
+ "author": "Marius",
17
+ "license": "MIT",
18
+ "homepage": "https://github.com/mvriu5/payload-ai-plugin#readme",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/mvriu5/payload-ai-plugin.git"
22
+ },
23
+ "bugs": {
24
+ "url": "https://github.com/mvriu5/payload-ai-plugin/issues"
25
+ },
26
+ "type": "module",
27
+ "exports": {
28
+ ".": {
29
+ "import": "./dist/index.js",
30
+ "types": "./dist/index.d.ts",
31
+ "default": "./dist/index.js"
32
+ },
33
+ "./client": {
34
+ "import": "./dist/exports/client.js",
35
+ "types": "./dist/exports/client.d.ts",
36
+ "default": "./dist/exports/client.js"
37
+ }
38
+ },
39
+ "main": "./dist/index.js",
40
+ "types": "./dist/index.d.ts",
41
+ "files": [
42
+ "dist"
110
43
  ],
111
- "project": [
112
- "src/**/*.{ts,tsx}",
113
- "dev/**/*.{ts,tsx,mjs}"
114
- ]
115
- },
116
- "dependencies": {
117
- "@ai-sdk/anthropic": "^3.0.81",
118
- "@ai-sdk/google": "^3.0.80",
119
- "@ai-sdk/groq": "^3.0.39",
120
- "@ai-sdk/mistral": "^3.0.37",
121
- "@ai-sdk/openai": "^3.0.67",
122
- "ai": "^6.0.193",
123
- "zod": "^4.4.3"
124
- }
44
+ "scripts": {
45
+ "build": "pnpm copyfiles && pnpm build:types && pnpm build:swc",
46
+ "build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
47
+ "build:types": "tsc --outDir dist --rootDir ./src",
48
+ "clean": "rimraf {dist,*.tsbuildinfo}",
49
+ "copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
50
+ "dev": "next dev dev --turbo",
51
+ "dev:generate-importmap": "pnpm dev:payload generate:importmap",
52
+ "dev:generate-types": "pnpm dev:payload generate:types",
53
+ "dev:payload": "cross-env PAYLOAD_CONFIG_PATH=./dev/payload.config.ts payload",
54
+ "generate:importmap": "pnpm dev:generate-importmap",
55
+ "generate:types": "pnpm dev:generate-types",
56
+ "lint": "eslint",
57
+ "lint:fix": "eslint ./src --fix",
58
+ "prepublishOnly": "pnpm clean && pnpm build"
59
+ },
60
+ "devDependencies": {
61
+ "@payloadcms/db-postgres": "3.84.1",
62
+ "@payloadcms/next": "3.84.1",
63
+ "@payloadcms/richtext-lexical": "3.84.1",
64
+ "@payloadcms/ui": "3.84.1",
65
+ "@swc/cli": "0.8.1",
66
+ "@types/node": "25.9.3",
67
+ "@types/react": "19.2.17",
68
+ "@types/react-dom": "19.2.3",
69
+ "copyfiles": "2.4.1",
70
+ "cross-env": "^7.0.3",
71
+ "eslint": "^10.5.0",
72
+ "graphql": "^16.8.1",
73
+ "knip": "^6.16.1",
74
+ "next": "16.2.9",
75
+ "payload": "3.84.1",
76
+ "prettier": "^3.8.4",
77
+ "react": "19.2.7",
78
+ "react-dom": "19.2.6",
79
+ "rimraf": "6.1.3",
80
+ "sharp": "0.35.1",
81
+ "typescript": "5.9.3",
82
+ "vite-tsconfig-paths": "6.1.1",
83
+ "vitest": "4.1.9"
84
+ },
85
+ "peerDependencies": {
86
+ "payload": "^3.84.1"
87
+ },
88
+ "engines": {
89
+ "node": "^18.20.2 || >=20.9.0",
90
+ "pnpm": "^9 || ^10 || ^11"
91
+ },
92
+ "publishConfig": {
93
+ "access": "public"
94
+ },
95
+ "knip": {
96
+ "entry": [
97
+ "dev/payload.config.ts",
98
+ "dev/next.config.mjs",
99
+ "dev/app/**/*.{ts,tsx}"
100
+ ],
101
+ "ignore": [
102
+ "dev/payload-types.ts"
103
+ ],
104
+ "project": [
105
+ "src/**/*.{ts,tsx}",
106
+ "dev/**/*.{ts,tsx,mjs}"
107
+ ]
108
+ },
109
+ "dependencies": {
110
+ "@ai-sdk/anthropic": "^3.0.81",
111
+ "@ai-sdk/google": "^3.0.80",
112
+ "@ai-sdk/mistral": "^3.0.37",
113
+ "@ai-sdk/openai": "^3.0.67",
114
+ "ai": "^6.0.193",
115
+ "zod": "^4.4.3"
116
+ }
125
117
  }