@respira/wordpress-mcp-server 7.1.4 → 7.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SOUL.md +1 -1
- package/dist/divi-context.d.ts +2 -2
- package/dist/divi-context.d.ts.map +1 -1
- package/dist/divi-context.js +2 -2
- package/dist/divi-prompts.d.ts.map +1 -1
- package/dist/divi-prompts.js +131 -5
- package/dist/divi-prompts.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +124 -19
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/SOUL.md
CHANGED
|
@@ -29,7 +29,7 @@ Non-negotiable principles. If a request asks you to violate one, refuse and expl
|
|
|
29
29
|
|
|
30
30
|
**Privacy is a hard line.** Telemetry collects metadata only: site UUID, plugin version, builder names, agent type, write counts, locale. Never prompts. Never tool arguments. Never tool results. Never WordPress content. Never customer URLs without explicit opt-in. The customer can set `RESPIRA_USAGE_OPT_OUT=1` and all collection stops at the source.
|
|
31
31
|
|
|
32
|
-
**Builder-native edits.** When editing content inside a page builder, always use the element-level tools: `respira_find_element` then `respira_update_element` or `respira_update_module`. Never reach for `respira_update_page` to change content. Never write to `wp_postmeta` directly. Never write SQL. The whole point of Respira is that edits land in the native builder format, parseable by the builder, reversible by the snapshot system.
|
|
32
|
+
**Builder-native edits.** When editing content inside a page builder, always use the element-level tools: `respira_find_element` then `respira_update_element` or `respira_update_module`. Never reach for `respira_update_page` to change content. Never write to `wp_postmeta` directly. Never write SQL. The whole point of Respira is that edits land in the native builder format, parseable by the builder, reversible per page by the snapshot system.
|
|
33
33
|
|
|
34
34
|
**Dogfood first.** Every release is tested on the Respira Studio environment before the tag is cut. If a tool produces unexpected output, the founder ran it on real sites before you saw it. Treat reported edge cases seriously. They are reproducible.
|
|
35
35
|
|
package/dist/divi-context.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides comprehensive Divi documentation for AI assistants.
|
|
5
5
|
*/
|
|
6
|
-
export declare const diviContext = "\nYou are editing a Divi Builder page. Divi has two storage formats you must handle safely:\n- Divi 5: block-based layout using `divi/*` blocks in post content\n- Divi 4: legacy shortcode layout using `et_pb_*`\n\n## Divi 5 Structure (Primary)\n\n- **Sections (`divi/section`)**: Top-level containers\n- **Rows (`divi/row`)**: Layout containers inside sections\n- **Columns/Groups (`divi/column`, `divi/group`)**: Nested containers\n- **Modules (`divi/*`)**: Text, button, image, CTA, and other content blocks\n\n## Divi 4 Structure (Legacy)\n\n- **Sections (`et_pb_section`)**\n- **Rows (`et_pb_row`)**\n- **Modules (`et_pb_text`, `et_pb_image`, `et_pb_button`, etc.)**\n\n## Editing Contract\n\n- Use structured nodes: `{ type, attributes, children, content }`\n- Preserve unknown attributes exactly\n- Do not rewrite entire trees for small edits\n- Keep non-Divi blocks and legacy shortcode wrapper blocks unless explicitly asked to remove\n- Treat legacy wrappers as opaque: move/delete allowed, deep edits discouraged\n\n## Important Rules\n\n1. Prefer Divi 5 block edits (`divi/*`) when present\n2. Keep Divi 4 shortcode edits only for legacy pages\n3. Preserve parent/child nesting and ordering\n4. Preserve all existing attributes unless explicitly changed\n5. Use hex colors and full URLs where relevant\n6. Avoid lossy conversion between Divi 4 and Divi 5 formats\n7.
|
|
6
|
+
export declare const diviContext = "\nYou are editing a Divi Builder page. Divi has two storage formats you must handle safely:\n- Divi 5: block-based layout using `divi/*` blocks in post content\n- Divi 4: legacy shortcode layout using `et_pb_*`\n\n## Divi 5 Structure (Primary)\n\n- **Sections (`divi/section`)**: Top-level containers\n- **Rows (`divi/row`)**: Layout containers inside sections\n- **Columns/Groups (`divi/column`, `divi/group`)**: Nested containers\n- **Modules (`divi/*`)**: Text, button, image, CTA, and other content blocks\n\n## Divi 4 Structure (Legacy)\n\n- **Sections (`et_pb_section`)**\n- **Rows (`et_pb_row`)**\n- **Modules (`et_pb_text`, `et_pb_image`, `et_pb_button`, etc.)**\n\n## Editing Contract\n\n- Use structured nodes: `{ type, attributes, children, content }`\n- Preserve unknown attributes exactly\n- Do not rewrite entire trees for small edits\n- Keep non-Divi blocks and legacy shortcode wrapper blocks unless explicitly asked to remove\n- Treat legacy wrappers as opaque: move/delete allowed, deep edits discouraged\n\n## Important Rules\n\n1. Prefer Divi 5 block edits (`divi/*`) when present\n2. Keep Divi 4 shortcode edits only for legacy pages\n3. Preserve parent/child nesting and ordering\n4. Preserve all existing attributes unless explicitly changed\n5. Use hex colors and full URLs where relevant\n6. Avoid lossy conversion between Divi 4 and Divi 5 formats\n7. Auto-detect Divi 4 vs Divi 5 from the page. respira_get_builder_info and respira_read_page reveal the mode, and the plugin already detects Divi 5 and flips into block format on its own. Only ask the human when it is genuinely ambiguous, like a brand new page with no builder set yet\n8. For code modules, preserve extracted content encoding; do not blindly base64-encode content\n";
|
|
7
7
|
export declare const diviAttributeHelp: {
|
|
8
8
|
colors: string;
|
|
9
9
|
spacing: string;
|
|
@@ -11,5 +11,5 @@ export declare const diviAttributeHelp: {
|
|
|
11
11
|
fonts: string;
|
|
12
12
|
urls: string;
|
|
13
13
|
};
|
|
14
|
-
export declare const diviValidationRules = "\nCRITICAL Divi Rules:\n1. If Divi 5 blocks exist, keep output in block format (`divi/*`)\n2. Preserve `attributes` and `children` unless explicitly changed\n3. Keep legacy shortcode-wrapper blocks opaque\n4. Never overwrite a Divi 5 page with Divi 4 shortcodes\n5. Preserve module structure and ordering\n6. Always use proper attribute formats\n7.
|
|
14
|
+
export declare const diviValidationRules = "\nCRITICAL Divi Rules:\n1. If Divi 5 blocks exist, keep output in block format (`divi/*`)\n2. Preserve `attributes` and `children` unless explicitly changed\n3. Keep legacy shortcode-wrapper blocks opaque\n4. Never overwrite a Divi 5 page with Divi 4 shortcodes\n5. Preserve module structure and ordering\n6. Always use proper attribute formats\n7. Auto-detect Divi 4 vs Divi 5 from the page (respira_get_builder_info / respira_read_page); only ask the human on a genuinely ambiguous page with no builder set\n";
|
|
15
15
|
//# sourceMappingURL=divi-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"divi-context.d.ts","sourceRoot":"","sources":["../src/divi-context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"divi-context.d.ts","sourceRoot":"","sources":["../src/divi-context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,WAAW,muDAoCvB,CAAC;AAEF,eAAO,MAAM,iBAAiB;;;;;;CAM7B,CAAC;AAEF,eAAO,MAAM,mBAAmB,mgBAS/B,CAAC"}
|
package/dist/divi-context.js
CHANGED
|
@@ -37,7 +37,7 @@ You are editing a Divi Builder page. Divi has two storage formats you must handl
|
|
|
37
37
|
4. Preserve all existing attributes unless explicitly changed
|
|
38
38
|
5. Use hex colors and full URLs where relevant
|
|
39
39
|
6. Avoid lossy conversion between Divi 4 and Divi 5 formats
|
|
40
|
-
7.
|
|
40
|
+
7. Auto-detect Divi 4 vs Divi 5 from the page. respira_get_builder_info and respira_read_page reveal the mode, and the plugin already detects Divi 5 and flips into block format on its own. Only ask the human when it is genuinely ambiguous, like a brand new page with no builder set yet
|
|
41
41
|
8. For code modules, preserve extracted content encoding; do not blindly base64-encode content
|
|
42
42
|
`;
|
|
43
43
|
export const diviAttributeHelp = {
|
|
@@ -55,6 +55,6 @@ CRITICAL Divi Rules:
|
|
|
55
55
|
4. Never overwrite a Divi 5 page with Divi 4 shortcodes
|
|
56
56
|
5. Preserve module structure and ordering
|
|
57
57
|
6. Always use proper attribute formats
|
|
58
|
-
7.
|
|
58
|
+
7. Auto-detect Divi 4 vs Divi 5 from the page (respira_get_builder_info / respira_read_page); only ask the human on a genuinely ambiguous page with no builder set
|
|
59
59
|
`;
|
|
60
60
|
//# sourceMappingURL=divi-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"divi-prompts.d.ts","sourceRoot":"","sources":["../src/divi-prompts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,gBAAgB,wLAI5B,CAAC;AAEF,eAAO,MAAM,8BAA8B,oHACmE,CAAC;AAE/G,eAAO,MAAM,2BAA2B;;;;GA0BvC,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"divi-prompts.d.ts","sourceRoot":"","sources":["../src/divi-prompts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,gBAAgB,wLAI5B,CAAC;AAEF,eAAO,MAAM,8BAA8B,oHACmE,CAAC;AAE/G,eAAO,MAAM,2BAA2B;;;;GA0BvC,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAoNlD,CAAC;AAEF,eAAO,MAAM,oBAAoB,UAShC,CAAC;AAEF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAElE;AAED,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,MAAM,CAYR"}
|
package/dist/divi-prompts.js
CHANGED
|
@@ -39,22 +39,148 @@ export const diviMigrationCopilotPrompts = [
|
|
|
39
39
|
export const diviPrompts = {
|
|
40
40
|
createHeroSection: {
|
|
41
41
|
name: 'create_divi_hero',
|
|
42
|
-
description: '
|
|
43
|
-
template: `
|
|
42
|
+
description: 'Build a Divi 5 hero section with native heading, text, and button modules',
|
|
43
|
+
template: `Build a Divi 5 hero with native modules (heading, text, button). Use node format { type, attributes, children, content }. The plugin auto-detects Divi 4 vs Divi 5, so write Divi 5 unless the page is on legacy Divi 4.
|
|
44
44
|
{
|
|
45
45
|
type: "divi/section",
|
|
46
|
-
attributes: { background_color: "{bg_color}"
|
|
46
|
+
attributes: { background_color: "{bg_color}" },
|
|
47
47
|
children: [
|
|
48
48
|
{
|
|
49
49
|
type: "divi/row",
|
|
50
50
|
attributes: {},
|
|
51
51
|
children: [
|
|
52
|
-
{
|
|
53
|
-
|
|
52
|
+
{
|
|
53
|
+
type: "divi/column",
|
|
54
|
+
attributes: {},
|
|
55
|
+
children: [
|
|
56
|
+
{ type: "divi/heading", attributes: { title: "{heading}", text_orientation: "center" }, content: "" },
|
|
57
|
+
{ type: "divi/text", attributes: { text_orientation: "center" }, content: "<p>{subheading}</p>" },
|
|
58
|
+
{ type: "divi/button", attributes: { linkUrl: "{url}", button_text: "{text}", button_alignment: "center" }, content: "" }
|
|
59
|
+
]
|
|
60
|
+
}
|
|
54
61
|
]
|
|
55
62
|
}
|
|
56
63
|
]
|
|
57
64
|
}`,
|
|
65
|
+
},
|
|
66
|
+
createFeaturesSection: {
|
|
67
|
+
name: 'create_divi_features',
|
|
68
|
+
description: 'Build a Divi 5 features row of three blurb columns',
|
|
69
|
+
template: `Build a Divi 5 features section: one row, three columns, each with a native divi/blurb. Use node format { type, attributes, children, content }. divi/blurb title is an object: { "text": "..." }.
|
|
70
|
+
{
|
|
71
|
+
type: "divi/section",
|
|
72
|
+
attributes: {},
|
|
73
|
+
children: [
|
|
74
|
+
{
|
|
75
|
+
type: "divi/row",
|
|
76
|
+
attributes: { flexColumnStructure: "8_24,8_24,8_24" },
|
|
77
|
+
children: [
|
|
78
|
+
{
|
|
79
|
+
type: "divi/column",
|
|
80
|
+
attributes: {},
|
|
81
|
+
children: [
|
|
82
|
+
{ type: "divi/blurb", attributes: { title: { text: "{feature_1_title}" }, image: "{feature_1_icon}" }, content: "<p>{feature_1_text}</p>" }
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
type: "divi/column",
|
|
87
|
+
attributes: {},
|
|
88
|
+
children: [
|
|
89
|
+
{ type: "divi/blurb", attributes: { title: { text: "{feature_2_title}" }, image: "{feature_2_icon}" }, content: "<p>{feature_2_text}</p>" }
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
type: "divi/column",
|
|
94
|
+
attributes: {},
|
|
95
|
+
children: [
|
|
96
|
+
{ type: "divi/blurb", attributes: { title: { text: "{feature_3_title}" }, image: "{feature_3_icon}" }, content: "<p>{feature_3_text}</p>" }
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}`,
|
|
103
|
+
},
|
|
104
|
+
createCtaSection: {
|
|
105
|
+
name: 'create_divi_cta',
|
|
106
|
+
description: 'Build a centered Divi 5 call-to-action section',
|
|
107
|
+
template: `Build a centered Divi 5 call-to-action: heading, text, and button in one column. Use node format { type, attributes, children, content }.
|
|
108
|
+
{
|
|
109
|
+
type: "divi/section",
|
|
110
|
+
attributes: { background_color: "{bg_color}" },
|
|
111
|
+
children: [
|
|
112
|
+
{
|
|
113
|
+
type: "divi/row",
|
|
114
|
+
attributes: {},
|
|
115
|
+
children: [
|
|
116
|
+
{
|
|
117
|
+
type: "divi/column",
|
|
118
|
+
attributes: {},
|
|
119
|
+
children: [
|
|
120
|
+
{ type: "divi/heading", attributes: { title: "{heading}", text_orientation: "center" }, content: "" },
|
|
121
|
+
{ type: "divi/text", attributes: { text_orientation: "center" }, content: "<p>{subheading}</p>" },
|
|
122
|
+
{ type: "divi/button", attributes: { linkUrl: "{url}", button_text: "{text}", button_alignment: "center" }, content: "" }
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}`,
|
|
129
|
+
},
|
|
130
|
+
createLandingPage: {
|
|
131
|
+
name: 'create_divi_landing',
|
|
132
|
+
description: 'Build a basic Divi 5 landing page: hero, features, image, and CTA sections',
|
|
133
|
+
template: `Build a basic Divi 5 landing page by composing native-module sections in order: hero, features, image, then CTA. Use node format { type, attributes, children, content }. Pass this whole array as the page content.
|
|
134
|
+
[
|
|
135
|
+
{
|
|
136
|
+
type: "divi/section",
|
|
137
|
+
attributes: { background_color: "{hero_bg}" },
|
|
138
|
+
children: [
|
|
139
|
+
{ type: "divi/row", attributes: {}, children: [
|
|
140
|
+
{ type: "divi/column", attributes: {}, children: [
|
|
141
|
+
{ type: "divi/heading", attributes: { title: "{hero_heading}", text_orientation: "center" }, content: "" },
|
|
142
|
+
{ type: "divi/text", attributes: { text_orientation: "center" }, content: "<p>{hero_subheading}</p>" },
|
|
143
|
+
{ type: "divi/button", attributes: { linkUrl: "{hero_url}", button_text: "{hero_cta}", button_alignment: "center" }, content: "" }
|
|
144
|
+
] }
|
|
145
|
+
] }
|
|
146
|
+
]
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
type: "divi/section",
|
|
150
|
+
attributes: {},
|
|
151
|
+
children: [
|
|
152
|
+
{ type: "divi/row", attributes: { flexColumnStructure: "8_24,8_24,8_24" }, children: [
|
|
153
|
+
{ type: "divi/column", attributes: {}, children: [ { type: "divi/blurb", attributes: { title: { text: "{feature_1_title}" } }, content: "<p>{feature_1_text}</p>" } ] },
|
|
154
|
+
{ type: "divi/column", attributes: {}, children: [ { type: "divi/blurb", attributes: { title: { text: "{feature_2_title}" } }, content: "<p>{feature_2_text}</p>" } ] },
|
|
155
|
+
{ type: "divi/column", attributes: {}, children: [ { type: "divi/blurb", attributes: { title: { text: "{feature_3_title}" } }, content: "<p>{feature_3_text}</p>" } ] }
|
|
156
|
+
] }
|
|
157
|
+
]
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
type: "divi/section",
|
|
161
|
+
attributes: {},
|
|
162
|
+
children: [
|
|
163
|
+
{ type: "divi/row", attributes: {}, children: [
|
|
164
|
+
{ type: "divi/column", attributes: {}, children: [
|
|
165
|
+
{ type: "divi/image", attributes: { src: "{image_url}", alt: "{image_alt}", align: "center" }, content: "" }
|
|
166
|
+
] }
|
|
167
|
+
] }
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
type: "divi/section",
|
|
172
|
+
attributes: { background_color: "{cta_bg}" },
|
|
173
|
+
children: [
|
|
174
|
+
{ type: "divi/row", attributes: {}, children: [
|
|
175
|
+
{ type: "divi/column", attributes: {}, children: [
|
|
176
|
+
{ type: "divi/heading", attributes: { title: "{cta_heading}", text_orientation: "center" }, content: "" },
|
|
177
|
+
{ type: "divi/text", attributes: { text_orientation: "center" }, content: "<p>{cta_subheading}</p>" },
|
|
178
|
+
{ type: "divi/button", attributes: { linkUrl: "{cta_url}", button_text: "{cta_text}", button_alignment: "center" }, content: "" }
|
|
179
|
+
] }
|
|
180
|
+
] }
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
]`,
|
|
58
184
|
},
|
|
59
185
|
updateModuleStyle: {
|
|
60
186
|
name: 'update_divi_style',
|
package/dist/divi-prompts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"divi-prompts.js","sourceRoot":"","sources":["../src/divi-prompts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;CAI/B,CAAC;AAEF,MAAM,CAAC,MAAM,8BAA8B,GACzC,4GAA4G,CAAC;AAE/G,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC;QACE,EAAE,EAAE,iBAAiB;QACrB,KAAK,EAAE,2BAA2B;QAClC,MAAM,EAAE,wOAAwO;KACjP;IACD;QACE,EAAE,EAAE,qBAAqB;QACzB,KAAK,EAAE,uBAAuB;QAC9B,MAAM,EAAE,2MAA2M;KACpN;IACD;QACE,EAAE,EAAE,uBAAuB;QAC3B,KAAK,EAAE,4BAA4B;QACnC,MAAM,EAAE,gNAAgN;KACzN;IACD;QACE,EAAE,EAAE,mBAAmB;QACvB,KAAK,EAAE,mBAAmB;QAC1B,MAAM,EAAE,yMAAyM;KAClN;IACD;QACE,EAAE,EAAE,kBAAkB;QACtB,KAAK,EAAE,uBAAuB;QAC9B,MAAM,EAAE,8OAA8O;KACvP;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAA+B;IACrD,iBAAiB,EAAE;QACjB,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"divi-prompts.js","sourceRoot":"","sources":["../src/divi-prompts.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoBH,OAAO,KAAK,EAAE,mBAAmB,EAAe,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoBH,OAAO,KAAK,EAAE,mBAAmB,EAAe,MAAM,kBAAkB,CAAC;AAkQzE,qBAAa,sBAAsB;IACjC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,KAAK,CAA2C;IACxD,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,YAAY,CAA4B;IAChD,8EAA8E;IAC9E,OAAO,CAAC,YAAY,CAA4B;IAChD,8EAA8E;IAC9E,OAAO,CAAC,mBAAmB,CAAS;IAEpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAsB;IAEhE;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;gBA4Bb,WAAW,EAAE,mBAAmB,EAAE,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE;IAqUvE,OAAO,CAAC,cAAc;IAItB;;;;;;;;;OASG;IACH,OAAO,CAAC,oBAAoB;IAkB5B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,aAAa;IA4BrB,gEAAgE;IAChE,OAAO,CAAC,aAAa;IAUrB;;;;;;OAMG;YACW,UAAU;IA2CxB;;;;;;;;;;;;;;OAcG;YACW,WAAW;IAiJzB;;;;;;;;;OASG;YACW,kBAAkB;IA0GhC;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,6BAA6B;IA0BrC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,yBAAyB;IA+BjC,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,aAAa;YAuPP,kBAAkB;YA6BlB,yBAAyB;IASvC;;;OAGG;IACH,OAAO,CAAC,oBAAoB;YAyBd,QAAQ;IAmvFtB;;;;;;OAMG;IACH,yEAAyE;IACzE,OAAO,CAAC,mBAAmB,CAAoD;IAC/E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAU;YAEpC,oBAAoB;YAqDpB,2BAA2B;IAazC;;;;OAIG;YACW,cAAc;IAY5B,OAAO,CAAC,mBAAmB;IAwT3B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAe3C;IAEF;;;;OAIG;IACH,OAAO,CAAC,0BAA0B;YAmCpB,cAAc;IAqG5B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,eAAe;YAuCT,gBAAgB;IAy2B9B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoUzB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA6UxB,GAAG;CAyCV"}
|
package/dist/server.js
CHANGED
|
@@ -123,6 +123,81 @@ class ToolTimeoutError extends Error {
|
|
|
123
123
|
function getMaxToolTimeoutMs() {
|
|
124
124
|
return Math.max(5000, parseInt(process.env.RESPIRA_MAX_TOOL_TIMEOUT_MS || '120000', 10));
|
|
125
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* v7.2.1: hoist plugin-side dropped-styling warnings to the TOP of a build
|
|
128
|
+
* write result so the agent sees them before it inspects anything else.
|
|
129
|
+
*
|
|
130
|
+
* The Divi 5 build path (and any builder write) can drop style settings the
|
|
131
|
+
* builder does not recognise. The plugin reports these under the tool result's
|
|
132
|
+
* `warnings` array (objects shaped { reason: 'unknown_setting', key, type }) or
|
|
133
|
+
* a top-level `dropped_settings` array. This mirrors the existing
|
|
134
|
+
* write_was_noop hoist on update_element: the dashboard shows agents retry the
|
|
135
|
+
* same write blindly when the signal sits deep in the payload. Front-loading a
|
|
136
|
+
* plain-English hint stops the retry loop and tells the agent to pick a
|
|
137
|
+
* supported attribute or drop into a divi/code block instead.
|
|
138
|
+
*
|
|
139
|
+
* Defensive about the exact key shape: handles both the `warnings` array and a
|
|
140
|
+
* possible top-level `dropped_settings` array, and a pre-summarised
|
|
141
|
+
* `styling_dropped` count/string if the plugin sends one.
|
|
142
|
+
*/
|
|
143
|
+
function hoistDroppedStylingWarnings(result) {
|
|
144
|
+
if (!result || typeof result !== 'object') {
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
const dropped = [];
|
|
148
|
+
// Shape 1: a `warnings` array of objects with reason: 'unknown_setting'.
|
|
149
|
+
if (Array.isArray(result.warnings)) {
|
|
150
|
+
for (const w of result.warnings) {
|
|
151
|
+
if (w && typeof w === 'object' && w.reason === 'unknown_setting') {
|
|
152
|
+
dropped.push({ key: w.key, type: w.type, reason: w.reason });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Shape 2: a top-level `dropped_settings` array. Entries may be plain strings
|
|
157
|
+
// (the setting key) or objects with key/type.
|
|
158
|
+
if (Array.isArray(result.dropped_settings)) {
|
|
159
|
+
for (const d of result.dropped_settings) {
|
|
160
|
+
if (typeof d === 'string') {
|
|
161
|
+
dropped.push({ key: d });
|
|
162
|
+
}
|
|
163
|
+
else if (d && typeof d === 'object') {
|
|
164
|
+
dropped.push({ key: d.key, type: d.type, reason: d.reason });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (dropped.length === 0) {
|
|
169
|
+
// Shape 3: a pre-summarised count/string with no per-setting detail.
|
|
170
|
+
const summary = result.styling_dropped;
|
|
171
|
+
if (typeof summary === 'number' && summary > 0) {
|
|
172
|
+
const hint = `${summary} style settings did not apply. use a supported attribute or a divi/code block. do not retry the same write.`;
|
|
173
|
+
result.dropped_styling_hint = hint;
|
|
174
|
+
const original = typeof result.message === 'string' ? result.message : '';
|
|
175
|
+
result.message = `STYLING DROPPED — ${hint}\n\n${original}`.trim();
|
|
176
|
+
result.agent_must_not_retry = true;
|
|
177
|
+
}
|
|
178
|
+
else if (typeof summary === 'string' && summary.trim() !== '') {
|
|
179
|
+
const hint = `${summary} use a supported attribute or a divi/code block. do not retry the same write.`;
|
|
180
|
+
result.dropped_styling_hint = hint;
|
|
181
|
+
const original = typeof result.message === 'string' ? result.message : '';
|
|
182
|
+
result.message = `STYLING DROPPED — ${hint}\n\n${original}`.trim();
|
|
183
|
+
result.agent_must_not_retry = true;
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
// Build a compact, readable list grouped by module type where known.
|
|
188
|
+
const parts = dropped.map((d) => {
|
|
189
|
+
const where = d.type ? ` on ${d.type}` : '';
|
|
190
|
+
return d.key ? `${d.key}${where}` : `unknown setting${where}`;
|
|
191
|
+
});
|
|
192
|
+
const list = parts.join(', ');
|
|
193
|
+
const hint = `${dropped.length} style setting${dropped.length === 1 ? '' : 's'} did not apply on these modules: ${list}. use a supported attribute or a divi/code block. do not retry the same write.`;
|
|
194
|
+
const original = typeof result.message === 'string' ? result.message : '';
|
|
195
|
+
result.message = `STYLING DROPPED — ${hint}\n\n${original}`.trim();
|
|
196
|
+
result.dropped_styling_hint = hint;
|
|
197
|
+
result.dropped_styling = dropped;
|
|
198
|
+
result.agent_must_not_retry = true;
|
|
199
|
+
return result;
|
|
200
|
+
}
|
|
126
201
|
/**
|
|
127
202
|
* v6.12.0: Tool names that do NOT receive the optional site_id input parameter.
|
|
128
203
|
* These tools operate on global Respira config or pre-site setup state, so a
|
|
@@ -248,9 +323,9 @@ export class RespiraWordPressServer {
|
|
|
248
323
|
|
|
249
324
|
---
|
|
250
325
|
|
|
251
|
-
Respira MCP Server
|
|
326
|
+
Respira MCP Server — tools for editing WordPress across page builders (Elementor, Divi, Bricks, Beaver, Oxygen, Gutenberg, and more) plus WooCommerce and ACF.
|
|
252
327
|
|
|
253
|
-
IMPORTANT: Always use Respira tools to read and edit WordPress content. NEVER access the database directly (SQL queries, wp_postmeta, wp_options), edit PHP files, or modify theme templates to change page content. Respira tools handle
|
|
328
|
+
IMPORTANT: Always use Respira tools to read and edit WordPress content. NEVER access the database directly (SQL queries, wp_postmeta, wp_options), edit PHP files, or modify theme templates to change page content. Respira tools handle content edits safely with per-page snapshots, cache invalidation, and builder-native formats. Even for simple changes like updating a copyright year in a footer — use respira_find_element, not SQL.
|
|
254
329
|
|
|
255
330
|
CRITICAL TOOL CHOICE: For ANY in-page content edit (changing text, images, buttons, headings, links, colors, settings on existing widgets), use respira_find_element + respira_update_element. Do NOT use respira_update_page for content edits. respira_update_page replaces the ENTIRE page body and bypasses the page builder's structure — it produces "all code" pages where the builder treats every widget as a single text blob. respira_update_page is ONLY for: page title, slug, status, custom CSS, or full HTML replacement (e.g. "convert this Word doc into a page"). Telemetry across the user base shows respira_update_page being chosen ~13× more often than respira_update_element, but the right tool for "change the headline text" or "swap the hero image" is always respira_update_element.
|
|
256
331
|
|
|
@@ -340,6 +415,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
340
415
|
- HTML-to-Elementor conversion creates native widgets with mapped CSS styles, responsive breakpoints, and optional global color/font creation
|
|
341
416
|
|
|
342
417
|
### Divi 5 (Full Intelligence)
|
|
418
|
+
- Build real pages with the native modules. divi/heading, divi/text, divi/image, divi/button, and divi/blurb are advertised by default and safe to use. Prefer them over divi/code raw HTML for real content. Reach for divi/code only for genuinely custom markup the native modules cannot express.
|
|
343
419
|
- Content format: Block comments wrapping JSON module definitions inside <!-- wp:divi/placeholder -->
|
|
344
420
|
- Every module needs "builderVersion": "5.0.1"
|
|
345
421
|
- Hierarchy is strict: Section → Row → Column → Module (never skip levels)
|
|
@@ -352,6 +428,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
352
428
|
- Blurb title must be {"text": "..."} object format, not a plain string
|
|
353
429
|
- 40+ module definitions and 7 page patterns available
|
|
354
430
|
- 13-point payload validation with 16 actionable error messages
|
|
431
|
+
- If a write comes back with dropped styling (dropped_styling_hint, or a STYLING DROPPED message at the top of the result), the builder did not recognise those settings. Do not retry the same write. Pick a supported attribute or move that bit into a divi/code block, then write again.
|
|
355
432
|
|
|
356
433
|
### Divi 4 Legacy (Smart Defaults)
|
|
357
434
|
- Content format: Shortcode-based — [et_pb_section][et_pb_row][et_pb_column][et_pb_text]content[/et_pb_text][/et_pb_column][/et_pb_row][/et_pb_section]
|
|
@@ -459,7 +536,7 @@ Use respira_get_builder_info first to detect which builder is active. Then use t
|
|
|
459
536
|
|
|
460
537
|
## Safety features
|
|
461
538
|
|
|
462
|
-
- Snapshots: respira_list_snapshots, respira_get_snapshot, respira_diff_snapshots, respira_restore_snapshot — every edit creates a rollback point
|
|
539
|
+
- Snapshots: respira_list_snapshots, respira_get_snapshot, respira_diff_snapshots, respira_restore_snapshot — every page or post edit creates a rollback point. Destructive structure changes Respira makes (deleting a field group, post type, taxonomy, or changing an option) ALSO capture a recovery snapshot, returned as recovery_snapshot_uuid. An entire multi-step session can be undone in one call with wordpress_restore_session (use wordpress_begin_session / wordpress_end_session to bracket a cascade explicitly).
|
|
463
540
|
- Duplicate workflow: respira_create_page_duplicate creates a safe copy; edits go to the duplicate; user approves in wp-admin to go live
|
|
464
541
|
- Direct edit mode: when enabled in settings, writes go straight to the original (skip duplicate workflow)
|
|
465
542
|
- respira_validate_security — check content for XSS and security issues before saving
|
|
@@ -1109,7 +1186,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
1109
1186
|
content: [
|
|
1110
1187
|
{
|
|
1111
1188
|
type: 'text',
|
|
1112
|
-
text: JSON.stringify({ ...errorPayload, site: activeSite }
|
|
1189
|
+
text: JSON.stringify({ ...errorPayload, site: activeSite }),
|
|
1113
1190
|
},
|
|
1114
1191
|
],
|
|
1115
1192
|
isError: true,
|
|
@@ -1126,7 +1203,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
1126
1203
|
content: [
|
|
1127
1204
|
{
|
|
1128
1205
|
type: 'text',
|
|
1129
|
-
text: JSON.stringify(resultWithVersionWarning
|
|
1206
|
+
text: JSON.stringify(resultWithVersionWarning),
|
|
1130
1207
|
},
|
|
1131
1208
|
],
|
|
1132
1209
|
// MCP 2025-06-18+: raw JSON for programmatic access alongside text for LLMs.
|
|
@@ -1155,7 +1232,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
1155
1232
|
'To triangulate which network layer (origin / Cloudflare / Wordfence) is slow, run respira_diagnose_connection — it probes the same site with HEAD/GET/OPTIONS and reports per-layer latency + edge-layer presence. ' +
|
|
1156
1233
|
'To file a structured bug report from inside this chat, call respira_report_issue.',
|
|
1157
1234
|
site: activeSite,
|
|
1158
|
-
}
|
|
1235
|
+
}),
|
|
1159
1236
|
},
|
|
1160
1237
|
],
|
|
1161
1238
|
isError: true,
|
|
@@ -1270,7 +1347,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
1270
1347
|
// filing (see the "When something goes wrong" section in the
|
|
1271
1348
|
// server handshake instructions).
|
|
1272
1349
|
file_bug_hint: 'If retry + respira_diagnose_connection do not resolve this, ask the user if they want to file a bug report. If yes, call respira_report_issue with title, brief, severity, steps_to_reproduce, expected, actual, error_messages, and last_tool. The bug lands at https://www.respira.press/dashboard/bug-reports with full MCP context auto-attached.',
|
|
1273
|
-
}
|
|
1350
|
+
}),
|
|
1274
1351
|
},
|
|
1275
1352
|
],
|
|
1276
1353
|
isError: true,
|
|
@@ -1493,7 +1570,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
1493
1570
|
},
|
|
1494
1571
|
{
|
|
1495
1572
|
name: 'wordpress_create_page_duplicate',
|
|
1496
|
-
description: 'Create
|
|
1573
|
+
description: 'Create an approval-gated duplicate of a page for staged editing. Optional, NOT required before edits: every write already auto-captures a snapshot, and the write response returns a snapshot_uuid for one-call rollback via respira_restore_snapshot. Use a duplicate only when you want a separate copy the user reviews and approves in WordPress admin (Respira → Page Approvals) before it replaces the original. After creating it, edit the duplicate with wordpress_update_page.',
|
|
1497
1574
|
inputSchema: {
|
|
1498
1575
|
type: 'object',
|
|
1499
1576
|
properties: {
|
|
@@ -1639,7 +1716,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
1639
1716
|
},
|
|
1640
1717
|
{
|
|
1641
1718
|
name: 'wordpress_create_post_duplicate',
|
|
1642
|
-
description: 'Create
|
|
1719
|
+
description: 'Create an approval-gated duplicate of a post for staged editing. Optional, NOT required before edits: every write already auto-captures a snapshot, and the write response returns a snapshot_uuid for one-call rollback via respira_restore_snapshot. Use a duplicate only when you want a separate copy the user reviews and approves in WordPress admin (Respira → Page Approvals) before it replaces the original. After creating it, edit the duplicate with wordpress_update_post.',
|
|
1643
1720
|
inputSchema: {
|
|
1644
1721
|
type: 'object',
|
|
1645
1722
|
properties: {
|
|
@@ -1943,7 +2020,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
1943
2020
|
},
|
|
1944
2021
|
{
|
|
1945
2022
|
name: 'wordpress_inject_builder_content',
|
|
1946
|
-
description: 'REPLACE (or append to) the entire page builder layout. WARNING: By default this REPLACES all existing content (use mode:"append" to add content without destroying existing elements). For editing a single module, use wordpress_update_module instead. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery. For Divi, divi_version is required ("4" or "5").
|
|
2023
|
+
description: 'REPLACE (or append to) the entire page builder layout. WARNING: By default this REPLACES all existing content (use mode:"append" to add content without destroying existing elements). For editing a single module, use wordpress_update_module instead. Use exactly: gutenberg, divi, elementor, bricks, beaver, oxygen, breakdance, brizy, thrive, visual-composer, wpbakery. For Divi, divi_version is required ("4" or "5"). Replacing a page that already has content with mode="replace" requires confirm_replace=true, else returns 409 respira_replace_confirmation_required. Alternatives: mode="append" to add to existing content, or edit_target="live" to overwrite the live page directly. The gate prevents silent data loss.\n\nCanonical Divi 5 nested shape: `content: [{ type: "section", children: [{ type: "row", children: [{ type: "column", children: [{ type: "heading", settings: {...} }] }] }] }]` (rows/cols/columns/modules/elements/innerBlocks also accepted as `children` aliases). Each Divi module needs its render-critical attr in `settings` (e.g. heading→title, text→content, button→button_text); the plugin names any missing one via `respira_divi_required_attrs_missing`.',
|
|
1947
2024
|
inputSchema: {
|
|
1948
2025
|
type: 'object',
|
|
1949
2026
|
properties: {
|
|
@@ -2150,6 +2227,28 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
2150
2227
|
},
|
|
2151
2228
|
idempotentHint: true,
|
|
2152
2229
|
},
|
|
2230
|
+
{
|
|
2231
|
+
name: 'wordpress_restore_session',
|
|
2232
|
+
description: 'Cascade rollback: undo an entire session of changes in ONE call. Restores every distinct object the session touched (pages, ACF field groups, post types, taxonomies, options) to its pre-session state. Pass the session_id surfaced as recovery_session_id on a destructive response (or returned by wordpress_begin_session). Use this to recover from a destructive multi-step mess instead of restoring snapshots one at a time.',
|
|
2233
|
+
inputSchema: {
|
|
2234
|
+
type: 'object',
|
|
2235
|
+
properties: {
|
|
2236
|
+
session_id: { type: 'string', description: 'The session id to roll back.' },
|
|
2237
|
+
},
|
|
2238
|
+
required: ['session_id'],
|
|
2239
|
+
},
|
|
2240
|
+
idempotentHint: true,
|
|
2241
|
+
},
|
|
2242
|
+
{
|
|
2243
|
+
name: 'wordpress_begin_session',
|
|
2244
|
+
description: 'Begin an explicit snapshot session. Every change made after this (until wordpress_end_session) is grouped under one session_id, so the whole batch can be rolled back together with wordpress_restore_session. Returns the session_id. Without an explicit session, changes are auto-grouped by a time window.',
|
|
2245
|
+
inputSchema: { type: 'object', properties: {} },
|
|
2246
|
+
},
|
|
2247
|
+
{
|
|
2248
|
+
name: 'wordpress_end_session',
|
|
2249
|
+
description: 'End the explicit snapshot session started by wordpress_begin_session. Later changes fall back to automatic time-window grouping.',
|
|
2250
|
+
inputSchema: { type: 'object', properties: {} },
|
|
2251
|
+
},
|
|
2153
2252
|
{
|
|
2154
2253
|
name: 'wordpress_apply_builder_patch',
|
|
2155
2254
|
description: 'Apply a list of targeted builder patch operations. Each operation is { identifier: { id|admin_label|path|type [+match_content] }, updates: { content?, attributes?, ...flat_settings? } }. The identifier block follows the same shape as wordpress_find_element\'s identifier; the updates block follows the same shape as wordpress_update_module\'s updates. Returns 400 respira_patch_invalid_operation when an entry is missing either field. This is NOT a JSON-Patch document — do not pass { op, path, value } shapes (those will be rejected). Example: { operations: [{ identifier: { admin_label: "Hero" }, updates: { admin_label: "Hero Content" } }] }.',
|
|
@@ -2333,7 +2432,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
2333
2432
|
// token or per-site license api_token), exactly like mcp-spend.
|
|
2334
2433
|
// Server-side this lands as a bug_report row with source='mcp'.
|
|
2335
2434
|
name: 'wordpress_report_issue',
|
|
2336
|
-
description: 'File a structured bug report from inside the chat
|
|
2435
|
+
description: 'File a structured bug report from inside the chat when something breaks: a tool failed, an edit produced wrong output, a step timed out, or the MCP behaved differently than its description. Goes directly to the maintainer with live MCP context and shows up at https://www.respira.press/dashboard/bug-reports. Required: title (8-120 chars), brief (20-280 chars), steps_to_reproduce (>=12 chars). Optional but encouraged: severity (blocker|major|minor|cosmetic), expected, actual, error_messages (verbatim), last_tool. Auto-attached: site_url, mcp_version, builder, builder_version. If you ran respira_diagnose_connection, pass its full result as diagnostics. Privacy: never sends prompts, tool args, tool results, or WordPress content, only the structured fields you put in.',
|
|
2337
2436
|
inputSchema: {
|
|
2338
2437
|
type: 'object',
|
|
2339
2438
|
required: ['title', 'brief', 'steps_to_reproduce'],
|
|
@@ -3261,13 +3360,13 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
3261
3360
|
},
|
|
3262
3361
|
{
|
|
3263
3362
|
name: 'wordpress_create_acf_field_group',
|
|
3264
|
-
description: "Create an ACF (Advanced Custom Fields) field group. Requires ACF (free or Pro) active on the site — call wordpress_get_site_context first to confirm. Stored in wp_option respira_custom_acf_field_groups and registered via acf_add_local_field_group() on acf/init. Use to bind structured fields (text, number, image, post relation) to specific post types via the location rules.",
|
|
3363
|
+
description: "Create an ACF (Advanced Custom Fields) field group. Requires ACF (free or Pro) active on the site — call wordpress_get_site_context first to confirm. Stored in wp_option respira_custom_acf_field_groups and registered via acf_add_local_field_group() on acf/init. Use to bind structured fields (text, number, image, post relation) to specific post types via the location rules. Note: groups created this way are registered locally, so they are read-only in the ACF admin UI and editable only via these tools. The response includes `field_hints` when a field looks like it picked the wrong type or width.",
|
|
3265
3364
|
inputSchema: {
|
|
3266
3365
|
type: 'object',
|
|
3267
3366
|
properties: {
|
|
3268
3367
|
key: { type: 'string', description: 'ACF group key. Defaults to "group_<uuid>" if omitted. Must start with "group_".' },
|
|
3269
3368
|
title: { type: 'string', description: 'Human-readable title shown in the post edit screen.' },
|
|
3270
|
-
fields: { type: 'array', description:
|
|
3369
|
+
fields: { type: 'array', description: "Array of ACF field definitions. Each field: { name (machine snake_case), label (human), type, wrapper:{ width: 1-100 }, return_format?, ... }. `key` is auto-generated if omitted. PICK THE RIGHT TYPE — do not default everything to 'text': use 'taxonomy' to link real WordPress terms (categories/tags), 'relationship' or 'post_object' to reference other posts/pages, 'url' for links and map links (not 'text'), 'image'/'file'/'gallery' with return_format ('array'|'url'|'id') for media so it uploads to the media library instead of storing a raw URL, plus 'number'/'email'/'true_false'/'select'/'checkbox'/'radio'/'date_picker'/'wysiwyg'/'repeater'/'group' where they fit. Set wrapper.width to lay related fields side by side (e.g. 50/50, 33/33/33, 25) rather than leaving every field at the 100% default. Set return_format on image/file/url/date fields.", items: { type: 'object' } },
|
|
3271
3370
|
location: { type: 'array', description: 'ACF location rules nested array. Example: [[{param:"post_type", operator:"==", value:"case_study"}]] = attach to case_study post type.', items: { type: 'array', items: { type: 'object' } } },
|
|
3272
3371
|
},
|
|
3273
3372
|
required: ['title'],
|
|
@@ -4877,17 +4976,17 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
4877
4976
|
case 'wordpress_get_builder_inline_schemas':
|
|
4878
4977
|
return await client.getBuilderInlineSchemas(args.builder, args.types);
|
|
4879
4978
|
case 'wordpress_inject_builder_content':
|
|
4880
|
-
return {
|
|
4979
|
+
return hoistDroppedStylingWarnings({
|
|
4881
4980
|
...(await client.injectBuilderContent(args.builder, args.page_id, args.content, args.divi_version, args.edit_target, args.mode, args.confirm_replace)),
|
|
4882
4981
|
respira_approvals_url: client.getApprovalsUrl(),
|
|
4883
|
-
};
|
|
4982
|
+
});
|
|
4884
4983
|
case 'wordpress_make_responsive':
|
|
4885
4984
|
return await client.makeResponsive(args.page_id, args.dry_run || false);
|
|
4886
4985
|
case 'wordpress_update_module':
|
|
4887
|
-
return {
|
|
4986
|
+
return hoistDroppedStylingWarnings({
|
|
4888
4987
|
...(await client.updateModule(args.builder, args.page_id, args.module_identifier, args.updates, args.edit_target)),
|
|
4889
4988
|
respira_approvals_url: client.getApprovalsUrl(),
|
|
4890
|
-
};
|
|
4989
|
+
});
|
|
4891
4990
|
case 'wordpress_validate_security':
|
|
4892
4991
|
return await client.validateSecurity(args.content);
|
|
4893
4992
|
case 'wordpress_read_theme_file':
|
|
@@ -5181,6 +5280,12 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
5181
5280
|
return await client.diffSnapshots(args.snapshot_uuid_a, args.snapshot_uuid_b);
|
|
5182
5281
|
case 'wordpress_restore_snapshot':
|
|
5183
5282
|
return await client.restoreSnapshot(args.snapshot_uuid);
|
|
5283
|
+
case 'wordpress_restore_session':
|
|
5284
|
+
return await client.callRestV2('POST', '/snapshots/restore-session', { session_id: args.session_id });
|
|
5285
|
+
case 'wordpress_begin_session':
|
|
5286
|
+
return await client.callRestV2('POST', '/snapshots/session/begin', {});
|
|
5287
|
+
case 'wordpress_end_session':
|
|
5288
|
+
return await client.callRestV2('POST', '/snapshots/session/end', {});
|
|
5184
5289
|
case 'wordpress_apply_builder_patch':
|
|
5185
5290
|
return await client.applyBuilderPatch(args.builder, args.post_id, args.operations, args.include, args.edit_target);
|
|
5186
5291
|
case 'woocommerce_list_products':
|
|
@@ -5309,7 +5414,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
5309
5414
|
return await client.callRestV2('POST', `/builder/elements/reorder/${post_id}`, rest);
|
|
5310
5415
|
}
|
|
5311
5416
|
case 'wordpress_build_page':
|
|
5312
|
-
return await client.callRestV2('POST', '/builder/build', args);
|
|
5417
|
+
return hoistDroppedStylingWarnings(await client.callRestV2('POST', '/builder/build', args));
|
|
5313
5418
|
case 'wordpress_convert_html_to_builder':
|
|
5314
5419
|
return await client.callRestV2('POST', '/builder/convert', args);
|
|
5315
5420
|
case 'wordpress_bulk_pages_operation':
|
|
@@ -5549,7 +5654,7 @@ Allowlist: css, scss, less, json. PHP / JS theme writes are intentionally out of
|
|
|
5549
5654
|
// --- Composite Tools ---
|
|
5550
5655
|
{
|
|
5551
5656
|
name: 'wordpress_build_page',
|
|
5552
|
-
description: 'Create a complete page from a declarative structure. Accepts builder-specific widget definitions and creates the page with all elements in one call. Returns page_id, edit_url, and preview_url.\n\nNested
|
|
5657
|
+
description: 'Create a complete page from a declarative structure. Accepts builder-specific widget definitions and creates the page with all elements in one call. Returns page_id, edit_url, and preview_url.\n\nNested shape (Divi 5 / any nesting builder): use `children: [...]` at every container level, e.g. `structure: [{ type: "section", children: [{ type: "row", children: [{ type: "column", children: [{ type: "heading", settings: { title: "Hi", tag: "h1" } }] }] }] }]`. Divi also accepts `rows/cols/columns/modules/elements/innerBlocks` as `children` aliases. Flat shape also works: pass leaf modules at the top level and the builder auto-wraps them in section > row > column.',
|
|
5553
5658
|
inputSchema: {
|
|
5554
5659
|
type: 'object',
|
|
5555
5660
|
properties: {
|