@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
@@ -0,0 +1,138 @@
1
+ import { verifyAIActionProposal } from "../ai/proposals.js";
2
+ import { redactSensitiveData } from "../ai/sensitiveData.js";
3
+ import { getCollectionFields, normalizeAuthData, normalizeDataForFields } from "../payload/normalizeData.js";
4
+ import { isCollectionActionAllowed } from "../payload/collectionPermissions.js";
5
+ const isRecord = (value)=>{
6
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
7
+ };
8
+ const isActionProposal = (proposal)=>{
9
+ if (!isRecord(proposal) || typeof proposal.label !== "string") return false;
10
+ if (proposal.action === "create") {
11
+ return typeof proposal.collection === "string" && isRecord(proposal.data);
12
+ }
13
+ if (proposal.action === "update") {
14
+ return typeof proposal.collection === "string" && typeof proposal.id === "string" && isRecord(proposal.data);
15
+ }
16
+ if (proposal.action === "delete") {
17
+ return typeof proposal.collection === "string" && typeof proposal.id === "string";
18
+ }
19
+ if (proposal.action === "updateGlobal") {
20
+ return typeof proposal.slug === "string" && isRecord(proposal.data);
21
+ }
22
+ return false;
23
+ };
24
+ const mergeData = (current, next)=>{
25
+ return Object.fromEntries(Object.entries({
26
+ ...current,
27
+ ...next
28
+ }).map(([key, value])=>{
29
+ const currentValue = current[key];
30
+ if (isRecord(currentValue) && isRecord(value)) {
31
+ return [
32
+ key,
33
+ mergeData(currentValue, value)
34
+ ];
35
+ }
36
+ return [
37
+ key,
38
+ value
39
+ ];
40
+ }));
41
+ };
42
+ export const createAIProposalDiffEndpointHandler = (options = {})=>async (req)=>{
43
+ if (!req.user) return Response.json({
44
+ error: "Unauthorized"
45
+ }, {
46
+ status: 401
47
+ });
48
+ const body = req.json ? await req.json().catch(()=>null) : null;
49
+ const proposal = body?.proposal;
50
+ if (!proposal) return Response.json({
51
+ error: "Proposal is required"
52
+ }, {
53
+ status: 400
54
+ });
55
+ if (!verifyAIActionProposal(proposal)) return Response.json({
56
+ error: "Proposal signature is invalid or expired."
57
+ }, {
58
+ status: 400
59
+ });
60
+ if (!isActionProposal(proposal)) return Response.json({
61
+ error: "Proposal is invalid."
62
+ }, {
63
+ status: 400
64
+ });
65
+ try {
66
+ if (proposal.action === "updateGlobal") {
67
+ const globalConfig = req.payload.config.globals?.find((global)=>global.slug === proposal.slug);
68
+ if (!globalConfig) return Response.json({
69
+ error: "Unknown global"
70
+ }, {
71
+ status: 400
72
+ });
73
+ const normalized = normalizeDataForFields(globalConfig.fields || [], proposal.data);
74
+ const doc = await req.payload.findGlobal({
75
+ depth: 2,
76
+ overrideAccess: false,
77
+ req,
78
+ slug: proposal.slug
79
+ });
80
+ return Response.json({
81
+ after: redactSensitiveData(mergeData(doc, normalized.data)),
82
+ before: redactSensitiveData(doc)
83
+ });
84
+ }
85
+ if (!isCollectionActionAllowed({
86
+ action: proposal.action === "delete" ? "delete" : "read",
87
+ permissions: options.collections,
88
+ req,
89
+ slug: proposal.collection
90
+ })) return Response.json({
91
+ error: "Unknown collection"
92
+ }, {
93
+ status: 400
94
+ });
95
+ if (proposal.action === "delete") {
96
+ const doc = await req.payload.findByID({
97
+ collection: proposal.collection,
98
+ depth: 2,
99
+ id: proposal.id,
100
+ overrideAccess: false,
101
+ req
102
+ });
103
+ return Response.json({
104
+ after: {},
105
+ before: redactSensitiveData(doc)
106
+ });
107
+ }
108
+ const collectionConfig = req.payload.config.collections.find((collection)=>collection.slug === proposal.collection);
109
+ const normalized = normalizeAuthData(collectionConfig, normalizeDataForFields(getCollectionFields(collectionConfig), proposal.data));
110
+ if (proposal.action === "create") {
111
+ return Response.json({
112
+ after: redactSensitiveData(normalized.data),
113
+ before: {}
114
+ });
115
+ }
116
+ const doc = await req.payload.findByID({
117
+ collection: proposal.collection,
118
+ depth: 2,
119
+ id: proposal.id,
120
+ overrideAccess: false,
121
+ req
122
+ });
123
+ return Response.json({
124
+ after: redactSensitiveData(mergeData(doc, normalized.data)),
125
+ before: redactSensitiveData(doc)
126
+ });
127
+ } catch (err) {
128
+ req.payload.logger.error({
129
+ err,
130
+ msg: "AI proposal diff failed"
131
+ });
132
+ return Response.json({
133
+ error: "Could not load proposal diff."
134
+ }, {
135
+ status: 400
136
+ });
137
+ }
138
+ };
@@ -0,0 +1,6 @@
1
+ import type { PayloadHandler } from "payload";
2
+ type AIRecentChangesEndpointOptions = {
3
+ changeLogCollection: string;
4
+ };
5
+ export declare const createAIRecentChangesEndpointHandler: (options: AIRecentChangesEndpointOptions) => PayloadHandler;
6
+ export {};
@@ -0,0 +1,35 @@
1
+ const getNumber = (value)=>{
2
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
3
+ };
4
+ const getString = (value)=>{
5
+ return typeof value === "string" ? value : null;
6
+ };
7
+ export const createAIRecentChangesEndpointHandler = (options)=>async (req)=>{
8
+ if (!req.user) return Response.json({
9
+ error: "Unauthorized"
10
+ }, {
11
+ status: 401
12
+ });
13
+ const result = await req.payload.find({
14
+ collection: options.changeLogCollection,
15
+ depth: 0,
16
+ limit: 12,
17
+ overrideAccess: false,
18
+ req,
19
+ sort: "-createdAt"
20
+ });
21
+ return Response.json({
22
+ changes: result.docs.map((doc)=>({
23
+ action: getString(doc.action),
24
+ additions: getNumber(doc.additions),
25
+ after: doc.after,
26
+ before: doc.before,
27
+ collection: getString(doc.collection),
28
+ documentID: getString(doc.documentID),
29
+ removals: getNumber(doc.removals),
30
+ slug: getString(doc.slug),
31
+ title: getString(doc.title) || "AI change",
32
+ url: getString(doc.targetURL)
33
+ }))
34
+ });
35
+ };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import type { CollectionSlug, Config } from "payload";
2
2
  import { type AIModelConfig } from "./ai/providerOptions.js";
3
+ import { type AICollectionPermissionConfig } from "./payload/collectionPermissions.js";
3
4
  export type PayloadAiPluginOptions = {
4
- collections?: Partial<Record<CollectionSlug, true>>;
5
+ allowUserApiKeys?: boolean;
6
+ collections?: Partial<Record<CollectionSlug, AICollectionPermissionConfig>>;
5
7
  disabled?: boolean;
6
8
  models?: AIModelConfig;
7
9
  };
package/dist/index.js CHANGED
@@ -2,11 +2,102 @@ import { aiProviders, getResolvedAIModelConfig } from "./ai/providerOptions.js";
2
2
  import { createAIApplyActionEndpointHandler } from "./endpoints/aiApplyActionEndpointHandler.js";
3
3
  import { createAIChatEndpointHandler } from "./endpoints/aiChatEndpointHandler.js";
4
4
  import { createAIMentionSuggestionsEndpointHandler } from "./endpoints/aiMentionSuggestionsEndpointHandler.js";
5
- const getEnabledCollections = (collections)=>{
6
- if (!collections) return undefined;
7
- return Object.entries(collections).filter(([, enabled])=>enabled).map(([slug])=>slug);
8
- };
9
- const addAccountFields = (config)=>{
5
+ import { createAIProposalDiffEndpointHandler } from "./endpoints/aiProposalDiffEndpointHandler.js";
6
+ import { createAIRecentChangesEndpointHandler } from "./endpoints/aiRecentChangesEndpointHandler.js";
7
+ import { resolveCollectionPermissions } from "./payload/collectionPermissions.js";
8
+ import { isInternalCollection } from "./payload/shared.js";
9
+ const aiChangesCollectionSlug = "payload-ai-changes";
10
+ const createAIChangesCollection = ()=>({
11
+ slug: aiChangesCollectionSlug,
12
+ access: {
13
+ create: ()=>false,
14
+ delete: ()=>false,
15
+ read: ({ req })=>Boolean(req.user),
16
+ update: ()=>false
17
+ },
18
+ admin: {
19
+ defaultColumns: [
20
+ "title",
21
+ "action",
22
+ "additions",
23
+ "removals",
24
+ "createdAt"
25
+ ],
26
+ group: "AI",
27
+ useAsTitle: "title"
28
+ },
29
+ fields: [
30
+ {
31
+ name: "title",
32
+ type: "text",
33
+ required: true
34
+ },
35
+ {
36
+ name: "action",
37
+ type: "select",
38
+ options: [
39
+ "create",
40
+ "update",
41
+ "delete",
42
+ "updateGlobal"
43
+ ],
44
+ required: true
45
+ },
46
+ {
47
+ name: "targetType",
48
+ type: "select",
49
+ options: [
50
+ "collection",
51
+ "global"
52
+ ],
53
+ required: true
54
+ },
55
+ {
56
+ name: "collection",
57
+ type: "text"
58
+ },
59
+ {
60
+ name: "slug",
61
+ type: "text"
62
+ },
63
+ {
64
+ name: "documentID",
65
+ type: "text"
66
+ },
67
+ {
68
+ name: "targetURL",
69
+ type: "text"
70
+ },
71
+ {
72
+ name: "additions",
73
+ type: "number",
74
+ defaultValue: 0
75
+ },
76
+ {
77
+ name: "removals",
78
+ type: "number",
79
+ defaultValue: 0
80
+ },
81
+ {
82
+ name: "before",
83
+ type: "json"
84
+ },
85
+ {
86
+ name: "after",
87
+ type: "json"
88
+ },
89
+ {
90
+ name: "proposal",
91
+ type: "json"
92
+ },
93
+ {
94
+ name: "userID",
95
+ type: "text"
96
+ }
97
+ ],
98
+ timestamps: true
99
+ });
100
+ const addAccountFields = ({ allowUserApiKeys, config })=>{
10
101
  const adminUserSlug = config.admin?.user;
11
102
  if (!adminUserSlug || !config.collections) return;
12
103
  const userCollection = config.collections.find((c)=>c.slug === adminUserSlug);
@@ -16,29 +107,43 @@ const addAccountFields = (config)=>{
16
107
  type: "select",
17
108
  defaultValue: "openai",
18
109
  options: aiProviders
19
- }, {
20
- name: "aiApiKey",
21
- type: "text",
22
- admin: {
23
- components: {
24
- Field: "payload-ai-plugin/client#AIApiKeyField"
25
- }
26
- }
27
110
  });
111
+ if (allowUserApiKeys) {
112
+ userCollection.fields.push({
113
+ name: "aiApiKey",
114
+ type: "text",
115
+ admin: {
116
+ components: {
117
+ Field: "payload-ai-plugin/client#AIApiKeyField"
118
+ },
119
+ description: "Optional. If empty, the plugin uses the provider API key from environment variables."
120
+ }
121
+ });
122
+ }
28
123
  };
29
124
  export const payloadAiPlugin = (pluginOptions)=>(config)=>{
30
125
  const incomingOnInit = config.onInit;
31
- const enabledCollections = getEnabledCollections(pluginOptions.collections);
126
+ const collectionPermissions = resolveCollectionPermissions(pluginOptions.collections);
127
+ const allowUserApiKeys = pluginOptions.allowUserApiKeys !== false;
32
128
  const modelConfig = getResolvedAIModelConfig(pluginOptions.models);
33
129
  if (!config.collections) config.collections = [];
34
- addAccountFields(config);
130
+ if (!config.collections.some((collection)=>collection.slug === aiChangesCollectionSlug)) {
131
+ config.collections.push(createAIChangesCollection());
132
+ }
133
+ addAccountFields({
134
+ allowUserApiKeys,
135
+ config
136
+ });
35
137
  if (pluginOptions.disabled) return config;
138
+ const mentionCollectionSlugs = config.collections.filter((collection)=>!isInternalCollection(collection.slug)).filter((collection)=>collectionPermissions ? Boolean(collectionPermissions[collection.slug]?.read) : true).map((collection)=>collection.slug);
36
139
  if (!config.endpoints) config.endpoints = [];
37
140
  if (!config.admin) config.admin = {};
38
141
  config.admin.custom = {
39
142
  ...config.admin.custom || {},
40
143
  payloadAiPlugin: {
41
144
  ...config.admin.custom?.payloadAiPlugin || {},
145
+ collectionSlugs: mentionCollectionSlugs,
146
+ allowUserApiKeys,
42
147
  models: modelConfig
43
148
  }
44
149
  };
@@ -47,21 +152,38 @@ export const payloadAiPlugin = (pluginOptions)=>(config)=>{
47
152
  config.admin.components.beforeDashboard.push(`payload-ai-plugin/client#AIInput`);
48
153
  config.endpoints.push({
49
154
  handler: createAIChatEndpointHandler({
50
- collections: enabledCollections
155
+ allowUserApiKeys,
156
+ collections: collectionPermissions,
157
+ models: modelConfig
51
158
  }),
52
159
  method: "post",
53
160
  path: "/ai-chat"
54
161
  });
55
162
  config.endpoints.push({
56
163
  handler: createAIApplyActionEndpointHandler({
57
- collections: enabledCollections
164
+ changeLogCollection: aiChangesCollectionSlug,
165
+ collections: collectionPermissions
58
166
  }),
59
167
  method: "post",
60
168
  path: "/ai-apply-action"
61
169
  });
170
+ config.endpoints.push({
171
+ handler: createAIRecentChangesEndpointHandler({
172
+ changeLogCollection: aiChangesCollectionSlug
173
+ }),
174
+ method: "get",
175
+ path: "/ai-recent-changes"
176
+ });
177
+ config.endpoints.push({
178
+ handler: createAIProposalDiffEndpointHandler({
179
+ collections: collectionPermissions
180
+ }),
181
+ method: "post",
182
+ path: "/ai-proposal-diff"
183
+ });
62
184
  config.endpoints.push({
63
185
  handler: createAIMentionSuggestionsEndpointHandler({
64
- collections: enabledCollections
186
+ collections: collectionPermissions
65
187
  }),
66
188
  method: "post",
67
189
  path: "/ai-mention-suggestions"
@@ -0,0 +1,22 @@
1
+ import type { PayloadHandler } from "payload";
2
+ export type AICollectionAction = "create" | "delete" | "read" | "update";
3
+ export type AICollectionPermissions = Partial<Record<AICollectionAction, boolean>>;
4
+ export type AICollectionPermissionConfig = true | AICollectionPermissions;
5
+ export type AICollectionPermissionMap = Partial<Record<string, AICollectionPermissionConfig>>;
6
+ export type ResolvedAICollectionPermissionMap = Partial<Record<string, Record<AICollectionAction, boolean>>>;
7
+ export declare const resolveCollectionPermissions: (collections?: AICollectionPermissionMap) => ResolvedAICollectionPermissionMap | undefined;
8
+ export declare const getCollectionSlugsForAction: ({ action, permissions, req, }: {
9
+ action: AICollectionAction;
10
+ permissions?: ResolvedAICollectionPermissionMap;
11
+ req: Parameters<PayloadHandler>[0];
12
+ }) => string[];
13
+ export declare const isCollectionActionAllowed: ({ action, permissions, req, slug, }: {
14
+ action: AICollectionAction;
15
+ permissions?: ResolvedAICollectionPermissionMap;
16
+ req: Parameters<PayloadHandler>[0];
17
+ slug: string;
18
+ }) => boolean;
19
+ export declare const getCollectionPermissions: ({ permissions, slug, }: {
20
+ permissions?: ResolvedAICollectionPermissionMap;
21
+ slug: string;
22
+ }) => Record<AICollectionAction, boolean>;
@@ -0,0 +1,68 @@
1
+ import { isInternalCollection } from "./shared.js";
2
+ const allActions = [
3
+ "create",
4
+ "delete",
5
+ "read",
6
+ "update"
7
+ ];
8
+ const getKnownCollectionSlugs = (req)=>{
9
+ return req.payload.config.collections.map((collection)=>collection.slug).filter((slug)=>!isInternalCollection(slug));
10
+ };
11
+ export const resolveCollectionPermissions = (collections)=>{
12
+ if (!collections) return undefined;
13
+ return Object.fromEntries(Object.entries(collections).map(([slug, config])=>{
14
+ if (config === true) {
15
+ return [
16
+ slug,
17
+ {
18
+ create: true,
19
+ delete: true,
20
+ read: true,
21
+ update: true
22
+ }
23
+ ];
24
+ }
25
+ if (!config) {
26
+ return [
27
+ slug,
28
+ {
29
+ create: false,
30
+ delete: false,
31
+ read: false,
32
+ update: false
33
+ }
34
+ ];
35
+ }
36
+ return [
37
+ slug,
38
+ {
39
+ create: Boolean(config.create),
40
+ delete: Boolean(config.delete),
41
+ read: Boolean(config.read),
42
+ update: Boolean(config.update)
43
+ }
44
+ ];
45
+ }));
46
+ };
47
+ export const getCollectionSlugsForAction = ({ action, permissions, req })=>{
48
+ const knownSlugs = getKnownCollectionSlugs(req);
49
+ if (!permissions) return knownSlugs;
50
+ return knownSlugs.filter((slug)=>Boolean(permissions[slug]?.[action]));
51
+ };
52
+ export const isCollectionActionAllowed = ({ action, permissions, req, slug })=>{
53
+ if (!getKnownCollectionSlugs(req).includes(slug)) return false;
54
+ if (!permissions) return true;
55
+ return Boolean(permissions[slug]?.[action]);
56
+ };
57
+ export const getCollectionPermissions = ({ permissions, slug })=>{
58
+ if (!permissions) {
59
+ return Object.fromEntries(allActions.map((action)=>[
60
+ action,
61
+ true
62
+ ]));
63
+ }
64
+ return permissions[slug] || Object.fromEntries(allActions.map((action)=>[
65
+ action,
66
+ false
67
+ ]));
68
+ };
@@ -1,4 +1,5 @@
1
1
  import type { PayloadHandler } from "payload";
2
+ import { type ResolvedAICollectionPermissionMap } from "./collectionPermissions.js";
2
3
  export type AIChatMention = {
3
4
  collection?: string;
4
5
  id?: string;
@@ -8,11 +9,19 @@ export type AIChatMention = {
8
9
  type?: "block" | "collection" | "doc" | "global";
9
10
  };
10
11
  export type FieldConfig = {
12
+ admin?: {
13
+ condition?: unknown;
14
+ };
11
15
  blocks?: BlockConfig[];
12
16
  fields?: FieldConfig[];
13
17
  hasMany?: boolean;
14
18
  label?: unknown;
19
+ localized?: boolean;
15
20
  name?: string;
21
+ options?: (string | {
22
+ label?: unknown;
23
+ value?: string;
24
+ })[];
16
25
  relationTo?: unknown;
17
26
  required?: boolean;
18
27
  type?: string;
@@ -25,16 +34,51 @@ type BlockConfig = {
25
34
  };
26
35
  slug: string;
27
36
  };
37
+ type VersionConfig = boolean | {
38
+ drafts?: boolean | Record<string, unknown>;
39
+ };
40
+ type CollectionLikeConfig = {
41
+ access?: Record<string, unknown>;
42
+ auth?: unknown;
43
+ fields?: FieldConfig[];
44
+ label?: unknown;
45
+ labels?: {
46
+ plural?: unknown;
47
+ singular?: unknown;
48
+ };
49
+ slug: string;
50
+ versions?: VersionConfig;
51
+ };
28
52
  type MentionContext = {
29
53
  blockContexts: (Record<string, unknown> & {
30
54
  parent: string;
31
55
  slug: string;
32
56
  })[];
33
57
  collectionSlugs: string[];
58
+ collections?: ResolvedAICollectionPermissionMap;
34
59
  globalSlugs: string[];
35
60
  mentions?: AIChatMention[];
36
61
  req: Parameters<PayloadHandler>[0];
37
62
  };
63
+ export declare const describeCollectionLikeConfig: ({ config, permissions, type, }: {
64
+ config: CollectionLikeConfig;
65
+ permissions?: ResolvedAICollectionPermissionMap;
66
+ type: "collection" | "global";
67
+ }) => {
68
+ access: {
69
+ aiPermissions: Record<import("./collectionPermissions.js").AICollectionAction, boolean> | {
70
+ read: boolean;
71
+ update: boolean;
72
+ };
73
+ hasPayloadAccessControl: boolean;
74
+ };
75
+ fields: Record<string, unknown>[];
76
+ hasAuth: true | undefined;
77
+ hasDrafts: true | undefined;
78
+ label: {};
79
+ slug: string;
80
+ type: "collection" | "global";
81
+ };
38
82
  export declare const describeField: (field: FieldConfig) => Record<string, unknown>;
39
83
  export declare const collectBlocks: ({ fields, parent, }: {
40
84
  fields: FieldConfig[];
@@ -43,8 +87,8 @@ export declare const collectBlocks: ({ fields, parent, }: {
43
87
  parent: string;
44
88
  slug: string;
45
89
  })[];
46
- export declare const getAllowedCollectionSlugs: (req: Parameters<PayloadHandler>[0], collections?: string[]) => string[];
47
- export declare const getMentionContext: ({ blockContexts, collectionSlugs, globalSlugs, mentions, req, }: MentionContext) => Promise<Record<string, unknown>[]>;
90
+ export declare const getAllowedCollectionSlugs: (req: Parameters<PayloadHandler>[0], collections?: ResolvedAICollectionPermissionMap) => string[];
91
+ export declare const getMentionContext: ({ blockContexts, collectionSlugs, collections, globalSlugs, mentions, req, }: MentionContext) => Promise<Record<string, unknown>[]>;
48
92
  export declare const buildPromptWithMentionContext: ({ mentionContext, prompt, }: {
49
93
  mentionContext: Record<string, unknown>[];
50
94
  prompt: string;