@ai-stack/payloadcms 3.68.0 → 3.76.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/core/media/image/generateImage.js +2 -6
- package/dist/ai/core/media/image/generateImage.js.map +1 -1
- package/dist/ai/core/media/image/handlers/multimodal.js +13 -28
- package/dist/ai/core/media/image/handlers/multimodal.js.map +1 -1
- package/dist/ai/core/media/image/handlers/standard.js +10 -7
- package/dist/ai/core/media/image/handlers/standard.js.map +1 -1
- package/dist/ai/core/media/speech/generateSpeech.js +8 -8
- package/dist/ai/core/media/speech/generateSpeech.js.map +1 -1
- package/dist/ai/core/media/types.d.ts +1 -1
- package/dist/ai/core/media/types.js.map +1 -1
- package/dist/ai/core/streamObject.js +3 -3
- package/dist/ai/core/streamObject.js.map +1 -1
- package/dist/ai/core/types.d.ts +3 -0
- package/dist/ai/core/types.js.map +1 -1
- package/dist/ai/prompts.d.ts +1 -2
- package/dist/ai/prompts.js +0 -110
- package/dist/ai/prompts.js.map +1 -1
- package/dist/ai/providers/blocks/anthropic.js +2 -1
- package/dist/ai/providers/blocks/anthropic.js.map +1 -1
- package/dist/ai/providers/blocks/elevenlabs.js +3 -2
- package/dist/ai/providers/blocks/elevenlabs.js.map +1 -1
- package/dist/ai/providers/blocks/fal.js +2 -1
- package/dist/ai/providers/blocks/fal.js.map +1 -1
- package/dist/ai/providers/blocks/google.js +12 -6
- package/dist/ai/providers/blocks/google.js.map +1 -1
- package/dist/ai/providers/blocks/openai-compatible.js +2 -1
- package/dist/ai/providers/blocks/openai-compatible.js.map +1 -1
- package/dist/ai/providers/blocks/openai.js +3 -2
- package/dist/ai/providers/blocks/openai.js.map +1 -1
- package/dist/ai/providers/blocks/xai.js +2 -1
- package/dist/ai/providers/blocks/xai.js.map +1 -1
- package/dist/ai/providers/icons.d.ts +7 -0
- package/dist/ai/providers/icons.js +9 -0
- package/dist/ai/providers/icons.js.map +1 -0
- package/dist/ai/providers/registry.js +36 -26
- package/dist/ai/providers/registry.js.map +1 -1
- package/dist/ai/utils/filterEditorSchemaByNodes.d.ts +9 -0
- package/dist/ai/utils/filterEditorSchemaByNodes.js +30 -3
- package/dist/ai/utils/filterEditorSchemaByNodes.js.map +1 -1
- package/dist/ai/utils/nodeToSchemaMap.d.ts +22 -0
- package/dist/ai/utils/nodeToSchemaMap.js +72 -0
- package/dist/ai/utils/nodeToSchemaMap.js.map +1 -0
- package/dist/collections/AIJobs.js +1 -1
- package/dist/collections/AIJobs.js.map +1 -1
- package/dist/collections/AIProviders.d.ts +2 -0
- package/dist/collections/{AISettings.js → AIProviders.js} +53 -25
- package/dist/collections/AIProviders.js.map +1 -0
- package/dist/collections/Instructions.js +45 -4
- package/dist/collections/Instructions.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/chat.d.ts +4 -0
- package/dist/endpoints/fetchFields.js +10 -0
- package/dist/endpoints/fetchFields.js.map +1 -1
- package/dist/endpoints/fetchVoices.js +42 -25
- package/dist/endpoints/fetchVoices.js.map +1 -1
- package/dist/endpoints/index.js +248 -35
- package/dist/endpoints/index.js.map +1 -1
- package/dist/exports/client.d.ts +1 -1
- package/dist/exports/client.js +1 -1
- package/dist/exports/client.js.map +1 -1
- package/dist/exports/fields.d.ts +1 -0
- package/dist/exports/fields.js +1 -0
- package/dist/exports/fields.js.map +1 -1
- package/dist/fields/ArrayComposeField/ArrayComposeField.d.ts +15 -0
- package/dist/fields/ArrayComposeField/ArrayComposeField.js +87 -0
- package/dist/fields/ArrayComposeField/ArrayComposeField.js.map +1 -0
- package/dist/fields/ArrayComposeField/ArrayComposeField.jsx +73 -0
- package/dist/fields/PromptEditorField/PromptEditorField.js +7 -2
- package/dist/fields/PromptEditorField/PromptEditorField.js.map +1 -1
- package/dist/fields/PromptEditorField/PromptEditorField.jsx +5 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/payload-ai.d.ts +152 -0
- package/dist/plugin.js +18 -34
- package/dist/plugin.js.map +1 -1
- package/dist/providers/InstructionsProvider/InstructionsProvider.js +47 -15
- package/dist/providers/InstructionsProvider/InstructionsProvider.js.map +1 -1
- package/dist/providers/InstructionsProvider/InstructionsProvider.jsx +39 -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 +22 -3
- package/dist/providers/InstructionsProvider/useInstructions.js.map +1 -1
- package/dist/styles.d.ts +11 -0
- package/dist/types/handlebars-async-helpers.d.ts +1 -0
- package/dist/types/handlebars-dist-handlebars.d.ts +1 -0
- package/dist/types/react-mentions.d.ts +1 -0
- package/dist/types.d.ts +36 -7
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/dist/ui/AIConfigDashboard/index.d.ts +1 -1
- package/dist/ui/AIConfigDashboard/index.js +201 -23
- package/dist/ui/AIConfigDashboard/index.js.map +1 -1
- package/dist/ui/AIConfigDashboard/index.jsx +166 -15
- package/dist/ui/Compose/Compose.d.ts +1 -0
- package/dist/ui/Compose/Compose.js +23 -4
- package/dist/ui/Compose/Compose.js.map +1 -1
- package/dist/ui/Compose/Compose.jsx +23 -4
- package/dist/ui/Compose/UndoRedoActions.d.ts +2 -2
- package/dist/ui/Compose/UndoRedoActions.js +8 -5
- package/dist/ui/Compose/UndoRedoActions.js.map +1 -1
- package/dist/ui/Compose/UndoRedoActions.jsx +6 -5
- package/dist/ui/Compose/compose.module.css +56 -16
- package/dist/ui/Compose/hooks/menu/TranslateMenu.d.ts +5 -0
- package/dist/ui/Compose/hooks/menu/TranslateMenu.js +45 -4
- package/dist/ui/Compose/hooks/menu/TranslateMenu.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/TranslateMenu.jsx +41 -5
- package/dist/ui/Compose/hooks/menu/itemsMap.js +12 -6
- package/dist/ui/Compose/hooks/menu/itemsMap.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/menu.module.scss +4 -1
- package/dist/ui/Compose/hooks/menu/useMenu.js +26 -15
- package/dist/ui/Compose/hooks/menu/useMenu.js.map +1 -1
- package/dist/ui/Compose/hooks/menu/useMenu.jsx +25 -12
- package/dist/ui/Compose/hooks/useActiveFieldTracking.js +34 -0
- package/dist/ui/Compose/hooks/useActiveFieldTracking.js.map +1 -1
- package/dist/ui/Compose/hooks/useGenerate.js +26 -174
- 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 +156 -0
- package/dist/ui/Compose/hooks/useGenerateUpload.js.map +1 -0
- package/dist/ui/Compose/hooks/useHistory.d.ts +0 -1
- package/dist/ui/Compose/hooks/useHistory.js +65 -25
- package/dist/ui/Compose/hooks/useHistory.js.map +1 -1
- 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/ConfigDashboard/index.d.ts +2 -0
- package/dist/ui/ConfigDashboard/index.js +224 -0
- package/dist/ui/ConfigDashboard/index.js.map +1 -0
- package/dist/ui/ConfigDashboard/index.jsx +175 -0
- package/dist/ui/DynamicModelSelect/index.js +1 -1
- package/dist/ui/DynamicModelSelect/index.js.map +1 -1
- package/dist/ui/DynamicModelSelect/index.jsx +1 -1
- package/dist/ui/DynamicProviderSelect/index.js +1 -1
- package/dist/ui/DynamicProviderSelect/index.js.map +1 -1
- package/dist/ui/DynamicProviderSelect/index.jsx +1 -1
- package/dist/ui/DynamicVoiceSelect/index.js +63 -11
- package/dist/ui/DynamicVoiceSelect/index.js.map +1 -1
- package/dist/ui/DynamicVoiceSelect/index.jsx +47 -14
- 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/ui/ProviderOptionsEditor/index.js +1 -1
- package/dist/ui/ProviderOptionsEditor/index.js.map +1 -1
- package/dist/ui/ProviderOptionsEditor/index.jsx +1 -1
- package/dist/ui/VoicesFetcher/index.js +34 -16
- package/dist/ui/VoicesFetcher/index.js.map +1 -1
- package/dist/ui/VoicesFetcher/index.jsx +32 -15
- package/dist/utilities/buildSmartPrompt.d.ts +22 -0
- package/dist/utilities/buildSmartPrompt.js +141 -0
- package/dist/utilities/buildSmartPrompt.js.map +1 -0
- package/dist/utilities/encryption.js +2 -1
- package/dist/utilities/encryption.js.map +1 -1
- package/dist/utilities/fieldToJsonSchema.js +32 -3
- package/dist/utilities/fieldToJsonSchema.js.map +1 -1
- package/dist/utilities/resolveImageReferences.d.ts +3 -1
- package/dist/utilities/resolveImageReferences.js +21 -2
- package/dist/utilities/resolveImageReferences.js.map +1 -1
- package/dist/utilities/seedProperties.d.ts +7 -0
- package/dist/utilities/seedProperties.js +100 -0
- package/dist/utilities/seedProperties.js.map +1 -0
- package/dist/utilities/setSafeLexicalState.js +79 -6
- package/dist/utilities/setSafeLexicalState.js.map +1 -1
- package/dist/utilities/updateFieldsConfig.d.ts +1 -1
- package/dist/utilities/updateFieldsConfig.js +9 -2
- package/dist/utilities/updateFieldsConfig.js.map +1 -1
- package/package.json +35 -33
- package/dist/collections/AISettings.d.ts +0 -2
- package/dist/collections/AISettings.js.map +0 -1
- package/dist/endpoints/chat.d.js +0 -3
- package/dist/endpoints/chat.d.js.map +0 -1
- package/dist/init.d.ts +0 -7
- package/dist/init.js +0 -135
- package/dist/init.js.map +0 -1
- package/dist/payload-ai.d.js +0 -3
- package/dist/payload-ai.d.js.map +0 -1
- package/dist/styles.d.js +0 -2
- package/dist/styles.d.js.map +0 -1
- package/dist/types/handlebars-async-helpers.d.js +0 -2
- package/dist/types/handlebars-async-helpers.d.js.map +0 -1
- package/dist/types/handlebars-dist-handlebars.d.js +0 -2
- package/dist/types/handlebars-dist-handlebars.d.js.map +0 -1
- package/dist/types/react-mentions.d.js +0 -2
- package/dist/types/react-mentions.d.js.map +0 -1
|
@@ -1,14 +1,29 @@
|
|
|
1
|
-
import { InstructionsContext } from '@ai-stack/payloadcms/client';
|
|
2
1
|
import { useDocumentInfo } from '@payloadcms/ui';
|
|
3
2
|
import { useContext, useEffect, useMemo, useState } from 'react';
|
|
4
3
|
import { PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js';
|
|
5
4
|
import { handlebarsHelpers, handlebarsHelpersMap } from '../../libraries/handlebars/helpersMap.js';
|
|
5
|
+
import { InstructionsContext } from './context.js';
|
|
6
|
+
/**
|
|
7
|
+
* Normalize a schema path by removing array indices.
|
|
8
|
+
* This allows fields inside arrays to match their instruction records.
|
|
9
|
+
*
|
|
10
|
+
* Example:
|
|
11
|
+
* 'array-test-cases.keywords.0.keyword' -> 'array-test-cases.keywords.keyword'
|
|
12
|
+
* 'characters.views.2.description' -> 'characters.views.description'
|
|
13
|
+
* 'posts.title' -> 'posts.title' (no change)
|
|
14
|
+
*/ const normalizeSchemaPath = (path)=>{
|
|
15
|
+
if (!path) {
|
|
16
|
+
return path;
|
|
17
|
+
}
|
|
18
|
+
// Remove numeric path segments (array indices) and new Lexical _index- based keys
|
|
19
|
+
return path.split('.').filter((segment)=>!/^\d+$/.test(segment) && !segment.startsWith('_index-')).join('.');
|
|
20
|
+
};
|
|
6
21
|
const warnedOnceOnNoInstructionId = new Set();
|
|
7
22
|
const warnOnceOnMissingInstructions = (path)=>{
|
|
8
23
|
if (!warnedOnceOnNoInstructionId.has(path)) {
|
|
9
24
|
warnedOnceOnNoInstructionId.add(path);
|
|
10
25
|
// eslint-disable-next-line no-console
|
|
11
|
-
console.info(`[AI Plugin] There are no AI instructions for this field: ${path}
|
|
26
|
+
console.info(`[AI Plugin] There are no AI instructions for this field: ${path}.`);
|
|
12
27
|
}
|
|
13
28
|
};
|
|
14
29
|
export const useInstructions = (update = {})=>{
|
|
@@ -91,13 +106,17 @@ export const useInstructions = (update = {})=>{
|
|
|
91
106
|
instructions,
|
|
92
107
|
promptFields
|
|
93
108
|
]);
|
|
94
|
-
|
|
109
|
+
// Normalize the schema path to handle array indices
|
|
110
|
+
const normalizedSchemaPath = normalizeSchemaPath(schemaPath);
|
|
111
|
+
const pathInstructions = instructions[normalizedSchemaPath];
|
|
95
112
|
if (debugging && !pathInstructions && schemaPath && hasInstructions) {
|
|
96
113
|
warnOnceOnMissingInstructions(schemaPath);
|
|
97
114
|
}
|
|
115
|
+
const isCollectionEnabled = context.enabledCollections?.includes(collectionSlug || activeCollection || '') ?? false;
|
|
98
116
|
return {
|
|
99
117
|
...context,
|
|
100
118
|
...pathInstructions || {},
|
|
119
|
+
disabled: !isCollectionEnabled || (pathInstructions?.disabled ?? false),
|
|
101
120
|
promptEditorSuggestions
|
|
102
121
|
};
|
|
103
122
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/InstructionsProvider/useInstructions.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/InstructionsProvider/useInstructions.ts"],"sourcesContent":["import { useDocumentInfo } from '@payloadcms/ui'\nimport { useContext, useEffect, useMemo, useState } from 'react'\n\nimport { PLUGIN_INSTRUCTIONS_TABLE } from '../../defaults.js'\nimport { handlebarsHelpers, handlebarsHelpersMap } from '../../libraries/handlebars/helpersMap.js'\nimport { InstructionsContext } from './context.js'\n\n/**\n * Normalize a schema path by removing array indices.\n * This allows fields inside arrays to match their instruction records.\n * \n * Example:\n * 'array-test-cases.keywords.0.keyword' -> 'array-test-cases.keywords.keyword'\n * 'characters.views.2.description' -> 'characters.views.description'\n * 'posts.title' -> 'posts.title' (no change)\n */\nconst normalizeSchemaPath = (path: string): string => {\n if (!path) {\n return path\n }\n // Remove numeric path segments (array indices) and new Lexical _index- based keys\n return path\n .split('.')\n .filter((segment) => !/^\\d+$/.test(segment) && !segment.startsWith('_index-'))\n .join('.')\n}\n\nconst warnedOnceOnNoInstructionId = new Set<string>()\nconst warnOnceOnMissingInstructions = (path: string) => {\n if (!warnedOnceOnNoInstructionId.has(path)) {\n warnedOnceOnNoInstructionId.add(path)\n // eslint-disable-next-line no-console\n console.info(`[AI Plugin] There are no AI instructions for this field: ${path}.`)\n }\n}\n\nexport const useInstructions = (\n update: {\n schemaPath?: unknown\n } = {},\n) => {\n const context = useContext(InstructionsContext)\n const { collectionSlug } = useDocumentInfo()\n const { activeCollection, debugging, hasInstructions, instructions, promptFields, setActiveCollection } = context\n\n const [schemaPath, setSchemaPath] = useState(update.schemaPath as string)\n\n useEffect(() => {\n if (update.schemaPath !== schemaPath) {\n setSchemaPath((update.schemaPath as string) ?? '')\n }\n }, [update.schemaPath, schemaPath])\n\n useEffect(() => {\n if (\n activeCollection !== collectionSlug &&\n collectionSlug !== PLUGIN_INSTRUCTIONS_TABLE &&\n typeof setActiveCollection === 'function'\n ) {\n setActiveCollection(collectionSlug ?? '')\n }\n }, [activeCollection, collectionSlug, setActiveCollection])\n\n const groupedFields = useMemo(() => {\n const result: Record<string, string[]> = {}\n\n for (const fullKey of Object.keys(instructions || {})) {\n const [collection, ...pathParts] = fullKey.split('.')\n const path = pathParts.join('.')\n if (!result[collection]) {\n result[collection] = []\n }\n result[collection].push(path)\n }\n\n return result\n }, [instructions])\n\n // Suggestions for prompt editor\n const promptEditorSuggestions = useMemo(() => {\n const activeFields = groupedFields[activeCollection as string] || []\n const suggestions: string[] = []\n\n // Build instruction lookup map once for O(1) access instead of O(n) search per field\n const instructionLookup = new Map(\n Object.entries(instructions).map(([key, value]) => {\n const path = key.split('.').slice(1).join('.')\n return [path, value]\n })\n )\n\n activeFields.forEach((f) => {\n const fieldInfo = instructionLookup.get(f)\n\n if (!fieldInfo) {return}\n\n if (fieldInfo.fieldType === 'upload') {\n return\n }\n\n const helpers = handlebarsHelpers.filter(\n (h) => (handlebarsHelpersMap as Record<string, { field?: string }>)[h]?.field === fieldInfo.fieldType,\n )\n\n if (helpers.length) {\n for (const helper of helpers) {\n suggestions.push(`${helper} ${f}`)\n }\n } else {\n suggestions.push(f)\n }\n })\n\n promptFields.forEach(({ name, collections }) => {\n if (!activeCollection) {return}\n\n if (!collections || collections.includes(activeCollection)) {\n suggestions.push(name)\n }\n })\n\n return suggestions\n }, [groupedFields, activeCollection, instructions, promptFields])\n\n // Normalize the schema path to handle array indices\n const normalizedSchemaPath = normalizeSchemaPath(schemaPath)\n const pathInstructions = instructions[normalizedSchemaPath]\n\n if (debugging && !pathInstructions && schemaPath && hasInstructions) {\n warnOnceOnMissingInstructions(schemaPath)\n }\n\n const isCollectionEnabled = context.enabledCollections?.includes(collectionSlug || activeCollection || '') ?? false\n\n return {\n ...context,\n ...(pathInstructions || {}),\n disabled: !isCollectionEnabled || (pathInstructions?.disabled ?? false),\n promptEditorSuggestions,\n }\n}\n\n"],"names":["useDocumentInfo","useContext","useEffect","useMemo","useState","PLUGIN_INSTRUCTIONS_TABLE","handlebarsHelpers","handlebarsHelpersMap","InstructionsContext","normalizeSchemaPath","path","split","filter","segment","test","startsWith","join","warnedOnceOnNoInstructionId","Set","warnOnceOnMissingInstructions","has","add","console","info","useInstructions","update","context","collectionSlug","activeCollection","debugging","hasInstructions","instructions","promptFields","setActiveCollection","schemaPath","setSchemaPath","groupedFields","result","fullKey","Object","keys","collection","pathParts","push","promptEditorSuggestions","activeFields","suggestions","instructionLookup","Map","entries","map","key","value","slice","forEach","f","fieldInfo","get","fieldType","helpers","h","field","length","helper","name","collections","includes","normalizedSchemaPath","pathInstructions","isCollectionEnabled","enabledCollections","disabled"],"mappings":"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"}
|
package/dist/styles.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module 'handlebars-async-helpers'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module 'handlebars/dist/handlebars.js'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module 'react-mentions/dist/react-mentions.cjs.js'
|
package/dist/types.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import type { GenerateObjectResult, ModelMessage } from 'ai';
|
|
1
2
|
import type { JSONSchema } from 'openai/lib/jsonschema';
|
|
2
3
|
import type { ImageGenerateParams } from 'openai/resources/images';
|
|
3
4
|
import type { CollectionConfig, CollectionSlug, DataFromCollectionSlug, Endpoint, Field, File, GlobalConfig, GroupField, PayloadRequest, TypedCollection } from 'payload';
|
|
4
5
|
import type { CSSProperties, MouseEventHandler } from 'react';
|
|
5
6
|
import type { MediaResult } from './ai/core/index.js';
|
|
6
|
-
import type { PLUGIN_INSTRUCTIONS_TABLE } from
|
|
7
|
+
import type { PLUGIN_INSTRUCTIONS_TABLE } from './defaults.js';
|
|
7
8
|
export interface PluginConfigAccess {
|
|
8
9
|
/**
|
|
9
10
|
* Control access to AI generation features (generate text, images, audio)
|
|
@@ -39,16 +40,12 @@ export interface PluginConfig {
|
|
|
39
40
|
* By default, all AI features require authentication
|
|
40
41
|
*/
|
|
41
42
|
access?: PluginConfigAccess;
|
|
42
|
-
collections: {
|
|
43
|
-
[key: CollectionSlug]: boolean;
|
|
44
|
-
};
|
|
45
43
|
debugging?: boolean;
|
|
46
44
|
disableSponsorMessage?: boolean;
|
|
47
45
|
editorConfig?: {
|
|
48
46
|
nodes: JSONSchema[];
|
|
49
47
|
};
|
|
50
48
|
fields?: Field[];
|
|
51
|
-
generatePromptOnInit?: boolean;
|
|
52
49
|
generationModels?: ((defaultModels: GenerationModel[]) => GenerationModel[]) | GenerationModel[];
|
|
53
50
|
globals?: {
|
|
54
51
|
[key: GlobalConfig['slug']]: boolean;
|
|
@@ -66,8 +63,7 @@ export interface PluginConfig {
|
|
|
66
63
|
prompts?: ActionPrompt[];
|
|
67
64
|
/**
|
|
68
65
|
* Custom seed prompt function for generating field-specific prompts
|
|
69
|
-
* If not provided,
|
|
70
|
-
* You can access default seed prompts by importing { defaultSeedPrompts } from '@ai-stack/payloadcms'
|
|
66
|
+
* If not provided, fields will have empty prompts by default
|
|
71
67
|
*/
|
|
72
68
|
seedPrompts?: SeedPromptFunction;
|
|
73
69
|
uploadCollectionSlug?: CollectionSlug;
|
|
@@ -135,6 +131,7 @@ export type UseMenuOptions = {
|
|
|
135
131
|
};
|
|
136
132
|
export type BaseItemProps<T = any> = {
|
|
137
133
|
children?: React.ReactNode;
|
|
134
|
+
className?: string;
|
|
138
135
|
disabled?: boolean;
|
|
139
136
|
hideIcon?: boolean;
|
|
140
137
|
isActive?: boolean;
|
|
@@ -169,3 +166,35 @@ export type PromptFieldGetterContext = {
|
|
|
169
166
|
export type PromptField = {
|
|
170
167
|
getter?: (data: object, ctx: PromptFieldGetterContext) => Promise<string> | string;
|
|
171
168
|
} & SerializedPromptField;
|
|
169
|
+
export interface BeforeGenerateArgs<T = any> {
|
|
170
|
+
doc: T;
|
|
171
|
+
field: Field;
|
|
172
|
+
headers: Record<string, string>;
|
|
173
|
+
instructions: Record<string, unknown>;
|
|
174
|
+
messages?: ModelMessage[];
|
|
175
|
+
payload: PayloadRequest['payload'];
|
|
176
|
+
prompt: string;
|
|
177
|
+
req: PayloadRequest;
|
|
178
|
+
system: string;
|
|
179
|
+
}
|
|
180
|
+
export type BeforeGenerateResult = {
|
|
181
|
+
messages?: ModelMessage[];
|
|
182
|
+
prompt?: string;
|
|
183
|
+
system?: string;
|
|
184
|
+
} | void;
|
|
185
|
+
export type BeforeGenerateHook<T = any> = (args: BeforeGenerateArgs<T>) => BeforeGenerateResult | Promise<BeforeGenerateResult>;
|
|
186
|
+
export interface AfterGenerateArgs<T = any> {
|
|
187
|
+
doc: T;
|
|
188
|
+
field: Field;
|
|
189
|
+
headers: Record<string, string>;
|
|
190
|
+
instructions: Record<string, unknown>;
|
|
191
|
+
payload: PayloadRequest['payload'];
|
|
192
|
+
req: PayloadRequest;
|
|
193
|
+
result: GenerateObjectResult<any> | MediaResult | string;
|
|
194
|
+
}
|
|
195
|
+
export type AfterGenerateHook<T = any> = (args: AfterGenerateArgs<T>) => Promise<void> | void;
|
|
196
|
+
export interface AIFieldConfig {
|
|
197
|
+
[key: string]: unknown;
|
|
198
|
+
afterGenerate?: AfterGenerateHook[];
|
|
199
|
+
beforeGenerate?: BeforeGenerateHook[];
|
|
200
|
+
}
|
package/dist/types.js
CHANGED
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { JSONSchema } from 'openai/lib/jsonschema'\nimport type { ImageGenerateParams } from 'openai/resources/images'\nimport type {\n CollectionConfig,\n CollectionSlug,\n DataFromCollectionSlug,\n Endpoint,\n Field,\n File,\n GlobalConfig,\n GroupField,\n PayloadRequest,\n TypedCollection,\n} from 'payload'\nimport type { CSSProperties, MouseEventHandler } from 'react'\n\nimport type { MediaResult } from './ai/core/index.js'\nimport type {PLUGIN_INSTRUCTIONS_TABLE} from
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { GenerateObjectResult, ModelMessage } from 'ai'\nimport type { JSONSchema } from 'openai/lib/jsonschema'\nimport type { ImageGenerateParams } from 'openai/resources/images'\nimport type {\n CollectionConfig,\n CollectionSlug,\n DataFromCollectionSlug,\n Endpoint,\n Field,\n File,\n GlobalConfig,\n GroupField,\n PayloadRequest,\n TypedCollection,\n} from 'payload'\nimport type { CSSProperties, MouseEventHandler } from 'react'\n\nimport type { MediaResult } from './ai/core/index.js'\nimport type { PLUGIN_INSTRUCTIONS_TABLE } from './defaults.js'\n\nexport interface PluginConfigAccess {\n /**\n * Control access to AI generation features (generate text, images, audio)\n * @default () => !!req.user (requires authentication)\n */\n generate?: ({ req }: { req: PayloadRequest }) => boolean | Promise<boolean>\n /**\n * Control access to AI settings/configuration\n * @default () => !!req.user (requires authentication)\n */\n settings?: ({ req }: { req: PayloadRequest }) => boolean | Promise<boolean>\n}\n\nexport interface PluginOptions {\n /**\n * Provide local tags to filter language options from the Translate Menu\n * Check for the available local tags,\n * visit: https://www.npmjs.com/package/locale-codes\n * Example: [\"en-US\", \"zh-SG\", \"zh-CN\", \"en\"]\n */\n enabledLanguages?: string[]\n}\n\nexport type PluginConfigMediaUploadFunction = (\n result: MediaResult,\n {\n collection,\n request,\n }: {\n collection: CollectionSlug\n request: PayloadRequest\n },\n) => Promise<DataFromCollectionSlug<CollectionSlug>>\n\nexport interface PluginConfig {\n /**\n * Access control configuration for AI features\n * By default, all AI features require authentication\n */\n access?: PluginConfigAccess\n debugging?: boolean\n disableSponsorMessage?: boolean\n editorConfig?: { nodes: JSONSchema[] }\n fields?: Field[]\n generationModels?: ((defaultModels: GenerationModel[]) => GenerationModel[]) | GenerationModel[]\n globals?: {\n [key: GlobalConfig['slug']]: boolean\n }\n interfaceName?: string\n mediaUpload?: PluginConfigMediaUploadFunction\n options?: PluginOptions\n // Override the instructions collection config\n overrideInstructions?: Partial<CollectionConfig>\n promptFields?: PromptField[]\n /**\n * Custom action prompts for AI text generation\n * If not provided, uses default prompts\n * You can access default prompts by importing { defaultPrompts } from '@ai-stack/payloadcms'\n */\n prompts?: ActionPrompt[]\n /**\n * Custom seed prompt function for generating field-specific prompts\n * If not provided, fields will have empty prompts by default\n */\n seedPrompts?: SeedPromptFunction\n uploadCollectionSlug?: CollectionSlug\n}\n\nexport interface GenerationModel {\n fields: string[]\n generateText?: (prompt: string, system: string) => Promise<string>\n handler?: (prompt: string, options: any) => File | Promise<any> | Response\n id: string\n name: string\n output: 'audio' | 'file' | 'image' | 'json' | 'text' | 'video'\n settings?: GroupField\n supportsPromptOptimization?: boolean\n}\n\nexport interface GenerationConfig {\n models: GenerationModel[]\n provider: string\n}\n\nexport type GenerateTextarea<T = any> = (args: {\n collectionSlug: CollectionSlug\n doc: T\n documentId?: number | string\n locale?: string\n options?: any\n}) => Promise<string> | string\n\nexport interface Endpoints {\n fetchVoices?: Omit<Endpoint, 'root'>\n textarea: Omit<Endpoint, 'root'>\n upload: Omit<Endpoint, 'root'>\n videogenWebhook?: Omit<Endpoint, 'root'>\n}\n\nexport type ActionMenuItems =\n | 'Compose'\n | 'Expand'\n | 'Proofread'\n | 'Rephrase'\n | 'Settings'\n | 'Simplify'\n | 'Summarize'\n | 'Tone'\n | 'Translate'\n\nexport type ActionPromptOptions = {\n layout?: string\n locale?: string\n prompt?: string\n systemPrompt?: string\n}\n\nexport type ActionPrompt = {\n layout?: (options?: ActionPromptOptions) => string\n name: ActionMenuItems\n system: (options: ActionPromptOptions) => string\n}\n\nexport type SeedPromptOptions = {\n fieldLabel: string\n fieldSchemaPaths: Record<string, any>\n fieldType: string\n path: string\n}\n\nexport type SeedPromptData = Omit<\n TypedCollection[typeof PLUGIN_INSTRUCTIONS_TABLE],\n 'createdAt' | 'id' | 'updatedAt'\n>\n\nexport type SeedPromptResult =\n | {\n data?: SeedPromptData\n }\n | {\n data?: SeedPromptData\n prompt: string\n system: string\n }\n | false\n | undefined\n | void\n\nexport type SeedPromptFunction = (\n options: SeedPromptOptions,\n) => Promise<SeedPromptResult> | SeedPromptResult\n\nexport type ActionMenuEvents =\n | 'onCompose'\n | 'onExpand'\n | 'onProofread'\n | 'onRephrase'\n | 'onSettings'\n | 'onSimplify'\n | 'onSummarize'\n | 'onTone'\n | 'onTranslate'\n\nexport type UseMenuEvents = {\n [key in ActionMenuEvents]?: (data?: unknown) => void\n}\n\nexport type UseMenuOptions = {\n isConfigAllowed: boolean\n}\n\nexport type BaseItemProps<T = any> = {\n children?: React.ReactNode\n className?: string\n disabled?: boolean\n hideIcon?: boolean\n isActive?: boolean\n isMenu?: boolean\n onClick: (data?: unknown) => void\n onMouseEnter?: MouseEventHandler<T> | undefined\n onMouseLeave?: MouseEventHandler<T> | undefined\n style?: CSSProperties | undefined\n title?: string\n}\n\nexport type ImageReference = {\n data: Blob\n name: string\n size: number\n type: string\n url: string\n}\n\nexport type GenerateImageParams = {\n images?: ImageReference[]\n size?: ImageGenerateParams['size']\n style?: ImageGenerateParams['style']\n version?: ImageGenerateParams['model']\n}\n\nexport type SerializedPromptField = {\n collections?: CollectionSlug[]\n name: string\n}\n\nexport type PromptFieldGetterContext = {\n collection: CollectionSlug\n type: string\n}\n\nexport type PromptField = {\n // If not provided, the value will be returned from the data object as-is\n getter?: (data: object, ctx: PromptFieldGetterContext) => Promise<string> | string\n} & SerializedPromptField\n\nexport interface BeforeGenerateArgs<T = any> {\n doc: T\n field: Field\n headers: Record<string, string>\n instructions: Record<string, unknown> // The instruction document\n messages?: ModelMessage[]\n payload: PayloadRequest['payload']\n prompt: string\n req: PayloadRequest\n system: string\n}\n\nexport type BeforeGenerateResult = {\n messages?: ModelMessage[]\n prompt?: string\n system?: string\n} | void\n\nexport type BeforeGenerateHook<T = any> = (\n args: BeforeGenerateArgs<T>,\n) => BeforeGenerateResult | Promise<BeforeGenerateResult>\n\nexport interface AfterGenerateArgs<T = any> {\n doc: T\n field: Field\n headers: Record<string, string>\n instructions: Record<string, unknown>\n payload: PayloadRequest['payload']\n req: PayloadRequest\n result: GenerateObjectResult<any> | MediaResult | string // depends on context\n}\n\nexport type AfterGenerateHook<T = any> = (args: AfterGenerateArgs<T>) => Promise<void> | void\n\n// Add to PluginConfig or a new interface if accessed via custom.ai\nexport interface AIFieldConfig {\n [key: string]: unknown\n afterGenerate?: AfterGenerateHook[]\n beforeGenerate?: BeforeGenerateHook[]\n}\n"],"names":[],"mappings":"AA6QA,mEAAmE;AACnE,WAIC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const ConfigDashboard: React.FC;
|
|
@@ -1,43 +1,221 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import
|
|
4
|
-
|
|
3
|
+
import { Button, toast, useConfig } from '@payloadcms/ui';
|
|
4
|
+
// @ts-expect-error - Next.js types are not resolving correctly with nodenext but runtime is fine
|
|
5
|
+
import { useRouter } from 'next/navigation';
|
|
6
|
+
import React, { use, useEffect, useState } from 'react';
|
|
7
|
+
import { excludeCollections } from '../../defaults.js';
|
|
8
|
+
import { InstructionsContext } from '../../providers/InstructionsProvider/context.js';
|
|
9
|
+
export const ConfigDashboard = ()=>{
|
|
10
|
+
const { config: { collections, routes: { admin: adminRoute, api: apiRoute } } } = useConfig();
|
|
11
|
+
const router = useRouter();
|
|
12
|
+
const { refresh, setEnabledCollections: setEnabledCollectionsInContext } = use(InstructionsContext);
|
|
13
|
+
const [enabledCollections, setEnabledCollections] = useState([]);
|
|
14
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
15
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
16
|
+
const availableCollections = collections.filter((c)=>!excludeCollections.includes(c.slug) && !c.admin?.hidden);
|
|
17
|
+
useEffect(()=>{
|
|
18
|
+
const fetchSettings = async ()=>{
|
|
19
|
+
try {
|
|
20
|
+
const response = await fetch(`${apiRoute}/globals/ai-providers`);
|
|
21
|
+
if (response.ok) {
|
|
22
|
+
const data = await response.json();
|
|
23
|
+
// Handle both simple array and object wrapper if Payload wraps it
|
|
24
|
+
const storedEnabled = data.enabledCollections || [];
|
|
25
|
+
setEnabledCollections(Array.isArray(storedEnabled) ? storedEnabled : []);
|
|
26
|
+
}
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error('Failed to fetch AI settings:', error);
|
|
29
|
+
} finally{
|
|
30
|
+
setIsLoading(false);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
fetchSettings().catch((e)=>{
|
|
34
|
+
console.log(e);
|
|
35
|
+
});
|
|
36
|
+
}, [
|
|
37
|
+
apiRoute
|
|
38
|
+
]);
|
|
39
|
+
const handleToggle = (slug)=>{
|
|
40
|
+
setEnabledCollections((prev)=>{
|
|
41
|
+
if (prev.includes(slug)) {
|
|
42
|
+
return prev.filter((s)=>s !== slug);
|
|
43
|
+
}
|
|
44
|
+
return [
|
|
45
|
+
...prev,
|
|
46
|
+
slug
|
|
47
|
+
];
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
const handleSave = async ()=>{
|
|
51
|
+
setIsSaving(true);
|
|
52
|
+
try {
|
|
53
|
+
// First fetch current settings to get ID or just rely on global update behavior
|
|
54
|
+
// We need to adhere to Payload's global update API
|
|
55
|
+
const response = await fetch(`${apiRoute}/globals/ai-providers`, {
|
|
56
|
+
body: JSON.stringify({
|
|
57
|
+
enabledCollections
|
|
58
|
+
}),
|
|
59
|
+
headers: {
|
|
60
|
+
'Content-Type': 'application/json'
|
|
61
|
+
},
|
|
62
|
+
method: 'POST'
|
|
63
|
+
});
|
|
64
|
+
if (response.ok) {
|
|
65
|
+
toast.success('Settings saved successfully');
|
|
66
|
+
if (setEnabledCollectionsInContext) {
|
|
67
|
+
setEnabledCollectionsInContext(enabledCollections);
|
|
68
|
+
}
|
|
69
|
+
if (refresh) {
|
|
70
|
+
await refresh();
|
|
71
|
+
}
|
|
72
|
+
router.refresh();
|
|
73
|
+
} else {
|
|
74
|
+
toast.error('Failed to save settings');
|
|
75
|
+
}
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.error('Error saving settings:', error);
|
|
78
|
+
toast.error('Error saving settings');
|
|
79
|
+
} finally{
|
|
80
|
+
setIsSaving(false);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
if (isLoading) {
|
|
84
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
85
|
+
style: {
|
|
86
|
+
padding: '20px',
|
|
87
|
+
textAlign: 'center'
|
|
88
|
+
},
|
|
89
|
+
children: "Loading configuration..."
|
|
90
|
+
});
|
|
91
|
+
}
|
|
5
92
|
return /*#__PURE__*/ _jsxs("div", {
|
|
6
93
|
style: {
|
|
7
|
-
alignItems: 'center',
|
|
8
94
|
background: 'var(--theme-elevation-50)',
|
|
9
|
-
border: '1px solid var(--theme-elevation-150)',
|
|
10
|
-
borderRadius: '8px',
|
|
11
|
-
|
|
12
|
-
|
|
95
|
+
// border: '1px solid var(--theme-elevation-150)',
|
|
96
|
+
// borderRadius: '8px',
|
|
97
|
+
// borderBottom: '1px solid var(--theme-elevation-150)',
|
|
98
|
+
// borderTop: '1px solid var(--theme-elevation-150)',
|
|
13
99
|
marginBottom: '20px',
|
|
14
|
-
|
|
100
|
+
overflow: 'hidden'
|
|
15
101
|
},
|
|
16
102
|
children: [
|
|
17
103
|
/*#__PURE__*/ _jsxs("div", {
|
|
104
|
+
style: {
|
|
105
|
+
alignItems: 'center',
|
|
106
|
+
borderBottom: '1px solid var(--theme-elevation-150)',
|
|
107
|
+
display: 'flex',
|
|
108
|
+
justifyContent: 'space-between',
|
|
109
|
+
padding: '8px var(--gutter-h)'
|
|
110
|
+
},
|
|
18
111
|
children: [
|
|
19
|
-
/*#__PURE__*/
|
|
112
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
113
|
+
children: [
|
|
114
|
+
/*#__PURE__*/ _jsx("h2", {
|
|
115
|
+
style: {
|
|
116
|
+
margin: '0 0 5px 0'
|
|
117
|
+
},
|
|
118
|
+
children: "Let's configure your AI Plugin"
|
|
119
|
+
}),
|
|
120
|
+
/*#__PURE__*/ _jsx("p", {
|
|
121
|
+
style: {
|
|
122
|
+
color: 'var(--theme-elevation-500)',
|
|
123
|
+
fontSize: '14px',
|
|
124
|
+
margin: '0'
|
|
125
|
+
},
|
|
126
|
+
children: "Set up the provider → Choose the content → Refine the behavior."
|
|
127
|
+
})
|
|
128
|
+
]
|
|
129
|
+
}),
|
|
130
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
20
131
|
style: {
|
|
21
|
-
|
|
132
|
+
display: 'flex',
|
|
133
|
+
gap: '10px'
|
|
22
134
|
},
|
|
23
|
-
children:
|
|
135
|
+
children: [
|
|
136
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
137
|
+
buttonStyle: "secondary",
|
|
138
|
+
el: "link",
|
|
139
|
+
to: `${adminRoute}/globals/ai-providers`,
|
|
140
|
+
children: "Providers"
|
|
141
|
+
}),
|
|
142
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
143
|
+
disabled: isSaving,
|
|
144
|
+
onClick: handleSave,
|
|
145
|
+
children: isSaving ? 'Saving...' : 'Save Changes'
|
|
146
|
+
})
|
|
147
|
+
]
|
|
148
|
+
})
|
|
149
|
+
]
|
|
150
|
+
}),
|
|
151
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
152
|
+
style: {
|
|
153
|
+
padding: '24px var(--gutter-h)'
|
|
154
|
+
},
|
|
155
|
+
children: [
|
|
156
|
+
/*#__PURE__*/ _jsx("h5", {
|
|
157
|
+
style: {
|
|
158
|
+
marginBottom: '15px'
|
|
159
|
+
},
|
|
160
|
+
children: "Select the collections where AI features should be available, toggle them on or off, and save your changes."
|
|
24
161
|
}),
|
|
25
|
-
/*#__PURE__*/ _jsx("
|
|
162
|
+
/*#__PURE__*/ _jsx("div", {
|
|
26
163
|
style: {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
164
|
+
display: 'grid',
|
|
165
|
+
gap: '15px',
|
|
166
|
+
gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))'
|
|
30
167
|
},
|
|
31
|
-
children:
|
|
168
|
+
children: availableCollections.map((collection)=>{
|
|
169
|
+
const isEnabled = enabledCollections.includes(collection.slug);
|
|
170
|
+
return /*#__PURE__*/ _jsxs("button", {
|
|
171
|
+
onClick: ()=>handleToggle(collection.slug),
|
|
172
|
+
style: {
|
|
173
|
+
alignItems: 'center',
|
|
174
|
+
background: isEnabled ? 'var(--theme-elevation-100)' : 'var(--theme-elevation-50)',
|
|
175
|
+
border: `1px solid ${isEnabled ? 'var(--theme-text-success)' : 'var(--theme-elevation-200)'}`,
|
|
176
|
+
borderRadius: '6px',
|
|
177
|
+
cursor: 'pointer',
|
|
178
|
+
display: 'flex',
|
|
179
|
+
gap: '10px',
|
|
180
|
+
padding: '10px 15px',
|
|
181
|
+
textAlign: 'left',
|
|
182
|
+
transition: 'all 0.2s ease',
|
|
183
|
+
width: '100%'
|
|
184
|
+
},
|
|
185
|
+
type: "button",
|
|
186
|
+
children: [
|
|
187
|
+
/*#__PURE__*/ _jsx("div", {
|
|
188
|
+
style: {
|
|
189
|
+
alignItems: 'center',
|
|
190
|
+
background: isEnabled ? 'var(--theme-text-success)' : 'var(--theme-elevation-200)',
|
|
191
|
+
borderRadius: '12px',
|
|
192
|
+
display: 'flex',
|
|
193
|
+
height: '24px',
|
|
194
|
+
justifyContent: isEnabled ? 'flex-end' : 'flex-start',
|
|
195
|
+
padding: '2px',
|
|
196
|
+
transition: 'all 0.2s ease',
|
|
197
|
+
width: '44px'
|
|
198
|
+
},
|
|
199
|
+
children: /*#__PURE__*/ _jsx("div", {
|
|
200
|
+
style: {
|
|
201
|
+
background: 'white',
|
|
202
|
+
borderRadius: '50%',
|
|
203
|
+
height: '20px',
|
|
204
|
+
width: '20px'
|
|
205
|
+
}
|
|
206
|
+
})
|
|
207
|
+
}),
|
|
208
|
+
/*#__PURE__*/ _jsx("span", {
|
|
209
|
+
style: {
|
|
210
|
+
fontWeight: 500
|
|
211
|
+
},
|
|
212
|
+
children: typeof collection.labels?.singular === 'string' ? collection.labels.singular : collection.labels?.singular?.en || collection.slug
|
|
213
|
+
})
|
|
214
|
+
]
|
|
215
|
+
}, collection.slug);
|
|
216
|
+
})
|
|
32
217
|
})
|
|
33
218
|
]
|
|
34
|
-
}),
|
|
35
|
-
/*#__PURE__*/ _jsx("a", {
|
|
36
|
-
href: "/admin/globals/ai-settings",
|
|
37
|
-
children: /*#__PURE__*/ _jsx("button", {
|
|
38
|
-
className: "btn btn--style-primary btn--size-small",
|
|
39
|
-
children: "Manage AI Settings"
|
|
40
|
-
})
|
|
41
219
|
})
|
|
42
220
|
]
|
|
43
221
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/ui/AIConfigDashboard/index.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\n\nexport const AIConfigDashboard: React.FC = () => {\n return (\n <div\n style={{\n alignItems: 'center',\n background: 'var(--theme-elevation-50)',\n border: '1px solid var(--theme-elevation-150)',\n borderRadius: '8px',\n display: 'flex',\n justifyContent: 'space-between',\n marginBottom: '20px',\n padding: '20px',\n }}\n >\n <div>\n <h4 style={{ margin: '0 0 5px 0' }}>AI Configuration</h4>\n <p style={{ color: 'var(--theme-elevation-500)', fontSize: '14px', margin: '0' }}>\n Manage your AI providers, API keys, and default models.\n </p>\n </div>\n <a href=\"/admin/globals/ai-settings\">\n <button className=\"btn btn--style-primary btn--size-small\">Manage AI Settings</button>\n </a>\n </div>\n )\n}\n"],"names":["React","AIConfigDashboard","div","style","alignItems","background","border","borderRadius","display","justifyContent","marginBottom","padding","h4","margin","p","color","fontSize","a","href","button","className"],"mappings":"AAAA;;AAEA,OAAOA,WAAW,QAAO;AAEzB,OAAO,MAAMC,oBAA8B;IACzC,qBACE,MAACC;QACCC,OAAO;YACLC,YAAY;YACZC,YAAY;YACZC,QAAQ;YACRC,cAAc;YACdC,SAAS;YACTC,gBAAgB;YAChBC,cAAc;YACdC,SAAS;QACX;;0BAEA,MAACT;;kCACC,KAACU;wBAAGT,OAAO;4BAAEU,QAAQ;wBAAY;kCAAG;;kCACpC,KAACC;wBAAEX,OAAO;4BAAEY,OAAO;4BAA8BC,UAAU;4BAAQH,QAAQ;wBAAI;kCAAG;;;;0BAIpF,KAACI;gBAAEC,MAAK;0BACN,cAAA,KAACC;oBAAOC,WAAU;8BAAyC;;;;;AAInE,EAAC"}
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/AIConfigDashboard/index.tsx"],"sourcesContent":["'use client'\n\nimport { Button, toast, useConfig } from '@payloadcms/ui'\n// @ts-expect-error - Next.js types are not resolving correctly with nodenext but runtime is fine\nimport { useRouter } from 'next/navigation'\nimport React, { use, useEffect, useState } from 'react'\n\nimport { excludeCollections } from '../../defaults.js'\nimport { InstructionsContext } from '../../providers/InstructionsProvider/context.js'\n\nexport const ConfigDashboard: React.FC = () => {\n const {\n config: {\n collections,\n routes: { admin: adminRoute, api: apiRoute },\n },\n } = useConfig()\n const router = useRouter()\n const { refresh, setEnabledCollections: setEnabledCollectionsInContext } =\n use(InstructionsContext)\n\n const [enabledCollections, setEnabledCollections] = useState<string[]>([])\n const [isLoading, setIsLoading] = useState(true)\n const [isSaving, setIsSaving] = useState(false)\n\n const availableCollections = collections.filter(\n (c) =>\n !excludeCollections.includes(c.slug) &&\n !(c.admin as unknown as { hidden?: ((args: any) => boolean) | boolean })?.hidden,\n )\n\n useEffect(() => {\n const fetchSettings = async () => {\n try {\n const response = await fetch(`${apiRoute}/globals/ai-providers`)\n if (response.ok) {\n const data = await response.json()\n // Handle both simple array and object wrapper if Payload wraps it\n const storedEnabled = data.enabledCollections || []\n setEnabledCollections(Array.isArray(storedEnabled) ? storedEnabled : [])\n }\n } catch (error) {\n console.error('Failed to fetch AI settings:', error)\n } finally {\n setIsLoading(false)\n }\n }\n\n fetchSettings().catch((e) => {\n console.log(e)\n })\n }, [apiRoute])\n\n const handleToggle = (slug: string) => {\n setEnabledCollections((prev) => {\n if (prev.includes(slug)) {\n return prev.filter((s) => s !== slug)\n }\n return [...prev, slug]\n })\n }\n\n const handleSave = async () => {\n setIsSaving(true)\n try {\n // First fetch current settings to get ID or just rely on global update behavior\n // We need to adhere to Payload's global update API\n const response = await fetch(`${apiRoute}/globals/ai-providers`, {\n body: JSON.stringify({\n enabledCollections,\n }),\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n\n if (response.ok) {\n toast.success('Settings saved successfully')\n if (setEnabledCollectionsInContext) {\n setEnabledCollectionsInContext(enabledCollections)\n }\n if (refresh) {\n await refresh()\n }\n router.refresh()\n } else {\n toast.error('Failed to save settings')\n }\n } catch (error) {\n console.error('Error saving settings:', error)\n toast.error('Error saving settings')\n } finally {\n setIsSaving(false)\n }\n }\n\n if (isLoading) {\n return <div style={{ padding: '20px', textAlign: 'center' }}>Loading configuration...</div>\n }\n\n return (\n <div\n style={{\n background: 'var(--theme-elevation-50)',\n // border: '1px solid var(--theme-elevation-150)',\n // borderRadius: '8px',\n // borderBottom: '1px solid var(--theme-elevation-150)',\n // borderTop: '1px solid var(--theme-elevation-150)',\n marginBottom: '20px',\n overflow: 'hidden',\n }}\n >\n <div\n style={{\n alignItems: 'center',\n borderBottom: '1px solid var(--theme-elevation-150)',\n display: 'flex',\n justifyContent: 'space-between',\n padding: '8px var(--gutter-h)',\n }}\n >\n <div>\n <h2 style={{ margin: '0 0 5px 0' }}>Let's configure your AI Plugin</h2>\n <p style={{ color: 'var(--theme-elevation-500)', fontSize: '14px', margin: '0' }}>\n Set up the provider → Choose the content → Refine the behavior.\n </p>\n </div>\n <div style={{ display: 'flex', gap: '10px' }}>\n <Button buttonStyle=\"secondary\" el=\"link\" to={`${adminRoute}/globals/ai-providers`}>\n Providers\n </Button>\n <Button disabled={isSaving} onClick={handleSave}>\n {isSaving ? 'Saving...' : 'Save Changes'}\n </Button>\n </div>\n </div>\n\n <div style={{ padding: '24px var(--gutter-h)' }}>\n <h5 style={{ marginBottom: '15px' }}>\n Select the collections where AI features should be available, toggle them on or off, and\n save your changes.\n </h5>\n <div\n style={{\n display: 'grid',\n gap: '15px',\n gridTemplateColumns: 'repeat(auto-fill, minmax(250px, 1fr))',\n }}\n >\n {availableCollections.map((collection) => {\n const isEnabled = enabledCollections.includes(collection.slug)\n return (\n <button\n key={collection.slug}\n onClick={() => handleToggle(collection.slug)}\n style={{\n alignItems: 'center',\n background: isEnabled\n ? 'var(--theme-elevation-100)'\n : 'var(--theme-elevation-50)',\n border: `1px solid ${isEnabled ? 'var(--theme-text-success)' : 'var(--theme-elevation-200)'}`,\n borderRadius: '6px',\n cursor: 'pointer',\n display: 'flex',\n gap: '10px',\n padding: '10px 15px',\n textAlign: 'left',\n transition: 'all 0.2s ease',\n width: '100%',\n }}\n type=\"button\"\n >\n <div\n style={{\n alignItems: 'center',\n background: isEnabled\n ? 'var(--theme-text-success)'\n : 'var(--theme-elevation-200)',\n borderRadius: '12px',\n display: 'flex',\n height: '24px',\n justifyContent: isEnabled ? 'flex-end' : 'flex-start',\n padding: '2px',\n transition: 'all 0.2s ease',\n width: '44px',\n }}\n >\n <div\n style={{\n background: 'white',\n borderRadius: '50%',\n height: '20px',\n width: '20px',\n }}\n />\n </div>\n <span style={{ fontWeight: 500 }}>\n {typeof collection.labels?.singular === 'string'\n ? collection.labels.singular\n : collection.labels?.singular?.en || collection.slug}\n </span>\n </button>\n )\n })}\n </div>\n </div>\n </div>\n )\n}\n"],"names":["Button","toast","useConfig","useRouter","React","use","useEffect","useState","excludeCollections","InstructionsContext","ConfigDashboard","config","collections","routes","admin","adminRoute","api","apiRoute","router","refresh","setEnabledCollections","setEnabledCollectionsInContext","enabledCollections","isLoading","setIsLoading","isSaving","setIsSaving","availableCollections","filter","c","includes","slug","hidden","fetchSettings","response","fetch","ok","data","json","storedEnabled","Array","isArray","error","console","catch","e","log","handleToggle","prev","s","handleSave","body","JSON","stringify","headers","method","success","div","style","padding","textAlign","background","marginBottom","overflow","alignItems","borderBottom","display","justifyContent","h2","margin","p","color","fontSize","gap","buttonStyle","el","to","disabled","onClick","h5","gridTemplateColumns","map","collection","isEnabled","button","border","borderRadius","cursor","transition","width","type","height","span","fontWeight","labels","singular","en"],"mappings":"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"}
|