@ai-stack/payloadcms 3.2.20-beta → 3.2.21-beta

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 (63) hide show
  1. package/dist/ai/models/anthropic/index.js +9 -15
  2. package/dist/ai/models/anthropic/index.js.map +1 -1
  3. package/dist/ai/models/generateObject.d.ts +11 -0
  4. package/dist/ai/models/generateObject.js +22 -0
  5. package/dist/ai/models/generateObject.js.map +1 -0
  6. package/dist/ai/models/openai/index.js +19 -17
  7. package/dist/ai/models/openai/index.js.map +1 -1
  8. package/dist/collections/Instructions.js +2 -0
  9. package/dist/collections/Instructions.js.map +1 -1
  10. package/dist/endpoints/index.js +55 -6
  11. package/dist/endpoints/index.js.map +1 -1
  12. package/dist/fields/ComposeField/ComposeField.js +5 -3
  13. package/dist/fields/ComposeField/ComposeField.js.map +1 -1
  14. package/dist/fields/ComposeField/ComposeField.jsx +32 -0
  15. package/dist/fields/LexicalEditor/ComposeFeatureComponent.js +1 -1
  16. package/dist/fields/LexicalEditor/ComposeFeatureComponent.js.map +1 -1
  17. package/dist/fields/LexicalEditor/ComposeFeatureComponent.jsx +24 -0
  18. package/dist/fields/LexicalEditor/feature.client.jsx +21 -0
  19. package/dist/fields/PromptEditorField/PromptEditorField.jsx +42 -0
  20. package/dist/fields/SelectField/SelectField.jsx +38 -0
  21. package/dist/providers/FieldProvider/FieldProvider.d.ts +7 -4
  22. package/dist/providers/FieldProvider/FieldProvider.js +7 -6
  23. package/dist/providers/FieldProvider/FieldProvider.js.map +1 -1
  24. package/dist/providers/FieldProvider/FieldProvider.jsx +27 -0
  25. package/dist/providers/FieldProvider/useFieldProps.d.ts +1 -1
  26. package/dist/providers/FieldProvider/useFieldProps.js +2 -2
  27. package/dist/providers/FieldProvider/useFieldProps.js.map +1 -1
  28. package/dist/providers/InstructionsProvider/InstructionsProvider.jsx +45 -0
  29. package/dist/types.d.ts +4 -4
  30. package/dist/types.js.map +1 -1
  31. package/dist/ui/Compose/Compose.js +12 -81
  32. package/dist/ui/Compose/Compose.js.map +1 -1
  33. package/dist/ui/Compose/Compose.jsx +141 -0
  34. package/dist/ui/Compose/UndoRedoActions.jsx +34 -0
  35. package/dist/ui/Compose/compose.module.css +99 -12
  36. package/dist/ui/Compose/hooks/menu/Item.jsx +15 -0
  37. package/dist/ui/Compose/hooks/menu/TranslateMenu.jsx +58 -0
  38. package/dist/ui/Compose/hooks/menu/items.jsx +10 -0
  39. package/dist/ui/Compose/hooks/menu/useMenu.js +1 -1
  40. package/dist/ui/Compose/hooks/menu/useMenu.js.map +1 -1
  41. package/dist/ui/Compose/hooks/menu/useMenu.jsx +89 -0
  42. package/dist/ui/Compose/hooks/useActiveFieldTracking.d.ts +5 -0
  43. package/dist/ui/Compose/hooks/useActiveFieldTracking.js +148 -0
  44. package/dist/ui/Compose/hooks/useActiveFieldTracking.js.map +1 -0
  45. package/dist/ui/Compose/hooks/useGenerate.js +46 -79
  46. package/dist/ui/Compose/hooks/useGenerate.js.map +1 -1
  47. package/dist/ui/Icons/Icons.jsx +78 -0
  48. package/dist/ui/Icons/LottieAnimation.jsx +64 -0
  49. package/dist/utilities/extractPromptAttachments.d.ts +2 -2
  50. package/dist/utilities/extractPromptAttachments.js.map +1 -1
  51. package/dist/utilities/fieldToJsonSchema.d.ts +37 -0
  52. package/dist/utilities/fieldToJsonSchema.js +274 -0
  53. package/dist/utilities/fieldToJsonSchema.js.map +1 -0
  54. package/dist/utilities/getFieldBySchemaPath.d.ts +12 -1
  55. package/dist/utilities/getFieldBySchemaPath.js +63 -29
  56. package/dist/utilities/getFieldBySchemaPath.js.map +1 -1
  57. package/package.json +2 -1
  58. package/dist/ai/models/anthropic/generateRichText.d.ts +0 -1
  59. package/dist/ai/models/anthropic/generateRichText.js +0 -36
  60. package/dist/ai/models/anthropic/generateRichText.js.map +0 -1
  61. package/dist/ai/models/openai/generateRichText.d.ts +0 -1
  62. package/dist/ai/models/openai/generateRichText.js +0 -37
  63. package/dist/ai/models/openai/generateRichText.js.map +0 -1
@@ -0,0 +1,64 @@
1
+ // @ts-nocheck
2
+ import React, { useEffect, useRef, useState } from 'react';
3
+ import styles from './icons.module.css';
4
+ const LottieAnimation = ({ isLoading = false }) => {
5
+ const svgRef = useRef(null);
6
+ const [animations, setAnimations] = useState([]);
7
+ useEffect(() => {
8
+ const svg = svgRef.current;
9
+ if (!svg)
10
+ return;
11
+ const animateTransform = (element, keyframes) => {
12
+ const animation = element.animate(keyframes, {
13
+ direction: 'alternate',
14
+ duration: 1000,
15
+ easing: 'ease-in-out',
16
+ iterations: Infinity,
17
+ });
18
+ return animation;
19
+ };
20
+ // Animate Group 2 (Rectangle)
21
+ const rectangle = svg.querySelector('#group2');
22
+ const rectangleAnimation = animateTransform(rectangle, [
23
+ { transform: 'translate(0, 0) scale(1)' },
24
+ { transform: 'translate(0, 0) scale(2.54)' },
25
+ { transform: 'translate(0, 0) scale(1)' },
26
+ ]);
27
+ // Animate Group 3 (Triangle)
28
+ const triangle = svg.querySelector('#group3');
29
+ const triangleAnimation = animateTransform(triangle, [
30
+ { transform: 'translate(-69.5px, 77.5px) scale(1)' },
31
+ { transform: 'translate(-70px, 73px) scale(0.36)' },
32
+ { transform: 'translate(-69.5px, 77.5px) scale(1)' },
33
+ ]);
34
+ setAnimations([rectangleAnimation, triangleAnimation]);
35
+ // Clean up animations on unmount
36
+ return () => {
37
+ rectangleAnimation.cancel();
38
+ triangleAnimation.cancel();
39
+ };
40
+ }, []);
41
+ useEffect(() => {
42
+ if (isLoading) {
43
+ animations.forEach((animation) => animation.play());
44
+ }
45
+ else {
46
+ animations.forEach((animation) => animation.pause());
47
+ }
48
+ }, [isLoading, animations]);
49
+ return (<span style={{
50
+ left: '3px',
51
+ position: 'relative',
52
+ top: '-6px',
53
+ }}>
54
+ <svg height="41" ref={svgRef} viewBox="-250 -250 500 500" width="41">
55
+ <g id="group2">
56
+ <rect className={styles.color_fill} height="41" width="41" x="-20.5" y="-20.5"/>
57
+ </g>
58
+ <g id="group3">
59
+ <path className={styles.color_fill} d="M48.5 57.5L48.5 -57.5L-49.5 -1.093L48.5 57.5Z"/>
60
+ </g>
61
+ </svg>
62
+ </span>);
63
+ };
64
+ export default LottieAnimation;
@@ -1,2 +1,2 @@
1
- import type { UserModelMessage } from "ai";
2
- export declare function extractPromptAttachments(prompt: string): UserModelMessage[];
1
+ import type { ModelMessage } from 'ai';
2
+ export declare function extractPromptAttachments(prompt: string): ModelMessage[];
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/extractPromptAttachments.ts"],"sourcesContent":["import type { UserModelMessage } from \"ai\"\n\n// Converts prompt into messages, extracting images in the process\nexport function extractPromptAttachments(prompt: string): UserModelMessage[] {\n // Regex to match absolute HTTPS URLs with image extensions\n const imageUrlRegex = /https:\\/\\/\\S+\\.(?:png|jpe?g|webp)/gi\n \n const messages: UserModelMessage[] = []\n const imageUrls: string[] = []\n \n // Find all image URLs in the prompt\n let match\n while ((match = imageUrlRegex.exec(prompt)) !== null) {\n imageUrls.push(match[0])\n }\n \n // Create image messages first\n for (const imageUrl of imageUrls) {\n messages.push({\n content: [\n {\n type: 'image',\n image: new URL(imageUrl)\n }\n ],\n role: 'user'\n })\n }\n \n // Add the text prompt as a regular user message if there's any text left\n messages.push({\n content: prompt,\n role: 'user'\n })\n\n return messages\n}"],"names":["extractPromptAttachments","prompt","imageUrlRegex","messages","imageUrls","match","exec","push","imageUrl","content","type","image","URL","role"],"mappings":"AAEA,kEAAkE;AAClE,OAAO,SAASA,yBAAyBC,MAAc;IACrD,2DAA2D;IAC3D,MAAMC,gBAAgB;IAEtB,MAAMC,WAA+B,EAAE;IACvC,MAAMC,YAAsB,EAAE;IAE9B,oCAAoC;IACpC,IAAIC;IACJ,MAAO,AAACA,CAAAA,QAAQH,cAAcI,IAAI,CAACL,OAAM,MAAO,KAAM;QACpDG,UAAUG,IAAI,CAACF,KAAK,CAAC,EAAE;IACzB;IAEA,8BAA8B;IAC9B,KAAK,MAAMG,YAAYJ,UAAW;QAChCD,SAASI,IAAI,CAAC;YACZE,SAAS;gBACP;oBACEC,MAAM;oBACNC,OAAO,IAAIC,IAAIJ;gBACjB;aACD;YACDK,MAAM;QACR;IACF;IAEA,yEAAyE;IACzEV,SAASI,IAAI,CAAC;QACZE,SAASR;QACTY,MAAM;IACR;IAEA,OAAOV;AACT"}
1
+ {"version":3,"sources":["../../src/utilities/extractPromptAttachments.ts"],"sourcesContent":["import type { ModelMessage } from 'ai'\n\n// Converts prompt into messages, extracting images in the process\nexport function extractPromptAttachments(prompt: string): ModelMessage[] {\n // Regex to match absolute HTTPS URLs with image extensions\n const imageUrlRegex = /https:\\/\\/\\S+\\.(?:png|jpe?g|webp)/gi\n \n const messages: ModelMessage[] = []\n const imageUrls: string[] = []\n \n // Find all image URLs in the prompt\n let match\n while ((match = imageUrlRegex.exec(prompt)) !== null) {\n imageUrls.push(match[0])\n }\n \n // Create image messages first\n for (const imageUrl of imageUrls) {\n messages.push({\n content: [\n {\n type: 'image',\n image: new URL(imageUrl)\n }\n ],\n role: 'user'\n })\n }\n \n // Add the text prompt as a regular user message if there's any text left\n messages.push({\n content: prompt,\n role: 'user'\n })\n\n return messages\n}"],"names":["extractPromptAttachments","prompt","imageUrlRegex","messages","imageUrls","match","exec","push","imageUrl","content","type","image","URL","role"],"mappings":"AAEA,kEAAkE;AAClE,OAAO,SAASA,yBAAyBC,MAAc;IACrD,2DAA2D;IAC3D,MAAMC,gBAAgB;IAEtB,MAAMC,WAA2B,EAAE;IACnC,MAAMC,YAAsB,EAAE;IAE9B,oCAAoC;IACpC,IAAIC;IACJ,MAAO,AAACA,CAAAA,QAAQH,cAAcI,IAAI,CAACL,OAAM,MAAO,KAAM;QACpDG,UAAUG,IAAI,CAACF,KAAK,CAAC,EAAE;IACzB;IAEA,8BAA8B;IAC9B,KAAK,MAAMG,YAAYJ,UAAW;QAChCD,SAASI,IAAI,CAAC;YACZE,SAAS;gBACP;oBACEC,MAAM;oBACNC,OAAO,IAAIC,IAAIJ;gBACjB;aACD;YACDK,MAAM;QACR;IACF;IAEA,yEAAyE;IACzEV,SAASI,IAAI,CAAC;QACZE,SAASR;QACTY,MAAM;IACR;IAEA,OAAOV;AACT"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * fieldToJsonSchema
3
+ * Convert a Payload Field (server or client) into a minimal JSON Schema object,
4
+ * wrapped as { type: 'object', properties: { [name]: valueSchema }, required: [...] }
5
+ *
6
+ * Supported types:
7
+ * - text, textarea, select, number, date, code, email, json
8
+ * Arrays are emitted only when field.hasMany is true and the field type supports hasMany
9
+ * (text, textarea, select; for others only if your config truly sets hasMany).
10
+ */
11
+ export type JsonSchema = Record<string, any>;
12
+ type BaseField = {
13
+ admin?: {
14
+ description?: unknown;
15
+ language?: unknown;
16
+ };
17
+ hasMany?: boolean;
18
+ jsonSchema?: unknown;
19
+ max?: number;
20
+ maxRows?: number;
21
+ min?: number;
22
+ minRows?: number;
23
+ name?: string;
24
+ options?: Array<{
25
+ label?: unknown;
26
+ value: number | string;
27
+ } | number | string>;
28
+ required?: boolean;
29
+ schema?: unknown;
30
+ type?: string;
31
+ typescriptSchema?: unknown;
32
+ };
33
+ export declare function fieldToJsonSchema(fieldInput: BaseField, opts?: {
34
+ nameOverride?: string;
35
+ wrapObject?: boolean;
36
+ }): JsonSchema;
37
+ export {};
@@ -0,0 +1,274 @@
1
+ /**
2
+ * fieldToJsonSchema
3
+ * Convert a Payload Field (server or client) into a minimal JSON Schema object,
4
+ * wrapped as { type: 'object', properties: { [name]: valueSchema }, required: [...] }
5
+ *
6
+ * Supported types:
7
+ * - text, textarea, select, number, date, code, email, json
8
+ * Arrays are emitted only when field.hasMany is true and the field type supports hasMany
9
+ * (text, textarea, select; for others only if your config truly sets hasMany).
10
+ */ function isString(s) {
11
+ return typeof s === 'string';
12
+ }
13
+ function isPlainObject(o) {
14
+ return !!o && typeof o === 'object' && !Array.isArray(o);
15
+ }
16
+ function getDescription(field) {
17
+ const d = field?.admin?.description;
18
+ return typeof d === 'string' ? d : undefined;
19
+ }
20
+ function stringWithDescription(field) {
21
+ const out = {
22
+ type: 'string'
23
+ };
24
+ const description = getDescription(field);
25
+ if (description) {
26
+ out.description = description;
27
+ }
28
+ return out;
29
+ }
30
+ function numberWithBounds(field) {
31
+ const out = {
32
+ type: 'number'
33
+ };
34
+ if (typeof field.min === 'number') {
35
+ out.minimum = field.min;
36
+ }
37
+ if (typeof field.max === 'number') {
38
+ out.maximum = field.max;
39
+ }
40
+ const description = getDescription(field);
41
+ if (description) {
42
+ out.description = description;
43
+ }
44
+ return out;
45
+ }
46
+ function dateSchema(field) {
47
+ const out = {
48
+ type: 'string',
49
+ format: 'date-time'
50
+ };
51
+ const description = getDescription(field);
52
+ if (description) {
53
+ out.description = description;
54
+ }
55
+ return out;
56
+ }
57
+ function codeSchema(field) {
58
+ const out = {
59
+ type: 'string'
60
+ };
61
+ let description = getDescription(field);
62
+ const lang = field?.admin?.language;
63
+ if (typeof lang === 'string' && lang.trim()) {
64
+ description = description ? `${description} (language: ${lang})` : `language: ${lang}`;
65
+ }
66
+ if (description) {
67
+ out.description = description;
68
+ }
69
+ return out;
70
+ }
71
+ function emailSchema(field) {
72
+ const out = {
73
+ type: 'string',
74
+ format: 'email'
75
+ };
76
+ const description = getDescription(field);
77
+ if (description) {
78
+ out.description = description;
79
+ }
80
+ return out;
81
+ }
82
+ function jsonValueSchema(field) {
83
+ // Prefer a provided JSON Schema object
84
+ if (isPlainObject(field.jsonSchema)) {
85
+ return field.jsonSchema;
86
+ }
87
+ if (isPlainObject(field.schema)) {
88
+ return field.schema;
89
+ }
90
+ // typescriptSchema cannot be executed here; default to object
91
+ return {
92
+ type: 'object'
93
+ };
94
+ }
95
+ function normalizeSelectOptions(field) {
96
+ const raw = field.options || [];
97
+ const values = [];
98
+ for (const opt of raw){
99
+ if (typeof opt === 'string' || typeof opt === 'number') {
100
+ values.push(opt);
101
+ } else if (isPlainObject(opt) && 'value' in opt) {
102
+ const v = opt.value;
103
+ if (typeof v === 'string' || typeof v === 'number') {
104
+ values.push(v);
105
+ }
106
+ }
107
+ }
108
+ // Infer primitive type
109
+ const allNumbers = values.length > 0 && values.every((v)=>typeof v === 'number');
110
+ const valueType = allNumbers ? 'number' : 'string';
111
+ return {
112
+ values,
113
+ valueType
114
+ };
115
+ }
116
+ function supportsHasMany(fieldType) {
117
+ // Out of the box: text, textarea, select support hasMany
118
+ // Others can be arrays only if your config truly sets hasMany; we return boolean based on type here.
119
+ return fieldType === 'text' || fieldType === 'textarea' || fieldType === 'select';
120
+ }
121
+ export function fieldToJsonSchema(fieldInput, opts) {
122
+ const field = fieldInput || {};
123
+ const name = isString(opts?.nameOverride) && opts?.nameOverride.length ? opts.nameOverride : field.name || 'value';
124
+ const type = field.type;
125
+ let valueSchema = null;
126
+ switch(type){
127
+ case 'code':
128
+ {
129
+ const base = codeSchema(field);
130
+ if (field.hasMany) {
131
+ valueSchema = {
132
+ type: 'array',
133
+ items: base
134
+ };
135
+ } else {
136
+ valueSchema = base;
137
+ }
138
+ break;
139
+ }
140
+ case 'date':
141
+ {
142
+ const base = dateSchema(field);
143
+ if (field.hasMany) {
144
+ valueSchema = {
145
+ type: 'array',
146
+ items: base
147
+ };
148
+ } else {
149
+ valueSchema = base;
150
+ }
151
+ break;
152
+ }
153
+ case 'email':
154
+ {
155
+ const base = emailSchema(field);
156
+ if (field.hasMany) {
157
+ valueSchema = {
158
+ type: 'array',
159
+ items: base
160
+ };
161
+ } else {
162
+ valueSchema = base;
163
+ }
164
+ break;
165
+ }
166
+ case 'json':
167
+ {
168
+ const base = jsonValueSchema(field);
169
+ if (field.hasMany) {
170
+ valueSchema = {
171
+ type: 'array',
172
+ items: base
173
+ };
174
+ } else {
175
+ valueSchema = base;
176
+ }
177
+ break;
178
+ }
179
+ case 'number':
180
+ {
181
+ const base = numberWithBounds(field);
182
+ if (field.hasMany) {
183
+ // Respect hasMany only if truly configured; Payload rarely uses hasMany for number, but allow if present.
184
+ valueSchema = {
185
+ type: 'array',
186
+ items: base
187
+ };
188
+ } else {
189
+ valueSchema = base;
190
+ }
191
+ break;
192
+ }
193
+ case 'select':
194
+ {
195
+ const { values, valueType } = normalizeSelectOptions(field);
196
+ const baseSingle = {
197
+ type: valueType,
198
+ enum: values
199
+ };
200
+ const description = getDescription(field);
201
+ if (description) {
202
+ baseSingle.description = description;
203
+ }
204
+ if (field.hasMany && supportsHasMany(type)) {
205
+ valueSchema = {
206
+ type: 'array',
207
+ items: {
208
+ type: valueType,
209
+ enum: values
210
+ },
211
+ ...description ? {
212
+ description
213
+ } : {}
214
+ };
215
+ } else {
216
+ valueSchema = baseSingle;
217
+ }
218
+ break;
219
+ }
220
+ case 'text':
221
+ case 'textarea':
222
+ {
223
+ const base = stringWithDescription(field);
224
+ if (field.hasMany && supportsHasMany(type)) {
225
+ const arr = {
226
+ type: 'array',
227
+ items: {
228
+ type: 'string'
229
+ }
230
+ };
231
+ if (typeof field.minRows === 'number') {
232
+ arr.minItems = field.minRows;
233
+ }
234
+ if (typeof field.maxRows === 'number') {
235
+ arr.maxItems = field.maxRows;
236
+ }
237
+ if (base.description) {
238
+ arr.description = base.description;
239
+ }
240
+ valueSchema = arr;
241
+ } else {
242
+ valueSchema = base;
243
+ }
244
+ break;
245
+ }
246
+ default:
247
+ {
248
+ // Unsupported type: return null to allow caller to decide how to proceed (e.g., no schema)
249
+ valueSchema = null;
250
+ break;
251
+ }
252
+ }
253
+ const wrap = opts?.wrapObject !== false;
254
+ if (!wrap) {
255
+ return valueSchema || {};
256
+ }
257
+ if (!valueSchema) {
258
+ // Return undefined-like schema if not supported; caller may choose to skip passing schema
259
+ return {};
260
+ }
261
+ const schema = {
262
+ type: 'object',
263
+ additionalProperties: false,
264
+ properties: {
265
+ [name]: valueSchema
266
+ },
267
+ required: [
268
+ name
269
+ ]
270
+ };
271
+ return schema;
272
+ }
273
+
274
+ //# sourceMappingURL=fieldToJsonSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/fieldToJsonSchema.ts"],"sourcesContent":["/**\n * fieldToJsonSchema\n * Convert a Payload Field (server or client) into a minimal JSON Schema object,\n * wrapped as { type: 'object', properties: { [name]: valueSchema }, required: [...] }\n *\n * Supported types:\n * - text, textarea, select, number, date, code, email, json\n * Arrays are emitted only when field.hasMany is true and the field type supports hasMany\n * (text, textarea, select; for others only if your config truly sets hasMany).\n */\n\nexport type JsonSchema = Record<string, any>;\n\n// Narrowed minimal typing to avoid anywhere possible without pulling the full payload types at runtime.\n// In a Payload project, you can import type { Field, ClientField } from 'payload' and use those instead.\ntype BaseField = {\n admin?: {\n description?: unknown;\n language?: unknown;\n };\n hasMany?: boolean;\n // json\n jsonSchema?: unknown;\n max?: number;\n maxRows?: number;\n // number\n min?: number;\n // text/textarea\n minRows?: number;\n name?: string;\n // select\n options?: Array<\n | {\n label?: unknown;\n value: number | string;\n }\n | number\n | string\n >;\n required?: boolean;\n schema?: unknown;\n type?: string;\n typescriptSchema?: unknown;\n};\n\nfunction isString(s: unknown): s is string {\n return typeof s === 'string';\n}\n\nfunction isPlainObject(o: unknown): o is Record<string, unknown> {\n return !!o && typeof o === 'object' && !Array.isArray(o);\n}\n\nfunction getDescription(field: BaseField): string | undefined {\n const d = field?.admin?.description;\n return typeof d === 'string' ? d : undefined;\n}\n\nfunction stringWithDescription(field: BaseField) {\n const out: Record<string, any> = { type: 'string' };\n const description = getDescription(field);\n if (description) {out.description = description;}\n return out;\n}\n\nfunction numberWithBounds(field: BaseField) {\n const out: Record<string, any> = { type: 'number' };\n if (typeof field.min === 'number') {out.minimum = field.min;}\n if (typeof field.max === 'number') {out.maximum = field.max;}\n const description = getDescription(field);\n if (description) {out.description = description;}\n return out;\n}\n\nfunction dateSchema(field: BaseField) {\n const out: Record<string, any> = { type: 'string', format: 'date-time' };\n const description = getDescription(field);\n if (description) {out.description = description;}\n return out;\n}\n\nfunction codeSchema(field: BaseField) {\n const out: Record<string, any> = { type: 'string' };\n let description = getDescription(field);\n const lang = field?.admin?.language;\n if (typeof lang === 'string' && lang.trim()) {\n description = description ? `${description} (language: ${lang})` : `language: ${lang}`;\n }\n if (description) {out.description = description;}\n return out;\n}\n\nfunction emailSchema(field: BaseField) {\n const out: Record<string, any> = { type: 'string', format: 'email' };\n const description = getDescription(field);\n if (description) {out.description = description;}\n return out;\n}\n\nfunction jsonValueSchema(field: BaseField) {\n // Prefer a provided JSON Schema object\n if (isPlainObject(field.jsonSchema)) {return field.jsonSchema as object;}\n if (isPlainObject(field.schema)) {return field.schema as object;}\n\n // typescriptSchema cannot be executed here; default to object\n return { type: 'object' };\n}\n\nfunction normalizeSelectOptions(field: BaseField): { values: Array<number | string>; valueType: 'number' | 'string' } {\n const raw = field.options || [];\n const values: Array<number | string> = [];\n\n for (const opt of raw) {\n if (typeof opt === 'string' || typeof opt === 'number') {\n values.push(opt);\n } else if (isPlainObject(opt) && ('value' in opt)) {\n const v = (opt as any).value;\n if (typeof v === 'string' || typeof v === 'number') {\n values.push(v);\n }\n }\n }\n\n // Infer primitive type\n const allNumbers = values.length > 0 && values.every((v) => typeof v === 'number');\n const valueType: 'number' | 'string' = allNumbers ? 'number' : 'string';\n return { values, valueType };\n}\n\nfunction supportsHasMany(fieldType: string | undefined): boolean {\n // Out of the box: text, textarea, select support hasMany\n // Others can be arrays only if your config truly sets hasMany; we return boolean based on type here.\n return fieldType === 'text' || fieldType === 'textarea' || fieldType === 'select';\n}\n\nexport function fieldToJsonSchema(\n fieldInput: BaseField,\n opts?: { nameOverride?: string; wrapObject?: boolean },\n): JsonSchema {\n const field: BaseField = fieldInput || {};\n const name = isString(opts?.nameOverride) && opts?.nameOverride.length ? opts.nameOverride : (field.name || 'value');\n const type = field.type;\n\n let valueSchema: null | Record<string, any> = null;\n\n switch (type) {\n case 'code': {\n const base = codeSchema(field);\n if (field.hasMany) {\n valueSchema = { type: 'array', items: base };\n } else {\n valueSchema = base;\n }\n break;\n }\n case 'date': {\n const base = dateSchema(field);\n if (field.hasMany) {\n valueSchema = { type: 'array', items: base };\n } else {\n valueSchema = base;\n }\n break;\n }\n\n case 'email': {\n const base = emailSchema(field);\n if (field.hasMany) {\n valueSchema = { type: 'array', items: base };\n } else {\n valueSchema = base;\n }\n break;\n }\n\n case 'json': {\n const base = jsonValueSchema(field);\n if (field.hasMany) {\n valueSchema = { type: 'array', items: base };\n } else {\n valueSchema = base as Record<string, any>;\n }\n break;\n }\n\n case 'number': {\n const base = numberWithBounds(field);\n if (field.hasMany) {\n // Respect hasMany only if truly configured; Payload rarely uses hasMany for number, but allow if present.\n valueSchema = { type: 'array', items: base };\n } else {\n valueSchema = base;\n }\n break;\n }\n\n case 'select': {\n const { values, valueType } = normalizeSelectOptions(field);\n const baseSingle: Record<string, any> = { type: valueType, enum: values };\n const description = getDescription(field);\n if (description) {baseSingle.description = description;}\n\n if (field.hasMany && supportsHasMany(type)) {\n valueSchema = {\n type: 'array',\n items: { type: valueType, enum: values },\n ...(description ? { description } : {}),\n };\n } else {\n valueSchema = baseSingle;\n }\n break;\n }\n\n case 'text':\n case 'textarea': {\n const base = stringWithDescription(field);\n if (field.hasMany && supportsHasMany(type)) {\n const arr: Record<string, any> = {\n type: 'array',\n items: { type: 'string' },\n };\n if (typeof field.minRows === 'number') {arr.minItems = field.minRows;}\n if (typeof field.maxRows === 'number') {arr.maxItems = field.maxRows;}\n if (base.description) {arr.description = base.description;}\n valueSchema = arr;\n } else {\n valueSchema = base;\n }\n break;\n }\n\n default: {\n // Unsupported type: return null to allow caller to decide how to proceed (e.g., no schema)\n valueSchema = null;\n break;\n }\n }\n\n const wrap = opts?.wrapObject !== false;\n\n if (!wrap) {\n return (valueSchema || {}) as JsonSchema;\n }\n\n if (!valueSchema) {\n // Return undefined-like schema if not supported; caller may choose to skip passing schema\n return {} as JsonSchema;\n }\n\n const schema: JsonSchema = {\n type: 'object',\n additionalProperties: false,\n properties: {\n [name]: valueSchema,\n },\n required: [name]\n };\n\n return schema;\n}\n"],"names":["isString","s","isPlainObject","o","Array","isArray","getDescription","field","d","admin","description","undefined","stringWithDescription","out","type","numberWithBounds","min","minimum","max","maximum","dateSchema","format","codeSchema","lang","language","trim","emailSchema","jsonValueSchema","jsonSchema","schema","normalizeSelectOptions","raw","options","values","opt","push","v","value","allNumbers","length","every","valueType","supportsHasMany","fieldType","fieldToJsonSchema","fieldInput","opts","name","nameOverride","valueSchema","base","hasMany","items","baseSingle","enum","arr","minRows","minItems","maxRows","maxItems","wrap","wrapObject","additionalProperties","properties","required"],"mappings":"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"}
@@ -1,2 +1,13 @@
1
1
  import type { ClientCollectionConfig, CollectionConfig, Field } from 'payload';
2
- export declare const getFieldBySchemaPath: (collectionConfig: ClientCollectionConfig | CollectionConfig, schemaPath: string) => Field | null;
2
+ type AnyCollectionConfig = ClientCollectionConfig | CollectionConfig;
3
+ /**
4
+ * Resolve a Payload field definition by a full schemaPath like:
5
+ * "{collectionSlug}.fieldA.subFieldB.blockSlug.innerField"
6
+ *
7
+ * Notes:
8
+ * - Tabs are a UI construct and are not part of schemaPath (fields inside tabs are at the same level).
9
+ * - Blocks include the block slug as part of the path (we must consume it between the block field and its inner fields).
10
+ * - Rows are skipped by this plugin&#39;s schema path mapping; support added defensively.
11
+ */
12
+ export declare const getFieldBySchemaPath: (collectionConfig: AnyCollectionConfig, schemaPath: string) => Field | null;
13
+ export {};
@@ -1,45 +1,79 @@
1
- export const getFieldBySchemaPath = (collectionConfig, schemaPath)=>{
2
- const pathParts = schemaPath.split('.');
3
- const targetFieldName = pathParts[pathParts.length - 1];
4
- const findField = (fields, remainingPath)=>{
1
+ /**
2
+ * Resolve a Payload field definition by a full schemaPath like:
3
+ * "{collectionSlug}.fieldA.subFieldB.blockSlug.innerField"
4
+ *
5
+ * Notes:
6
+ * - Tabs are a UI construct and are not part of schemaPath (fields inside tabs are at the same level).
7
+ * - Blocks include the block slug as part of the path (we must consume it between the block field and its inner fields).
8
+ * - Rows are skipped by this plugin&#39;s schema path mapping; support added defensively.
9
+ */ export const getFieldBySchemaPath = (collectionConfig, schemaPath)=>{
10
+ if (!collectionConfig || !schemaPath) {
11
+ return null;
12
+ }
13
+ const parts = schemaPath.split('.');
14
+ if (!parts.length) {
15
+ return null;
16
+ }
17
+ // Strip the collection slug prefix if present
18
+ const [collectionSlug, ...rest] = parts;
19
+ const pathParts = collectionSlug === collectionConfig.slug ? rest.filter(Boolean) : parts.filter(Boolean);
20
+ if (!pathParts.length) {
21
+ return null;
22
+ }
23
+ const findInFields = (fields, segments)=>{
24
+ if (!segments.length) {
25
+ return null;
26
+ }
27
+ const [current, ...remaining] = segments;
28
+ // First, try to match a field by name
5
29
  for (const field of fields){
6
- if (remainingPath.length === 1 && field.name === targetFieldName) {
7
- return field;
8
- }
9
- if (field.type === 'group' && field.fields) {
10
- const result = findField(field.fields, remainingPath.slice(1));
11
- if (result) {
12
- return result;
30
+ // Tabs do not contribute to path segments; search inside all tabs with the same segments
31
+ if (field.tabs) {
32
+ const tabs = field.tabs;
33
+ for (const tab of tabs){
34
+ const foundInTab = tab.fields && tab.fields.length ? findInFields(tab.fields, segments) : null;
35
+ if (foundInTab) {
36
+ return foundInTab;
37
+ }
13
38
  }
14
39
  }
15
- if (field.type === 'array' && field.fields) {
16
- const result = findField(field.fields, remainingPath.slice(1));
17
- if (result) {
18
- return result;
40
+ if (field.name === current) {
41
+ // If this is the last segment, we found the target field
42
+ if (remaining.length === 0) {
43
+ return field;
19
44
  }
20
- }
21
- if (field.type === 'tabs') {
22
- for (const tab of field.tabs){
23
- const result = findField(tab.fields, remainingPath);
24
- if (result) {
25
- return result;
45
+ // Recurse into composite field types
46
+ if (field.fields && Array.isArray(field.fields)) {
47
+ const found = findInFields(field.fields, remaining);
48
+ if (found) {
49
+ return found;
26
50
  }
27
51
  }
28
- }
29
- if (field.type === 'blocks') {
30
- for (const block of field.blocks){
31
- if (block.slug === remainingPath[0]) {
32
- const result = findField(block.fields, remainingPath.slice(1));
33
- if (result) {
34
- return result;
52
+ if (field.blocks && Array.isArray(field.blocks)) {
53
+ // Next segment should be a block slug, then continue into block fields
54
+ if (!remaining.length) {
55
+ return field;
56
+ } // path stops at block container (unlikely for our mapping)
57
+ const [blockSlug, ...afterBlock] = remaining;
58
+ const blocks = field.blocks;
59
+ const block = blocks.find((b)=>b.slug === blockSlug);
60
+ if (block) {
61
+ const found = findInFields(block.fields, afterBlock);
62
+ if (found) {
63
+ return found;
35
64
  }
36
65
  }
37
66
  }
38
67
  }
39
68
  }
69
+ // Not found at this level
40
70
  return null;
41
71
  };
42
- return findField(collectionConfig.fields, pathParts.slice(1));
72
+ const rootFields = collectionConfig.fields;
73
+ if (!rootFields || !Array.isArray(rootFields)) {
74
+ return null;
75
+ }
76
+ return findInFields(rootFields, pathParts);
43
77
  };
44
78
 
45
79
  //# sourceMappingURL=getFieldBySchemaPath.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/getFieldBySchemaPath.ts"],"sourcesContent":["import type { ClientCollectionConfig, CollectionConfig, Field } from 'payload'\n\nexport const getFieldBySchemaPath = (\n collectionConfig: ClientCollectionConfig | CollectionConfig,\n schemaPath: string, // e.g., \"posts.content\"\n): Field | null => {\n const pathParts = schemaPath.split('.')\n const targetFieldName = pathParts[pathParts.length - 1]\n\n const findField = (fields: any[], remainingPath: string[]): Field | null => {\n for (const field of fields) {\n if (remainingPath.length === 1 && field.name === targetFieldName) {\n return field\n }\n\n if (field.type === 'group' && field.fields) {\n const result = findField(field.fields, remainingPath.slice(1))\n if (result) {\n return result\n }\n }\n\n if (field.type === 'array' && field.fields) {\n const result = findField(field.fields, remainingPath.slice(1))\n if (result) {\n return result\n }\n }\n\n if (field.type === 'tabs') {\n for (const tab of field.tabs) {\n const result = findField(tab.fields, remainingPath)\n if (result) {\n return result\n }\n }\n }\n\n if (field.type === 'blocks') {\n for (const block of field.blocks) {\n if (block.slug === remainingPath[0]) {\n const result = findField(block.fields, remainingPath.slice(1))\n if (result) {\n return result\n }\n }\n }\n }\n }\n\n return null\n }\n\n return findField(collectionConfig.fields, pathParts.slice(1))\n}\n"],"names":["getFieldBySchemaPath","collectionConfig","schemaPath","pathParts","split","targetFieldName","length","findField","fields","remainingPath","field","name","type","result","slice","tab","tabs","block","blocks","slug"],"mappings":"AAEA,OAAO,MAAMA,uBAAuB,CAClCC,kBACAC;IAEA,MAAMC,YAAYD,WAAWE,KAAK,CAAC;IACnC,MAAMC,kBAAkBF,SAAS,CAACA,UAAUG,MAAM,GAAG,EAAE;IAEvD,MAAMC,YAAY,CAACC,QAAeC;QAChC,KAAK,MAAMC,SAASF,OAAQ;YAC1B,IAAIC,cAAcH,MAAM,KAAK,KAAKI,MAAMC,IAAI,KAAKN,iBAAiB;gBAChE,OAAOK;YACT;YAEA,IAAIA,MAAME,IAAI,KAAK,WAAWF,MAAMF,MAAM,EAAE;gBAC1C,MAAMK,SAASN,UAAUG,MAAMF,MAAM,EAAEC,cAAcK,KAAK,CAAC;gBAC3D,IAAID,QAAQ;oBACV,OAAOA;gBACT;YACF;YAEA,IAAIH,MAAME,IAAI,KAAK,WAAWF,MAAMF,MAAM,EAAE;gBAC1C,MAAMK,SAASN,UAAUG,MAAMF,MAAM,EAAEC,cAAcK,KAAK,CAAC;gBAC3D,IAAID,QAAQ;oBACV,OAAOA;gBACT;YACF;YAEA,IAAIH,MAAME,IAAI,KAAK,QAAQ;gBACzB,KAAK,MAAMG,OAAOL,MAAMM,IAAI,CAAE;oBAC5B,MAAMH,SAASN,UAAUQ,IAAIP,MAAM,EAAEC;oBACrC,IAAII,QAAQ;wBACV,OAAOA;oBACT;gBACF;YACF;YAEA,IAAIH,MAAME,IAAI,KAAK,UAAU;gBAC3B,KAAK,MAAMK,SAASP,MAAMQ,MAAM,CAAE;oBAChC,IAAID,MAAME,IAAI,KAAKV,aAAa,CAAC,EAAE,EAAE;wBACnC,MAAMI,SAASN,UAAUU,MAAMT,MAAM,EAAEC,cAAcK,KAAK,CAAC;wBAC3D,IAAID,QAAQ;4BACV,OAAOA;wBACT;oBACF;gBACF;YACF;QACF;QAEA,OAAO;IACT;IAEA,OAAON,UAAUN,iBAAiBO,MAAM,EAAEL,UAAUW,KAAK,CAAC;AAC5D,EAAC"}
1
+ {"version":3,"sources":["../../src/utilities/getFieldBySchemaPath.ts"],"sourcesContent":["import type { ClientCollectionConfig, CollectionConfig, Field } from 'payload'\n\ntype AnyCollectionConfig = ClientCollectionConfig | CollectionConfig\n\n/**\n * Resolve a Payload field definition by a full schemaPath like:\n * \"{collectionSlug}.fieldA.subFieldB.blockSlug.innerField\"\n *\n * Notes:\n * - Tabs are a UI construct and are not part of schemaPath (fields inside tabs are at the same level).\n * - Blocks include the block slug as part of the path (we must consume it between the block field and its inner fields).\n * - Rows are skipped by this plugin&#39;s schema path mapping; support added defensively.\n */\nexport const getFieldBySchemaPath = (\n collectionConfig: AnyCollectionConfig,\n schemaPath: string,\n): Field | null => {\n if (!collectionConfig || !schemaPath) {\n return null\n }\n\n const parts = schemaPath.split('.')\n if (!parts.length) {\n return null\n }\n\n // Strip the collection slug prefix if present\n const [collectionSlug, ...rest] = parts\n const pathParts =\n collectionSlug === collectionConfig.slug ? rest.filter(Boolean) : parts.filter(Boolean)\n\n if (!pathParts.length) {\n return null\n }\n\n const findInFields = (fields: Field[], segments: string[]): Field | null => {\n if (!segments.length) {\n return null\n }\n\n const [current, ...remaining] = segments\n\n // First, try to match a field by name\n for (const field of fields) {\n // Tabs do not contribute to path segments; search inside all tabs with the same segments\n if ((field as any).tabs) {\n const tabs = (field as any).tabs as Array<{ fields?: Field[] }>\n for (const tab of tabs) {\n const foundInTab =\n tab.fields && tab.fields.length ? findInFields(tab.fields, segments) : null\n if (foundInTab) {\n return foundInTab\n }\n }\n }\n\n if ((field as any).name === current) {\n // If this is the last segment, we found the target field\n if (remaining.length === 0) {\n return field\n }\n\n // Recurse into composite field types\n if ((field as any).fields && Array.isArray((field as any).fields)) {\n const found = findInFields((field as any).fields, remaining)\n if (found) {\n return found\n }\n }\n\n if ((field as any).blocks && Array.isArray((field as any).blocks)) {\n // Next segment should be a block slug, then continue into block fields\n if (!remaining.length) {\n return field\n } // path stops at block container (unlikely for our mapping)\n const [blockSlug, ...afterBlock] = remaining\n const blocks = (field as any).blocks as Array<{ fields: Field[]; slug: string }>\n const block = blocks.find((b) => b.slug === blockSlug)\n if (block) {\n const found = findInFields(block.fields, afterBlock)\n if (found) {\n return found\n }\n }\n }\n }\n }\n\n // Not found at this level\n return null\n }\n\n const rootFields = (collectionConfig as any).fields as Field[] | undefined\n if (!rootFields || !Array.isArray(rootFields)) {\n return null\n }\n\n return findInFields(rootFields, pathParts)\n}\n"],"names":["getFieldBySchemaPath","collectionConfig","schemaPath","parts","split","length","collectionSlug","rest","pathParts","slug","filter","Boolean","findInFields","fields","segments","current","remaining","field","tabs","tab","foundInTab","name","Array","isArray","found","blocks","blockSlug","afterBlock","block","find","b","rootFields"],"mappings":"AAIA;;;;;;;;CAQC,GACD,OAAO,MAAMA,uBAAuB,CAClCC,kBACAC;IAEA,IAAI,CAACD,oBAAoB,CAACC,YAAY;QACpC,OAAO;IACT;IAEA,MAAMC,QAAQD,WAAWE,KAAK,CAAC;IAC/B,IAAI,CAACD,MAAME,MAAM,EAAE;QACjB,OAAO;IACT;IAEA,8CAA8C;IAC9C,MAAM,CAACC,gBAAgB,GAAGC,KAAK,GAAGJ;IAClC,MAAMK,YACJF,mBAAmBL,iBAAiBQ,IAAI,GAAGF,KAAKG,MAAM,CAACC,WAAWR,MAAMO,MAAM,CAACC;IAEjF,IAAI,CAACH,UAAUH,MAAM,EAAE;QACrB,OAAO;IACT;IAEA,MAAMO,eAAe,CAACC,QAAiBC;QACrC,IAAI,CAACA,SAAST,MAAM,EAAE;YACpB,OAAO;QACT;QAEA,MAAM,CAACU,SAAS,GAAGC,UAAU,GAAGF;QAEhC,sCAAsC;QACtC,KAAK,MAAMG,SAASJ,OAAQ;YAC1B,yFAAyF;YACzF,IAAI,AAACI,MAAcC,IAAI,EAAE;gBACvB,MAAMA,OAAO,AAACD,MAAcC,IAAI;gBAChC,KAAK,MAAMC,OAAOD,KAAM;oBACtB,MAAME,aACJD,IAAIN,MAAM,IAAIM,IAAIN,MAAM,CAACR,MAAM,GAAGO,aAAaO,IAAIN,MAAM,EAAEC,YAAY;oBACzE,IAAIM,YAAY;wBACd,OAAOA;oBACT;gBACF;YACF;YAEA,IAAI,AAACH,MAAcI,IAAI,KAAKN,SAAS;gBACnC,yDAAyD;gBACzD,IAAIC,UAAUX,MAAM,KAAK,GAAG;oBAC1B,OAAOY;gBACT;gBAEA,qCAAqC;gBACrC,IAAI,AAACA,MAAcJ,MAAM,IAAIS,MAAMC,OAAO,CAAC,AAACN,MAAcJ,MAAM,GAAG;oBACjE,MAAMW,QAAQZ,aAAa,AAACK,MAAcJ,MAAM,EAAEG;oBAClD,IAAIQ,OAAO;wBACT,OAAOA;oBACT;gBACF;gBAEA,IAAI,AAACP,MAAcQ,MAAM,IAAIH,MAAMC,OAAO,CAAC,AAACN,MAAcQ,MAAM,GAAG;oBACjE,uEAAuE;oBACvE,IAAI,CAACT,UAAUX,MAAM,EAAE;wBACrB,OAAOY;oBACT,EAAE,2DAA2D;oBAC7D,MAAM,CAACS,WAAW,GAAGC,WAAW,GAAGX;oBACnC,MAAMS,SAAS,AAACR,MAAcQ,MAAM;oBACpC,MAAMG,QAAQH,OAAOI,IAAI,CAAC,CAACC,IAAMA,EAAErB,IAAI,KAAKiB;oBAC5C,IAAIE,OAAO;wBACT,MAAMJ,QAAQZ,aAAagB,MAAMf,MAAM,EAAEc;wBACzC,IAAIH,OAAO;4BACT,OAAOA;wBACT;oBACF;gBACF;YACF;QACF;QAEA,0BAA0B;QAC1B,OAAO;IACT;IAEA,MAAMO,aAAa,AAAC9B,iBAAyBY,MAAM;IACnD,IAAI,CAACkB,cAAc,CAACT,MAAMC,OAAO,CAACQ,aAAa;QAC7C,OAAO;IACT;IAEA,OAAOnB,aAAamB,YAAYvB;AAClC,EAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-stack/payloadcms",
3
- "version": "3.2.20-beta",
3
+ "version": "3.2.21-beta",
4
4
  "private": false,
5
5
  "bugs": "https://github.com/ashbuilds/payload-ai/issues",
6
6
  "repository": "https://github.com/ashbuilds/payload-ai",
@@ -127,6 +127,7 @@
127
127
  "@ai-sdk/react": "^2.0.39",
128
128
  "@ai-sdk/ui-utils": "^1.2.10",
129
129
  "@anthropic-ai/sdk": "^0.62.0",
130
+ "@fal-ai/client": "^1.7.0",
130
131
  "ai": "^5.0.39",
131
132
  "ajv": "^8.17.1",
132
133
  "elevenlabs": "^0.8.2",
@@ -1 +0,0 @@
1
- export declare const generateRichText: (text: string, options: any) => Response;
@@ -1,36 +0,0 @@
1
- import { anthropic } from '@ai-sdk/anthropic';
2
- import { jsonSchema, streamObject } from 'ai';
3
- import { extractPromptAttachments } from "../../../utilities/extractPromptAttachments.js";
4
- export const generateRichText = (text, options)=>{
5
- const streamResult = streamObject({
6
- maxOutputTokens: options.maxTokens || 5000,
7
- model: anthropic(options.model),
8
- onError: (error)=>{
9
- console.error(`generateRichText: `, error);
10
- },
11
- prompt: options.extractAttachments ? extractPromptAttachments(text) : text,
12
- schema: jsonSchema(options.editorSchema),
13
- system: `${options.system}
14
-
15
- RULES:
16
- - Generate original and unique content based on the given topic.
17
- - Strictly adhere to the specified layout and formatting instructions.
18
- - Utilize the provided rich text editor tools for appropriate formatting.
19
- - Ensure the output follows the structure of the sample output object.
20
- - Produce valid JSON with no undefined or null values.
21
- ---
22
- LAYOUT INSTRUCTIONS:
23
- ${options.layout}
24
-
25
- ---
26
- ADDITIONAL GUIDELINES:
27
- - Ensure coherence and logical flow between all sections.
28
- - Maintain a consistent tone and style throughout the content.
29
- - Use clear and concise language appropriate for the target audience.
30
- `,
31
- temperature: options.temperature || 0.7
32
- });
33
- return streamResult.toTextStreamResponse();
34
- };
35
-
36
- //# sourceMappingURL=generateRichText.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/ai/models/anthropic/generateRichText.ts"],"sourcesContent":["import { anthropic } from '@ai-sdk/anthropic'\nimport { jsonSchema, streamObject } from 'ai'\n\nimport {extractPromptAttachments} from \"../../../utilities/extractPromptAttachments.js\";\n\nexport const generateRichText = (text: string, options: any) => {\n const streamResult = streamObject({\n maxOutputTokens: options.maxTokens || 5000,\n model: anthropic(options.model),\n onError: (error) => {\n console.error(`generateRichText: `, error)\n },\n prompt: options.extractAttachments ? extractPromptAttachments(text) : text,\n schema: jsonSchema(options.editorSchema),\n system: `${options.system}\n\nRULES:\n- Generate original and unique content based on the given topic.\n- Strictly adhere to the specified layout and formatting instructions.\n- Utilize the provided rich text editor tools for appropriate formatting.\n- Ensure the output follows the structure of the sample output object.\n- Produce valid JSON with no undefined or null values.\n---\nLAYOUT INSTRUCTIONS:\n${options.layout}\n\n---\nADDITIONAL GUIDELINES:\n- Ensure coherence and logical flow between all sections.\n- Maintain a consistent tone and style throughout the content.\n- Use clear and concise language appropriate for the target audience.\n`,\n temperature: options.temperature || 0.7,\n })\n\n return streamResult.toTextStreamResponse()\n}\n"],"names":["anthropic","jsonSchema","streamObject","extractPromptAttachments","generateRichText","text","options","streamResult","maxOutputTokens","maxTokens","model","onError","error","console","prompt","extractAttachments","schema","editorSchema","system","layout","temperature","toTextStreamResponse"],"mappings":"AAAA,SAASA,SAAS,QAAQ,oBAAmB;AAC7C,SAASC,UAAU,EAAEC,YAAY,QAAQ,KAAI;AAE7C,SAAQC,wBAAwB,QAAO,iDAAiD;AAExF,OAAO,MAAMC,mBAAmB,CAACC,MAAcC;IAC7C,MAAMC,eAAeL,aAAa;QAChCM,iBAAiBF,QAAQG,SAAS,IAAI;QACtCC,OAAOV,UAAUM,QAAQI,KAAK;QAC9BC,SAAS,CAACC;YACRC,QAAQD,KAAK,CAAC,CAAC,kBAAkB,CAAC,EAAEA;QACtC;QACAE,QAAQR,QAAQS,kBAAkB,GAAGZ,yBAAyBE,QAAQA;QACtEW,QAAQf,WAAWK,QAAQW,YAAY;QACvCC,QAAQ,GAAGZ,QAAQY,MAAM,CAAC;;;;;;;;;;AAU9B,EAAEZ,QAAQa,MAAM,CAAC;;;;;;;AAOjB,CAAC;QACGC,aAAad,QAAQc,WAAW,IAAI;IACtC;IAEA,OAAOb,aAAac,oBAAoB;AAC1C,EAAC"}
@@ -1 +0,0 @@
1
- export declare const generateRichText: (text: string, options?: any) => Response;