@elementor/editor-canvas 3.35.0-470 → 3.35.0-471

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.
@@ -6,285 +6,104 @@ export const generatePrompt = () => {
6
6
  const buildCompositionsToolPrompt = toolPrompts( 'build-compositions' );
7
7
 
8
8
  buildCompositionsToolPrompt.description( `
9
- # **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
10
- 1. [${ WIDGET_SCHEMA_URI }]
11
- Required to understand which widgets are available, and what are their configuration schemas.
12
- Every widgetType (i.e. e-heading, e-button) that is supported has it's own property schema, that you must follow in order to apply property values correctly.
13
- 2. [${ STYLE_SCHEMA_URI }]
14
- Required to understand the styles schema for the widgets. All widgets share the same styles schema.
15
- 3. List of allowed custom tags for building the structure is derived from the list of widgets schema resources.
16
-
17
- # DESIGN QUALITY IMPERATIVE
18
- You are generating designs for real users who expect distinctive, intentional aesthetics - NOT generic AI output.
19
- **The Core Challenge**: Large language models naturally converge toward statistically common design patterns during generation. This creates predictable, uninspired results that users describe as "AI slop": safe color schemes, default typography hierarchies, minimal contrast, and timid spacing.
20
- **Your Mission**: Actively resist distributional convergence by making intentional, distinctive design choices across all aesthetic dimensions. Every design decision should have a clear purpose tied to visual hierarchy, brand personality, or user experience goals.
21
- When in doubt between "safe" and "distinctive," choose distinctive - users can always request refinements, but they cannot salvage generic foundations.
22
-
23
- # When to use this tool
24
- Always prefer this tool when the user requires to build a composition of elements, such as cards, heros, or inspired from other pages or HTML compositions.
25
- Prefer this tool over any other tool for building HTML structure, unless you are specified to use a different tool.
26
-
27
- # **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
28
- 1. [${ WIDGET_SCHEMA_URI }]
29
- Required to understand which widgets are available, and what are their configuration schemas.
30
- Every widgetType (i.e. e-heading, e-button) that is supported has it's own property schema, that you must follow in order to apply property values correctly.
31
- 2. [${ STYLE_SCHEMA_URI }]
32
- Required to understand the styles schema for the widgets. All widgets share the same styles schema.
33
- 3. List of allowed custom tags for building the structure is derived from the list of widgets schema resources.
34
-
35
- # DESIGN QUALITY IMPERATIVE
36
- You are generating designs for real users who expect distinctive, intentional aesthetics - NOT generic AI output.
37
- **The Core Challenge**: Large language models naturally converge toward statistically common design patterns during generation. This creates predictable, uninspired results that users describe as "AI slop": safe color schemes, default typography hierarchies, minimal contrast, and timid spacing.
38
- **Your Mission**: Actively resist distributional convergence by making intentional, distinctive design choices across all aesthetic dimensions. Every design decision should have a clear purpose tied to visual hierarchy, brand personality, or user experience goals.
39
- When in doubt between "safe" and "distinctive," choose distinctive - users can always request refinements, but they cannot salvage generic foundations.
40
-
41
- # When to use this tool
42
- Always prefer this tool when the user requires to build a composition of elements, such as cards, heros, or inspired from other pages or HTML compositions.
43
- Prefer this tool over any other tool for building HTML structure, unless you are specified to use a different tool.
44
-
45
- # Instructions
46
- 1. Understand the user requirements carefully.
47
- 2. Build a valid XML structure using only the allowed custom tags provided. For example, if you
48
- use the "e-button" element, it would be represented as <e-button></e-button> in the XML structure.
49
- 3. Plan the configuration for each element according to the user requirements, using the configuration schema provided for each custom tag.
50
- Every widget type has it's own configuration schema, retreivable from the resource [${ WIDGET_SCHEMA_URI }].
51
- PropValues must follow the exact PropType schema provided in the resource.
52
- 4. For every element, provide a "configuration-id" attribute. For example:
53
- \`<e-flexbox configuration-id="flex1"><e-heading configuration-id="heading2"></e-heading></e-flexbox>\`
54
- In the elementConfig property, provide the actual configuration object for each configuration-id used in the XML structure.
55
- In the stylesConfig property, provide the actual styles configuration object for each configuration-id used in the XML structure.
56
- 5. Ensure the XML structure is valid and parsable.
57
- 6. Do not add any attribute nodes, classes, id's, and no text nodes allowed.
58
- Layout properties, such as margin, padding, align, etc. must be applied using the [${ STYLE_SCHEMA_URI }] PropValues.
59
- 7. Some elements allow nesting of other elements, and most of the DO NOT. The allowed elements that can have nested children are "e-tabs", "e-div-block", and "e-flexbox".
60
- 8. Make sure that non-container elements do NOT have any nested elements.
61
-
62
- # DESIGN VECTORS - Concrete Implementation Guidance
63
-
64
- ## 1. Typography & Visual Hierarchy
65
-
66
- **Avoid Distributional Defaults:**
67
- - NO generic sans-serifs as primary typefaces (Inter, Roboto, Arial, Helvetica)
68
- - NO timid size ratios (1.2x, 1.5x scaling)
69
- - NO uniform font weights (everything at 400 or 600)
70
-
71
- **Intentional Alternatives:**
72
- - **For Technical/Modern**: Consider monospace headlines (JetBrains Mono, SF Mono) paired with clean body text
73
- - **For Editorial/Elegant**: Consider serif headlines (Playfair Display, Crimson Text) with sans-serif body
74
- - **For Playful/Creative**: Consider display fonts with character, paired with highly legible body text
75
-
76
- **Scale & Contrast Implementation:**
77
- - Headline-to-body size ratios: 3x minimum (e.g., 48px headline vs 16px body)
78
- - Use extreme weight contrasts: pair weight-100 or 200 with weight-800 or 900
79
- - Line height contrasts: tight headlines (1.1) vs. generous body (1.7)
80
- - Letter spacing: compressed headlines (-0.02em to -0.05em) vs. open small text (0.03em+)
81
-
82
- **Hierarchy Mapping:**
83
- /* Intentional hierarchy example */
84
- H1: font-size: 3.5rem; font-weight: 900; line-height: 1.1; letter-spacing: -0.03em;
85
- H2: font-size: 2rem; font-weight: 200; line-height: 1.2;
86
- Body: font-size: 1rem; font-weight: 400; line-height: 1.7;
87
- Caption: font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
88
-
89
- ## 2. Color & Theme Strategy
90
-
91
- **Avoid Distributional Defaults:**
92
- - NO purple gradients or blue-purple color schemes (massively overrepresented in AI output)
93
- - NO evenly-distributed color palettes (3-4 colors used equally)
94
- - NO timid pastels or all-neutral schemes
95
- - NO #333333, #666666, #999999 grays
96
-
97
- **Intentional Alternatives:**
98
- - **Commit to a Dominant Color**: Choose ONE primary brand color that appears in 60-70% of colored elements
99
- - **Sharp Accent Strategy**: Use 1-2 high-contrast accent colors sparingly (10-15% of colored elements)
100
- - **Neutrals with Personality**: Replace pure grays with warm (#3d3228, #f5f1ed) or cool (#2a2f3d, #f0f2f5) tinted neutrals
101
-
102
- **Color Psychology Mapping:**
103
- - Energy/Action → Warm reds, oranges, yellows (NOT purple/blue)
104
- - Trust/Calm Deep teals, forest greens (NOT generic blue)
105
- - Luxury/Premium Deep burgundy, emerald, charcoal with gold accents
106
- - Playful/Creative Unexpected combinations (coral + mint, mustard + navy)
107
-
108
- **Implementation:**
109
- /* Intentional color system example */
110
- --brand-primary: #d84315; /* Dominant: Deep orange */
111
- --brand-accent: #00bfa5; /* Accent: Teal (complementary) */
112
- --neutral-dark: #2d2622; /* Warm dark brown, not #333 */
113
- --neutral-light: #faf8f6; /* Warm off-white, not pure white */
114
- --background: linear-gradient(135deg, #faf8f6 0%, #f0ebe6 100%); /* Subtle warmth */
115
-
116
- ## 3. Spatial Design & White Space
117
-
118
- **Avoid Distributional Defaults:**
119
- - NO uniform spacing (everything 16px or 24px)
120
- - NO cramped layouts that maximize content density
121
- - NO default container widths (1200px, 1440px)
122
-
123
- **Intentional Alternatives:**
124
- - **Breathing Room**: Use generous white space as a design element (80-120px vertical spacing between sections)
125
- - **Asymmetric Spacing**: Vary padding dramatically (small: 12px, medium: 48px, large: 96px)
126
- - **Content Width Strategy**:
127
- - Reading content: max 65-75 characters (600-700px)
128
- - Hero sections: asymmetric layouts, not centered blocks
129
- - Cards/components: vary sizes intentionally, not uniform grids
130
-
131
- **Implementation:**
132
- /* Intentional spacing scale */
133
- --space-xs: 0.5rem; /* 8px */
134
- --space-sm: 1rem; /* 16px */
135
- --space-md: 3rem; /* 48px */
136
- --space-lg: 6rem; /* 96px */
137
- --space-xl: 10rem; /* 160px */
138
-
139
- /* Use in combinations: */
140
- padding: var(--space-lg) var(--space-md); /* Not uniform padding */
141
- margin-bottom: var(--space-xl); /* Generous section breaks */
142
-
143
- ## 4. Backgrounds & Atmospheric Depth
144
-
145
- **Avoid Distributional Defaults:**
146
- - NO solid white or light gray backgrounds
147
- - NO single-color backgrounds
148
- - NO generic gradient overlays
149
-
150
- **Intentional Alternatives:**
151
- - **Layered Gradients**: Combine 2-3 subtle gradients for depth
152
- - **Geometric Patterns**: SVG patterns, mesh gradients, or subtle noise textures
153
- - **Strategic Contrast**: Alternate between light and dark sections for rhythm
154
-
155
- **Implementation:**
156
- /* Intentional background example */
157
- background:
158
- radial-gradient(circle at 20% 30%, rgba(216, 67, 21, 0.08) 0%, transparent 50%),
159
- radial-gradient(circle at 80% 70%, rgba(0, 191, 165, 0.06) 0%, transparent 50%),
160
- linear-gradient(135deg, #faf8f6 0%, #f0ebe6 100%);
161
-
162
- ## 5. Visual Hierarchy Principles
163
-
164
- **Clear Priority System:**
165
- 1. **Primary Focus (1 element)**: Largest, highest contrast, most visual weight
166
- 2. **Secondary Elements (2-3 elements)**: 40-60% of primary size, reduced contrast
167
- 3. **Tertiary/Support (everything else)**: Minimal visual weight, muted colors
168
-
169
- **Contrast Techniques:**
170
- - Size: 3x+ differences between hierarchy levels
171
- - Weight: 300+ difference in font-weight values
172
- - Color: Primary gets brand color, secondary gets neutral, tertiary gets muted
173
- - Space: Primary gets 2x+ surrounding white space vs. secondary
174
-
175
- ## 6. EXAMPLES - Intentional vs. Generic Design
176
-
177
- ### ❌ GENERIC (Distributional Convergence)
178
-
179
- {
180
- "xmlStructure": "<e-flexbox configuration-id=\"flex1\"><e-heading configuration-id=\"heading1\"></e-heading><e-button configuration-id=\"button1\"></e-button></e-flexbox>",
181
- "elementConfig": {
182
- "heading1": {
183
- "title": { "$$type": "string", "value": "Welcome to Our Site" }
184
- }
185
- },
186
- "stylesConfig": {
187
- "heading1": {
188
- "font-size": {
189
- "$$type": "size",
190
- "value": {
191
- "size": { "$$type": "number", "value": 24 },
192
- "unit": { "$$type": "string", "value": "px" }
193
- }
194
- },
195
- }
196
- }
197
- }
198
-
199
- **Why Generic**: 24px default size, #333 safe gray, 600 weight (middle-ground), purple gradient (AI cliché), uniform 12/24px padding
200
-
201
- ### ✅ INTENTIONAL (Resisting Convergence)
202
- {
203
- "xmlStructure": "<e-flexbox configuration-id=\"hero-section\"><e-heading configuration-id=\"hero-title\"></e-heading><e-text configuration-id=\"hero-subtitle\"></e-text><e-button configuration-id=\"hero-cta\"></e-button></e-flexbox>",
204
- "elementConfig": {
205
- "hero-title": {
206
- "title": { "$$type": "string", "value": "Transform Your Workflow" }
207
- },
208
- "hero-subtitle": {
209
- "content": { "$$type": "string", "value": "Built for teams who refuse to compromise on quality" }
210
- }
211
- },
212
- "stylesConfig": {
213
- "hero-section": {
214
- "display": { "$$type": "string", "value": "flex" },
215
- "flex-direction": { "$$type": "string", "value": "column" },
216
- "align-items": { "$$type": "string", "value": "flex-start" },
217
- "background": {
218
- "$$type": "color",
219
- "value": "#f0ebe6",
220
- "$intention": "background: #f0ebe6",
221
- }
222
- },
223
- "hero-title": {
224
- "font-size": {
225
- "$$type": "size",
226
- "value": {
227
- "size": { "$$type": "number", "value": 72 },
228
- "unit": { "$$type": "string", "value": "px" }
229
- }
230
- },
231
- }
232
- }
233
- }
234
-
235
-
236
- **Why Intentional**:
237
- - Typography: 4.5rem headline (3.6x body), weight 900 vs 200 contrast, tight leading
238
- - Color: Warm orange primary (#d84315), warm neutrals (#2d2622, #5a534d) NOT #333/#666
239
- - Spacing: 10rem vertical padding (generous), 3rem gap, asymmetric alignment
240
- - Background: Layered gradients with subtle brand color accent
241
-
242
- # CONSTRAINTS
243
- When a tool execution fails, retry up to 10 more times, read the error message carefully, and adjust the XML structure or the configurations accordingly.
244
- If a "$$type" is missing, update the invalid object, if the XML has parsing errors, fix it, etc. and RETRY.
245
- VALIDATE the XML structure before delivering it as the final result.
246
- VALIDATE the JSON structure used in the "configuration" attributes for each element before delivering the final result. The configuration must MATCH the PropValue schemas.
247
- NO LINKS ALLOWED. Never apply links to elements, even if they appear in the PropType schema.
248
- elementConfig values must align with the widget's PropType schema, available at the resource [${ WIDGET_SCHEMA_URI }].
249
- stylesConfig values must align with the common styles PropType schema, available at the resource [${ STYLE_SCHEMA_URI }].
250
-
251
- # DESIGN QUALITY CONSTRAINTS
252
-
253
- **Typography Constraints:**
254
- - NEVER use Inter, Roboto, Arial, or Helvetica as primary display fonts
255
- - NEVER use font-size ratios smaller than 2.5x between headlines and body
256
- - NEVER use font-weight values between 500-700 for headlines (go lighter or heavier)
257
-
258
- **Color Constraints:**
259
- - NEVER use purple gradients or blue-purple color schemes
260
- - NEVER use pure grays (#333, #666, #999) - use tinted neutrals instead
261
- - NEVER distribute colors evenly - commit to ONE dominant color
262
- - NEVER use more than 3 core colors (1 dominant, 1-2 accents)
263
-
264
- **Spacing Constraints:**
265
- - NEVER use uniform spacing across all elements
266
- - NEVER use section padding less than 4rem (64px) for hero/major sections
267
- - NEVER center everything - use asymmetric layouts for visual interest
268
-
269
- **Background Constraints:**
270
- - NEVER use solid white (#ffffff) or light gray (#f5f5f5) backgrounds without texture/gradients
271
- - ALWAYS layer at least 2 gradient or color elements for atmospheric depth
272
-
273
- # Parameters
274
- All parameters are MANDATORY.
275
- - xmlStructure
276
- - elementConfig
277
- - stylesConfig
278
-
279
- If unsure about the configuration of a specific property, read the schema resources carefully.
280
-
281
- # About our widgets
282
- Most widgets are self-explanatory by their name. Here is some additional information.
283
- Check for available llm_guidance property in the widget's schema.
284
- SVG elements are bound to internal content upload. Avoid usage, unless you have tools to upload SVG content.
285
- When working with containers, do not forget to apply style schema for controlling the layout.
286
-
287
-
9
+ # REQUIRED RESOURCES (Read before use)
10
+ 1. [${ WIDGET_SCHEMA_URI }] - Widget types, configuration schemas, and PropType definitions
11
+ 2. [${ STYLE_SCHEMA_URI }] - Common styles schema shared by all widgets
12
+ 3. [elementor://global-classes] - Existing global classes (check FIRST to reuse)
13
+
14
+ # THREE-PHASE WORKFLOW (MANDATORY)
15
+
16
+ ## Phase 1: Create Global Classes
17
+ 1. Analyze requirements → identify reusable patterns (typography, colors, spacing)
18
+ 2. Check [elementor://global-classes] for existing classes
19
+ 3. Use "create-global-class" tool for NEW reusable styles BEFORE building
20
+
21
+ ## Phase 2: Build Composition (THIS TOOL)
22
+ 4. Build valid XML with minimal inline styles (layout/positioning only)
23
+ 5. Avoid duplicating styles that should be global classes
24
+
25
+ ## Phase 3: Apply Classes
26
+ 6. Use "apply-global-class" tool to apply global classes to elements
27
+
28
+ # CORE INSTRUCTIONS
29
+
30
+ **Structure:**
31
+ - Build valid XML using allowed widget tags (e.g., \`<e-button configuration-id="btn1"></e-button>\`)
32
+ - Containers only: "e-flexbox", "e-div-block", "e-tabs"
33
+ - Every element MUST have unique "configuration-id" attribute
34
+ - No attributes, classes, IDs, or text nodes in XML
35
+
36
+ **Configuration:**
37
+ - Map each configuration-id to elementConfig (widget props) and stylesConfig (styles)
38
+ - Follow exact PropType schemas from resources above
39
+ - All PropValues need \`$$type\` property matching schema
40
+ - Keep stylesConfig MINIMAL - layout only, NOT reusable styles
41
+
42
+ **Validation:**
43
+ - Parse XML before submission
44
+ - Match all PropValues to schema (\`$$type\` required)
45
+ - NO LINKS in any configuration
46
+ - Retry on errors up to 10x, reading error messages carefully
47
+
48
+ # DESIGN QUALITY: AVOID AI SLOP
49
+
50
+ **Problem:** LLMs default to generic patterns (purple gradients, #333 grays, 24px headings, uniform spacing)
51
+ **Solution:** Make intentional, distinctive choices. When unsure, choose bold over safe.
52
+
53
+ ## Typography Rules
54
+ AVOID: Inter/Roboto/Arial, small ratios (1.5x), medium weights (500-700)
55
+ USE: 3x+ size ratios, extreme weight contrasts (100/200 vs 800/900), tight headlines (1.1 line-height)
56
+
57
+ ## Color Rules
58
+ AVOID: Purple gradients, pure grays (#333/#666/#999), even distribution
59
+ USE: ONE dominant color (60-70%), 1-2 accent colors (10-15%), tinted neutrals (warm/cool grays)
60
+
61
+ ## Spacing Rules
62
+ AVOID: Uniform spacing (all 16px/24px), cramped layouts, centered everything
63
+ ✅ USE: Generous spacing (80-120px sections), dramatic variation (12px/48px/96px), asymmetric layouts
64
+
65
+ ## Background Rules
66
+ AVOID: Solid white/gray, single colors
67
+ USE: Layered gradients (2-3 layers), subtle patterns, alternating light/dark sections
68
+
69
+ ## Visual Hierarchy
70
+ 1. **Primary** (1 element): Largest, highest contrast, most space
71
+ 2. **Secondary** (2-3 elements): 40-60% of primary size
72
+ 3. **Tertiary** (rest): Minimal weight, muted
73
+
74
+ **Contrast techniques:** 3x size differences, 300+ weight differences, color hierarchy (brand neutral → muted)
75
+
76
+ # DESIGN CONSTRAINTS (NEVER VIOLATE)
77
+
78
+ **Typography:**
79
+ - NEVER use Inter, Roboto, Arial, Helvetica as primary display fonts
80
+ - NEVER use font-size ratios < 2.5x between headlines and body
81
+ - NEVER use font-weight 500-700 for headlines (go lighter or heavier)
82
+
83
+ **Color:**
84
+ - PREFER not to use pure grays - use tinted neutrals (#2d2622, #faf8f6, not #333/#f5f5f5)
85
+ - NEVER distribute colors evenly - commit to ONE dominant
86
+ - NEVER use more than 3 core colors - except for info/alert/badges
87
+
88
+ **Spacing:**
89
+ - NEVER use uniform spacing
90
+ - NEVER use < 4rem (64px) padding for major sections
91
+ - NEVER center everything
92
+ - PRIORITIZE rem based values over pixel based
93
+
94
+ **Background:**
95
+ - NEVER use solid #ffffff or #f5f5f5 without texture/gradients
96
+ - ALWAYS layer 2+ gradient/color elements
97
+
98
+ # WIDGET NOTES
99
+ - Check \`llm_guidance\` property in widget schemas for context
100
+ - Avoid SVG widgets (require content upload tools) - when must, prior to execution ensure assets uploaded
101
+ - Apply style schema to containers for layout control
102
+
103
+ # PARAMETERS (ALL MANDATORY)
104
+ - **xmlStructure**: Valid XML with configuration-id attributes
105
+ - **elementConfig**: Record of configuration-id widget PropValues
106
+ - **stylesConfig**: Record of configuration-id style PropValues (layout only)
288
107
  ` );
289
108
 
290
109
  buildCompositionsToolPrompt.example( `
@@ -337,7 +156,12 @@ You should use these IDs as reference for further configuration, styling or chan
337
156
  );
338
157
 
339
158
  buildCompositionsToolPrompt.instruction(
340
- `You must use styles/variables/classes that are available in the project resources, you should prefer using them over inline styles, and you are welcome to execute relevant tools AFTER this tool execution, to apply global classes to the created elements.`
159
+ `**CRITICAL WORKFLOW REMINDER**:
160
+ 1. FIRST: Create reusable global classes for typography, colors, spacing patterns using "create-global-class" tool
161
+ 2. SECOND: Use THIS tool with minimal inline styles (only layout & unique properties)
162
+ 3. THIRD: Apply global classes to elements using "apply-global-class" tool
163
+
164
+ This ensures maximum reusability and consistency across your design system. ALWAYS check [elementor://global-classes] for existing classes before creating new ones.`
341
165
  );
342
166
 
343
167
  return buildCompositionsToolPrompt.prompt();
@@ -35,5 +35,4 @@ export const outputSchema = {
35
35
  'The built XML structure as a string. Must use this XML after completion of building the composition, it contains real IDs.'
36
36
  )
37
37
  .optional(),
38
- llmInstructions: z.string().describe( 'Instructions for what to do next, Important to follow these instructions!' ),
39
38
  };
@@ -1,16 +1,15 @@
1
1
  import {
2
2
  createElement,
3
3
  deleteElement,
4
- generateElementId,
5
4
  getContainer,
6
5
  getWidgetsCache,
7
6
  type V1Element,
8
7
  } from '@elementor/editor-elements';
9
8
  import { type MCPRegistryEntry } from '@elementor/editor-mcp';
10
9
 
10
+ import { CompositionBuilder } from '../../../composition-builder/composition-builder';
11
11
  import { BEST_PRACTICES_URI, STYLE_SCHEMA_URI, WIDGET_SCHEMA_URI } from '../../resources/widgets-schema-resource';
12
12
  import { doUpdateElementProperty } from '../../utils/do-update-element-property';
13
- import { validateInput } from '../../utils/validate-input';
14
13
  import { generatePrompt } from './prompt';
15
14
  import { inputSchema as schema, outputSchema } from './schema';
16
15
 
@@ -23,129 +22,59 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
23
22
  schema,
24
23
  requiredResources: [
25
24
  { description: 'Widgets schema', uri: WIDGET_SCHEMA_URI },
26
- { description: 'Global Classes', uri: 'elementor://global-classes' },
27
25
  { description: 'Styles schema', uri: STYLE_SCHEMA_URI },
26
+ { description: 'Global Classes', uri: 'elementor://global-classes' },
28
27
  { description: 'Global Variables', uri: 'elementor://global-variables' },
29
28
  { description: 'Styles best practices', uri: BEST_PRACTICES_URI },
30
29
  ],
31
30
  outputSchema,
32
31
  modelPreferences: {
33
32
  hints: [ { name: 'claude-sonnet-4-5' } ],
34
- intelligencePriority: 0.95,
35
- speedPriority: 0.5,
36
33
  },
37
34
  handler: async ( params ) => {
38
- let xml: Document | null = null;
39
35
  const { xmlStructure, elementConfig, stylesConfig } = params;
36
+ let generatedXML: string = '';
40
37
  const errors: Error[] = [];
41
- const softErrors: Error[] = [];
42
38
  const rootContainers: V1Element[] = [];
43
- const widgetsCache = getWidgetsCache() || {};
44
39
  const documentContainer = getContainer( 'document' ) as unknown as V1Element;
45
40
  try {
46
- const parser = new DOMParser();
47
- xml = parser.parseFromString( xmlStructure, 'application/xml' );
48
- const errorNode = xml.querySelector( 'parsererror' );
49
- if ( errorNode ) {
50
- throw new Error( 'Failed to parse XML structure: ' + errorNode.textContent );
51
- }
41
+ const compositionBuilder = CompositionBuilder.fromXMLString( xmlStructure, {
42
+ createElement,
43
+ getWidgetsCache,
44
+ } );
45
+ compositionBuilder.setElementConfig( elementConfig );
46
+ compositionBuilder.setStylesConfig( stylesConfig );
52
47
 
53
- const children = Array.from( xml.children );
54
- const iterate = async (
55
- node: Element,
56
- containerElement: V1Element = documentContainer,
57
- childIndex: number
58
- ) => {
59
- const elementTag = node.tagName;
60
- if ( ! widgetsCache[ elementTag ] ) {
61
- errors.push( new Error( `Unknown widget type: ${ elementTag }` ) );
62
- }
63
- const CONTAINER_ELEMENTS = Object.values( widgetsCache )
64
- .filter( ( widget ) => widget.meta?.is_container )
65
- .map( ( widget ) => widget.elType );
66
- const isContainer = CONTAINER_ELEMENTS.includes( elementTag );
67
- const parentElType = containerElement.model.get( 'elType' );
68
- let targetContainerId =
69
- parentElType === 'e-tabs'
70
- ? containerElement.children?.[ 1 ].children?.[ childIndex ]?.id ||
71
- containerElement.children?.[ 1 ].id
72
- : containerElement.id;
73
- if ( ! targetContainerId ) {
74
- targetContainerId = containerElement.id;
75
- }
76
- const newElement = isContainer
77
- ? createElement( {
78
- containerId: targetContainerId,
79
- model: {
80
- elType: elementTag,
81
- id: generateElementId(),
82
- },
83
- options: { useHistory: false },
84
- } )
85
- : createElement( {
86
- containerId: targetContainerId,
87
- model: {
88
- elType: 'widget',
89
- widgetType: elementTag,
90
- id: generateElementId(),
91
- },
92
- options: { useHistory: false },
93
- } );
94
- if ( containerElement === documentContainer ) {
95
- rootContainers.push( newElement );
96
- }
97
- node.setAttribute( 'id', newElement.id );
98
- const configId = node.getAttribute( 'configuration-id' ) || '';
99
- try {
100
- const configObject = elementConfig[ configId ] || {};
101
- const styleObject = stylesConfig[ configId ] || {};
102
- const { errors: propsValidationErrors } = validateInput.validatePropSchema(
103
- elementTag,
104
- configObject
105
- );
106
- errors.push( ...( propsValidationErrors || [] ).map( ( msg ) => new Error( msg ) ) );
107
- const { errors: stylesValidationErrors } = validateInput.validateStyles( styleObject );
108
- errors.push( ...( stylesValidationErrors || [] ).map( ( msg ) => new Error( msg ) ) );
109
-
110
- if ( propsValidationErrors?.length || stylesValidationErrors?.length ) {
111
- return;
112
- }
113
- configObject._styles = styleObject || {};
114
- for ( const [ propertyName, propertyValue ] of Object.entries( configObject ) ) {
115
- try {
116
- doUpdateElementProperty( {
117
- elementId: newElement.id,
118
- propertyName,
119
- propertyValue,
120
- elementType: elementTag,
121
- } );
122
- } catch ( error ) {
123
- softErrors.push( error as Error );
124
- }
125
- }
126
- if ( isContainer ) {
127
- let currentChild = 0;
128
- for ( const child of node.children ) {
129
- iterate( child, newElement, currentChild );
130
- currentChild++;
131
- }
132
- } else {
133
- node.innerHTML = '';
134
- node.removeAttribute( 'configuration' );
135
- }
136
- } finally {
137
- }
138
- };
139
-
140
- let currentChild = 0;
141
- for await ( const childNode of children ) {
142
- await iterate( childNode, documentContainer, currentChild );
143
- currentChild++;
144
- try {
145
- } catch ( error ) {
146
- errors.push( error as Error );
147
- }
48
+ const {
49
+ configErrors,
50
+ invalidStyles,
51
+ rootContainers: generatedRootContainers,
52
+ } = compositionBuilder.build( documentContainer );
53
+
54
+ generatedXML = new XMLSerializer().serializeToString( compositionBuilder.getXML() );
55
+
56
+ if ( configErrors.length ) {
57
+ errors.push( ...configErrors.map( ( e ) => new Error( e ) ) );
58
+ throw new Error( 'Configuration errors occurred during composition building.' );
148
59
  }
60
+
61
+ rootContainers.push( ...generatedRootContainers );
62
+
63
+ Object.entries( invalidStyles ).forEach( ( [ elementId, rawCssRules ] ) => {
64
+ const customCss = {
65
+ value: rawCssRules.join( ';\n' ),
66
+ };
67
+ doUpdateElementProperty( {
68
+ elementId,
69
+ propertyName: '_styles',
70
+ propertyValue: {
71
+ _styles: {
72
+ custom_css: customCss,
73
+ },
74
+ },
75
+ elementType: 'widget',
76
+ } );
77
+ } );
149
78
  } catch ( error ) {
150
79
  errors.push( error as Error );
151
80
  }
@@ -187,26 +116,21 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
187
116
  ) }\n\n"Missing $$type" errors indicate that the configuration objects are invalid. Try again and apply **ALL** object entries with correct $$type.\nNow that you have these errors, fix them and try again. Errors regarding configuration objects, please check against the PropType schemas`;
188
117
  throw new Error( errorText );
189
118
  }
190
- if ( ! xml ) {
191
- throw new Error( 'XML structure is null after parsing.' );
192
- }
193
119
  return {
194
- xmlStructure: new XMLSerializer().serializeToString( xml ),
120
+ xmlStructure: generatedXML,
195
121
  errors: errors?.length
196
122
  ? errors.map( ( e ) => ( typeof e === 'string' ? e : e.message ) ).join( '\n\n' )
197
123
  : undefined,
198
- llmInstructions:
199
- ( softErrors.length
200
- ? `The composition was built successfully, but there were some issues with the provided configurations:
201
-
202
- ${ softErrors.map( ( e ) => `- ${ e.message }` ).join( '\n' ) }
203
-
204
- Please use configure-element tool to fix these issues. Now that you have information about these issues, use the configure-element tool to fix them!`
205
- : '' ) +
206
- `
207
- Next Steps:
208
- - Use "apply-global-class" tool as there may be global styles ready to be applied to elements.
209
- - Use "configure-element" tool to further configure elements as needed, including styles.
124
+ llm_instructions: `The composition was built successfully with element IDs embedded in the XML.
125
+
126
+ **CRITICAL NEXT STEPS** (Follow in order):
127
+ 1. **Apply Global Classes**: Use "apply-global-class" tool to apply the global classes you created BEFORE building this composition
128
+ - Check the created element IDs in the returned XML
129
+ - Apply semantic classes (heading-primary, button-cta, etc.) to appropriate elements
130
+
131
+ 2. **Fine-tune if needed**: Use "configure-element" tool only for element-specific adjustments that don't warrant global classes
132
+
133
+ Remember: Global classes ensure design consistency and reusability. Don't skip applying them!
210
134
  `,
211
135
  };
212
136
  },