@ai-stack/payloadcms 3.68.0-beta.2 → 3.68.0-beta.3
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/ai/core/media/image/generateImage.js +2 -6
- package/dist/ai/core/media/image/generateImage.js.map +1 -1
- package/dist/ai/providers/blocks/elevenlabs.js +1 -1
- package/dist/ai/providers/blocks/elevenlabs.js.map +1 -1
- package/dist/ai/providers/blocks/google.js +9 -5
- package/dist/ai/providers/blocks/google.js.map +1 -1
- package/dist/ai/providers/blocks/openai.js +1 -1
- package/dist/ai/providers/blocks/openai.js.map +1 -1
- package/dist/collections/AISettings.js +44 -17
- package/dist/collections/AISettings.js.map +1 -1
- package/dist/defaults.d.ts +1 -0
- package/dist/defaults.js +8 -0
- package/dist/defaults.js.map +1 -1
- package/dist/endpoints/fetchFields.js +10 -0
- package/dist/endpoints/fetchFields.js.map +1 -1
- package/dist/plugin.js +16 -32
- package/dist/plugin.js.map +1 -1
- package/dist/providers/InstructionsProvider/InstructionsProvider.js +44 -15
- package/dist/providers/InstructionsProvider/InstructionsProvider.js.map +1 -1
- package/dist/providers/InstructionsProvider/InstructionsProvider.jsx +36 -16
- package/dist/providers/InstructionsProvider/context.d.ts +3 -0
- package/dist/providers/InstructionsProvider/context.js +2 -0
- package/dist/providers/InstructionsProvider/context.js.map +1 -1
- package/dist/providers/InstructionsProvider/useInstructions.js +3 -1
- package/dist/providers/InstructionsProvider/useInstructions.js.map +1 -1
- package/dist/types.d.ts +0 -3
- package/dist/types.js.map +1 -1
- package/dist/ui/AIConfigDashboard/index.js +198 -22
- package/dist/ui/AIConfigDashboard/index.js.map +1 -1
- package/dist/ui/AIConfigDashboard/index.jsx +159 -13
- package/dist/ui/Compose/Compose.js +5 -3
- package/dist/ui/Compose/Compose.js.map +1 -1
- package/dist/ui/Compose/Compose.jsx +3 -3
- package/dist/ui/Compose/hooks/useGenerate.js +34 -131
- package/dist/ui/Compose/hooks/useGenerate.js.map +1 -1
- package/dist/ui/Compose/hooks/useGenerateUpload.d.ts +11 -0
- package/dist/ui/Compose/hooks/useGenerateUpload.js +123 -0
- package/dist/ui/Compose/hooks/useGenerateUpload.js.map +1 -0
- package/dist/ui/Compose/hooks/useStreamingUpdate.d.ts +8 -0
- package/dist/ui/Compose/hooks/useStreamingUpdate.js +48 -0
- package/dist/ui/Compose/hooks/useStreamingUpdate.js.map +1 -0
- package/dist/ui/EncryptedTextField/index.js +4 -4
- package/dist/ui/EncryptedTextField/index.js.map +1 -1
- package/dist/ui/EncryptedTextField/index.jsx +4 -4
- package/dist/utilities/seedProperties.d.ts +7 -0
- package/dist/utilities/seedProperties.js +117 -0
- package/dist/utilities/seedProperties.js.map +1 -0
- package/dist/utilities/setSafeLexicalState.js +80 -6
- package/dist/utilities/setSafeLexicalState.js.map +1 -1
- package/dist/utilities/updateFieldsConfig.d.ts +1 -1
- package/dist/utilities/updateFieldsConfig.js +1 -0
- package/dist/utilities/updateFieldsConfig.js.map +1 -1
- package/package.json +2 -1
- package/dist/init.d.ts +0 -7
- package/dist/init.js +0 -152
- package/dist/init.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { useField } from '@payloadcms/ui';
|
|
2
|
+
import { Button, useField } from '@payloadcms/ui';
|
|
3
3
|
import React, { useState } from 'react';
|
|
4
4
|
export const EncryptedTextField = ({ label, path, required }) => {
|
|
5
5
|
const { setValue, value } = useField({ path });
|
|
@@ -24,12 +24,12 @@ export const EncryptedTextField = ({ label, path, required }) => {
|
|
|
24
24
|
✓ Configured
|
|
25
25
|
</span>
|
|
26
26
|
</div>
|
|
27
|
-
<
|
|
27
|
+
<Button buttonStyle="secondary" onClick={() => {
|
|
28
28
|
setValue('');
|
|
29
29
|
setIsEditing(true);
|
|
30
|
-
}}
|
|
30
|
+
}} size="medium">
|
|
31
31
|
Change
|
|
32
|
-
</
|
|
32
|
+
</Button>
|
|
33
33
|
</div>) : (<input onChange={(e) => setValue(e.target.value)} placeholder="sk-..." style={{ width: '100%' }} type="password" value={value || ''}/>)}
|
|
34
34
|
</div>);
|
|
35
35
|
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { defaultSeedPrompts } from '../ai/prompts.js';
|
|
2
|
+
import { PLUGIN_INSTRUCTIONS_TABLE } from '../defaults.js';
|
|
3
|
+
import { updateFieldsConfig } from './updateFieldsConfig.js';
|
|
4
|
+
export const seedProperties = async ({ enabledCollections, req })=>{
|
|
5
|
+
const { payload } = req;
|
|
6
|
+
if (!enabledCollections || enabledCollections.length === 0) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
// Get all collections from payload config
|
|
10
|
+
const allCollections = payload.config.collections;
|
|
11
|
+
for (const collectionSlug of enabledCollections){
|
|
12
|
+
const collectionConfig = allCollections.find((c)=>c.slug === collectionSlug);
|
|
13
|
+
if (!collectionConfig) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
// Traverse the collection config effectively using updateFieldsConfig
|
|
17
|
+
// Use the side-effect of getting schemaPathMap from it
|
|
18
|
+
const { schemaPathMap } = updateFieldsConfig(collectionConfig);
|
|
19
|
+
for (const [schemaPath, fieldInfo] of Object.entries(schemaPathMap)){
|
|
20
|
+
const { type, custom, label, relationTo } = fieldInfo;
|
|
21
|
+
// Check if instruction already exists
|
|
22
|
+
const existingInstruction = await payload.find({
|
|
23
|
+
collection: PLUGIN_INSTRUCTIONS_TABLE,
|
|
24
|
+
depth: 0,
|
|
25
|
+
limit: 1,
|
|
26
|
+
overrideAccess: true,
|
|
27
|
+
where: {
|
|
28
|
+
'schema-path': {
|
|
29
|
+
equals: schemaPath
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
if (existingInstruction.totalDocs > 0) {
|
|
34
|
+
// If developer has provided custom prompts in the schema, update the existing record
|
|
35
|
+
// but only if the values have actually changed.
|
|
36
|
+
if (custom?.ai?.prompt || custom?.ai?.system) {
|
|
37
|
+
const doc = existingInstruction.docs[0];
|
|
38
|
+
const currentPrompt = doc.prompt;
|
|
39
|
+
const currentSystem = doc.system;
|
|
40
|
+
let needsUpdate = false;
|
|
41
|
+
const updateData = {};
|
|
42
|
+
if (custom?.ai?.prompt && custom.ai.prompt !== currentPrompt) {
|
|
43
|
+
updateData.prompt = custom.ai.prompt;
|
|
44
|
+
needsUpdate = true;
|
|
45
|
+
}
|
|
46
|
+
if (custom?.ai?.system && custom.ai.system !== currentSystem) {
|
|
47
|
+
updateData.system = custom.ai.system;
|
|
48
|
+
needsUpdate = true;
|
|
49
|
+
}
|
|
50
|
+
if (needsUpdate) {
|
|
51
|
+
try {
|
|
52
|
+
await payload.update({
|
|
53
|
+
id: doc.id,
|
|
54
|
+
collection: PLUGIN_INSTRUCTIONS_TABLE,
|
|
55
|
+
data: updateData,
|
|
56
|
+
overrideAccess: true
|
|
57
|
+
});
|
|
58
|
+
} catch (error) {
|
|
59
|
+
payload.logger.error(`Failed to update instruction for ${schemaPath}: ${error}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
// Generate seed prompts
|
|
66
|
+
const seeded = await defaultSeedPrompts({
|
|
67
|
+
fieldLabel: label,
|
|
68
|
+
fieldSchemaPaths: {},
|
|
69
|
+
fieldType: type,
|
|
70
|
+
path: schemaPath
|
|
71
|
+
});
|
|
72
|
+
if (!seeded || typeof seeded !== 'object') {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
let prompt = 'prompt' in seeded ? seeded.prompt : '';
|
|
76
|
+
let system = 'system' in seeded ? seeded.system : '';
|
|
77
|
+
// Override with custom prompts if defined
|
|
78
|
+
if (custom?.ai?.prompt) {
|
|
79
|
+
prompt = custom.ai.prompt;
|
|
80
|
+
}
|
|
81
|
+
if (custom?.ai?.system) {
|
|
82
|
+
system = custom.ai.system;
|
|
83
|
+
}
|
|
84
|
+
// Determine model-id based on field type
|
|
85
|
+
let modelId = 'text';
|
|
86
|
+
if (type === 'richText') {
|
|
87
|
+
modelId = 'richtext';
|
|
88
|
+
}
|
|
89
|
+
if (type === 'upload') {
|
|
90
|
+
modelId = 'image';
|
|
91
|
+
} // defaulting to image generation for uploads
|
|
92
|
+
if (type === 'array') {
|
|
93
|
+
modelId = 'array';
|
|
94
|
+
}
|
|
95
|
+
// Create new instruction
|
|
96
|
+
try {
|
|
97
|
+
await payload.create({
|
|
98
|
+
collection: PLUGIN_INSTRUCTIONS_TABLE,
|
|
99
|
+
data: {
|
|
100
|
+
prompt,
|
|
101
|
+
system,
|
|
102
|
+
disabled: false,
|
|
103
|
+
'field-type': type,
|
|
104
|
+
'model-id': modelId,
|
|
105
|
+
'relation-to': relationTo,
|
|
106
|
+
'schema-path': schemaPath
|
|
107
|
+
},
|
|
108
|
+
overrideAccess: true
|
|
109
|
+
});
|
|
110
|
+
} catch (error) {
|
|
111
|
+
payload.logger.error(`Failed to seed instruction for ${schemaPath}: ${error}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
//# sourceMappingURL=seedProperties.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/seedProperties.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\nimport { defaultSeedPrompts } from '../ai/prompts.js'\nimport { PLUGIN_INSTRUCTIONS_TABLE } from '../defaults.js'\nimport { updateFieldsConfig } from './updateFieldsConfig.js'\n\ninterface SeedPropertiesArgs {\n enabledCollections: string[]\n req: PayloadRequest\n}\n\nexport const seedProperties = async ({ enabledCollections, req }: SeedPropertiesArgs): Promise<void> => {\n const { payload } = req\n\n if (!enabledCollections || enabledCollections.length === 0) {\n return\n }\n\n // Get all collections from payload config\n const allCollections = payload.config.collections\n\n for (const collectionSlug of enabledCollections) {\n const collectionConfig = allCollections.find((c) => c.slug === collectionSlug)\n if (!collectionConfig) {\n continue\n }\n\n // Traverse the collection config effectively using updateFieldsConfig\n // Use the side-effect of getting schemaPathMap from it\n const { schemaPathMap } = updateFieldsConfig(collectionConfig)\n\n for (const [schemaPath, fieldInfo] of Object.entries(schemaPathMap)) {\n const { type, custom, label, relationTo } = fieldInfo as {\n custom?: any\n label: string\n relationTo?: string\n type: string\n }\n\n // Check if instruction already exists\n const existingInstruction = await payload.find({\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n depth: 0,\n limit: 1,\n overrideAccess: true,\n where: {\n 'schema-path': {\n equals: schemaPath,\n },\n },\n })\n\n if (existingInstruction.totalDocs > 0) {\n // If developer has provided custom prompts in the schema, update the existing record\n // but only if the values have actually changed.\n if (custom?.ai?.prompt || custom?.ai?.system) {\n const doc = existingInstruction.docs[0] as any\n const currentPrompt = doc.prompt\n const currentSystem = doc.system\n\n let needsUpdate = false\n const updateData: any = {}\n\n if (custom?.ai?.prompt && custom.ai.prompt !== currentPrompt) {\n updateData.prompt = custom.ai.prompt\n needsUpdate = true\n }\n if (custom?.ai?.system && custom.ai.system !== currentSystem) {\n updateData.system = custom.ai.system\n needsUpdate = true\n }\n\n if (needsUpdate) {\n try {\n await payload.update({\n id: doc.id,\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n data: updateData,\n overrideAccess: true,\n })\n } catch (error) {\n payload.logger.error(`Failed to update instruction for ${schemaPath}: ${error}`)\n }\n }\n }\n continue\n }\n\n // Generate seed prompts\n const seeded = await defaultSeedPrompts({\n fieldLabel: label,\n fieldSchemaPaths: {}, // We might not need the full map here for individual seeding\n fieldType: type,\n path: schemaPath,\n })\n\n if (!seeded || typeof seeded !== 'object') {\n continue\n }\n\n let prompt = 'prompt' in seeded ? seeded.prompt : ''\n let system = 'system' in seeded ? seeded.system : ''\n\n // Override with custom prompts if defined\n if (custom?.ai?.prompt) {\n prompt = custom.ai.prompt\n }\n if (custom?.ai?.system) {\n system = custom.ai.system\n }\n\n // Determine model-id based on field type\n let modelId = 'text'\n if (type === 'richText') {\n modelId = 'richtext'\n }\n if (type === 'upload') {\n modelId = 'image'\n } // defaulting to image generation for uploads\n if (type === 'array') {\n modelId = 'array'\n }\n\n // Create new instruction\n try {\n await payload.create({\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n data: {\n prompt,\n system,\n disabled: false,\n 'field-type': type,\n 'model-id': modelId,\n 'relation-to': relationTo,\n 'schema-path': schemaPath,\n },\n overrideAccess: true,\n })\n } catch (error) {\n payload.logger.error(`Failed to seed instruction for ${schemaPath}: ${error}`)\n }\n }\n }\n}\n"],"names":["defaultSeedPrompts","PLUGIN_INSTRUCTIONS_TABLE","updateFieldsConfig","seedProperties","enabledCollections","req","payload","length","allCollections","config","collections","collectionSlug","collectionConfig","find","c","slug","schemaPathMap","schemaPath","fieldInfo","Object","entries","type","custom","label","relationTo","existingInstruction","collection","depth","limit","overrideAccess","where","equals","totalDocs","ai","prompt","system","doc","docs","currentPrompt","currentSystem","needsUpdate","updateData","update","id","data","error","logger","seeded","fieldLabel","fieldSchemaPaths","fieldType","path","modelId","create","disabled"],"mappings":"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"}
|
|
@@ -1,15 +1,89 @@
|
|
|
1
|
+
const sanitizeLexicalState = (state)=>{
|
|
2
|
+
// 1. Ensure root exists and is valid
|
|
3
|
+
if (!state || typeof state !== 'object') {
|
|
4
|
+
return null;
|
|
5
|
+
}
|
|
6
|
+
// If no root, or root is not an object, it's invalid
|
|
7
|
+
if (!state.root || typeof state.root !== 'object') {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
// 2. Clone to avoid mutation
|
|
11
|
+
const cleanState = JSON.parse(JSON.stringify(state));
|
|
12
|
+
// 3. Ensure root has required props
|
|
13
|
+
cleanState.root.type = 'root';
|
|
14
|
+
cleanState.root.format = cleanState.root.format || '';
|
|
15
|
+
cleanState.root.indent = cleanState.root.indent || 0;
|
|
16
|
+
cleanState.root.version = cleanState.root.version || 1;
|
|
17
|
+
// 4. Recursive sanitizer for children
|
|
18
|
+
const sanitizeNode = (node)=>{
|
|
19
|
+
if (!node || typeof node !== 'object') {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
// Must have a type. If streaming incomplete node (type is missing/empty), discard it.
|
|
23
|
+
if (!node.type || typeof node.type !== 'string') {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
// Default version if missing
|
|
27
|
+
node.version = node.version || 1;
|
|
28
|
+
// If node has children, sanitize them
|
|
29
|
+
if (Array.isArray(node.children)) {
|
|
30
|
+
node.children = node.children.map(sanitizeNode).filter((child)=>child !== null);
|
|
31
|
+
} else {
|
|
32
|
+
// Ensure children is at least an empty array if it's supposed to be there?
|
|
33
|
+
// Actually lots of leaf nodes don't have children.
|
|
34
|
+
// But Root, Paragraph, etc do.
|
|
35
|
+
// Let's safe-guard standard ElementNodes:
|
|
36
|
+
if ([
|
|
37
|
+
'heading',
|
|
38
|
+
'link',
|
|
39
|
+
'list',
|
|
40
|
+
'listitem',
|
|
41
|
+
'paragraph',
|
|
42
|
+
'quote',
|
|
43
|
+
'root'
|
|
44
|
+
].includes(node.type)) {
|
|
45
|
+
node.children = node.children || [];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Specific node fixes
|
|
49
|
+
if (node.type === 'text') {
|
|
50
|
+
// Text nodes must have text prop
|
|
51
|
+
if (typeof node.text !== 'string') {
|
|
52
|
+
// If text is missing, it might be incomplete.
|
|
53
|
+
// We can either discard or default to empty string.
|
|
54
|
+
// For streaming, empty string is safer than discarding early if we want to show cursor?
|
|
55
|
+
node.text = node.text || '';
|
|
56
|
+
}
|
|
57
|
+
node.mode = node.mode ?? 0;
|
|
58
|
+
node.style = node.style || '';
|
|
59
|
+
node.detail = node.detail ?? 0;
|
|
60
|
+
node.format = node.format ?? 0;
|
|
61
|
+
}
|
|
62
|
+
return node;
|
|
63
|
+
};
|
|
64
|
+
// 5. Sanitize root's children
|
|
65
|
+
if (Array.isArray(cleanState.root.children)) {
|
|
66
|
+
cleanState.root.children = cleanState.root.children.map(sanitizeNode).filter((child)=>child !== null);
|
|
67
|
+
} else {
|
|
68
|
+
cleanState.root.children = [];
|
|
69
|
+
}
|
|
70
|
+
return cleanState;
|
|
71
|
+
};
|
|
1
72
|
export const setSafeLexicalState = (state, editorInstance)=>{
|
|
2
73
|
try {
|
|
3
|
-
const
|
|
74
|
+
const validState = sanitizeLexicalState(state);
|
|
75
|
+
if (!validState) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const editorState = editorInstance.parseEditorState(validState);
|
|
4
79
|
if (editorState.isEmpty()) {
|
|
5
80
|
return;
|
|
6
81
|
}
|
|
7
82
|
editorInstance.setEditorState(editorState);
|
|
8
|
-
} catch (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
});
|
|
83
|
+
} catch (_error) {
|
|
84
|
+
// Silently catch errors during streaming to avoid console noise.
|
|
85
|
+
// Lexical's parseEditorState is very strict and will throw if the
|
|
86
|
+
// object structure is even slightly incomplete during the stream.
|
|
13
87
|
}
|
|
14
88
|
};
|
|
15
89
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/setSafeLexicalState.ts"],"sourcesContent":["import type { LexicalEditor } from 'lexical'\n\
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/setSafeLexicalState.ts"],"sourcesContent":["import type { LexicalEditor } from 'lexical'\n\nconst sanitizeLexicalState = (state: any): any => {\n // 1. Ensure root exists and is valid\n if (!state || typeof state !== 'object') {\n return null\n }\n\n // If no root, or root is not an object, it's invalid\n if (!state.root || typeof state.root !== 'object') {\n return null\n }\n\n // 2. Clone to avoid mutation\n const cleanState = JSON.parse(JSON.stringify(state))\n\n // 3. Ensure root has required props\n cleanState.root.type = 'root'\n cleanState.root.format = cleanState.root.format || ''\n cleanState.root.indent = cleanState.root.indent || 0\n cleanState.root.version = cleanState.root.version || 1\n\n // 4. Recursive sanitizer for children\n const sanitizeNode = (node: any): any => {\n if (!node || typeof node !== 'object') {\n return null\n }\n\n // Must have a type. If streaming incomplete node (type is missing/empty), discard it.\n if (!node.type || typeof node.type !== 'string') {\n return null\n }\n\n // Default version if missing\n node.version = node.version || 1\n\n // If node has children, sanitize them\n if (Array.isArray(node.children)) {\n node.children = node.children\n .map(sanitizeNode)\n .filter((child: any) => child !== null)\n } else {\n // Ensure children is at least an empty array if it's supposed to be there? \n // Actually lots of leaf nodes don't have children. \n // But Root, Paragraph, etc do. \n // Let's safe-guard standard ElementNodes:\n if (['heading', 'link', 'list', 'listitem', 'paragraph', 'quote', 'root'].includes(node.type)) {\n node.children = node.children || []\n }\n }\n\n // Specific node fixes\n if (node.type === 'text') {\n // Text nodes must have text prop\n if (typeof node.text !== 'string') {\n // If text is missing, it might be incomplete. \n // We can either discard or default to empty string.\n // For streaming, empty string is safer than discarding early if we want to show cursor?\n node.text = node.text || ''\n }\n node.mode = node.mode ?? 0\n node.style = node.style || ''\n node.detail = node.detail ?? 0\n node.format = node.format ?? 0\n }\n\n return node\n }\n\n // 5. Sanitize root's children\n if (Array.isArray(cleanState.root.children)) {\n cleanState.root.children = cleanState.root.children\n .map(sanitizeNode)\n .filter((child: any) => child !== null)\n } else {\n cleanState.root.children = []\n }\n\n return cleanState\n}\n\nexport const setSafeLexicalState = (state: unknown, editorInstance: LexicalEditor) => {\n try {\n const validState = sanitizeLexicalState(state)\n \n if (!validState) {\n return\n }\n\n const editorState = editorInstance.parseEditorState(validState)\n if (editorState.isEmpty()) {\n return\n }\n\n editorInstance.setEditorState(editorState)\n } catch (_error) {\n // Silently catch errors during streaming to avoid console noise.\n // Lexical's parseEditorState is very strict and will throw if the\n // object structure is even slightly incomplete during the stream.\n }\n}\n"],"names":["sanitizeLexicalState","state","root","cleanState","JSON","parse","stringify","type","format","indent","version","sanitizeNode","node","Array","isArray","children","map","filter","child","includes","text","mode","style","detail","setSafeLexicalState","editorInstance","validState","editorState","parseEditorState","isEmpty","setEditorState","_error"],"mappings":"AAEA,MAAMA,uBAAuB,CAACC;IAC5B,qCAAqC;IACrC,IAAI,CAACA,SAAS,OAAOA,UAAU,UAAU;QACvC,OAAO;IACT;IAEA,qDAAqD;IACrD,IAAI,CAACA,MAAMC,IAAI,IAAI,OAAOD,MAAMC,IAAI,KAAK,UAAU;QACjD,OAAO;IACT;IAEA,6BAA6B;IAC7B,MAAMC,aAAaC,KAAKC,KAAK,CAACD,KAAKE,SAAS,CAACL;IAE7C,oCAAoC;IACpCE,WAAWD,IAAI,CAACK,IAAI,GAAG;IACvBJ,WAAWD,IAAI,CAACM,MAAM,GAAGL,WAAWD,IAAI,CAACM,MAAM,IAAI;IACnDL,WAAWD,IAAI,CAACO,MAAM,GAAGN,WAAWD,IAAI,CAACO,MAAM,IAAI;IACnDN,WAAWD,IAAI,CAACQ,OAAO,GAAGP,WAAWD,IAAI,CAACQ,OAAO,IAAI;IAErD,sCAAsC;IACtC,MAAMC,eAAe,CAACC;QACpB,IAAI,CAACA,QAAQ,OAAOA,SAAS,UAAU;YACrC,OAAO;QACT;QAEA,sFAAsF;QACtF,IAAI,CAACA,KAAKL,IAAI,IAAI,OAAOK,KAAKL,IAAI,KAAK,UAAU;YAC/C,OAAO;QACT;QAEA,6BAA6B;QAC7BK,KAAKF,OAAO,GAAGE,KAAKF,OAAO,IAAI;QAE/B,sCAAsC;QACtC,IAAIG,MAAMC,OAAO,CAACF,KAAKG,QAAQ,GAAG;YAChCH,KAAKG,QAAQ,GAAGH,KAAKG,QAAQ,CAC1BC,GAAG,CAACL,cACJM,MAAM,CAAC,CAACC,QAAeA,UAAU;QACtC,OAAO;YACL,4EAA4E;YAC5E,oDAAoD;YACpD,gCAAgC;YAChC,0CAA0C;YAC1C,IAAI;gBAAC;gBAAW;gBAAQ;gBAAQ;gBAAY;gBAAa;gBAAS;aAAO,CAACC,QAAQ,CAACP,KAAKL,IAAI,GAAG;gBAC7FK,KAAKG,QAAQ,GAAGH,KAAKG,QAAQ,IAAI,EAAE;YACrC;QACF;QAEA,sBAAsB;QACtB,IAAIH,KAAKL,IAAI,KAAK,QAAQ;YACxB,iCAAiC;YACjC,IAAI,OAAOK,KAAKQ,IAAI,KAAK,UAAU;gBACjC,+CAA+C;gBAC/C,oDAAoD;gBACpD,wFAAwF;gBACxFR,KAAKQ,IAAI,GAAGR,KAAKQ,IAAI,IAAI;YAC3B;YACAR,KAAKS,IAAI,GAAGT,KAAKS,IAAI,IAAI;YACzBT,KAAKU,KAAK,GAAGV,KAAKU,KAAK,IAAI;YAC3BV,KAAKW,MAAM,GAAGX,KAAKW,MAAM,IAAI;YAC7BX,KAAKJ,MAAM,GAAGI,KAAKJ,MAAM,IAAI;QAC/B;QAEA,OAAOI;IACT;IAEA,8BAA8B;IAC9B,IAAIC,MAAMC,OAAO,CAACX,WAAWD,IAAI,CAACa,QAAQ,GAAG;QAC3CZ,WAAWD,IAAI,CAACa,QAAQ,GAAGZ,WAAWD,IAAI,CAACa,QAAQ,CAChDC,GAAG,CAACL,cACJM,MAAM,CAAC,CAACC,QAAeA,UAAU;IACtC,OAAO;QACLf,WAAWD,IAAI,CAACa,QAAQ,GAAG,EAAE;IAC/B;IAEA,OAAOZ;AACT;AAEA,OAAO,MAAMqB,sBAAsB,CAACvB,OAAgBwB;IAClD,IAAI;QACF,MAAMC,aAAa1B,qBAAqBC;QAExC,IAAI,CAACyB,YAAY;YACf;QACF;QAEA,MAAMC,cAAcF,eAAeG,gBAAgB,CAACF;QACpD,IAAIC,YAAYE,OAAO,IAAI;YACzB;QACF;QAEAJ,eAAeK,cAAc,CAACH;IAChC,EAAE,OAAOI,QAAQ;IACf,iEAAiE;IACjE,kEAAkE;IAClE,kEAAkE;IACpE;AACF,EAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CollectionConfig, GlobalConfig } from 'payload';
|
|
2
2
|
interface UpdateFieldsConfig {
|
|
3
|
-
schemaPathMap: Record<string,
|
|
3
|
+
schemaPathMap: Record<string, any>;
|
|
4
4
|
updatedCollectionConfig: CollectionConfig | GlobalConfig;
|
|
5
5
|
}
|
|
6
6
|
export declare const updateFieldsConfig: (collectionConfig: CollectionConfig | GlobalConfig) => UpdateFieldsConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/updateFieldsConfig.ts"],"sourcesContent":["import type { CollectionConfig, GlobalConfig } from 'payload'\n\ninterface UpdateFieldsConfig {\n schemaPathMap: Record<string,
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/updateFieldsConfig.ts"],"sourcesContent":["import type { CollectionConfig, GlobalConfig } from 'payload'\n\ninterface UpdateFieldsConfig {\n schemaPathMap: Record<string, any>\n updatedCollectionConfig: CollectionConfig | GlobalConfig\n}\n\nexport const updateFieldsConfig = (collectionConfig: CollectionConfig | GlobalConfig): UpdateFieldsConfig => {\n let schemaPathMap = {}\n\n function updateField(field: any, parentPath = ''): any {\n const currentPath = parentPath ? `${parentPath}.${field.name}` : field.name\n const currentSchemaPath = `${collectionConfig.slug}.${currentPath}`\n\n // Disabled fields/ field types\n if (\n field.admin?.disabled ||\n field.admin?.readOnly ||\n field.admin?.hidden ||\n field.type === 'row'\n ) {\n return field\n }\n\n // Map field path for global fieldInstructionsMap to load related instructions\n // This is done due to save extra API call to get instructions when Field components are loaded in admin\n // Doing is will only call instructions data when user clicks on settings\n if (['array', 'richText', 'text', 'textarea', 'upload'].includes(field.type)) {\n schemaPathMap = {\n ...schemaPathMap,\n [currentSchemaPath]: {\n type: field.type,\n custom: field.custom,\n label: field.label || field.name,\n relationTo: field.relationTo,\n },\n }\n }\n\n // Inject AI actions, richText is not included here as it has to be explicitly defined by user\n // Array fields also get AI injection for bulk generation\n if (['array', 'text', 'textarea', 'upload'].includes(field.type)) {\n let customField = {}\n\n // Custom fields don't fully adhere to the Payload schema, making it difficult to\n // determine which components support injecting ComposeField as a Description.\n if (field.admin?.components?.Field || field.admin?.components?.Description) {\n // TODO: If a field already provides its own Description, we still inject our ComposeField\n // by overriding Description. If you need both, consider composing your own wrapper.\n customField = {}\n }\n\n // Array fields use ArrayComposeField (always visible) since they don't have focus events\n // Other fields use ComposeField with focus-dependent visibility\n const componentPath = field.type === 'array'\n ? '@ai-stack/payloadcms/fields#ArrayComposeField'\n : '@ai-stack/payloadcms/fields#ComposeField'\n\n return {\n ...field,\n admin: {\n ...field.admin,\n components: {\n ...(field.admin?.components || {}),\n Description: {\n clientProps: {\n schemaPath: currentSchemaPath,\n },\n path: componentPath,\n },\n ...customField,\n },\n },\n }\n }\n\n if (field.fields) {\n return {\n ...field,\n fields: field.fields.map((subField: any) => updateField(subField, currentPath)),\n }\n }\n\n if (field.tabs) {\n return {\n ...field,\n tabs: field.tabs.map((tab: any) => {\n return {\n ...tab,\n // Tabs are a UI construct and should not add to the schema path\n fields: (tab.fields || []).map((subField: any) => updateField(subField, parentPath)),\n }\n }),\n }\n }\n\n if (field.blocks) {\n return {\n ...field,\n blocks: field.blocks.map((block: any) => ({\n ...block,\n fields: block.fields.map((subField: any) =>\n updateField(subField, `${currentPath}.${block.slug}`),\n ),\n })),\n }\n }\n\n return field\n }\n\n const updatedCollectionConfig = {\n ...collectionConfig,\n fields: collectionConfig.fields.map((field) => updateField(field)),\n }\n\n return {\n schemaPathMap,\n updatedCollectionConfig,\n }\n}\n"],"names":["updateFieldsConfig","collectionConfig","schemaPathMap","updateField","field","parentPath","currentPath","name","currentSchemaPath","slug","admin","disabled","readOnly","hidden","type","includes","custom","label","relationTo","customField","components","Field","Description","componentPath","clientProps","schemaPath","path","fields","map","subField","tabs","tab","blocks","block","updatedCollectionConfig"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-stack/payloadcms",
|
|
3
|
-
"version": "3.68.0-beta.
|
|
3
|
+
"version": "3.68.0-beta.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"bugs": "https://github.com/ashbuilds/payload-ai/issues",
|
|
6
6
|
"repository": "https://github.com/ashbuilds/payload-ai",
|
|
@@ -134,6 +134,7 @@
|
|
|
134
134
|
"@payloadcms/translations": "^3.55.1",
|
|
135
135
|
"@payloadcms/ui": "^3.55.1",
|
|
136
136
|
"lexical": "^0.35.0",
|
|
137
|
+
"next": ">=15.0.0",
|
|
137
138
|
"payload": "^3.55.1"
|
|
138
139
|
},
|
|
139
140
|
"engines": {
|
package/dist/init.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { Payload } from 'payload';
|
|
2
|
-
import type { PluginConfig } from './types.js';
|
|
3
|
-
export declare const init: (payload: Payload, fieldSchemaPaths: Record<string, {
|
|
4
|
-
label: string;
|
|
5
|
-
relationTo?: string;
|
|
6
|
-
type: string;
|
|
7
|
-
}>, pluginConfig: PluginConfig) => Promise<void>;
|
package/dist/init.js
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { defaultSeedPrompts } from './ai/prompts.js';
|
|
2
|
-
import { PLUGIN_INSTRUCTIONS_TABLE } from './defaults.js';
|
|
3
|
-
// Defined capabilities mapping for init
|
|
4
|
-
const CAPABILITY_MAP = [
|
|
5
|
-
{
|
|
6
|
-
id: 'text',
|
|
7
|
-
fields: [
|
|
8
|
-
'text',
|
|
9
|
-
'textarea'
|
|
10
|
-
]
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
id: 'richtext',
|
|
14
|
-
fields: [
|
|
15
|
-
'richText'
|
|
16
|
-
]
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
id: 'image',
|
|
20
|
-
fields: [
|
|
21
|
-
'upload'
|
|
22
|
-
]
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
id: 'array',
|
|
26
|
-
fields: [
|
|
27
|
-
'array'
|
|
28
|
-
]
|
|
29
|
-
}
|
|
30
|
-
];
|
|
31
|
-
export const init = async (payload, fieldSchemaPaths, pluginConfig)=>{
|
|
32
|
-
if (!pluginConfig.generatePromptOnInit) {
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
if (pluginConfig.debugging) {
|
|
36
|
-
payload.logger.info(`— AI Plugin: Initializing...`);
|
|
37
|
-
}
|
|
38
|
-
const paths = Object.keys(fieldSchemaPaths);
|
|
39
|
-
// Get all instructions for faster initialization
|
|
40
|
-
const { docs: allInstructions } = await payload.find({
|
|
41
|
-
collection: PLUGIN_INSTRUCTIONS_TABLE,
|
|
42
|
-
depth: 0,
|
|
43
|
-
pagination: false,
|
|
44
|
-
select: {
|
|
45
|
-
'field-type': true,
|
|
46
|
-
'model-id': true,
|
|
47
|
-
'schema-path': true
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
const fieldInstructionsMap = {};
|
|
51
|
-
for(let i = 0; i < paths.length; i++){
|
|
52
|
-
const path = paths[i];
|
|
53
|
-
const { type: fieldType, label: fieldLabel, relationTo } = fieldSchemaPaths[path];
|
|
54
|
-
let instructions = allInstructions.find((entry)=>entry['schema-path'] === path);
|
|
55
|
-
if (!instructions) {
|
|
56
|
-
let seed;
|
|
57
|
-
const seedOptions = {
|
|
58
|
-
fieldLabel,
|
|
59
|
-
fieldSchemaPaths,
|
|
60
|
-
fieldType,
|
|
61
|
-
path
|
|
62
|
-
};
|
|
63
|
-
if (pluginConfig.seedPrompts) {
|
|
64
|
-
seed = await pluginConfig.seedPrompts(seedOptions);
|
|
65
|
-
}
|
|
66
|
-
if (seed === undefined) {
|
|
67
|
-
seed = await defaultSeedPrompts(seedOptions);
|
|
68
|
-
}
|
|
69
|
-
// Field should be ignored
|
|
70
|
-
if (!seed) {
|
|
71
|
-
if (pluginConfig.debugging) {
|
|
72
|
-
payload.logger.info(`— AI Plugin: No seed prompt for ${path}, ignoring...`);
|
|
73
|
-
}
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
// Empty prompt - smart fallback will generate a contextual prompt at runtime
|
|
77
|
-
const generatedPrompt = '';
|
|
78
|
-
if ('prompt' in seed) {
|
|
79
|
-
// Prompt generation currently disabled during migration to AI SDK Providers
|
|
80
|
-
// TODO: Re-enable using a default provider from AI Settings if available
|
|
81
|
-
/*
|
|
82
|
-
generatedPrompt = await systemGenerate(
|
|
83
|
-
{
|
|
84
|
-
prompt: seed.prompt,
|
|
85
|
-
system: seed.system,
|
|
86
|
-
},
|
|
87
|
-
undefined // No generateTextFn currently
|
|
88
|
-
)
|
|
89
|
-
*/ }
|
|
90
|
-
const modelForId = CAPABILITY_MAP.find((a)=>a.fields.includes(fieldType));
|
|
91
|
-
const data = {
|
|
92
|
-
'model-id': modelForId?.id,
|
|
93
|
-
prompt: generatedPrompt,
|
|
94
|
-
...seed.data,
|
|
95
|
-
'field-type': fieldType,
|
|
96
|
-
'relation-to': relationTo,
|
|
97
|
-
'schema-path': path
|
|
98
|
-
};
|
|
99
|
-
payload.logger.info({
|
|
100
|
-
'model-id': data['model-id'],
|
|
101
|
-
prompt: generatedPrompt,
|
|
102
|
-
...seed.data
|
|
103
|
-
}, `Prompt seeded for "${path}" field`);
|
|
104
|
-
instructions = await payload.create({
|
|
105
|
-
collection: PLUGIN_INSTRUCTIONS_TABLE,
|
|
106
|
-
data
|
|
107
|
-
}).catch((err)=>{
|
|
108
|
-
payload.logger.error(err, '— AI Plugin: Error creating Compose settings-');
|
|
109
|
-
});
|
|
110
|
-
if (instructions?.id) {
|
|
111
|
-
fieldInstructionsMap[path] = {
|
|
112
|
-
id: instructions.id,
|
|
113
|
-
fieldType
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
} else {
|
|
117
|
-
const modelForId = CAPABILITY_MAP.find((a)=>a.fields.includes(fieldType));
|
|
118
|
-
if (instructions['field-type'] !== fieldType || !instructions['model-id']) {
|
|
119
|
-
payload.logger.warn(`— AI Plugin: Field config mismatch for ${path}! Updating...`);
|
|
120
|
-
const updateData = {
|
|
121
|
-
'field-type': fieldType
|
|
122
|
-
};
|
|
123
|
-
// Only set model-id if it's missing or we have a better default
|
|
124
|
-
if (!instructions['model-id'] && modelForId?.id) {
|
|
125
|
-
updateData['model-id'] = modelForId.id;
|
|
126
|
-
}
|
|
127
|
-
await payload.update({
|
|
128
|
-
id: instructions.id,
|
|
129
|
-
collection: PLUGIN_INSTRUCTIONS_TABLE,
|
|
130
|
-
data: updateData
|
|
131
|
-
});
|
|
132
|
-
instructions['field-type'] = fieldType;
|
|
133
|
-
if (updateData['model-id']) {
|
|
134
|
-
instructions['model-id'] = updateData['model-id'];
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
fieldInstructionsMap[path] = {
|
|
138
|
-
id: instructions.id,
|
|
139
|
-
fieldType
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (pluginConfig.debugging) {
|
|
144
|
-
payload.logger.info(`— AI Plugin: Enabled fields map: ${JSON.stringify(fieldInstructionsMap, null, 2)}`);
|
|
145
|
-
payload.logger.info(`— AI Plugin: Initialized!`);
|
|
146
|
-
}
|
|
147
|
-
if (pluginConfig.generatePromptOnInit) {
|
|
148
|
-
payload.logger.info('\n\n-AI Plugin: Example prompts are added to get you started, Now go break some code 🚀🚀🚀\n\n');
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
//# sourceMappingURL=init.js.map
|
package/dist/init.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/init.ts"],"sourcesContent":["import type { Payload } from 'payload'\n\nimport type { PluginConfig } from './types.js'\n\nimport { defaultSeedPrompts } from './ai/prompts.js'\nimport { systemGenerate } from './ai/utils/systemGenerate.js'\nimport { PLUGIN_INSTRUCTIONS_TABLE } from './defaults.js'\n\n// Defined capabilities mapping for init\nconst CAPABILITY_MAP = [\n { id: 'text', fields: ['text', 'textarea'] },\n { id: 'richtext', fields: ['richText'] },\n { id: 'image', fields: ['upload'] },\n { id: 'array', fields: ['array'] },\n // TTS usually outputs to upload, but init logic maps field types to capabilities\n]\n\nexport const init = async (\n payload: Payload,\n fieldSchemaPaths: Record<string, { label: string; relationTo?: string; type: string }>,\n pluginConfig: PluginConfig,\n) => {\n if (!pluginConfig.generatePromptOnInit) {\n return\n }\n\n if (pluginConfig.debugging) {\n payload.logger.info(`— AI Plugin: Initializing...`)\n }\n\n const paths = Object.keys(fieldSchemaPaths)\n\n // Get all instructions for faster initialization\n const { docs: allInstructions } = await payload.find({\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n depth: 0,\n pagination: false,\n select: {\n 'field-type': true,\n 'model-id': true,\n 'schema-path': true,\n },\n })\n\n const fieldInstructionsMap: Record<string, { fieldType: any; id: any }> = {}\n\n for (let i = 0; i < paths.length; i++) {\n const path = paths[i]\n const { type: fieldType, label: fieldLabel, relationTo } = fieldSchemaPaths[path]\n let instructions = allInstructions.find((entry) => entry['schema-path'] === path)\n\n if (!instructions) {\n let seed\n const seedOptions = {\n fieldLabel,\n fieldSchemaPaths,\n fieldType,\n path,\n }\n\n if (pluginConfig.seedPrompts) {seed = await pluginConfig.seedPrompts(seedOptions)}\n if (seed === undefined) {seed = await defaultSeedPrompts(seedOptions)}\n // Field should be ignored\n if (!seed) {\n if (pluginConfig.debugging) {\n payload.logger.info(`— AI Plugin: No seed prompt for ${path}, ignoring...`)\n }\n continue\n }\n\n // Empty prompt - smart fallback will generate a contextual prompt at runtime\n const generatedPrompt: string | undefined = ''\n if ('prompt' in seed) {\n // Prompt generation currently disabled during migration to AI SDK Providers\n // TODO: Re-enable using a default provider from AI Settings if available\n /*\n generatedPrompt = await systemGenerate(\n {\n prompt: seed.prompt,\n system: seed.system,\n },\n undefined // No generateTextFn currently\n )\n */\n }\n\n const modelForId = CAPABILITY_MAP.find((a) => a.fields.includes(fieldType))\n\n const data = {\n 'model-id': modelForId?.id,\n prompt: generatedPrompt,\n ...seed.data, // allow to override data, but not the one below\n 'field-type': fieldType,\n 'relation-to': relationTo,\n 'schema-path': path,\n }\n\n payload.logger.info(\n {\n 'model-id': data['model-id'],\n prompt: generatedPrompt,\n ...seed.data,\n },\n `Prompt seeded for \"${path}\" field`,\n )\n\n instructions = (await payload\n .create({\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n data,\n })\n .catch((err) => {\n payload.logger.error(err, '— AI Plugin: Error creating Compose settings-')\n })) as (typeof allInstructions)[0]\n\n if (instructions?.id) {\n fieldInstructionsMap[path] = {\n id: instructions.id,\n fieldType,\n }\n }\n } else {\n const modelForId = CAPABILITY_MAP.find((a) => a.fields.includes(fieldType))\n\n if (instructions['field-type'] !== fieldType || !instructions['model-id']) {\n payload.logger.warn(\n `— AI Plugin: Field config mismatch for ${path}! Updating...`,\n )\n const updateData: any = {\n 'field-type': fieldType,\n }\n \n // Only set model-id if it's missing or we have a better default\n if (!instructions['model-id'] && modelForId?.id) {\n updateData['model-id'] = modelForId.id\n }\n \n await payload.update({\n id: instructions.id,\n collection: PLUGIN_INSTRUCTIONS_TABLE,\n data: updateData,\n })\n instructions['field-type'] = fieldType\n if (updateData['model-id']) {\n instructions['model-id'] = updateData['model-id']\n }\n }\n\n fieldInstructionsMap[path] = {\n id: instructions.id,\n fieldType,\n }\n }\n }\n\n if (pluginConfig.debugging) {\n payload.logger.info(\n `— AI Plugin: Enabled fields map: ${JSON.stringify(fieldInstructionsMap, null, 2)}`,\n )\n payload.logger.info(`— AI Plugin: Initialized!`)\n }\n\n if (pluginConfig.generatePromptOnInit) {\n payload.logger.info(\n '\\n\\n-AI Plugin: Example prompts are added to get you started, Now go break some code 🚀🚀🚀\\n\\n',\n )\n }\n}\n"],"names":["defaultSeedPrompts","PLUGIN_INSTRUCTIONS_TABLE","CAPABILITY_MAP","id","fields","init","payload","fieldSchemaPaths","pluginConfig","generatePromptOnInit","debugging","logger","info","paths","Object","keys","docs","allInstructions","find","collection","depth","pagination","select","fieldInstructionsMap","i","length","path","type","fieldType","label","fieldLabel","relationTo","instructions","entry","seed","seedOptions","seedPrompts","undefined","generatedPrompt","modelForId","a","includes","data","prompt","create","catch","err","error","warn","updateData","update","JSON","stringify"],"mappings":"AAIA,SAASA,kBAAkB,QAAQ,kBAAiB;AAEpD,SAASC,yBAAyB,QAAQ,gBAAe;AAEzD,wCAAwC;AACxC,MAAMC,iBAAiB;IACrB;QAAEC,IAAI;QAAQC,QAAQ;YAAC;YAAQ;SAAW;IAAC;IAC3C;QAAED,IAAI;QAAYC,QAAQ;YAAC;SAAW;IAAC;IACvC;QAAED,IAAI;QAASC,QAAQ;YAAC;SAAS;IAAC;IAClC;QAAED,IAAI;QAASC,QAAQ;YAAC;SAAQ;IAAC;CAElC;AAED,OAAO,MAAMC,OAAO,OAClBC,SACAC,kBACAC;IAEA,IAAI,CAACA,aAAaC,oBAAoB,EAAE;QACtC;IACF;IAEA,IAAID,aAAaE,SAAS,EAAE;QAC1BJ,QAAQK,MAAM,CAACC,IAAI,CAAC,CAAC,4BAA4B,CAAC;IACpD;IAEA,MAAMC,QAAQC,OAAOC,IAAI,CAACR;IAE1B,iDAAiD;IACjD,MAAM,EAAES,MAAMC,eAAe,EAAE,GAAG,MAAMX,QAAQY,IAAI,CAAC;QACnDC,YAAYlB;QACZmB,OAAO;QACPC,YAAY;QACZC,QAAQ;YACN,cAAc;YACd,YAAY;YACZ,eAAe;QACjB;IACF;IAEA,MAAMC,uBAAoE,CAAC;IAE3E,IAAK,IAAIC,IAAI,GAAGA,IAAIX,MAAMY,MAAM,EAAED,IAAK;QACrC,MAAME,OAAOb,KAAK,CAACW,EAAE;QACrB,MAAM,EAAEG,MAAMC,SAAS,EAAEC,OAAOC,UAAU,EAAEC,UAAU,EAAE,GAAGxB,gBAAgB,CAACmB,KAAK;QACjF,IAAIM,eAAef,gBAAgBC,IAAI,CAAC,CAACe,QAAUA,KAAK,CAAC,cAAc,KAAKP;QAE5E,IAAI,CAACM,cAAc;YACjB,IAAIE;YACJ,MAAMC,cAAc;gBAClBL;gBACAvB;gBACAqB;gBACAF;YACF;YAEA,IAAIlB,aAAa4B,WAAW,EAAE;gBAACF,OAAO,MAAM1B,aAAa4B,WAAW,CAACD;YAAY;YACjF,IAAID,SAASG,WAAW;gBAACH,OAAO,MAAMlC,mBAAmBmC;YAAY;YACrE,0BAA0B;YAC1B,IAAI,CAACD,MAAM;gBACT,IAAI1B,aAAaE,SAAS,EAAE;oBAC1BJ,QAAQK,MAAM,CAACC,IAAI,CAAC,CAAC,gCAAgC,EAAEc,KAAK,aAAa,CAAC;gBAC5E;gBACA;YACF;YAEA,6EAA6E;YAC7E,MAAMY,kBAAsC;YAC5C,IAAI,YAAYJ,MAAM;YACpB,4EAA4E;YAC5E,yEAAyE;YACzE;;;;;;;;QAQA,GACF;YAEA,MAAMK,aAAarC,eAAegB,IAAI,CAAC,CAACsB,IAAMA,EAAEpC,MAAM,CAACqC,QAAQ,CAACb;YAEhE,MAAMc,OAAO;gBACX,YAAYH,YAAYpC;gBACxBwC,QAAQL;gBACR,GAAGJ,KAAKQ,IAAI;gBACZ,cAAcd;gBACd,eAAeG;gBACf,eAAeL;YACjB;YAEApB,QAAQK,MAAM,CAACC,IAAI,CACjB;gBACE,YAAY8B,IAAI,CAAC,WAAW;gBAC5BC,QAAQL;gBACR,GAAGJ,KAAKQ,IAAI;YACd,GACA,CAAC,mBAAmB,EAAEhB,KAAK,OAAO,CAAC;YAGrCM,eAAgB,MAAM1B,QACnBsC,MAAM,CAAC;gBACNzB,YAAYlB;gBACZyC;YACF,GACCG,KAAK,CAAC,CAACC;gBACNxC,QAAQK,MAAM,CAACoC,KAAK,CAACD,KAAK;YAC5B;YAEF,IAAId,cAAc7B,IAAI;gBACpBoB,oBAAoB,CAACG,KAAK,GAAG;oBAC3BvB,IAAI6B,aAAa7B,EAAE;oBACnByB;gBACF;YACF;QACF,OAAO;YACL,MAAMW,aAAarC,eAAegB,IAAI,CAAC,CAACsB,IAAMA,EAAEpC,MAAM,CAACqC,QAAQ,CAACb;YAEhE,IAAII,YAAY,CAAC,aAAa,KAAKJ,aAAa,CAACI,YAAY,CAAC,WAAW,EAAE;gBACzE1B,QAAQK,MAAM,CAACqC,IAAI,CACjB,CAAC,uCAAuC,EAAEtB,KAAK,aAAa,CAAC;gBAE/D,MAAMuB,aAAkB;oBACrB,cAAcrB;gBACjB;gBAEA,gEAAgE;gBAChE,IAAI,CAACI,YAAY,CAAC,WAAW,IAAIO,YAAYpC,IAAI;oBAC9C8C,UAAU,CAAC,WAAW,GAAGV,WAAWpC,EAAE;gBACzC;gBAEA,MAAMG,QAAQ4C,MAAM,CAAC;oBACnB/C,IAAI6B,aAAa7B,EAAE;oBACnBgB,YAAYlB;oBACZyC,MAAMO;gBACR;gBACAjB,YAAY,CAAC,aAAa,GAAGJ;gBAC7B,IAAIqB,UAAU,CAAC,WAAW,EAAE;oBAC1BjB,YAAY,CAAC,WAAW,GAAGiB,UAAU,CAAC,WAAW;gBACnD;YACF;YAEA1B,oBAAoB,CAACG,KAAK,GAAG;gBAC3BvB,IAAI6B,aAAa7B,EAAE;gBACnByB;YACF;QACF;IACF;IAEA,IAAIpB,aAAaE,SAAS,EAAE;QAC1BJ,QAAQK,MAAM,CAACC,IAAI,CACjB,CAAC,iCAAiC,EAAEuC,KAAKC,SAAS,CAAC7B,sBAAsB,MAAM,GAAG,CAAC;QAErFjB,QAAQK,MAAM,CAACC,IAAI,CAAC,CAAC,yBAAyB,CAAC;IACjD;IAEA,IAAIJ,aAAaC,oBAAoB,EAAE;QACrCH,QAAQK,MAAM,CAACC,IAAI,CACjB;IAEJ;AACF,EAAC"}
|