@ai-stack/payloadcms 3.68.0-beta.1 → 3.68.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/dist/ai/core/media/image/handlers/multimodal.js +5 -0
  2. package/dist/ai/core/media/image/handlers/multimodal.js.map +1 -1
  3. package/dist/ai/core/streamObject.js +0 -3
  4. package/dist/ai/core/streamObject.js.map +1 -1
  5. package/dist/ai/providers/blocks/anthropic.js +2 -1
  6. package/dist/ai/providers/blocks/anthropic.js.map +1 -1
  7. package/dist/ai/providers/blocks/elevenlabs.js +2 -1
  8. package/dist/ai/providers/blocks/elevenlabs.js.map +1 -1
  9. package/dist/ai/providers/blocks/fal.js +2 -1
  10. package/dist/ai/providers/blocks/fal.js.map +1 -1
  11. package/dist/ai/providers/blocks/google.js +2 -1
  12. package/dist/ai/providers/blocks/google.js.map +1 -1
  13. package/dist/ai/providers/blocks/openai-compatible.js +2 -1
  14. package/dist/ai/providers/blocks/openai-compatible.js.map +1 -1
  15. package/dist/ai/providers/blocks/openai.js +2 -1
  16. package/dist/ai/providers/blocks/openai.js.map +1 -1
  17. package/dist/ai/providers/blocks/xai.js +2 -1
  18. package/dist/ai/providers/blocks/xai.js.map +1 -1
  19. package/dist/ai/providers/icons.d.ts +7 -0
  20. package/dist/ai/providers/icons.js +9 -0
  21. package/dist/ai/providers/icons.js.map +1 -0
  22. package/dist/ai/providers/registry.js +34 -23
  23. package/dist/ai/providers/registry.js.map +1 -1
  24. package/dist/collections/Instructions.js +37 -0
  25. package/dist/collections/Instructions.js.map +1 -1
  26. package/dist/endpoints/chat.d.ts +4 -0
  27. package/dist/endpoints/index.js +86 -10
  28. package/dist/endpoints/index.js.map +1 -1
  29. package/dist/exports/fields.d.ts +1 -0
  30. package/dist/exports/fields.js +1 -0
  31. package/dist/exports/fields.js.map +1 -1
  32. package/dist/fields/ArrayComposeField/ArrayComposeField.d.ts +15 -0
  33. package/dist/fields/ArrayComposeField/ArrayComposeField.js +87 -0
  34. package/dist/fields/ArrayComposeField/ArrayComposeField.js.map +1 -0
  35. package/dist/fields/ArrayComposeField/ArrayComposeField.jsx +73 -0
  36. package/dist/fields/PromptEditorField/PromptEditorField.js +7 -2
  37. package/dist/fields/PromptEditorField/PromptEditorField.js.map +1 -1
  38. package/dist/fields/PromptEditorField/PromptEditorField.jsx +5 -2
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.js +1 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/init.js +23 -6
  43. package/dist/init.js.map +1 -1
  44. package/dist/payload-ai.d.ts +149 -0
  45. package/dist/providers/InstructionsProvider/InstructionsProvider.js +3 -0
  46. package/dist/providers/InstructionsProvider/InstructionsProvider.js.map +1 -1
  47. package/dist/providers/InstructionsProvider/InstructionsProvider.jsx +3 -0
  48. package/dist/providers/InstructionsProvider/useInstructions.js +18 -1
  49. package/dist/providers/InstructionsProvider/useInstructions.js.map +1 -1
  50. package/dist/styles.d.ts +11 -0
  51. package/dist/types/handlebars-async-helpers.d.ts +1 -0
  52. package/dist/types/handlebars-dist-handlebars.d.ts +1 -0
  53. package/dist/types/react-mentions.d.ts +1 -0
  54. package/dist/ui/Compose/Compose.d.ts +1 -0
  55. package/dist/ui/Compose/Compose.js +2 -2
  56. package/dist/ui/Compose/Compose.js.map +1 -1
  57. package/dist/ui/Compose/Compose.jsx +2 -2
  58. package/dist/ui/Compose/UndoRedoActions.d.ts +2 -2
  59. package/dist/ui/Compose/UndoRedoActions.js +8 -5
  60. package/dist/ui/Compose/UndoRedoActions.js.map +1 -1
  61. package/dist/ui/Compose/UndoRedoActions.jsx +6 -5
  62. package/dist/ui/Compose/compose.module.css +56 -16
  63. package/dist/ui/Compose/hooks/menu/itemsMap.js +12 -6
  64. package/dist/ui/Compose/hooks/menu/itemsMap.js.map +1 -1
  65. package/dist/ui/Compose/hooks/menu/useMenu.js +26 -15
  66. package/dist/ui/Compose/hooks/menu/useMenu.js.map +1 -1
  67. package/dist/ui/Compose/hooks/menu/useMenu.jsx +25 -12
  68. package/dist/ui/Compose/hooks/useHistory.d.ts +0 -1
  69. package/dist/ui/Compose/hooks/useHistory.js +65 -25
  70. package/dist/ui/Compose/hooks/useHistory.js.map +1 -1
  71. package/dist/ui/DynamicVoiceSelect/index.js +63 -11
  72. package/dist/ui/DynamicVoiceSelect/index.js.map +1 -1
  73. package/dist/ui/DynamicVoiceSelect/index.jsx +47 -14
  74. package/dist/ui/VoicesFetcher/index.js +54 -8
  75. package/dist/ui/VoicesFetcher/index.js.map +1 -1
  76. package/dist/ui/VoicesFetcher/index.jsx +32 -9
  77. package/dist/utilities/buildSmartPrompt.d.ts +22 -0
  78. package/dist/utilities/buildSmartPrompt.js +143 -0
  79. package/dist/utilities/buildSmartPrompt.js.map +1 -0
  80. package/dist/utilities/resolveImageReferences.d.ts +3 -1
  81. package/dist/utilities/resolveImageReferences.js +21 -2
  82. package/dist/utilities/resolveImageReferences.js.map +1 -1
  83. package/dist/utilities/updateFieldsConfig.js +7 -1
  84. package/dist/utilities/updateFieldsConfig.js.map +1 -1
  85. package/package.json +3 -3
  86. package/dist/endpoints/chat.d.js +0 -3
  87. package/dist/endpoints/chat.d.js.map +0 -1
  88. package/dist/payload-ai.d.js +0 -3
  89. package/dist/payload-ai.d.js.map +0 -1
  90. package/dist/styles.d.js +0 -2
  91. package/dist/styles.d.js.map +0 -1
  92. package/dist/types/handlebars-async-helpers.d.js +0 -2
  93. package/dist/types/handlebars-async-helpers.d.js.map +0 -1
  94. package/dist/types/handlebars-dist-handlebars.d.js +0 -2
  95. package/dist/types/handlebars-dist-handlebars.d.js.map +0 -1
  96. package/dist/types/react-mentions.d.js +0 -2
  97. package/dist/types/react-mentions.d.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Button, useForm } from '@payloadcms/ui';
3
+ import { Button, useForm, useFormFields } from '@payloadcms/ui';
4
4
  import React, { useCallback, useState } from 'react';
5
5
  import { PLUGIN_API_ENDPOINT_FETCH_VOICES } from '../../defaults.js';
6
6
  /**
@@ -14,6 +14,9 @@ import { PLUGIN_API_ENDPOINT_FETCH_VOICES } from '../../defaults.js';
14
14
  const fieldPath = path || '';
15
15
  const blockPath = fieldPath.split('.').slice(0, -1).join('.');
16
16
  const voicesPath = `${blockPath}.voices`;
17
+ // Get the current voices array to know how many rows to remove
18
+ const voicesField = useFormFields(([fields])=>fields[voicesPath]);
19
+ const currentRowCount = voicesField && 'rows' in voicesField && Array.isArray(voicesField.rows) ? voicesField.rows.length : 0;
17
20
  const fetchVoices = useCallback(async ()=>{
18
21
  setLoading(true);
19
22
  try {
@@ -29,19 +32,62 @@ import { PLUGIN_API_ENDPOINT_FETCH_VOICES } from '../../defaults.js';
29
32
  throw new Error(error.message || 'Failed to fetch voices');
30
33
  }
31
34
  const data = await response.json();
32
- // Update the voices field with fetched voices
33
- dispatchFields({
34
- type: 'UPDATE',
35
- path: voicesPath,
36
- value: data.voices || []
37
- });
38
- alert(`Successfully fetched ${data.voices?.length || 0} voices!`);
35
+ const voices = data.voices || [];
36
+ // Remove existing rows first (in reverse order to maintain indices)
37
+ for(let i = currentRowCount - 1; i >= 0; i--){
38
+ dispatchFields({
39
+ type: 'REMOVE_ROW',
40
+ path: voicesPath,
41
+ rowIndex: i
42
+ });
43
+ }
44
+ // Add new rows for each voice using ADD_ROW action
45
+ for (const voice of voices){
46
+ dispatchFields({
47
+ type: 'ADD_ROW',
48
+ path: voicesPath,
49
+ subFieldState: {
50
+ id: {
51
+ initialValue: voice.id,
52
+ valid: true,
53
+ value: voice.id
54
+ },
55
+ name: {
56
+ initialValue: voice.name,
57
+ valid: true,
58
+ value: voice.name
59
+ },
60
+ category: {
61
+ initialValue: voice.category || 'premade',
62
+ valid: true,
63
+ value: voice.category || 'premade'
64
+ },
65
+ enabled: {
66
+ initialValue: voice.enabled !== false,
67
+ valid: true,
68
+ value: voice.enabled !== false
69
+ },
70
+ labels: {
71
+ initialValue: voice.labels || {},
72
+ valid: true,
73
+ value: voice.labels || {}
74
+ },
75
+ preview_url: {
76
+ initialValue: voice.preview_url || '',
77
+ valid: true,
78
+ value: voice.preview_url || ''
79
+ }
80
+ }
81
+ });
82
+ }
83
+ alert(`Successfully fetched ${voices.length} voices!`);
39
84
  } catch (error) {
40
85
  alert(`Error: ${error instanceof Error ? error.message : 'Failed to fetch voices'}`);
41
86
  } finally{
42
87
  setLoading(false);
43
88
  }
44
89
  }, [
90
+ currentRowCount,
45
91
  dispatchFields,
46
92
  voicesPath
47
93
  ]);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/VoicesFetcher/index.tsx"],"sourcesContent":["'use client'\n\nimport type { FieldClientComponent } from 'payload'\n\nimport { Button, useForm } from '@payloadcms/ui'\nimport React, { useCallback, useState } from 'react'\n\nimport { PLUGIN_API_ENDPOINT_FETCH_VOICES } from '../../defaults.js'\n\n/**\n * VoicesFetcher Component\n * Fetches voices from ElevenLabs API (server-side) and populates the voices array field\n * SECURE: API key is never exposed to the client\n */\nexport const VoicesFetcher: FieldClientComponent = ({ path }) => {\n const [loading, setLoading] = useState(false)\n const { dispatchFields } = useForm()\n\n // Get the parent path (the block path)\n const fieldPath = (path as string) || ''\n const blockPath = fieldPath.split('.').slice(0, -1).join('.')\n const voicesPath = `${blockPath}.voices`\n\n const fetchVoices = useCallback(async () => {\n setLoading(true)\n\n try {\n // Call server endpoint - it will read the API key from the database\n const response = await fetch(`/api${PLUGIN_API_ENDPOINT_FETCH_VOICES}`, {\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n\n if (!response.ok) {\n const error = await response.json()\n throw new Error(error.message || 'Failed to fetch voices')\n }\n\n const data = await response.json()\n\n // Update the voices field with fetched voices\n dispatchFields({\n type: 'UPDATE',\n path: voicesPath,\n value: data.voices || [],\n })\n\n alert(`Successfully fetched ${data.voices?.length || 0} voices!`)\n } catch (error) {\n alert(`Error: ${error instanceof Error ? error.message : 'Failed to fetch voices'}`)\n } finally {\n setLoading(false)\n }\n }, [dispatchFields, voicesPath])\n\n return (\n <div style={{ marginBottom: '20px' }}>\n <Button buttonStyle=\"secondary\" disabled={loading} onClick={fetchVoices} size=\"medium\">\n {loading ? 'Fetching Voices...' : 'Fetch Voices from ElevenLabs'}\n </Button>\n <p style={{ color: 'var(--theme-elevation-600)', fontSize: '13px', marginTop: '8px' }}>\n This will fetch all available voices from your ElevenLabs account. Make sure you have saved\n your API key in the Setup tab first.\n </p>\n </div>\n )\n}\n"],"names":["Button","useForm","React","useCallback","useState","PLUGIN_API_ENDPOINT_FETCH_VOICES","VoicesFetcher","path","loading","setLoading","dispatchFields","fieldPath","blockPath","split","slice","join","voicesPath","fetchVoices","response","fetch","headers","method","ok","error","json","Error","message","data","type","value","voices","alert","length","div","style","marginBottom","buttonStyle","disabled","onClick","size","p","color","fontSize","marginTop"],"mappings":"AAAA;;AAIA,SAASA,MAAM,EAAEC,OAAO,QAAQ,iBAAgB;AAChD,OAAOC,SAASC,WAAW,EAAEC,QAAQ,QAAQ,QAAO;AAEpD,SAASC,gCAAgC,QAAQ,oBAAmB;AAEpE;;;;CAIC,GACD,OAAO,MAAMC,gBAAsC,CAAC,EAAEC,IAAI,EAAE;IAC1D,MAAM,CAACC,SAASC,WAAW,GAAGL,SAAS;IACvC,MAAM,EAAEM,cAAc,EAAE,GAAGT;IAE3B,uCAAuC;IACvC,MAAMU,YAAY,AAACJ,QAAmB;IACtC,MAAMK,YAAYD,UAAUE,KAAK,CAAC,KAAKC,KAAK,CAAC,GAAG,CAAC,GAAGC,IAAI,CAAC;IACzD,MAAMC,aAAa,CAAC,EAAEJ,UAAU,OAAO,CAAC;IAExC,MAAMK,cAAcd,YAAY;QAC9BM,WAAW;QAEX,IAAI;YACF,oEAAoE;YACpE,MAAMS,WAAW,MAAMC,MAAM,CAAC,IAAI,EAAEd,iCAAiC,CAAC,EAAE;gBACtEe,SAAS;oBACP,gBAAgB;gBAClB;gBACAC,QAAQ;YACV;YAEA,IAAI,CAACH,SAASI,EAAE,EAAE;gBAChB,MAAMC,QAAQ,MAAML,SAASM,IAAI;gBACjC,MAAM,IAAIC,MAAMF,MAAMG,OAAO,IAAI;YACnC;YAEA,MAAMC,OAAO,MAAMT,SAASM,IAAI;YAEhC,8CAA8C;YAC9Cd,eAAe;gBACbkB,MAAM;gBACNrB,MAAMS;gBACNa,OAAOF,KAAKG,MAAM,IAAI,EAAE;YAC1B;YAEAC,MAAM,CAAC,qBAAqB,EAAEJ,KAAKG,MAAM,EAAEE,UAAU,EAAE,QAAQ,CAAC;QAClE,EAAE,OAAOT,OAAO;YACdQ,MAAM,CAAC,OAAO,EAAER,iBAAiBE,QAAQF,MAAMG,OAAO,GAAG,yBAAyB,CAAC;QACrF,SAAU;YACRjB,WAAW;QACb;IACF,GAAG;QAACC;QAAgBM;KAAW;IAE/B,qBACE,MAACiB;QAAIC,OAAO;YAAEC,cAAc;QAAO;;0BACjC,KAACnC;gBAAOoC,aAAY;gBAAYC,UAAU7B;gBAAS8B,SAASrB;gBAAasB,MAAK;0BAC3E/B,UAAU,uBAAuB;;0BAEpC,KAACgC;gBAAEN,OAAO;oBAAEO,OAAO;oBAA8BC,UAAU;oBAAQC,WAAW;gBAAM;0BAAG;;;;AAM7F,EAAC"}
1
+ {"version":3,"sources":["../../../src/ui/VoicesFetcher/index.tsx"],"sourcesContent":["'use client'\n\nimport type { FieldClientComponent } from 'payload'\n\nimport { Button, useForm, useFormFields } from '@payloadcms/ui'\nimport React, { useCallback, useState } from 'react'\n\nimport { PLUGIN_API_ENDPOINT_FETCH_VOICES } from '../../defaults.js'\n\ninterface Voice {\n category?: string\n enabled?: boolean\n id: string\n labels?: Record<string, unknown>\n name: string\n preview_url?: string\n}\n\n/**\n * VoicesFetcher Component\n * Fetches voices from ElevenLabs API (server-side) and populates the voices array field\n * SECURE: API key is never exposed to the client\n */\nexport const VoicesFetcher: FieldClientComponent = ({ path }) => {\n const [loading, setLoading] = useState(false)\n const { dispatchFields } = useForm()\n\n // Get the parent path (the block path)\n const fieldPath = (path as string) || ''\n const blockPath = fieldPath.split('.').slice(0, -1).join('.')\n const voicesPath = `${blockPath}.voices`\n\n // Get the current voices array to know how many rows to remove\n const voicesField = useFormFields(([fields]) => fields[voicesPath])\n const currentRowCount =\n voicesField && 'rows' in voicesField && Array.isArray(voicesField.rows)\n ? voicesField.rows.length\n : 0\n\n const fetchVoices = useCallback(async () => {\n setLoading(true)\n\n try {\n // Call server endpoint - it will read the API key from the database\n const response = await fetch(`/api${PLUGIN_API_ENDPOINT_FETCH_VOICES}`, {\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n\n if (!response.ok) {\n const error = await response.json()\n throw new Error(error.message || 'Failed to fetch voices')\n }\n\n const data = await response.json()\n const voices: Voice[] = data.voices || []\n\n // Remove existing rows first (in reverse order to maintain indices)\n for (let i = currentRowCount - 1; i >= 0; i--) {\n dispatchFields({\n type: 'REMOVE_ROW',\n path: voicesPath,\n rowIndex: i,\n })\n }\n\n // Add new rows for each voice using ADD_ROW action\n for (const voice of voices) {\n dispatchFields({\n type: 'ADD_ROW',\n path: voicesPath,\n subFieldState: {\n id: { initialValue: voice.id, valid: true, value: voice.id },\n name: { initialValue: voice.name, valid: true, value: voice.name },\n category: { initialValue: voice.category || 'premade', valid: true, value: voice.category || 'premade' },\n enabled: { initialValue: voice.enabled !== false, valid: true, value: voice.enabled !== false },\n labels: { initialValue: voice.labels || {}, valid: true, value: voice.labels || {} },\n preview_url: { initialValue: voice.preview_url || '', valid: true, value: voice.preview_url || '' },\n },\n })\n }\n\n alert(`Successfully fetched ${voices.length} voices!`)\n } catch (error) {\n alert(`Error: ${error instanceof Error ? error.message : 'Failed to fetch voices'}`)\n } finally {\n setLoading(false)\n }\n }, [currentRowCount, dispatchFields, voicesPath])\n\n return (\n <div style={{ marginBottom: '20px' }}>\n <Button buttonStyle=\"secondary\" disabled={loading} onClick={fetchVoices} size=\"medium\">\n {loading ? 'Fetching Voices...' : 'Fetch Voices from ElevenLabs'}\n </Button>\n <p style={{ color: 'var(--theme-elevation-600)', fontSize: '13px', marginTop: '8px' }}>\n This will fetch all available voices from your ElevenLabs account. Make sure you have saved\n your API key in the Setup tab first.\n </p>\n </div>\n )\n}\n\n\n\n"],"names":["Button","useForm","useFormFields","React","useCallback","useState","PLUGIN_API_ENDPOINT_FETCH_VOICES","VoicesFetcher","path","loading","setLoading","dispatchFields","fieldPath","blockPath","split","slice","join","voicesPath","voicesField","fields","currentRowCount","Array","isArray","rows","length","fetchVoices","response","fetch","headers","method","ok","error","json","Error","message","data","voices","i","type","rowIndex","voice","subFieldState","id","initialValue","valid","value","name","category","enabled","labels","preview_url","alert","div","style","marginBottom","buttonStyle","disabled","onClick","size","p","color","fontSize","marginTop"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { Button, useForm } from '@payloadcms/ui';
2
+ import { Button, useForm, useFormFields } from '@payloadcms/ui';
3
3
  import React, { useCallback, useState } from 'react';
4
4
  import { PLUGIN_API_ENDPOINT_FETCH_VOICES } from '../../defaults.js';
5
5
  /**
@@ -14,6 +14,11 @@ export const VoicesFetcher = ({ path }) => {
14
14
  const fieldPath = path || '';
15
15
  const blockPath = fieldPath.split('.').slice(0, -1).join('.');
16
16
  const voicesPath = `${blockPath}.voices`;
17
+ // Get the current voices array to know how many rows to remove
18
+ const voicesField = useFormFields(([fields]) => fields[voicesPath]);
19
+ const currentRowCount = voicesField && 'rows' in voicesField && Array.isArray(voicesField.rows)
20
+ ? voicesField.rows.length
21
+ : 0;
17
22
  const fetchVoices = useCallback(async () => {
18
23
  setLoading(true);
19
24
  try {
@@ -29,13 +34,31 @@ export const VoicesFetcher = ({ path }) => {
29
34
  throw new Error(error.message || 'Failed to fetch voices');
30
35
  }
31
36
  const data = await response.json();
32
- // Update the voices field with fetched voices
33
- dispatchFields({
34
- type: 'UPDATE',
35
- path: voicesPath,
36
- value: data.voices || [],
37
- });
38
- alert(`Successfully fetched ${data.voices?.length || 0} voices!`);
37
+ const voices = data.voices || [];
38
+ // Remove existing rows first (in reverse order to maintain indices)
39
+ for (let i = currentRowCount - 1; i >= 0; i--) {
40
+ dispatchFields({
41
+ type: 'REMOVE_ROW',
42
+ path: voicesPath,
43
+ rowIndex: i,
44
+ });
45
+ }
46
+ // Add new rows for each voice using ADD_ROW action
47
+ for (const voice of voices) {
48
+ dispatchFields({
49
+ type: 'ADD_ROW',
50
+ path: voicesPath,
51
+ subFieldState: {
52
+ id: { initialValue: voice.id, valid: true, value: voice.id },
53
+ name: { initialValue: voice.name, valid: true, value: voice.name },
54
+ category: { initialValue: voice.category || 'premade', valid: true, value: voice.category || 'premade' },
55
+ enabled: { initialValue: voice.enabled !== false, valid: true, value: voice.enabled !== false },
56
+ labels: { initialValue: voice.labels || {}, valid: true, value: voice.labels || {} },
57
+ preview_url: { initialValue: voice.preview_url || '', valid: true, value: voice.preview_url || '' },
58
+ },
59
+ });
60
+ }
61
+ alert(`Successfully fetched ${voices.length} voices!`);
39
62
  }
40
63
  catch (error) {
41
64
  alert(`Error: ${error instanceof Error ? error.message : 'Failed to fetch voices'}`);
@@ -43,7 +66,7 @@ export const VoicesFetcher = ({ path }) => {
43
66
  finally {
44
67
  setLoading(false);
45
68
  }
46
- }, [dispatchFields, voicesPath]);
69
+ }, [currentRowCount, dispatchFields, voicesPath]);
47
70
  return (<div style={{ marginBottom: '20px' }}>
48
71
  <Button buttonStyle="secondary" disabled={loading} onClick={fetchVoices} size="medium">
49
72
  {loading ? 'Fetching Voices...' : 'Fetch Voices from ElevenLabs'}
@@ -0,0 +1,22 @@
1
+ import type { Payload } from 'payload';
2
+ export interface SmartPromptContext {
3
+ /** The document data for template interpolation */
4
+ documentData?: Record<string, unknown>;
5
+ /** The Payload instance to access collection config */
6
+ payload: Payload;
7
+ /** The schema path like 'array-test-cases.teamMembers.contact.email' */
8
+ schemaPath: string;
9
+ }
10
+ /**
11
+ * Build a smart contextual prompt based on field metadata.
12
+ * This is used as a fallback when the user hasn't set a custom prompt.
13
+ *
14
+ * @param context - The context containing schema path and document data
15
+ * @returns A contextual prompt string that can be used for AI generation
16
+ */
17
+ export declare const buildSmartPrompt: (context: SmartPromptContext) => string;
18
+ /**
19
+ * Check if a prompt template is empty and should be replaced with a smart prompt.
20
+ * Only triggers when the prompt is completely empty or whitespace-only.
21
+ */
22
+ export declare const isGenericPrompt: (template: null | string | undefined) => boolean;
@@ -0,0 +1,143 @@
1
+ 'use strict';
2
+ import { getFieldBySchemaPath } from './getFieldBySchemaPath.js';
3
+ /**
4
+ * Extract field information from a schema path
5
+ */ const getFieldInfo = (schemaPath, payload)=>{
6
+ const parts = schemaPath.split('.');
7
+ const collectionSlug = parts[0];
8
+ const fieldPath = parts.slice(1);
9
+ const fieldName = fieldPath[fieldPath.length - 1] || '';
10
+ // Get parent context (e.g., 'teamMembers' for 'teamMembers.name')
11
+ let parentContext = null;
12
+ if (fieldPath.length > 1) {
13
+ parentContext = fieldPath[fieldPath.length - 2];
14
+ }
15
+ // Try to get the actual field configuration from the collection
16
+ let field = null;
17
+ const collection = payload.config.collections.find((c)=>c.slug === collectionSlug);
18
+ if (collection) {
19
+ field = getFieldBySchemaPath(collection, schemaPath);
20
+ }
21
+ return {
22
+ name: fieldName,
23
+ type: field?.type || 'text',
24
+ field,
25
+ label: field?.label || fieldName,
26
+ parentContext
27
+ };
28
+ };
29
+ /**
30
+ * Humanize a camelCase or snake_case field name
31
+ * e.g., 'teamMembers' -> 'team members', 'first_name' -> 'first name'
32
+ */ const humanize = (str)=>{
33
+ return str.replace(/([a-z])([A-Z])/g, '$1 $2') // camelCase to spaces
34
+ .replace(/[_-]/g, ' ') // underscores/dashes to spaces
35
+ .toLowerCase().trim();
36
+ };
37
+ /**
38
+ * Get a description snippet from field admin config
39
+ */ const getFieldDescription = (field)=>{
40
+ if (!field) {
41
+ return null;
42
+ }
43
+ const admin = field.admin;
44
+ if (admin?.description && typeof admin.description === 'string') {
45
+ return admin.description;
46
+ }
47
+ return null;
48
+ };
49
+ /**
50
+ * Build type-specific prompt guidance
51
+ */ const getTypeGuidance = (type, fieldName)=>{
52
+ const nameHint = humanize(fieldName);
53
+ switch(type){
54
+ case 'code':
55
+ return `Generate code for ${nameHint}`;
56
+ case 'date':
57
+ return `Generate an appropriate date for ${nameHint}`;
58
+ case 'email':
59
+ return `Generate a valid professional email address`;
60
+ case 'json':
61
+ return `Generate valid JSON data for ${nameHint}`;
62
+ case 'number':
63
+ return `Generate an appropriate numeric value for ${nameHint}`;
64
+ case 'select':
65
+ return `Select an appropriate option for ${nameHint}`;
66
+ case 'text':
67
+ return `Generate appropriate text for ${nameHint}`;
68
+ case 'textarea':
69
+ return `Write detailed content for ${nameHint}`;
70
+ case 'upload':
71
+ // Explicit image generation instruction for multimodal models
72
+ return `Generate an image of ${nameHint}`;
73
+ default:
74
+ return `Generate content for ${nameHint}`;
75
+ }
76
+ };
77
+ /**
78
+ * Build context from parent field name using generic humanization.
79
+ * Works universally for any collection structure.
80
+ */ const getParentContextPhrase = (parentContext)=>{
81
+ if (!parentContext) {
82
+ return '';
83
+ }
84
+ const humanized = humanize(parentContext);
85
+ // Use singular form if the name ends with 's' (common for arrays)
86
+ // e.g., "teamMembers" → "team member", "products" → "product"
87
+ if (humanized.endsWith('s') && humanized.length > 2) {
88
+ return `for a ${humanized.slice(0, -1)} entry`;
89
+ }
90
+ return `for ${humanized}`;
91
+ };
92
+ /**
93
+ * Build a smart contextual prompt based on field metadata.
94
+ * This is used as a fallback when the user hasn't set a custom prompt.
95
+ *
96
+ * @param context - The context containing schema path and document data
97
+ * @returns A contextual prompt string that can be used for AI generation
98
+ */ export const buildSmartPrompt = (context)=>{
99
+ const { documentData, payload, schemaPath } = context;
100
+ const fieldInfo = getFieldInfo(schemaPath, payload);
101
+ const { name, type, field, label, parentContext } = fieldInfo;
102
+ // Start with the field's own description if available
103
+ const description = getFieldDescription(field);
104
+ // Build the prompt components
105
+ const parts = [];
106
+ // Use description as primary guidance if available
107
+ if (description) {
108
+ parts.push(description);
109
+ } else {
110
+ // Fall back to type-based guidance, prefer label over name for better context
111
+ parts.push(getTypeGuidance(type, label || name));
112
+ }
113
+ // Add parent context if nested
114
+ const parentPhrase = getParentContextPhrase(parentContext);
115
+ if (parentPhrase) {
116
+ parts.push(parentPhrase);
117
+ }
118
+ // Add document title context if available
119
+ const title = documentData?.title;
120
+ if (title && typeof title === 'string') {
121
+ parts.push(`in the context of "${title}"`);
122
+ }
123
+ // Build the final prompt
124
+ let prompt = parts.join(' ');
125
+ // Ensure first letter is capitalized
126
+ prompt = prompt.charAt(0).toUpperCase() + prompt.slice(1);
127
+ // Add instruction suffix for clarity
128
+ if (!prompt.endsWith('.')) {
129
+ prompt += '.';
130
+ }
131
+ return prompt;
132
+ };
133
+ /**
134
+ * Check if a prompt template is empty and should be replaced with a smart prompt.
135
+ * Only triggers when the prompt is completely empty or whitespace-only.
136
+ */ export const isGenericPrompt = (template)=>{
137
+ if (!template) {
138
+ return true;
139
+ }
140
+ return template.trim() === '';
141
+ };
142
+
143
+ //# sourceMappingURL=buildSmartPrompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/buildSmartPrompt.ts"],"sourcesContent":["'use strict'\n\nimport type { Field, Payload } from 'payload'\n\nimport { getFieldBySchemaPath } from './getFieldBySchemaPath.js'\n\nexport interface SmartPromptContext {\n /** The document data for template interpolation */\n documentData?: Record<string, unknown>\n /** The Payload instance to access collection config */\n payload: Payload\n /** The schema path like 'array-test-cases.teamMembers.contact.email' */\n schemaPath: string\n}\n\ninterface FieldInfo {\n /** The field configuration */\n field: Field | null\n /** Human-readable field label */\n label: string\n /** Field name from the path */\n name: string\n /** Parent field name if nested (e.g., 'teamMembers' for 'teamMembers.name') */\n parentContext: null | string\n /** The field type */\n type: string\n}\n\n/**\n * Extract field information from a schema path\n */\nconst getFieldInfo = (schemaPath: string, payload: Payload): FieldInfo => {\n const parts = schemaPath.split('.')\n const collectionSlug = parts[0]\n const fieldPath = parts.slice(1)\n const fieldName = fieldPath[fieldPath.length - 1] || ''\n \n // Get parent context (e.g., 'teamMembers' for 'teamMembers.name')\n let parentContext: null | string = null\n if (fieldPath.length > 1) {\n parentContext = fieldPath[fieldPath.length - 2]\n }\n \n // Try to get the actual field configuration from the collection\n let field: Field | null = null\n const collection = payload.config.collections.find(c => c.slug === collectionSlug)\n if (collection) {\n field = getFieldBySchemaPath(collection, schemaPath)\n }\n \n return {\n name: fieldName,\n type: field?.type || 'text',\n field,\n label: (field as { label?: string })?.label || fieldName,\n parentContext,\n }\n}\n\n/**\n * Humanize a camelCase or snake_case field name\n * e.g., 'teamMembers' -> 'team members', 'first_name' -> 'first name'\n */\nconst humanize = (str: string): string => {\n return str\n .replace(/([a-z])([A-Z])/g, '$1 $2') // camelCase to spaces\n .replace(/[_-]/g, ' ') // underscores/dashes to spaces\n .toLowerCase()\n .trim()\n}\n\n/**\n * Get a description snippet from field admin config\n */\nconst getFieldDescription = (field: Field | null): null | string => {\n if (!field) {return null}\n const admin = (field as { admin?: { description?: string } }).admin\n if (admin?.description && typeof admin.description === 'string') {\n return admin.description\n }\n return null\n}\n\n/**\n * Build type-specific prompt guidance\n */\nconst getTypeGuidance = (type: string, fieldName: string): string => {\n const nameHint = humanize(fieldName)\n \n switch (type) {\n case 'code':\n return `Generate code for ${nameHint}`\n case 'date':\n return `Generate an appropriate date for ${nameHint}`\n case 'email':\n return `Generate a valid professional email address`\n case 'json':\n return `Generate valid JSON data for ${nameHint}`\n case 'number':\n return `Generate an appropriate numeric value for ${nameHint}`\n case 'select':\n return `Select an appropriate option for ${nameHint}`\n case 'text':\n return `Generate appropriate text for ${nameHint}`\n case 'textarea':\n return `Write detailed content for ${nameHint}`\n case 'upload':\n // Explicit image generation instruction for multimodal models\n return `Generate an image of ${nameHint}`\n default:\n return `Generate content for ${nameHint}`\n }\n}\n\n/**\n * Build context from parent field name using generic humanization.\n * Works universally for any collection structure.\n */\nconst getParentContextPhrase = (parentContext: null | string): string => {\n if (!parentContext) {\n return ''\n }\n \n const humanized = humanize(parentContext)\n \n // Use singular form if the name ends with 's' (common for arrays)\n // e.g., \"teamMembers\" → \"team member\", \"products\" → \"product\"\n if (humanized.endsWith('s') && humanized.length > 2) {\n return `for a ${humanized.slice(0, -1)} entry`\n }\n \n return `for ${humanized}`\n}\n\n/**\n * Build a smart contextual prompt based on field metadata.\n * This is used as a fallback when the user hasn't set a custom prompt.\n * \n * @param context - The context containing schema path and document data\n * @returns A contextual prompt string that can be used for AI generation\n */\nexport const buildSmartPrompt = (context: SmartPromptContext): string => {\n const { documentData, payload, schemaPath } = context\n \n const fieldInfo = getFieldInfo(schemaPath, payload)\n const { name, type, field, label, parentContext } = fieldInfo\n \n // Start with the field's own description if available\n const description = getFieldDescription(field)\n \n // Build the prompt components\n const parts: string[] = []\n \n // Use description as primary guidance if available\n if (description) {\n parts.push(description)\n } else {\n // Fall back to type-based guidance, prefer label over name for better context\n parts.push(getTypeGuidance(type, label || name))\n }\n \n // Add parent context if nested\n const parentPhrase = getParentContextPhrase(parentContext)\n if (parentPhrase) {\n parts.push(parentPhrase)\n }\n \n // Add document title context if available\n const title = documentData?.title\n if (title && typeof title === 'string') {\n parts.push(`in the context of \"${title}\"`)\n }\n \n // Build the final prompt\n let prompt = parts.join(' ')\n \n // Ensure first letter is capitalized\n prompt = prompt.charAt(0).toUpperCase() + prompt.slice(1)\n \n // Add instruction suffix for clarity\n if (!prompt.endsWith('.')) {\n prompt += '.'\n }\n \n return prompt\n}\n\n/**\n * Check if a prompt template is empty and should be replaced with a smart prompt.\n * Only triggers when the prompt is completely empty or whitespace-only.\n */\nexport const isGenericPrompt = (template: null | string | undefined): boolean => {\n if (!template) {\n return true\n }\n return template.trim() === ''\n}\n"],"names":["getFieldBySchemaPath","getFieldInfo","schemaPath","payload","parts","split","collectionSlug","fieldPath","slice","fieldName","length","parentContext","field","collection","config","collections","find","c","slug","name","type","label","humanize","str","replace","toLowerCase","trim","getFieldDescription","admin","description","getTypeGuidance","nameHint","getParentContextPhrase","humanized","endsWith","buildSmartPrompt","context","documentData","fieldInfo","push","parentPhrase","title","prompt","join","charAt","toUpperCase","isGenericPrompt","template"],"mappings":"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"}
@@ -17,12 +17,14 @@ interface ResolveImageReferencesResult {
17
17
  *
18
18
  * Supports two formats:
19
19
  * - @fieldName - for single upload fields
20
+ * - @collection.fieldName - schema path format (collection prefix is stripped)
20
21
  * - @fieldName:filename.jpg - for specific images in hasMany fields
21
22
  *
22
23
  * @param prompt - The prompt text containing @field references
23
24
  * @param contextData - The document data to resolve field values from
24
25
  * @param req - Payload request object for fetching media
26
+ * @param collectionSlug - Optional collection slug to strip from schema path references
25
27
  * @returns Processed prompt with references removed and array of resolved images
26
28
  */
27
- export declare function resolveImageReferences(prompt: string, contextData: Record<string, unknown>, req: PayloadRequest): Promise<ResolveImageReferencesResult>;
29
+ export declare function resolveImageReferences(prompt: string, contextData: Record<string, unknown>, req: PayloadRequest, collectionSlug?: string): Promise<ResolveImageReferencesResult>;
28
30
  export {};
@@ -1,15 +1,28 @@
1
+ /**
2
+ * Retrieves a nested value from an object using dot-notation path.
3
+ * For example, getNestedValue(obj, 'a.b.c') returns obj.a.b.c
4
+ */ function getNestedValue(obj, path) {
5
+ return path.split('.').reduce((current, key)=>{
6
+ if (current && typeof current === 'object' && key in current) {
7
+ return current[key];
8
+ }
9
+ return undefined;
10
+ }, obj);
11
+ }
1
12
  /**
2
13
  * Parses and resolves image references in prompts.
3
14
  *
4
15
  * Supports two formats:
5
16
  * - @fieldName - for single upload fields
17
+ * - @collection.fieldName - schema path format (collection prefix is stripped)
6
18
  * - @fieldName:filename.jpg - for specific images in hasMany fields
7
19
  *
8
20
  * @param prompt - The prompt text containing @field references
9
21
  * @param contextData - The document data to resolve field values from
10
22
  * @param req - Payload request object for fetching media
23
+ * @param collectionSlug - Optional collection slug to strip from schema path references
11
24
  * @returns Processed prompt with references removed and array of resolved images
12
- */ export async function resolveImageReferences(prompt, contextData, req) {
25
+ */ export async function resolveImageReferences(prompt, contextData, req, collectionSlug) {
13
26
  // Pattern matches: @fieldName or @fieldName:filename.ext (filename can have spaces)
14
27
  // The filename part matches everything up to and including an image extension
15
28
  const pattern = /@([\w.]+)(?::(.+?\.(?:png|jpe?g|webp|gif)))?/gi;
@@ -34,7 +47,13 @@
34
47
  // Resolve each reference
35
48
  for (const ref of references){
36
49
  try {
37
- const fieldValue = contextData[ref.fieldName];
50
+ // Strip collection prefix from schema path if it matches the current collection
51
+ // e.g., "characters.ortho3d.frame" becomes "ortho3d.frame" when collectionSlug is "characters"
52
+ let fieldPath = ref.fieldName;
53
+ if (collectionSlug && fieldPath.startsWith(`${collectionSlug}.`)) {
54
+ fieldPath = fieldPath.slice(collectionSlug.length + 1);
55
+ }
56
+ const fieldValue = getNestedValue(contextData, fieldPath);
38
57
  if (!fieldValue) {
39
58
  req.payload.logger.warn(`Image reference @${ref.fieldName} not found in document context`);
40
59
  continue;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/resolveImageReferences.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\ninterface ImageReference {\n fieldName: string\n filename?: string\n fullMatch: string\n}\n\nexport interface ResolvedImage {\n image: {\n mimeType?: string\n name: string\n thumbnailURL?: string\n type: string\n url: string\n }\n}\n\ninterface ResolveImageReferencesResult {\n images: ResolvedImage[]\n processedPrompt: string\n}\n\n/**\n * Parses and resolves image references in prompts.\n * \n * Supports two formats:\n * - @fieldName - for single upload fields\n * - @fieldName:filename.jpg - for specific images in hasMany fields\n * \n * @param prompt - The prompt text containing @field references\n * @param contextData - The document data to resolve field values from\n * @param req - Payload request object for fetching media\n * @returns Processed prompt with references removed and array of resolved images\n */\nexport async function resolveImageReferences(\n prompt: string,\n contextData: Record<string, unknown>,\n req: PayloadRequest,\n): Promise<ResolveImageReferencesResult> {\n // Pattern matches: @fieldName or @fieldName:filename.ext (filename can have spaces)\n // The filename part matches everything up to and including an image extension\n const pattern = /@([\\w.]+)(?::(.+?\\.(?:png|jpe?g|webp|gif)))?/gi\n const references: ImageReference[] = []\n let match: null | RegExpExecArray\n\n // Extract all image references\n while ((match = pattern.exec(prompt)) !== null) {\n references.push({\n fieldName: match[1],\n filename: match[2],\n fullMatch: match[0],\n })\n }\n\n if (references.length === 0) {\n return { images: [], processedPrompt: prompt }\n }\n\n const resolvedImages: ResolvedImage[] = []\n let processedPrompt = prompt\n\n // Resolve each reference\n for (const ref of references) {\n try {\n const fieldValue = contextData[ref.fieldName]\n\n if (!fieldValue) {\n req.payload.logger.warn(\n `Image reference @${ref.fieldName} not found in document context`,\n )\n continue\n }\n\n // Handle single upload field (value is an ID or object)\n if (!ref.filename) {\n const mediaDoc = await resolveMediaDocument(fieldValue, req)\n if (mediaDoc) {\n resolvedImages.push(formatImageData(mediaDoc))\n }\n }\n // Handle hasMany field with filename\n else {\n const mediaDoc = await resolveMediaFromArray(fieldValue, ref.filename, req)\n if (mediaDoc) {\n resolvedImages.push(formatImageData(mediaDoc))\n }\n }\n\n // Remove the reference from the prompt\n processedPrompt = processedPrompt.replace(ref.fullMatch, '')\n } catch (error) {\n req.payload.logger.error(\n error,\n `Error resolving image reference: ${ref.fullMatch}`,\n )\n }\n }\n\n // Clean up extra whitespace from removed references\n processedPrompt = processedPrompt.replace(/\\s+/g, ' ').trim()\n\n return {\n images: resolvedImages,\n processedPrompt,\n }\n}\n\n/**\n * Resolves a single media document from an ID or populated object\n */\nasync function resolveMediaDocument(\n value: unknown,\n req: PayloadRequest,\n): Promise<null | Record<string, unknown>> {\n // If it's already a populated object with required fields\n if (typeof value === 'object' && value !== null && 'url' in value) {\n return value as Record<string, unknown>\n }\n\n // If it's an ID string, fetch the media document\n if (typeof value === 'string' || typeof value === 'number') {\n try {\n // Try to find which collection this media belongs to\n // First, check the common 'media' collection\n const collections = ['media', 'uploads']\n\n for (const collectionSlug of collections) {\n try {\n const mediaDoc = await req.payload.findByID({\n id: value,\n collection: collectionSlug,\n req,\n })\n if (mediaDoc) {\n return mediaDoc as Record<string, unknown>\n }\n } catch (_ignore) {\n // Continue to next collection\n continue\n }\n }\n } catch (error) {\n req.payload.logger.error(error, 'Error fetching media document')\n }\n }\n\n return null\n}\n\n/**\n * Resolves a specific media document from an array by matching filename\n */\nasync function resolveMediaFromArray(\n arrayValue: unknown,\n filename: string,\n req: PayloadRequest,\n): Promise<null | Record<string, unknown>> {\n if (!Array.isArray(arrayValue)) {\n return null\n }\n\n // Search through array for matching filename\n for (const item of arrayValue) {\n const mediaDoc = await resolveMediaDocument(item, req)\n\n if (mediaDoc && matchesFilename(mediaDoc, filename)) {\n return mediaDoc\n }\n }\n\n return null\n}\n\n/**\n * Checks if a media document matches the given filename\n */\nfunction matchesFilename(mediaDoc: Record<string, unknown>, filename: string): boolean {\n const docFilename = mediaDoc.filename || mediaDoc.name\n\n if (!docFilename) {\n return false\n }\n\n // Case-insensitive match\n return (docFilename as string).toLowerCase() === filename.toLowerCase()\n}\n\n/**\n * Formats media document into the expected image data structure\n */\nfunction formatImageData(mediaDoc: Record<string, unknown>): ResolvedImage {\n return {\n image: {\n name: (mediaDoc.filename || mediaDoc.name || 'unknown') as string,\n type: extractFileExtension((mediaDoc.filename || mediaDoc.name || '') as string),\n mimeType: (mediaDoc.mimeType || mediaDoc.mimetype) as string | undefined,\n thumbnailURL: mediaDoc.thumbnailURL as string | undefined,\n url: mediaDoc.url as string,\n },\n }\n}\n\n/**\n * Extracts file extension from filename\n */\nfunction extractFileExtension(filename: string): string {\n const match = filename.match(/\\.([^.]+)$/)\n return match ? match[1].toLowerCase() : 'unknown'\n}\n"],"names":["resolveImageReferences","prompt","contextData","req","pattern","references","match","exec","push","fieldName","filename","fullMatch","length","images","processedPrompt","resolvedImages","ref","fieldValue","payload","logger","warn","mediaDoc","resolveMediaDocument","formatImageData","resolveMediaFromArray","replace","error","trim","value","collections","collectionSlug","findByID","id","collection","_ignore","arrayValue","Array","isArray","item","matchesFilename","docFilename","name","toLowerCase","image","type","extractFileExtension","mimeType","mimetype","thumbnailURL","url"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utilities/resolveImageReferences.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\ninterface ImageReference {\n fieldName: string\n filename?: string\n fullMatch: string\n}\n\nexport interface ResolvedImage {\n image: {\n mimeType?: string\n name: string\n thumbnailURL?: string\n type: string\n url: string\n }\n}\n\ninterface ResolveImageReferencesResult {\n images: ResolvedImage[]\n processedPrompt: string\n}\n\n/**\n * Retrieves a nested value from an object using dot-notation path.\n * For example, getNestedValue(obj, 'a.b.c') returns obj.a.b.c\n */\nfunction getNestedValue(obj: Record<string, unknown>, path: string): unknown {\n return path.split('.').reduce((current, key) => {\n if (current && typeof current === 'object' && key in current) {\n return (current as Record<string, unknown>)[key]\n }\n return undefined\n }, obj as unknown)\n}\n\n/**\n * Parses and resolves image references in prompts.\n * \n * Supports two formats:\n * - @fieldName - for single upload fields\n * - @collection.fieldName - schema path format (collection prefix is stripped)\n * - @fieldName:filename.jpg - for specific images in hasMany fields\n * \n * @param prompt - The prompt text containing @field references\n * @param contextData - The document data to resolve field values from\n * @param req - Payload request object for fetching media\n * @param collectionSlug - Optional collection slug to strip from schema path references\n * @returns Processed prompt with references removed and array of resolved images\n */\nexport async function resolveImageReferences(\n prompt: string,\n contextData: Record<string, unknown>,\n req: PayloadRequest,\n collectionSlug?: string,\n): Promise<ResolveImageReferencesResult> {\n // Pattern matches: @fieldName or @fieldName:filename.ext (filename can have spaces)\n // The filename part matches everything up to and including an image extension\n const pattern = /@([\\w.]+)(?::(.+?\\.(?:png|jpe?g|webp|gif)))?/gi\n const references: ImageReference[] = []\n let match: null | RegExpExecArray\n\n // Extract all image references\n while ((match = pattern.exec(prompt)) !== null) {\n references.push({\n fieldName: match[1],\n filename: match[2],\n fullMatch: match[0],\n })\n }\n\n if (references.length === 0) {\n return { images: [], processedPrompt: prompt }\n }\n\n const resolvedImages: ResolvedImage[] = []\n let processedPrompt = prompt\n\n // Resolve each reference\n for (const ref of references) {\n try {\n // Strip collection prefix from schema path if it matches the current collection\n // e.g., \"characters.ortho3d.frame\" becomes \"ortho3d.frame\" when collectionSlug is \"characters\"\n let fieldPath = ref.fieldName\n if (collectionSlug && fieldPath.startsWith(`${collectionSlug}.`)) {\n fieldPath = fieldPath.slice(collectionSlug.length + 1)\n }\n\n const fieldValue = getNestedValue(contextData, fieldPath)\n\n if (!fieldValue) {\n req.payload.logger.warn(\n `Image reference @${ref.fieldName} not found in document context`,\n )\n continue\n }\n\n // Handle single upload field (value is an ID or object)\n if (!ref.filename) {\n const mediaDoc = await resolveMediaDocument(fieldValue, req)\n if (mediaDoc) {\n resolvedImages.push(formatImageData(mediaDoc))\n }\n }\n // Handle hasMany field with filename\n else {\n const mediaDoc = await resolveMediaFromArray(fieldValue, ref.filename, req)\n if (mediaDoc) {\n resolvedImages.push(formatImageData(mediaDoc))\n }\n }\n\n // Remove the reference from the prompt\n processedPrompt = processedPrompt.replace(ref.fullMatch, '')\n } catch (error) {\n req.payload.logger.error(\n error,\n `Error resolving image reference: ${ref.fullMatch}`,\n )\n }\n }\n\n // Clean up extra whitespace from removed references\n processedPrompt = processedPrompt.replace(/\\s+/g, ' ').trim()\n\n return {\n images: resolvedImages,\n processedPrompt,\n }\n}\n\n/**\n * Resolves a single media document from an ID or populated object\n */\nasync function resolveMediaDocument(\n value: unknown,\n req: PayloadRequest,\n): Promise<null | Record<string, unknown>> {\n // If it's already a populated object with required fields\n if (typeof value === 'object' && value !== null && 'url' in value) {\n return value as Record<string, unknown>\n }\n\n // If it's an ID string, fetch the media document\n if (typeof value === 'string' || typeof value === 'number') {\n try {\n // Try to find which collection this media belongs to\n // First, check the common 'media' collection\n const collections = ['media', 'uploads']\n\n for (const collectionSlug of collections) {\n try {\n const mediaDoc = await req.payload.findByID({\n id: value,\n collection: collectionSlug,\n req,\n })\n if (mediaDoc) {\n return mediaDoc as Record<string, unknown>\n }\n } catch (_ignore) {\n // Continue to next collection\n continue\n }\n }\n } catch (error) {\n req.payload.logger.error(error, 'Error fetching media document')\n }\n }\n\n return null\n}\n\n/**\n * Resolves a specific media document from an array by matching filename\n */\nasync function resolveMediaFromArray(\n arrayValue: unknown,\n filename: string,\n req: PayloadRequest,\n): Promise<null | Record<string, unknown>> {\n if (!Array.isArray(arrayValue)) {\n return null\n }\n\n // Search through array for matching filename\n for (const item of arrayValue) {\n const mediaDoc = await resolveMediaDocument(item, req)\n\n if (mediaDoc && matchesFilename(mediaDoc, filename)) {\n return mediaDoc\n }\n }\n\n return null\n}\n\n/**\n * Checks if a media document matches the given filename\n */\nfunction matchesFilename(mediaDoc: Record<string, unknown>, filename: string): boolean {\n const docFilename = mediaDoc.filename || mediaDoc.name\n\n if (!docFilename) {\n return false\n }\n\n // Case-insensitive match\n return (docFilename as string).toLowerCase() === filename.toLowerCase()\n}\n\n/**\n * Formats media document into the expected image data structure\n */\nfunction formatImageData(mediaDoc: Record<string, unknown>): ResolvedImage {\n return {\n image: {\n name: (mediaDoc.filename || mediaDoc.name || 'unknown') as string,\n type: extractFileExtension((mediaDoc.filename || mediaDoc.name || '') as string),\n mimeType: (mediaDoc.mimeType || mediaDoc.mimetype) as string | undefined,\n thumbnailURL: mediaDoc.thumbnailURL as string | undefined,\n url: mediaDoc.url as string,\n },\n }\n}\n\n/**\n * Extracts file extension from filename\n */\nfunction extractFileExtension(filename: string): string {\n const match = filename.match(/\\.([^.]+)$/)\n return match ? match[1].toLowerCase() : 'unknown'\n}\n"],"names":["getNestedValue","obj","path","split","reduce","current","key","undefined","resolveImageReferences","prompt","contextData","req","collectionSlug","pattern","references","match","exec","push","fieldName","filename","fullMatch","length","images","processedPrompt","resolvedImages","ref","fieldPath","startsWith","slice","fieldValue","payload","logger","warn","mediaDoc","resolveMediaDocument","formatImageData","resolveMediaFromArray","replace","error","trim","value","collections","findByID","id","collection","_ignore","arrayValue","Array","isArray","item","matchesFilename","docFilename","name","toLowerCase","image","type","extractFileExtension","mimeType","mimetype","thumbnailURL","url"],"mappings":"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"}
@@ -11,6 +11,7 @@ export const updateFieldsConfig = (collectionConfig)=>{
11
11
  // This is done due to save extra API call to get instructions when Field components are loaded in admin
12
12
  // Doing is will only call instructions data when user clicks on settings
13
13
  if ([
14
+ 'array',
14
15
  'richText',
15
16
  'text',
16
17
  'textarea',
@@ -26,7 +27,9 @@ export const updateFieldsConfig = (collectionConfig)=>{
26
27
  };
27
28
  }
28
29
  // Inject AI actions, richText is not included here as it has to be explicitly defined by user
30
+ // Array fields also get AI injection for bulk generation
29
31
  if ([
32
+ 'array',
30
33
  'text',
31
34
  'textarea',
32
35
  'upload'
@@ -39,6 +42,9 @@ export const updateFieldsConfig = (collectionConfig)=>{
39
42
  // by overriding Description. If you need both, consider composing your own wrapper.
40
43
  customField = {};
41
44
  }
45
+ // Array fields use ArrayComposeField (always visible) since they don't have focus events
46
+ // Other fields use ComposeField with focus-dependent visibility
47
+ const componentPath = field.type === 'array' ? '@ai-stack/payloadcms/fields#ArrayComposeField' : '@ai-stack/payloadcms/fields#ComposeField';
42
48
  return {
43
49
  ...field,
44
50
  admin: {
@@ -49,7 +55,7 @@ export const updateFieldsConfig = (collectionConfig)=>{
49
55
  clientProps: {
50
56
  schemaPath: currentSchemaPath
51
57
  },
52
- path: '@ai-stack/payloadcms/fields#ComposeField'
58
+ path: componentPath
53
59
  },
54
60
  ...customField
55
61
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/updateFieldsConfig.ts"],"sourcesContent":["import type { CollectionConfig, GlobalConfig } from 'payload'\n\ninterface UpdateFieldsConfig {\n schemaPathMap: Record<string, string>\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 (['richText', 'text', 'textarea', 'upload'].includes(field.type)) {\n schemaPathMap = {\n ...schemaPathMap,\n [currentSchemaPath]: {\n type: field.type,\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 if (['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 return {\n ...field,\n admin: {\n ...field.admin,\n components: {\n ...(field.admin?.components || {}),\n Description: {\n clientProps: {\n schemaPath: currentSchemaPath,\n },\n path: '@ai-stack/payloadcms/fields#ComposeField',\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","label","relationTo","customField","components","Field","Description","clientProps","schemaPath","path","fields","map","subField","tabs","tab","blocks","block","updatedCollectionConfig"],"mappings":"AAOA,OAAO,MAAMA,qBAAqB,CAACC;IACjC,IAAIC,gBAAgB,CAAC;IAErB,SAASC,YAAYC,KAAU,EAAEC,aAAa,EAAE;QAC9C,MAAMC,cAAcD,aAAa,CAAC,EAAEA,WAAW,CAAC,EAAED,MAAMG,IAAI,CAAC,CAAC,GAAGH,MAAMG,IAAI;QAC3E,MAAMC,oBAAoB,CAAC,EAAEP,iBAAiBQ,IAAI,CAAC,CAAC,EAAEH,YAAY,CAAC;QAEnE,+BAA+B;QAC/B,IACEF,MAAMM,KAAK,EAAEC,YACbP,MAAMM,KAAK,EAAEE,YACbR,MAAMM,KAAK,EAAEG,UACbT,MAAMU,IAAI,KAAK,OACf;YACA,OAAOV;QACT;QAEA,8EAA8E;QAC9E,wGAAwG;QACxG,yEAAyE;QACzE,IAAI;YAAC;YAAY;YAAQ;YAAY;SAAS,CAACW,QAAQ,CAACX,MAAMU,IAAI,GAAG;YACnEZ,gBAAgB;gBACd,GAAGA,aAAa;gBAChB,CAACM,kBAAkB,EAAE;oBACnBM,MAAMV,MAAMU,IAAI;oBAChBE,OAAOZ,MAAMY,KAAK,IAAIZ,MAAMG,IAAI;oBAChCU,YAAYb,MAAMa,UAAU;gBAC9B;YACF;QACF;QAEA,8FAA8F;QAC9F,IAAI;YAAC;YAAQ;YAAY;SAAS,CAACF,QAAQ,CAACX,MAAMU,IAAI,GAAG;YACvD,IAAII,cAAc,CAAC;YAEnB,iFAAiF;YACjF,8EAA8E;YAC9E,IAAId,MAAMM,KAAK,EAAES,YAAYC,SAAShB,MAAMM,KAAK,EAAES,YAAYE,aAAa;gBAC1E,0FAA0F;gBAC1F,oFAAoF;gBACpFH,cAAc,CAAC;YACjB;YAEA,OAAO;gBACL,GAAGd,KAAK;gBACRM,OAAO;oBACL,GAAGN,MAAMM,KAAK;oBACdS,YAAY;wBACV,GAAIf,MAAMM,KAAK,EAAES,cAAc,CAAC,CAAC;wBACjCE,aAAa;4BACXC,aAAa;gCACXC,YAAYf;4BACd;4BACAgB,MAAM;wBACR;wBACA,GAAGN,WAAW;oBAChB;gBACF;YACF;QACF;QAEA,IAAId,MAAMqB,MAAM,EAAE;YAChB,OAAO;gBACL,GAAGrB,KAAK;gBACRqB,QAAQrB,MAAMqB,MAAM,CAACC,GAAG,CAAC,CAACC,WAAkBxB,YAAYwB,UAAUrB;YACpE;QACF;QAEA,IAAIF,MAAMwB,IAAI,EAAE;YACd,OAAO;gBACL,GAAGxB,KAAK;gBACRwB,MAAMxB,MAAMwB,IAAI,CAACF,GAAG,CAAC,CAACG;oBACpB,OAAO;wBACL,GAAGA,GAAG;wBACN,gEAAgE;wBAChEJ,QAAQ,AAACI,CAAAA,IAAIJ,MAAM,IAAI,EAAE,AAAD,EAAGC,GAAG,CAAC,CAACC,WAAkBxB,YAAYwB,UAAUtB;oBAC1E;gBACF;YACF;QACF;QAEA,IAAID,MAAM0B,MAAM,EAAE;YAChB,OAAO;gBACL,GAAG1B,KAAK;gBACR0B,QAAQ1B,MAAM0B,MAAM,CAACJ,GAAG,CAAC,CAACK,QAAgB,CAAA;wBACxC,GAAGA,KAAK;wBACRN,QAAQM,MAAMN,MAAM,CAACC,GAAG,CAAC,CAACC,WACxBxB,YAAYwB,UAAU,CAAC,EAAErB,YAAY,CAAC,EAAEyB,MAAMtB,IAAI,CAAC,CAAC;oBAExD,CAAA;YACF;QACF;QAEA,OAAOL;IACT;IAEA,MAAM4B,0BAA0B;QAC9B,GAAG/B,gBAAgB;QACnBwB,QAAQxB,iBAAiBwB,MAAM,CAACC,GAAG,CAAC,CAACtB,QAAUD,YAAYC;IAC7D;IAEA,OAAO;QACLF;QACA8B;IACF;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/utilities/updateFieldsConfig.ts"],"sourcesContent":["import type { CollectionConfig, GlobalConfig } from 'payload'\n\ninterface UpdateFieldsConfig {\n schemaPathMap: Record<string, string>\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 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","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.1",
3
+ "version": "3.68.0-beta.2",
4
4
  "private": false,
5
5
  "bugs": "https://github.com/ashbuilds/payload-ai/issues",
6
6
  "repository": "https://github.com/ashbuilds/payload-ai",
@@ -70,10 +70,10 @@
70
70
  "scripts": {
71
71
  "build": "pnpm copyfiles && pnpm build:types && pnpm build:swc",
72
72
  "build:dev": "pnpm build --watch",
73
- "build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
73
+ "build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths --ignore '**/*.d.ts'",
74
74
  "build:types": "tsc --outDir dist --rootDir ./src",
75
75
  "clean": "rimraf {dist,*.tsbuildinfo}",
76
- "copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
76
+ "copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json,d.ts}\" dist/",
77
77
  "dev": "next dev dev --turbo",
78
78
  "dev:generate-importmap": "pnpm dev:payload generate:importmap",
79
79
  "dev:generate-types": "pnpm dev:payload generate:types",
@@ -1,3 +0,0 @@
1
- export { };
2
-
3
- //# sourceMappingURL=chat.d.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/endpoints/chat.d.ts"],"sourcesContent":["import type { Endpoint } from 'payload';\n\nimport type { PluginConfig } from '../types.js';\nexport declare const Chat: (pluginConfig: PluginConfig) => Endpoint;\n"],"names":[],"mappings":"AAGA,WAAoE"}
@@ -1,3 +0,0 @@
1
- export { };
2
-
3
- //# sourceMappingURL=payload-ai.d.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/payload-ai.d.ts"],"sourcesContent":["import type { GenerateObjectResult } from 'ai'\n// Type definitions for payload.ai API\nimport type { Payload } from 'payload'\n\nimport type {\n MediaResult,\n PayloadGenerateMediaArgs,\n PayloadGenerateObjectArgs,\n PayloadGenerateTextArgs,\n} from './ai/core/types.js'\n\ndeclare module 'payload' {\n interface BasePayload {\n ai: {\n /**\n * @deprecated Use generateObject or generateText instead\n * Legacy generate method for backward compatibility\n */\n generate: (args: unknown) => Promise<unknown>\n\n /**\n * Generate media (images or videos)\n * @param args - Generation arguments including provider, model, prompt, and media options\n * @returns Promise resolving to either a file or async job info\n */\n generateMedia: (args: Omit<PayloadGenerateMediaArgs, 'payload'>) => Promise<MediaResult>\n\n /**\n * Generate structured output with schema validation\n * @param args - Generation arguments including provider, model, prompt, and schema\n * @returns Promise resolving to the generated object\n */\n generateObject: <T = unknown>(args: Omit<PayloadGenerateObjectArgs, 'payload'>) => Promise<GenerateObjectResult<T>>\n\n /**\n * Generate simple text output\n * @param args - Generation arguments including provider, model, and prompt\n * @returns Promise resolving to the generated text\n */\n generateText: (args: Omit<PayloadGenerateTextArgs, 'payload'>) => Promise<string>\n\n /**\n * Get a specific model instance\n * @param provider - Provider name (e.g., 'openai', 'anthropic')\n * @param modelId - Model ID (e.g., 'gpt-4', 'claude-3')\n * @param type - Model type ('text', 'image', or 'tts')\n * @returns Promise resolving to the model instance\n */\n getModel: (provider: string, modelId: string, type?: 'image' | 'text' | 'tts') => Promise<unknown>\n\n /**\n * Get the provider registry\n * @returns Promise resolving to the provider registry\n */\n getRegistry: () => Promise<Record<string, unknown>>\n\n /**\n * Stream structured output with schema validation\n * @param args - Generation arguments including provider, model, prompt, and schema\n * @returns Response stream\n */\n streamObject: <T = unknown>(\n args: Omit<PayloadGenerateObjectArgs, 'payload'>,\n ) => Promise<Response>\n\n /**\n * Stream text output\n * @param args - Generation arguments including provider, model, and prompt\n * @returns Response stream\n */\n streamText: (args: Omit<PayloadGenerateTextArgs, 'payload'>) => Promise<Response>\n }\n }\n}"],"names":[],"mappings":"AAIA,WAK2B"}
package/dist/styles.d.js DELETED
@@ -1,2 +0,0 @@
1
-
2
- //# sourceMappingURL=styles.d.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/styles.d.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
-
2
- //# sourceMappingURL=handlebars-async-helpers.d.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/types/handlebars-async-helpers.d.ts"],"names":[],"mappings":""}