@respira/wordpress-mcp-server 7.6.1 → 8.0.0

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 (34) hide show
  1. package/README.md +59 -31
  2. package/TOOL_CATALOG.md +288 -0
  3. package/dist/__tests__/pagespeed-error-classification.test.d.ts +2 -0
  4. package/dist/__tests__/pagespeed-error-classification.test.d.ts.map +1 -0
  5. package/dist/__tests__/pagespeed-error-classification.test.js +52 -0
  6. package/dist/__tests__/pagespeed-error-classification.test.js.map +1 -0
  7. package/dist/__tests__/rest-route-fallback.test.js +0 -64
  8. package/dist/__tests__/rest-route-fallback.test.js.map +1 -1
  9. package/dist/__tests__/site-token-401-error-classification.test.d.ts +0 -19
  10. package/dist/__tests__/site-token-401-error-classification.test.d.ts.map +1 -1
  11. package/dist/__tests__/site-token-401-error-classification.test.js +20 -60
  12. package/dist/__tests__/site-token-401-error-classification.test.js.map +1 -1
  13. package/dist/__tests__/tools-list-protocol-smoke.test.d.ts +2 -0
  14. package/dist/__tests__/tools-list-protocol-smoke.test.d.ts.map +1 -0
  15. package/dist/__tests__/tools-list-protocol-smoke.test.js +78 -0
  16. package/dist/__tests__/tools-list-protocol-smoke.test.js.map +1 -0
  17. package/dist/config.d.ts.map +1 -1
  18. package/dist/config.js +20 -7
  19. package/dist/config.js.map +1 -1
  20. package/dist/elementor-tools.js +2 -2
  21. package/dist/elementor-tools.js.map +1 -1
  22. package/dist/server.d.ts.map +1 -1
  23. package/dist/server.js +758 -19
  24. package/dist/server.js.map +1 -1
  25. package/dist/usage-emitter.d.ts +7 -0
  26. package/dist/usage-emitter.d.ts.map +1 -1
  27. package/dist/usage-emitter.js +41 -1
  28. package/dist/usage-emitter.js.map +1 -1
  29. package/dist/wordpress-client.d.ts +59 -42
  30. package/dist/wordpress-client.d.ts.map +1 -1
  31. package/dist/wordpress-client.js +149 -135
  32. package/dist/wordpress-client.js.map +1 -1
  33. package/package.json +5 -8
  34. package/tool-capabilities.json +4122 -0
package/README.md CHANGED
@@ -7,14 +7,14 @@
7
7
  <h1 align="center">Respira WordPress MCP Server</h1>
8
8
 
9
9
  <p align="center">
10
- <strong>200+ MCP tools (275+ with add-ons). 16 page builders. Context-aware tool filtering. The AI infrastructure layer for WordPress.</strong><br>
10
+ <strong>169 core MCP tools, 272 with the WooCommerce add-on. 16 page builders. Context-aware tool filtering. The AI infrastructure layer for WordPress.</strong><br>
11
11
  Element-level editing, full page creation, HTML-to-builder conversion with rendering fidelity validation, per-site tool governance, storefront design intelligence, stock images, bulk operations — all through one MCP server.
12
12
  </p>
13
13
 
14
14
  <p align="center">
15
15
  <a href="https://www.npmjs.com/package/@respira/wordpress-mcp-server"><img src="https://img.shields.io/npm/v/@respira/wordpress-mcp-server.svg?style=flat-square&color=10b981" alt="npm version"></a>
16
16
  <a href="https://www.npmjs.com/package/@respira/wordpress-mcp-server"><img src="https://img.shields.io/npm/dm/@respira/wordpress-mcp-server.svg?style=flat-square" alt="npm downloads"></a>
17
- <img src="https://img.shields.io/badge/tools-200+-10b981?style=flat-square" alt="200+ Tools">
17
+ <img src="https://img.shields.io/badge/tools-272-10b981?style=flat-square" alt="272 Tools with WooCommerce">
18
18
  <img src="https://img.shields.io/badge/builders-16-10b981?style=flat-square" alt="16 Page Builders">
19
19
  <img src="https://img.shields.io/badge/TypeScript-100%25-blue?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript">
20
20
  </p>
@@ -35,17 +35,38 @@ Other WordPress MCP servers wrap the REST API. They can create posts and pages,
35
35
 
36
36
  Respira includes a WordPress plugin that gives AI **native access** to 16 page builders, plus element-level precision, full page creation from structure, HTML-to-builder conversion, storefront design intelligence, stock image search, and bulk operations across hundreds of pages.
37
37
 
38
- ### New in v7.5.5: path-safe multi-site routing and custom Elementor guidance
38
+ ### Next release: verified FSE and WooCommerce operations
39
39
 
40
- - **Subdirectory WordPress sites now have distinct identities.** `https://example.com` derives `example-com`, while `https://example.com/blog` derives `example-com-blog`; non-default ports are included too. Legacy automatic collisions self-heal, and ambiguous duplicate explicit IDs fail clearly instead of silently replacing one site in memory.
41
- - **Custom Elementor widgets have a safe targeted workflow.** Respira reads Elementor's live widget registry, including controls registered by themes and third-party plugins. Agents are instructed to list widgets, fetch the exact runtime schema, find the existing element, patch only its changed settings by stable ID, and re-read it—never replace the full `_elementor_data` document for one widget.
40
+ - **First-class Site Editor tools.** Agents can list, inspect, create, target-update, and reset block templates and template parts; create and safely edit synced/unsynced patterns; and traverse native block navigation as exact nested paths. Every editable surface uses stale-write fingerprints, structural proposals, snapshots, compact diffs, cache invalidation, and truthful stored/rendered verification.
41
+ - **Native design-token tools.** Gutenberg `theme.json` colors, typography, and spacing variables are exposed through the existing WordPress storage model rather than a parallel token database.
42
+ - **Truthful storefront writes.** Woo product-card, checkout, sale-badge, and low-stock-badge tools resolve the real FSE template and registered block paths. An unsupported layout now returns `respira_woo_fse_write_not_supported`; it never reports an applied change that only logged intent.
43
+ - **Bounded, defined commerce reporting.** Revenue, sales time series, top products, order summaries, and privacy-safe customer summaries use paginated WooCommerce data-store queries compatible with HPOS. Responses state currency, timezone, boundaries, statuses, coverage, and metric definitions.
44
+ - **Safe store operations.** Read-only store configuration, payment gateway, shipping-zone, and tax-rate discovery is joined by approval-gated Woo webhooks with HTTPS targets, allowlisted topics, write-only secrets, and redacted rate-limited tests.
45
+ - **Agent-visible audit history.** Activity list/detail tools connect compact diffs to snapshots, proposals, approvals, and rollbacks.
46
+ - **Truthful capability discovery.** `wordpress_search_abilities` labels each result as Respira-native, inhaled, unavailable, or replaced by a safer audited Respira workflow, and returns the exact next action.
47
+ - **Explicit feed recovery.** `woocommerce_get_feed_status` stays read-only while `woocommerce_repair_feed_scheduler` can clear only a confirmed-stale Respira lock, resume the idempotent build, verify the repair, and preserve Action Scheduler history.
48
+ - **Safer plugin activation.** Dependency/version preflight, a signed fresh-process activation probe, REST/frontend boot checks, and narrowly scoped rollback prevent a broken plugin from taking the controlling request down with it.
49
+ - **Generated release integrity.** A public [tool catalog](./TOOL_CATALOG.md) and machine-readable `tool-capabilities.json` are generated from the declarations used in release CI. Missing native or documentation coverage requires an explicit, reviewable exclusion.
42
50
 
43
- ### Also shipped since v7.5.2
51
+ ### New in v7.6.2: clearer failures and trustworthy quality signals
44
52
 
45
- - **v7.5.3:** Windows absolute paths and `file://` URIs are recognized during media upload; `delete_media` now forwards its approval token and force flag so confirmation can complete.
46
- - **v7.5.4:** `tools/list` uses one shared, cached, two-second-bounded site-context fetch instead of three sequential WordPress calls. A slow or unreachable site can no longer hold the initial tool catalog open through multiple retry windows.
53
+ - **PageSpeed failures keep their real machine-readable reason.** Rate limits, upstream outages, proxy HTML responses, and other structured WordPress errors no longer collapse into a generic failure, so agents can distinguish “retry later” from a Respira defect.
54
+ - **PageSpeed tools reject incomplete requests before touching WordPress.** Both PageSpeed schemas require either `page_id` or `url`, preventing avoidable calls that could only fail.
55
+ - **Every transport attempt has its own identity.** The logical call id remains stable for replay-safe writes, while `attempt_id` preserves each network attempt so a retry can never overwrite the evidence from the first timeout.
56
+ - **Privacy remains metadata-only.** Retry detection uses a process-secret target hash. Respira never sends prompts, raw arguments, tool results, or WordPress content.
57
+ - **The admin quality dashboard now separates operational health from task completion.** Expected approval/safety blocks, caller mistakes, customer setup, upstream services, product errors, unknown failures, and incomplete attempts are measured independently. Alerts use comparable site cohorts and require failures across multiple sites, reducing false alarms caused by one unusual customer setup.
58
+ - **The npm package no longer publishes private repository metadata.** Support and product links point to respira.press.
47
59
 
48
- ### v7.5.2: reconnect-safe writes and drop diagnostics
60
+ ### Reliability and builder additions since v7.5.2
61
+
62
+ - **v7.5.3:** Windows media paths and `file://` uploads work correctly; `delete_media` approval tokens now reach the confirmation call.
63
+ - **v7.5.4:** `tools/list` shares one cached, two-second-bounded context fetch instead of making three sequential WordPress checks, preventing slow-site handshake disconnects.
64
+ - **v7.5.5:** subdirectory WordPress installs on the same hostname receive distinct site identities; custom Elementor widget guidance now uses live control schemas and targeted stable-ID updates.
65
+ - **v7.5.6:** a successful `?rest_route=` diagnostic fallback becomes sticky for the rest of the MCP session.
66
+ - **v7.6.0:** WPML translation tools and Divi Theme Builder header, footer, and body-template tools.
67
+ - **v7.6.1:** `wordpress_build_mega_menu` creates a complete native Divi 4 or Divi 5 mega-menu hierarchy in one call.
68
+
69
+ ### Reconnect-safe writes and drop diagnostics (v7.5.2)
49
70
 
50
71
  - **Writes carry a stable idempotency key.** The connector automatically retries transient reads. It retries a write only when WordPress explicitly confirms replay support; an ambiguous timeout/reset is reported as `respira_write_outcome_unknown` so the agent verifies the target before trying again.
51
72
  - **Telemetry queues and retries independently of tool execution.** A dashboard or network interruption cannot block a WordPress call, and failed metadata batches are retained with bounded exponential backoff.
@@ -53,13 +74,13 @@ Respira includes a WordPress plugin that gives AI **native access** to 16 page b
53
74
  - **The quality dashboard can separate exact retries from editing sweeps.** It records stable session/call identity, transport, incomplete calls, connector/plugin versions, total vs tool time, and privacy-safe stage durations. Target comparison uses a secret HMAC; arguments, results, prompts, and WordPress content are never sent.
54
75
  - **Native URL-connected clients gain timeout-safe writes.** Plugin 7.5.46 adds `_respira_async: true`, `respira_get_job_status`, stable `Mcp-Session-Id` responses, replay-safe `_respira_call_id`, and a native `respira_diagnose_connection` tool. The native endpoint is stateless HTTP—independent POST requests, not a persistent “write channel.”
55
76
 
56
- ### Also shipped since the README's previous v7.1 refresh
77
+ ### Also shipped between v7.1 and v7.5.1
57
78
 
58
79
  - **v7.2:** cascade session rollback; dropped-styling/no-op guidance; page-parent schemas; Oxygen 6 build guidance; completed live-edit confirmation parameters; bounded heavy-write/docs timeouts; and route-aware capability negotiation that hides tools an older plugin cannot execute.
59
80
  - **v7.3:** the WooCommerce add-on expanded from 21 to 56 tools across catalog, pricing, stock, storefront, brands, variations/attributes, coupons, customers, refunds, and AI-readiness.
60
81
  - **v7.4:** Agent-Ready Commerce expanded WooCommerce to 79 tools with feeds + store `llms.txt`, readiness fixes, signed cart links/attribution, and Subscriptions, Bookings, and Memberships writes. v7.4.1 then made newly connected dashboard sites self-heal into a running connector session.
61
82
  - **v7.5.0:** eight STAGGS configurator tools brought the WooCommerce total to 87.
62
- - **v7.5.1:** fixed normalized ACF tool routing and preserved dashboard-token 401 machine codes—the two fixes shipped immediately before this reliability release.
83
+ - **v7.5.1:** fixed normalized ACF tool routing and preserved dashboard-token 401 machine codes.
63
84
 
64
85
  ### New in v7.1 "Roots"
65
86
 
@@ -95,7 +116,7 @@ Every successful tool response includes `structuredContent`, the raw JSON object
95
116
 
96
117
  ### v6.0 "Storefront" — Context-Aware Tool Filtering
97
118
 
98
- The MCP server automatically filters the tool list based on your site's detected builder and active plugins. A Divi site without WooCommerce sees ~130 tools instead of ~170. Less noise, faster AI responses, lower token usage. Fail-open: if detection fails, the full list is returned.
119
+ The MCP server exposes 169 core tools and 103 WooCommerce add-on tools. It automatically filters the list based on the site's detected builder and active plugins, so clients receive only the useful subset. Fail-open: if detection fails, the full list is returned.
99
120
 
100
121
  | Capability | Respira | Typical WordPress MCP servers |
101
122
  |---|---|---|
@@ -203,7 +224,7 @@ Or run the interactive setup wizard: `npx @respira/wordpress-mcp-server --setup`
203
224
 
204
225
  ### Tool Limit? Use `enabledTools`
205
226
 
206
- Some MCP clients (Antigravity, etc.) have a hard limit on active tools (often 100). Respira exposes 172 tools by default. To stay under the limit, add `enabledTools` to your config — only those tools will appear in the listing:
227
+ Some MCP clients (Antigravity, etc.) have a hard limit on active tools (often 100). Respira can expose up to 272 tools when the WooCommerce add-on is active. To stay under the limit, add `enabledTools` to your config — only those tools will appear in the listing:
207
228
 
208
229
  ```json
209
230
  {
@@ -242,13 +263,13 @@ Unknown tool names now return a proper `CallToolResult` with `isError: true` and
242
263
  ## v6.0 "Storefront" — What's New
243
264
 
244
265
  ### Context-Aware Tool Filtering
245
- The MCP server automatically filters the tool list based on your site's detected builder and active plugins. A Divi site without WooCommerce sees ~130 tools instead of ~170. Less noise, faster AI responses, lower token usage. Fail-open: if detection fails, the full list is returned.
266
+ The MCP server automatically filters its 169 core and 103 WooCommerce tools based on the site's detected builder and active plugins. Less noise, faster AI responses, lower token usage. Fail-open: if detection fails, the full list is returned.
246
267
 
247
268
  ### Flatsome UX Builder (Builder #12)
248
269
  Full round-trip shortcode editing, element-level precision, declarative page creation, and 55-element intelligence. Detected by active theme — mixed-builder sites handled per-page.
249
270
 
250
271
  ### 15 New WooCommerce Commerce Tools
251
- Storefront design intelligence bridges commerce data and page builder visuals. Bulk pricing, catalog health audits, advanced filtering, natural language product search. Total WooCommerce tools: 36.
272
+ Storefront design intelligence bridges commerce data and page builder visuals. Bulk pricing, catalog health audits, advanced filtering, natural language product search. Total WooCommerce tools: 103.
252
273
 
253
274
  ### Element-Level Operations
254
275
  Find, update, move, duplicate, and remove individual elements inside any page builder — by ID, type, CSS class, or content text.
@@ -332,6 +353,23 @@ respira_add_image({ post_id: 42, image_url: "https://..." })
332
353
 
333
354
  ## All Tools
334
355
 
356
+ ### Native Site Editor structures (10 tools) — Next release
357
+
358
+ These are Respira-native WordPress operations, not a copied generic tool catalog. User-owned structures use the same approval, revision, snapshot, no-op detection, read-back, and render-verification contract as template editing. Theme and plugin patterns are inspectable but remain owned by their source.
359
+
360
+ | Tool | Description |
361
+ |---|---|
362
+ | `wordpress_list_site_patterns` | List user, theme, plugin, and core patterns with source, sync status, and fingerprints |
363
+ | `wordpress_get_site_pattern` | Inspect a pattern as a lossless path-addressed block tree |
364
+ | `wordpress_create_site_pattern` | Stage a synced or unsynced user pattern |
365
+ | `wordpress_update_site_pattern` | Apply exact block operations with stale/wrong-target protection |
366
+ | `wordpress_delete_site_pattern` | Delete through approval; referenced patterns are refused by default |
367
+ | `wordpress_list_site_navigations` | List block navigation entities with compact nested items and exact paths |
368
+ | `wordpress_get_site_navigation` | Inspect the full native navigation block document and its references |
369
+ | `wordpress_create_site_navigation` | Stage a native block navigation entity |
370
+ | `wordpress_update_site_navigation` | Target one link/submenu while preserving unknown extension blocks |
371
+ | `wordpress_delete_site_navigation` | Delete through approval; referenced navigation is refused by default |
372
+
335
373
  ### Bricks Deep Intelligence (20 tools) — NEW in v5.4
336
374
  | Tool | Description |
337
375
  |---|---|
@@ -476,12 +514,13 @@ Add any widget to a page in one call:
476
514
  | `respira_switch_site` | Switch active site |
477
515
  | `respira_get_active_site` | Get current site info |
478
516
 
479
- ### WooCommerce Add-on (21 tools)
517
+ ### WooCommerce Add-on (103 tools)
480
518
  Available when the [WooCommerce add-on](https://respira.press/addons/woocommerce) is installed. Included free with Studio and Founder plans.
481
519
 
482
520
  | Category | Tools |
483
521
  |---|---|
484
522
  | **Storefront intelligence** (NEW in v6.0) | `analyze_shop_page`, `analyze_product_page`, `update_product_card_layout`, `add_low_stock_badge`, `add_sale_badge`, `update_checkout_layout` |
523
+ | **Product-card fields** (NEW in 8.0) | `analyze_storefront_card`, `update_storefront_card_field` |
485
524
  | **Catalog operations** (NEW in v6.0) | `list_products_advanced`, `bulk_update_products`, `analyze_catalog_health`, `find_product_by_natural_language` |
486
525
  | **Pricing** (NEW in v6.0) | `bulk_update_prices`, `schedule_sale`, `revert_pricing` |
487
526
  | **Inventory** (NEW in v6.0) | `bulk_update_stock`, `find_low_stock` |
@@ -490,7 +529,9 @@ Available when the [WooCommerce add-on](https://respira.press/addons/woocommerce
490
529
  | **Inventory control** | `get_stock_status`, `update_stock` |
491
530
  | **Product categories** | `list_categories`, `get_category`, `create_category`, `update_category`, `delete_category` |
492
531
  | **Product tags** | `list_tags`, `get_tag`, `create_tag`, `update_tag`, `delete_tag` |
493
- | **Analytics** | `sales_report` |
532
+ | **Analytics** | `sales_report` (deprecated alias), `revenue_summary`, `sales_timeseries`, `top_products`, `orders_summary`, `customers_summary` |
533
+ | **Store configuration** | `get_store_configuration`, `list_payment_gateways`, `list_shipping_zones`, `list_tax_rates` |
534
+ | **Webhooks** | `list_webhooks`, `get_webhook`, `create_webhook`, `update_webhook`, `delete_webhook`, `test_webhook` |
494
535
 
495
536
  ---
496
537
 
@@ -523,19 +564,6 @@ Manage multiple WordPress sites from one config:
523
564
 
524
565
  Switch sites: `respira_switch_site({ siteId: "staging" })`
525
566
 
526
- Every non-global tool also accepts `site_id`. For shared connectors, include it on every call; set `RESPIRA_REQUIRE_SITE_ID=1` to reject multi-site writes that omit it. If two installs share a hostname (for example the root site and `/blog`), keep distinct explicit IDs as shown below. v7.5.5+ also derives distinct IDs from their paths automatically.
527
-
528
- ```json
529
- {
530
- "sites": [
531
- { "id": "brand24-main", "name": "Brand24 staging", "url": "https://stag.brand24.com", "apiKey": "respira_main_key", "default": true },
532
- { "id": "brand24-blog", "name": "Brand24 blog staging", "url": "https://stag.brand24.com/blog", "apiKey": "respira_blog_key" }
533
- ]
534
- }
535
- ```
536
-
537
- For the strongest isolation—especially when several testers work concurrently—use one connector/config per WordPress install. A shared connector is safe when IDs are unique, calls carry `site_id`, and `RESPIRA_REQUIRE_SITE_ID=1` is enabled.
538
-
539
567
  For agencies managing many sites, use the hosted setup at [respira.press/dashboard/mcp](https://www.respira.press/dashboard/mcp) to generate configs and install commands from your account.
540
568
 
541
569
  ---
@@ -774,6 +802,6 @@ MIT © [Respira](https://respira.press)
774
802
  ---
775
803
 
776
804
  <p align="center">
777
- <strong>200+ tools. 16 builders. The AI infrastructure layer for WordPress.</strong><br>
805
+ <strong>169 core tools, 272 with WooCommerce. 16 builders. The AI infrastructure layer for WordPress.</strong><br>
778
806
  <a href="https://respira.press">respira.press</a>
779
807
  </p>
@@ -0,0 +1,288 @@
1
+ # Respira MCP tool catalog
2
+
3
+ <!-- Generated by scripts/check-tool-registry-parity.mjs. Do not edit by hand. -->
4
+
5
+ Generated catalog: **169 core tools**, **105 WooCommerce tools**, **274 total**.
6
+
7
+ The runtime applies site context and per-site governance, so an individual connection may expose a smaller relevant subset.
8
+
9
+ ## WordPress and Respira
10
+
11
+ - `respira_duplicate_with_translations` — write; hosted/stdio
12
+ - `wordpress_abilities_gap_report` — read; hosted/stdio
13
+ - `wordpress_activate_plugin` — write; native + hosted
14
+ - `wordpress_analyze_aeo` — read; native + hosted
15
+ - `wordpress_analyze_images` — read; native + hosted
16
+ - `wordpress_analyze_pagespeed` — read; hosted/stdio
17
+ - `wordpress_analyze_performance` — read; native + hosted
18
+ - `wordpress_analyze_rankmath` — read; native + hosted
19
+ - `wordpress_analyze_readability` — read; native + hosted
20
+ - `wordpress_analyze_seo` — read; native + hosted
21
+ - `wordpress_append_theme_file` — read; hosted/stdio
22
+ - `wordpress_apply_accessibility_fixes` — write; hosted/stdio
23
+ - `wordpress_apply_builder_patch` — write; native + hosted
24
+ - `wordpress_assign_menu_location` — write; native + hosted
25
+ - `wordpress_batch_update` — write; native + hosted
26
+ - `wordpress_begin_session` — read; hosted/stdio
27
+ - `wordpress_build_mega_menu` — write; native + hosted
28
+ - `wordpress_build_page` — write; native + hosted
29
+ - `wordpress_bulk_pages_operation` — write; native + hosted
30
+ - `wordpress_check_seo_issues` — read; native + hosted
31
+ - `wordpress_check_structured_data` — read; native + hosted
32
+ - `wordpress_convert_html_to_builder` — write; native + hosted
33
+ - `wordpress_create_acf_field_group` — write; hosted/stdio
34
+ - `wordpress_create_comment` — write; native + hosted
35
+ - `wordpress_create_custom_post` — write; native + hosted
36
+ - `wordpress_create_design_token` — write; native + hosted
37
+ - `wordpress_create_menu` — write; native + hosted
38
+ - `wordpress_create_menu_item` — write; native + hosted
39
+ - `wordpress_create_page_duplicate` — write; native + hosted
40
+ - `wordpress_create_playbook` — write; hosted/stdio
41
+ - `wordpress_create_post_duplicate` — write; native + hosted
42
+ - `wordpress_create_post_type` — write; hosted/stdio
43
+ - `wordpress_create_site_navigation` — write; native + hosted
44
+ - `wordpress_create_site_pattern` — write; native + hosted
45
+ - `wordpress_create_site_template` — write; native + hosted
46
+ - `wordpress_create_taxonomy` — write; hosted/stdio
47
+ - `wordpress_create_term` — write; native + hosted
48
+ - `wordpress_create_theme_builder_template` — write; native + hosted
49
+ - `wordpress_create_translation` — write; native + hosted
50
+ - `wordpress_create_user` — write; native + hosted
51
+ - `wordpress_deactivate_plugin` — write; native + hosted
52
+ - `wordpress_delete_acf_field_group` — write; hosted/stdio
53
+ - `wordpress_delete_comment` — write; native + hosted
54
+ - `wordpress_delete_custom_post` — write; native + hosted
55
+ - `wordpress_delete_design_token` — write; native + hosted
56
+ - `wordpress_delete_media` — write; native + hosted
57
+ - `wordpress_delete_menu` — write; native + hosted
58
+ - `wordpress_delete_menu_item` — write; native + hosted
59
+ - `wordpress_delete_option` — write; native + hosted
60
+ - `wordpress_delete_page` — write; native + hosted
61
+ - `wordpress_delete_playbook` — write; hosted/stdio
62
+ - `wordpress_delete_plugin` — write; native + hosted
63
+ - `wordpress_delete_post` — write; native + hosted
64
+ - `wordpress_delete_post_type` — write; hosted/stdio
65
+ - `wordpress_delete_site_navigation` — write; native + hosted
66
+ - `wordpress_delete_site_pattern` — write; native + hosted
67
+ - `wordpress_delete_taxonomy` — write; hosted/stdio
68
+ - `wordpress_delete_term` — write; native + hosted
69
+ - `wordpress_delete_user` — write; native + hosted
70
+ - `wordpress_diagnose_connection` — read; hosted/stdio
71
+ - `wordpress_diff_snapshots` — read; native + hosted
72
+ - `wordpress_duplicate_element` — write; native + hosted
73
+ - `wordpress_end_session` — read; hosted/stdio
74
+ - `wordpress_extract_builder_content` — read; native + hosted
75
+ - `wordpress_find_builder_targets` — read; native + hosted
76
+ - `wordpress_find_element` — read; native + hosted
77
+ - `wordpress_get_accessibility_scan` — read; hosted/stdio
78
+ - `wordpress_get_active_site` — read; hosted/stdio
79
+ - `wordpress_get_activity` — read; native + hosted
80
+ - `wordpress_get_builder_info` — read; native + hosted
81
+ - `wordpress_get_builder_inline_schemas` — read; hosted/stdio
82
+ - `wordpress_get_comment` — read; native + hosted
83
+ - `wordpress_get_core_web_vitals` — read; native + hosted
84
+ - `wordpress_get_custom_post` — read; native + hosted
85
+ - `wordpress_get_divi_migration_readiness` — read; hosted/stdio
86
+ - `wordpress_get_media` — read; native + hosted
87
+ - `wordpress_get_menu` — read; native + hosted
88
+ - `wordpress_get_menu_item` — read; native + hosted
89
+ - `wordpress_get_option` — read; native + hosted
90
+ - `wordpress_get_page_outline` — read; hosted/stdio
91
+ - `wordpress_get_playbook` — read; hosted/stdio
92
+ - `wordpress_get_post_type` — read; native + hosted
93
+ - `wordpress_get_server_compatibility` — read; native + hosted
94
+ - `wordpress_get_site_context` — read; native + hosted
95
+ - `wordpress_get_site_navigation` — read; native + hosted
96
+ - `wordpress_get_site_pattern` — read; native + hosted
97
+ - `wordpress_get_site_template` — read; native + hosted
98
+ - `wordpress_get_snapshot` — read; native + hosted
99
+ - `wordpress_get_taxonomy` — read; native + hosted
100
+ - `wordpress_get_term` — read; native + hosted
101
+ - `wordpress_get_theme_docs` — read; native + hosted
102
+ - `wordpress_get_translations` — read; native + hosted
103
+ - `wordpress_get_user` — read; native + hosted
104
+ - `wordpress_inject_builder_content` — write; native + hosted
105
+ - `wordpress_install_plugin` — write; native + hosted
106
+ - `wordpress_invoke_ability` — write; hosted/stdio
107
+ - `wordpress_list_accessibility_scans` — read; hosted/stdio
108
+ - `wordpress_list_acf_field_groups` — read; hosted/stdio
109
+ - `wordpress_list_activity` — read; native + hosted
110
+ - `wordpress_list_comments` — read; native + hosted
111
+ - `wordpress_list_custom_post_types` — read; hosted/stdio
112
+ - `wordpress_list_custom_posts` — read; native + hosted
113
+ - `wordpress_list_custom_taxonomies` — read; hosted/stdio
114
+ - `wordpress_list_design_tokens` — read; native + hosted
115
+ - `wordpress_list_media` — read; native + hosted
116
+ - `wordpress_list_menu_items` — read; native + hosted
117
+ - `wordpress_list_menu_locations` — read; native + hosted
118
+ - `wordpress_list_menus` — read; native + hosted
119
+ - `wordpress_list_options` — read; native + hosted
120
+ - `wordpress_list_pages` — read; native + hosted
121
+ - `wordpress_list_playbooks` — read; hosted/stdio
122
+ - `wordpress_list_plugins` — read; native + hosted
123
+ - `wordpress_list_post_types` — read; native + hosted
124
+ - `wordpress_list_posts` — read; native + hosted
125
+ - `wordpress_list_site_navigations` — read; native + hosted
126
+ - `wordpress_list_site_patterns` — read; native + hosted
127
+ - `wordpress_list_site_templates` — read; native + hosted
128
+ - `wordpress_list_sites` — read; hosted/stdio
129
+ - `wordpress_list_snapshots` — read; native + hosted
130
+ - `wordpress_list_taxonomies` — read; native + hosted
131
+ - `wordpress_list_terms` — read; native + hosted
132
+ - `wordpress_list_theme_builder_templates` — read; native + hosted
133
+ - `wordpress_list_users` — read; native + hosted
134
+ - `wordpress_make_responsive` — read; hosted/stdio
135
+ - `wordpress_move_element` — write; native + hosted
136
+ - `wordpress_read_page` — read; native + hosted
137
+ - `wordpress_read_post` — read; native + hosted
138
+ - `wordpress_read_theme_file` — read; hosted/stdio
139
+ - `wordpress_redeem_token` — write; hosted/stdio
140
+ - `wordpress_remove_element` — write; native + hosted
141
+ - `wordpress_reorder_elements` — write; native + hosted
142
+ - `wordpress_report_issue` — read; hosted/stdio
143
+ - `wordpress_reset_site_template` — write; native + hosted
144
+ - `wordpress_restore_session` — write; hosted/stdio
145
+ - `wordpress_restore_snapshot` — write; native + hosted
146
+ - `wordpress_run_pagespeed_audit` — read; hosted/stdio
147
+ - `wordpress_scan_page_accessibility` — read; hosted/stdio
148
+ - `wordpress_search_abilities` — read; native + hosted
149
+ - `wordpress_search_docs` — read; hosted/stdio
150
+ - `wordpress_search_stock_images` — read; native + hosted
151
+ - `wordpress_sideload_image` — write; native + hosted
152
+ - `wordpress_switch_site` — write; native + hosted
153
+ - `wordpress_update_acf_field_group` — write; hosted/stdio
154
+ - `wordpress_update_comment` — write; native + hosted
155
+ - `wordpress_update_custom_post` — write; native + hosted
156
+ - `wordpress_update_design_token` — write; native + hosted
157
+ - `wordpress_update_element` — write; native + hosted
158
+ - `wordpress_update_media` — write; native + hosted
159
+ - `wordpress_update_media_batch` — write; hosted/stdio
160
+ - `wordpress_update_menu` — write; native + hosted
161
+ - `wordpress_update_menu_item` — write; native + hosted
162
+ - `wordpress_update_module` — write; native + hosted
163
+ - `wordpress_update_option` — write; native + hosted
164
+ - `wordpress_update_page` — write; native + hosted
165
+ - `wordpress_update_playbook` — write; hosted/stdio
166
+ - `wordpress_update_plugin` — write; native + hosted
167
+ - `wordpress_update_post` — write; native + hosted
168
+ - `wordpress_update_post_type` — write; hosted/stdio
169
+ - `wordpress_update_site_navigation` — write; native + hosted
170
+ - `wordpress_update_site_pattern` — write; native + hosted
171
+ - `wordpress_update_site_template` — write; native + hosted
172
+ - `wordpress_update_taxonomy` — write; hosted/stdio
173
+ - `wordpress_update_term` — write; native + hosted
174
+ - `wordpress_update_theme_builder_template` — write; native + hosted
175
+ - `wordpress_update_translation` — write; native + hosted
176
+ - `wordpress_update_user` — write; native + hosted
177
+ - `wordpress_upload_media` — write; native + hosted
178
+ - `wordpress_validate_security` — read; native + hosted
179
+ - `wordpress_write_theme_file` — read; hosted/stdio
180
+
181
+ ## WooCommerce add-on
182
+
183
+ - `woocommerce_add_low_stock_badge` — write; native + hosted
184
+ - `woocommerce_add_order_note` — write; native + hosted
185
+ - `woocommerce_add_sale_badge` — write; native + hosted
186
+ - `woocommerce_add_subscription_note` — write; native + hosted
187
+ - `woocommerce_agent_orders_report` — read; native + hosted
188
+ - `woocommerce_analyze_product_page` — read; native + hosted
189
+ - `woocommerce_analyze_shop_page` — read; native + hosted
190
+ - `woocommerce_analyze_storefront_card` — read; native + hosted
191
+ - `woocommerce_bulk_update_prices` — write; native + hosted
192
+ - `woocommerce_bulk_update_products` — write; native + hosted
193
+ - `woocommerce_bulk_update_stock` — write; native + hosted
194
+ - `woocommerce_catalog_ai_readiness` — read; native + hosted
195
+ - `woocommerce_catalog_health` — read; native + hosted
196
+ - `woocommerce_configurator_status` — read; native + hosted
197
+ - `woocommerce_configure_feed` — write; native + hosted
198
+ - `woocommerce_create_brand` — write; native + hosted
199
+ - `woocommerce_create_cart_link` — write; native + hosted
200
+ - `woocommerce_create_category` — write; native + hosted
201
+ - `woocommerce_create_coupon` — write; native + hosted
202
+ - `woocommerce_create_customer` — write; native + hosted
203
+ - `woocommerce_create_global_attribute` — write; native + hosted
204
+ - `woocommerce_create_order_refund` — write; native + hosted
205
+ - `woocommerce_create_product` — write; native + hosted
206
+ - `woocommerce_create_tag` — write; native + hosted
207
+ - `woocommerce_create_variation` — write; native + hosted
208
+ - `woocommerce_create_webhook` — write; native + hosted
209
+ - `woocommerce_customers_summary` — read; native + hosted
210
+ - `woocommerce_delete_brand` — write; native + hosted
211
+ - `woocommerce_delete_category` — write; native + hosted
212
+ - `woocommerce_delete_tag` — write; native + hosted
213
+ - `woocommerce_delete_webhook` — write; native + hosted
214
+ - `woocommerce_duplicate_product` — write; native + hosted
215
+ - `woocommerce_find_low_stock` — read; native + hosted
216
+ - `woocommerce_find_product` — read; native + hosted
217
+ - `woocommerce_generate_feed` — write; native + hosted
218
+ - `woocommerce_generate_variations` — write; native + hosted
219
+ - `woocommerce_get_booking` — read; native + hosted
220
+ - `woocommerce_get_brand` — read; native + hosted
221
+ - `woocommerce_get_category` — read; native + hosted
222
+ - `woocommerce_get_configurator_attribute_items` — read; native + hosted
223
+ - `woocommerce_get_feed_status` — read; native + hosted
224
+ - `woocommerce_get_membership` — read; native + hosted
225
+ - `woocommerce_get_order` — read; native + hosted
226
+ - `woocommerce_get_order_refunds` — read; native + hosted
227
+ - `woocommerce_get_plugin_state` — read; native + hosted
228
+ - `woocommerce_get_product` — read; native + hosted
229
+ - `woocommerce_get_product_configurator` — read; native + hosted
230
+ - `woocommerce_get_stock_status` — read; native + hosted
231
+ - `woocommerce_get_store_configuration` — read; native + hosted
232
+ - `woocommerce_get_subscription` — read; native + hosted
233
+ - `woocommerce_get_tag` — read; native + hosted
234
+ - `woocommerce_get_webhook` — read; native + hosted
235
+ - `woocommerce_list_bookings` — read; native + hosted
236
+ - `woocommerce_list_brands` — read; native + hosted
237
+ - `woocommerce_list_categories` — read; native + hosted
238
+ - `woocommerce_list_configurator_attributes` — read; native + hosted
239
+ - `woocommerce_list_coupons` — read; native + hosted
240
+ - `woocommerce_list_membership_plans` — read; native + hosted
241
+ - `woocommerce_list_memberships` — read; native + hosted
242
+ - `woocommerce_list_orders` — read; native + hosted
243
+ - `woocommerce_list_payment_gateways` — read; native + hosted
244
+ - `woocommerce_list_products` — read; native + hosted
245
+ - `woocommerce_list_products_advanced` — read; native + hosted
246
+ - `woocommerce_list_shipping_zones` — read; native + hosted
247
+ - `woocommerce_list_subscriptions` — read; native + hosted
248
+ - `woocommerce_list_tags` — read; native + hosted
249
+ - `woocommerce_list_tax_rates` — read; native + hosted
250
+ - `woocommerce_list_webhooks` — read; native + hosted
251
+ - `woocommerce_orders_summary` — read; native + hosted
252
+ - `woocommerce_product_ai_readiness` — read; native + hosted
253
+ - `woocommerce_readiness_fixlist` — read; native + hosted
254
+ - `woocommerce_repair_feed_scheduler` — write; native + hosted
255
+ - `woocommerce_reschedule_booking` — write; native + hosted
256
+ - `woocommerce_revenue_summary` — read; native + hosted
257
+ - `woocommerce_revert_pricing` — write; native + hosted
258
+ - `woocommerce_sales_report` — read; native + hosted
259
+ - `woocommerce_sales_timeseries` — read; native + hosted
260
+ - `woocommerce_schedule_sale` — write; native + hosted
261
+ - `woocommerce_set_configurator_attribute_items` — write; native + hosted
262
+ - `woocommerce_set_feed_category_mapping` — write; native + hosted
263
+ - `woocommerce_set_image_alt` — write; native + hosted
264
+ - `woocommerce_set_membership_end_date` — write; native + hosted
265
+ - `woocommerce_set_plugin_state` — write; native + hosted
266
+ - `woocommerce_set_product_attributes` — write; native + hosted
267
+ - `woocommerce_set_product_configurator` — write; native + hosted
268
+ - `woocommerce_set_variation_gallery` — write; native + hosted
269
+ - `woocommerce_test_webhook` — read; native + hosted
270
+ - `woocommerce_top_products` — read; native + hosted
271
+ - `woocommerce_update_booking_status` — write; native + hosted
272
+ - `woocommerce_update_brand` — write; native + hosted
273
+ - `woocommerce_update_category` — write; native + hosted
274
+ - `woocommerce_update_checkout_layout` — write; native + hosted
275
+ - `woocommerce_update_coupon` — write; native + hosted
276
+ - `woocommerce_update_customer` — write; native + hosted
277
+ - `woocommerce_update_membership_status` — write; native + hosted
278
+ - `woocommerce_update_order_status` — write; native + hosted
279
+ - `woocommerce_update_product` — write; native + hosted
280
+ - `woocommerce_update_product_card_layout` — write; native + hosted
281
+ - `woocommerce_update_stock` — write; native + hosted
282
+ - `woocommerce_update_storefront_card_field` — write; native + hosted
283
+ - `woocommerce_update_subscription_dates` — write; native + hosted
284
+ - `woocommerce_update_subscription_status` — write; native + hosted
285
+ - `woocommerce_update_tag` — write; native + hosted
286
+ - `woocommerce_update_webhook` — write; native + hosted
287
+ - `woocommerce_validate_feed` — read; native + hosted
288
+
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pagespeed-error-classification.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagespeed-error-classification.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pagespeed-error-classification.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,52 @@
1
+ import assert from 'node:assert/strict';
2
+ import { test } from 'node:test';
3
+ import { WordPressClient } from '../wordpress-client.js';
4
+ const config = {
5
+ id: 'pagespeed-test',
6
+ name: 'PageSpeed test',
7
+ url: 'https://example.com',
8
+ apiKey: 'respira_test_key',
9
+ };
10
+ function fakeResponse(status, data) {
11
+ return {
12
+ isAxiosError: true,
13
+ message: `Request failed with status code ${status}`,
14
+ response: {
15
+ status,
16
+ statusText: 'Error',
17
+ headers: {},
18
+ data,
19
+ config: {},
20
+ },
21
+ config: { url: '/analyze/pagespeed', method: 'post' },
22
+ };
23
+ }
24
+ test('PageSpeed rate limits retain a stable upstream error code', async () => {
25
+ const client = new WordPressClient(config);
26
+ const error = await client.handleError(fakeResponse(429, {
27
+ code: 'respira_pagespeed_rate_limited',
28
+ message: 'Google PSI rate limited this request.',
29
+ data: { status: 429, retry_after: 60 },
30
+ }));
31
+ assert.equal(error.name, 'respira_pagespeed_rate_limited');
32
+ assert.deepEqual(error.respiraErrorEnvelope, {
33
+ code: 'respira_pagespeed_rate_limited',
34
+ retry_after: 60,
35
+ });
36
+ });
37
+ test('PageSpeed upstream 5xx responses do not become unclassified', async () => {
38
+ const client = new WordPressClient(config);
39
+ const error = await client.handleError(fakeResponse(503, {
40
+ code: 'respira_pagespeed_upstream_unavailable',
41
+ message: 'Google PSI is unavailable.',
42
+ data: { status: 503 },
43
+ }));
44
+ assert.equal(error.name, 'respira_pagespeed_upstream_unavailable');
45
+ assert.match(error.message, /WordPress server error \(503\)/);
46
+ });
47
+ test('non-WordPress proxy errors receive a specific machine code', async () => {
48
+ const client = new WordPressClient(config);
49
+ const error = await client.handleError(fakeResponse(502, '<!DOCTYPE html><html><title>Bad Gateway</title></html>'));
50
+ assert.equal(error.name, 'http_502_non_wordpress');
51
+ });
52
+ //# sourceMappingURL=pagespeed-error-classification.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagespeed-error-classification.test.js","sourceRoot":"","sources":["../../src/__tests__/pagespeed-error-classification.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,MAAM,MAAM,GAAwB;IAClC,EAAE,EAAE,gBAAgB;IACpB,IAAI,EAAE,gBAAgB;IACtB,GAAG,EAAE,qBAAqB;IAC1B,MAAM,EAAE,kBAAkB;CAC3B,CAAC;AAEF,SAAS,YAAY,CAAC,MAAc,EAAE,IAAa;IACjD,OAAO;QACL,YAAY,EAAE,IAAI;QAClB,OAAO,EAAE,mCAAmC,MAAM,EAAE;QACpD,QAAQ,EAAE;YACR,MAAM;YACN,UAAU,EAAE,OAAO;YACnB,OAAO,EAAE,EAAE;YACX,IAAI;YACJ,MAAM,EAAE,EAAE;SACX;QACD,MAAM,EAAE,EAAE,GAAG,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE;KAC/C,CAAC;AACX,CAAC;AAED,IAAI,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;IAC3E,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,MAAO,MAAc,CAAC,WAAW,CAC7C,YAAY,CAAC,GAAG,EAAE;QAChB,IAAI,EAAE,gCAAgC;QACtC,OAAO,EAAE,uCAAuC;QAChD,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE;KACvC,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,gCAAgC,CAAC,CAAC;IAC3D,MAAM,CAAC,SAAS,CAAE,KAAa,CAAC,oBAAoB,EAAE;QACpD,IAAI,EAAE,gCAAgC;QACtC,WAAW,EAAE,EAAE;KAChB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;IAC7E,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,MAAO,MAAc,CAAC,WAAW,CAC7C,YAAY,CAAC,GAAG,EAAE;QAChB,IAAI,EAAE,wCAAwC;QAC9C,OAAO,EAAE,4BAA4B;QACrC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE;KACtB,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,wCAAwC,CAAC,CAAC;IACnE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,gCAAgC,CAAC,CAAC;AAChE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;IAC5E,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,MAAO,MAAc,CAAC,WAAW,CAC7C,YAAY,CAAC,GAAG,EAAE,wDAAwD,CAAC,CAC5E,CAAC;IAEF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;AACrD,CAAC,CAAC,CAAC"}
@@ -262,68 +262,4 @@ test('diagnose_connection reports rest_route_fallback_worked: true when applicab
262
262
  restoreAdapter();
263
263
  }
264
264
  });
265
- // Regression test for ticket 73b64e82: diagnoseConnection's own probes run
266
- // over a bare axios.request() and never touched the interceptor-wrapped
267
- // client, so a confirmed rest_route_fallback_worked: true never actually
268
- // flipped the sticky flag — every subsequent normal tool call kept retrying
269
- // the shadowed pretty path from scratch instead of going straight to
270
- // ?rest_route=, even though the diagnostic had already proven it works.
271
- test('diagnose_connection sticky flag: a confirmed rest_route_fallback_worked applies to the NEXT tool call, not just the report', async () => {
272
- installMockAdapter();
273
- try {
274
- const client = new WordPressClient(buildConfig());
275
- setHandler((config) => {
276
- const url = config.url || '';
277
- const baseURL = config.baseURL || '';
278
- const fullUrl = url.startsWith('http') ? url : `${baseURL}${url}`;
279
- if (/\/wp-json\/?$/.test(fullUrl) || fullUrl.endsWith('/wp-json/')) {
280
- return {
281
- status: 200,
282
- headers: { 'content-type': 'application/json' },
283
- data: { namespaces: ['respira/v1'] },
284
- };
285
- }
286
- if (/[?&]rest_route=/.test(fullUrl)) {
287
- return {
288
- status: 200,
289
- headers: { 'content-type': 'application/json' },
290
- data: { builder: 'elementor' },
291
- };
292
- }
293
- if (/\/wp-json\/respira\//.test(fullUrl)) {
294
- return {
295
- status: 200,
296
- headers: { 'content-type': 'text/html; charset=UTF-8' },
297
- data: HOMEPAGE_HTML,
298
- };
299
- }
300
- return {
301
- status: 404,
302
- headers: { 'content-type': 'application/json' },
303
- data: { code: 'rest_no_route' },
304
- };
305
- });
306
- // Before diagnosing, the sticky flag is off (nothing has proven the
307
- // fallback works yet on this client instance).
308
- assert.equal(client.useRestRouteFallback, false);
309
- const report = await client.diagnoseConnection({});
310
- assert.equal(report.rest_route_fallback_worked, true);
311
- // The diagnostic's own finding must flip the sticky flag immediately,
312
- // not just describe it in the report.
313
- assert.equal(client.useRestRouteFallback, true, 'diagnoseConnection should apply its own finding to the client');
314
- assert.equal(report.rest_route_fallback_active, true, 'report should reflect the now-active sticky flag');
315
- const callsBeforeNextTool = callLog.length;
316
- const info = await client.getBuilderInfo();
317
- assert.deepEqual(info, { builder: 'elementor' });
318
- // The next normal tool call must go straight to ?rest_route= — it must
319
- // NOT re-probe the pretty path that diagnose_connection already proved
320
- // is shadowed.
321
- const newCalls = callLog.slice(callsBeforeNextTool);
322
- assert.equal(newCalls.length, 1, 'sticky flag from diagnose_connection should skip the pretty-path probe entirely');
323
- assert.match(newCalls[0].url, /[?&]rest_route=/, 'post-diagnose tool call should be in rest_route form');
324
- }
325
- finally {
326
- restoreAdapter();
327
- }
328
- });
329
265
  //# sourceMappingURL=rest-route-fallback.test.js.map