@wootsup/yt-builder-mcp 1.1.7 → 1.3.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 (249) hide show
  1. package/README.md +14 -10
  2. package/bin/yt-builder-mcp.js +55 -40
  3. package/dist/auth.d.ts +18 -0
  4. package/dist/auth.d.ts.map +1 -1
  5. package/dist/auth.js +18 -0
  6. package/dist/auth.js.map +1 -1
  7. package/dist/catalog/build-catalog.d.ts +63 -0
  8. package/dist/catalog/build-catalog.d.ts.map +1 -0
  9. package/dist/catalog/build-catalog.js +166 -0
  10. package/dist/catalog/build-catalog.js.map +1 -0
  11. package/dist/cli/invocation-decision.d.ts +57 -0
  12. package/dist/cli/invocation-decision.d.ts.map +1 -0
  13. package/dist/cli/invocation-decision.js +86 -0
  14. package/dist/cli/invocation-decision.js.map +1 -0
  15. package/dist/client.d.ts +28 -0
  16. package/dist/client.d.ts.map +1 -1
  17. package/dist/client.js +40 -1
  18. package/dist/client.js.map +1 -1
  19. package/dist/clients/claude-code.d.ts.map +1 -1
  20. package/dist/clients/claude-code.js +3 -1
  21. package/dist/clients/claude-code.js.map +1 -1
  22. package/dist/clients/claude-desktop.d.ts.map +1 -1
  23. package/dist/clients/claude-desktop.js +3 -1
  24. package/dist/clients/claude-desktop.js.map +1 -1
  25. package/dist/clients/cline.d.ts.map +1 -1
  26. package/dist/clients/cline.js +3 -1
  27. package/dist/clients/cline.js.map +1 -1
  28. package/dist/clients/codex-cli.d.ts +1 -1
  29. package/dist/clients/codex-cli.d.ts.map +1 -1
  30. package/dist/clients/codex-cli.js +98 -0
  31. package/dist/clients/codex-cli.js.map +1 -1
  32. package/dist/clients/continue.d.ts.map +1 -1
  33. package/dist/clients/continue.js +70 -1
  34. package/dist/clients/continue.js.map +1 -1
  35. package/dist/clients/cursor.d.ts.map +1 -1
  36. package/dist/clients/cursor.js +3 -1
  37. package/dist/clients/cursor.js.map +1 -1
  38. package/dist/clients/gemini-cli.d.ts.map +1 -1
  39. package/dist/clients/gemini-cli.js +3 -1
  40. package/dist/clients/gemini-cli.js.map +1 -1
  41. package/dist/clients/index.d.ts +104 -0
  42. package/dist/clients/index.d.ts.map +1 -1
  43. package/dist/clients/index.js +141 -0
  44. package/dist/clients/index.js.map +1 -1
  45. package/dist/clients/roo-code.d.ts.map +1 -1
  46. package/dist/clients/roo-code.js +3 -1
  47. package/dist/clients/roo-code.js.map +1 -1
  48. package/dist/clients/zed.d.ts.map +1 -1
  49. package/dist/clients/zed.js +3 -1
  50. package/dist/clients/zed.js.map +1 -1
  51. package/dist/gateway/advanced-read-tool.d.ts +37 -0
  52. package/dist/gateway/advanced-read-tool.d.ts.map +1 -0
  53. package/dist/gateway/advanced-read-tool.js +156 -0
  54. package/dist/gateway/advanced-read-tool.js.map +1 -0
  55. package/dist/gateway/advanced-tool/domains.d.ts +18 -3
  56. package/dist/gateway/advanced-tool/domains.d.ts.map +1 -1
  57. package/dist/gateway/advanced-tool/domains.js +28 -9
  58. package/dist/gateway/advanced-tool/domains.js.map +1 -1
  59. package/dist/gateway/advanced-tool/register.d.ts.map +1 -1
  60. package/dist/gateway/advanced-tool/register.js +43 -11
  61. package/dist/gateway/advanced-tool/register.js.map +1 -1
  62. package/dist/gateway/essentials.d.ts +14 -4
  63. package/dist/gateway/essentials.d.ts.map +1 -1
  64. package/dist/gateway/essentials.js +55 -5
  65. package/dist/gateway/essentials.js.map +1 -1
  66. package/dist/gateway/test-support.d.ts +3 -3
  67. package/dist/gateway/test-support.js +3 -3
  68. package/dist/index.d.ts +2 -1
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +19 -1
  71. package/dist/index.js.map +1 -1
  72. package/dist/install-skill.js +1 -1
  73. package/dist/proxy/bridge.d.ts +36 -0
  74. package/dist/proxy/bridge.d.ts.map +1 -0
  75. package/dist/proxy/bridge.js +129 -0
  76. package/dist/proxy/bridge.js.map +1 -0
  77. package/dist/proxy/mode.d.ts +10 -0
  78. package/dist/proxy/mode.d.ts.map +1 -0
  79. package/dist/proxy/mode.js +20 -0
  80. package/dist/proxy/mode.js.map +1 -0
  81. package/dist/server.d.ts +6 -4
  82. package/dist/server.d.ts.map +1 -1
  83. package/dist/server.js +14 -4
  84. package/dist/server.js.map +1 -1
  85. package/dist/setup-cli.d.ts +41 -0
  86. package/dist/setup-cli.d.ts.map +1 -1
  87. package/dist/setup-cli.js +163 -1
  88. package/dist/setup-cli.js.map +1 -1
  89. package/dist/setup-prompts.d.ts +23 -0
  90. package/dist/setup-prompts.d.ts.map +1 -1
  91. package/dist/setup-prompts.js +76 -1
  92. package/dist/setup-prompts.js.map +1 -1
  93. package/dist/setup-wizard.d.ts.map +1 -1
  94. package/dist/setup-wizard.js +7 -0
  95. package/dist/setup-wizard.js.map +1 -1
  96. package/dist/sites/bootstrap.d.ts +41 -0
  97. package/dist/sites/bootstrap.d.ts.map +1 -0
  98. package/dist/sites/bootstrap.js +58 -0
  99. package/dist/sites/bootstrap.js.map +1 -0
  100. package/dist/sites/client-pool.d.ts +33 -0
  101. package/dist/sites/client-pool.d.ts.map +1 -1
  102. package/dist/sites/client-pool.js +69 -1
  103. package/dist/sites/client-pool.js.map +1 -1
  104. package/dist/sites/registry.d.ts +30 -0
  105. package/dist/sites/registry.d.ts.map +1 -1
  106. package/dist/sites/registry.js.map +1 -1
  107. package/dist/sites/store.d.ts +8 -1
  108. package/dist/sites/store.d.ts.map +1 -1
  109. package/dist/sites/store.js +17 -2
  110. package/dist/sites/store.js.map +1 -1
  111. package/dist/sites/tools/index.d.ts.map +1 -1
  112. package/dist/sites/tools/index.js +9 -1
  113. package/dist/sites/tools/index.js.map +1 -1
  114. package/dist/sites/tools/use-site.d.ts +47 -0
  115. package/dist/sites/tools/use-site.d.ts.map +1 -0
  116. package/dist/sites/tools/use-site.js +203 -0
  117. package/dist/sites/tools/use-site.js.map +1 -0
  118. package/dist/tools/bind-guidance.d.ts +80 -0
  119. package/dist/tools/bind-guidance.d.ts.map +1 -0
  120. package/dist/tools/bind-guidance.js +95 -0
  121. package/dist/tools/bind-guidance.js.map +1 -0
  122. package/dist/tools/elements/builders.d.ts.map +1 -1
  123. package/dist/tools/elements/builders.js +75 -18
  124. package/dist/tools/elements/builders.js.map +1 -1
  125. package/dist/tools/elements/handlers-write.d.ts +20 -3
  126. package/dist/tools/elements/handlers-write.d.ts.map +1 -1
  127. package/dist/tools/elements/handlers-write.js +372 -10
  128. package/dist/tools/elements/handlers-write.js.map +1 -1
  129. package/dist/tools/elements/handlers.d.ts +6 -1
  130. package/dist/tools/elements/handlers.d.ts.map +1 -1
  131. package/dist/tools/elements/handlers.js +77 -10
  132. package/dist/tools/elements/handlers.js.map +1 -1
  133. package/dist/tools/elements/layout-hierarchy-rules.d.ts +62 -0
  134. package/dist/tools/elements/layout-hierarchy-rules.d.ts.map +1 -0
  135. package/dist/tools/elements/layout-hierarchy-rules.js +154 -0
  136. package/dist/tools/elements/layout-hierarchy-rules.js.map +1 -0
  137. package/dist/tools/format/elements-format.d.ts +35 -0
  138. package/dist/tools/format/elements-format.d.ts.map +1 -1
  139. package/dist/tools/format/elements-format.js +134 -12
  140. package/dist/tools/format/elements-format.js.map +1 -1
  141. package/dist/tools/format/inspection-format.d.ts +29 -0
  142. package/dist/tools/format/inspection-format.d.ts.map +1 -1
  143. package/dist/tools/format/inspection-format.js +99 -22
  144. package/dist/tools/format/inspection-format.js.map +1 -1
  145. package/dist/tools/format/pages-format.d.ts.map +1 -1
  146. package/dist/tools/format/pages-format.js +7 -0
  147. package/dist/tools/format/pages-format.js.map +1 -1
  148. package/dist/tools/format/sources-format.d.ts +8 -0
  149. package/dist/tools/format/sources-format.d.ts.map +1 -1
  150. package/dist/tools/format/sources-format.js +10 -0
  151. package/dist/tools/format/sources-format.js.map +1 -1
  152. package/dist/tools/health.d.ts.map +1 -1
  153. package/dist/tools/health.js +24 -0
  154. package/dist/tools/health.js.map +1 -1
  155. package/dist/tools/index.d.ts.map +1 -1
  156. package/dist/tools/index.js +4 -0
  157. package/dist/tools/index.js.map +1 -1
  158. package/dist/tools/inspection.d.ts +24 -0
  159. package/dist/tools/inspection.d.ts.map +1 -1
  160. package/dist/tools/inspection.js +297 -5
  161. package/dist/tools/inspection.js.map +1 -1
  162. package/dist/tools/layout-flatten.d.ts +11 -8
  163. package/dist/tools/layout-flatten.d.ts.map +1 -1
  164. package/dist/tools/layout-flatten.js +17 -6
  165. package/dist/tools/layout-flatten.js.map +1 -1
  166. package/dist/tools/multi-items/builders.d.ts.map +1 -1
  167. package/dist/tools/multi-items/builders.js +18 -3
  168. package/dist/tools/multi-items/builders.js.map +1 -1
  169. package/dist/tools/multi-items/clean-implode-handler.d.ts.map +1 -1
  170. package/dist/tools/multi-items/clean-implode-handler.js +2 -2
  171. package/dist/tools/multi-items/clean-implode-handler.js.map +1 -1
  172. package/dist/tools/multi-items/format/inspection-format.d.ts +41 -0
  173. package/dist/tools/multi-items/format/inspection-format.d.ts.map +1 -0
  174. package/dist/tools/multi-items/format/inspection-format.js +64 -0
  175. package/dist/tools/multi-items/format/inspection-format.js.map +1 -0
  176. package/dist/tools/multi-items/inspect-handler.d.ts +50 -2
  177. package/dist/tools/multi-items/inspect-handler.d.ts.map +1 -1
  178. package/dist/tools/multi-items/inspect-handler.js +237 -10
  179. package/dist/tools/multi-items/inspect-handler.js.map +1 -1
  180. package/dist/tools/multi-items/inspection-cache.d.ts +85 -0
  181. package/dist/tools/multi-items/inspection-cache.d.ts.map +1 -0
  182. package/dist/tools/multi-items/inspection-cache.js +126 -0
  183. package/dist/tools/multi-items/inspection-cache.js.map +1 -0
  184. package/dist/tools/pages/builders.d.ts +31 -2
  185. package/dist/tools/pages/builders.d.ts.map +1 -1
  186. package/dist/tools/pages/builders.js +173 -17
  187. package/dist/tools/pages/builders.js.map +1 -1
  188. package/dist/tools/pages/handlers-read.d.ts +6 -2
  189. package/dist/tools/pages/handlers-read.d.ts.map +1 -1
  190. package/dist/tools/pages/handlers-read.js +228 -26
  191. package/dist/tools/pages/handlers-read.js.map +1 -1
  192. package/dist/tools/pages/handlers-write.d.ts +143 -7
  193. package/dist/tools/pages/handlers-write.d.ts.map +1 -1
  194. package/dist/tools/pages/handlers-write.js +215 -11
  195. package/dist/tools/pages/handlers-write.js.map +1 -1
  196. package/dist/tools/pages/index.d.ts +1 -1
  197. package/dist/tools/pages/index.d.ts.map +1 -1
  198. package/dist/tools/pages/index.js +1 -1
  199. package/dist/tools/pages/index.js.map +1 -1
  200. package/dist/tools/pages/schemas.d.ts +166 -0
  201. package/dist/tools/pages/schemas.d.ts.map +1 -1
  202. package/dist/tools/pages/schemas.js +347 -0
  203. package/dist/tools/pages/schemas.js.map +1 -1
  204. package/dist/tools/shared-schemas.d.ts.map +1 -1
  205. package/dist/tools/shared-schemas.js +26 -11
  206. package/dist/tools/shared-schemas.js.map +1 -1
  207. package/dist/tools/sources/builders.d.ts.map +1 -1
  208. package/dist/tools/sources/builders.js +64 -6
  209. package/dist/tools/sources/builders.js.map +1 -1
  210. package/dist/tools/sources/handlers-bind.d.ts +13 -1
  211. package/dist/tools/sources/handlers-bind.d.ts.map +1 -1
  212. package/dist/tools/sources/handlers-bind.js +219 -5
  213. package/dist/tools/sources/handlers-bind.js.map +1 -1
  214. package/dist/tools/sources/handlers.d.ts +3 -0
  215. package/dist/tools/sources/handlers.d.ts.map +1 -1
  216. package/dist/tools/sources/handlers.js +45 -8
  217. package/dist/tools/sources/handlers.js.map +1 -1
  218. package/dist/tools/sparse-fields.d.ts +23 -0
  219. package/dist/tools/sparse-fields.d.ts.map +1 -1
  220. package/dist/tools/sparse-fields.js +29 -0
  221. package/dist/tools/sparse-fields.js.map +1 -1
  222. package/dist/tools/sublayout/builders.d.ts +23 -0
  223. package/dist/tools/sublayout/builders.d.ts.map +1 -0
  224. package/dist/tools/sublayout/builders.js +54 -0
  225. package/dist/tools/sublayout/builders.js.map +1 -0
  226. package/dist/tools/sublayout/index.d.ts +13 -0
  227. package/dist/tools/sublayout/index.d.ts.map +1 -0
  228. package/dist/tools/sublayout/index.js +13 -0
  229. package/dist/tools/sublayout/index.js.map +1 -0
  230. package/dist/tools/sublayout/inspect-sublayout-handler.d.ts +95 -0
  231. package/dist/tools/sublayout/inspect-sublayout-handler.d.ts.map +1 -0
  232. package/dist/tools/sublayout/inspect-sublayout-handler.js +181 -0
  233. package/dist/tools/sublayout/inspect-sublayout-handler.js.map +1 -0
  234. package/dist/tools/tool-builder/results.d.ts +31 -0
  235. package/dist/tools/tool-builder/results.d.ts.map +1 -1
  236. package/dist/tools/tool-builder/results.js +95 -4
  237. package/dist/tools/tool-builder/results.js.map +1 -1
  238. package/dist/uninstall-skill.d.ts +52 -0
  239. package/dist/uninstall-skill.d.ts.map +1 -0
  240. package/dist/uninstall-skill.js +146 -0
  241. package/dist/uninstall-skill.js.map +1 -0
  242. package/dist/uninstall.d.ts +73 -0
  243. package/dist/uninstall.d.ts.map +1 -0
  244. package/dist/uninstall.js +82 -0
  245. package/dist/uninstall.js.map +1 -0
  246. package/icon.png +0 -0
  247. package/manifest.json +10 -10
  248. package/package.json +7 -3
  249. package/skills/yt-builder-mcp/SKILL.md +157 -88
@@ -8,11 +8,13 @@
8
8
  *
9
9
  * - Walk-order: depth-first, parent BEFORE children, original child
10
10
  * order preserved (no sort).
11
- * - `path` uses JSON-Pointer-style notation rooted at `/layout/<key>`
12
- * and descends via `/children/<index>` segments. The root segments
13
- * mirror the keys the REST plugin produces (string keys "0","1",…
14
- * when the top-level layout is an object; numeric indices when it
15
- * happens to be an array).
11
+ * - `path` uses JSON-Pointer-style notation rooted at
12
+ * `/layout/children/<key>` and descends via `/children/<index>`
13
+ * segments (M5: the top-level anchor carries the real `children`
14
+ * segment so `rel_path` mirrors the element-path input contract).
15
+ * The root keys mirror what the REST plugin produces (string keys
16
+ * "0","1",… when the top-level layout is an object; numeric indices
17
+ * when it happens to be an array).
16
18
  * - `parent_path` is `null` for top-level entries.
17
19
  * - The emitted record's `children` field is REMOVED — children become
18
20
  * their own emitted entries with their own `path`. Keeping the nested
@@ -46,7 +48,16 @@ export function flattenLayout(layout) {
46
48
  ? layout.map((v, i) => [String(i), v])
47
49
  : Object.entries(layout);
48
50
  for (const [key, node] of entries) {
49
- walk(node, `/layout/${key}`, null, 0, out);
51
+ // M5: anchor top-level nodes under the real `/children/<key>` segment
52
+ // (not a bare `/layout/<key>`). The canonical storage pointer for a
53
+ // top-level element is `/templates/<id>/layout/children/<key>`, so this
54
+ // makes both `path` (→ `/layout/children/<key>`) and `rel_path`
55
+ // (→ `/children/<key>`, after the `/layout` strip on line below) mirror
56
+ // it. Previously the bare anchor produced rel_path `/<key>/...` which
57
+ // the element-path input normaliser rejects (it only lifts forms that
58
+ // start with `/children/`), contradicting the pointer_hint's promise
59
+ // that the emitted rel_path can be passed straight back.
60
+ walk(node, `/layout/children/${key}`, null, 0, out);
50
61
  }
51
62
  return out;
52
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"layout-flatten.js","sourceRoot":"","sources":["../../src/tools/layout-flatten.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"layout-flatten.js","sourceRoot":"","sources":["../../src/tools/layout-flatten.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../../src/tools/multi-items/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAG7D,OAAO,EAKH,KAAK,iBAAiB,EACzB,MAAM,oBAAoB,CAAC;AAW5B,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,iBAAiB,EAAE,CA0DnF"}
1
+ {"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../../src/tools/multi-items/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAG7D,OAAO,EAKH,KAAK,iBAAiB,EACzB,MAAM,oBAAoB,CAAC;AAY5B,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,iBAAiB,EAAE,CAyEnF"}
@@ -23,7 +23,13 @@ import { ELEMENT_PATH, ETAG, SITE_ID_SCHEMA, TEMPLATE_ID } from '../shared-schem
23
23
  import { defineTool, destructive, readOnly, withSiteMeta, } from '../tool-builder.js';
24
24
  import { CLEAN_IMPLODE_OUTPUT_SCHEMA, handleCleanImplodeDirectives, } from './clean-implode-handler.js';
25
25
  import { INSPECT_MULTI_ITEMS_OUTPUT_SCHEMA, handleInspectMultiItemsBinding, } from './inspect-handler.js';
26
+ import { InspectionCache } from './inspection-cache.js';
26
27
  export function buildMultiItemsTools(pool) {
28
+ // 6.2 — one shared inspection cache per tool-build, keyed on
29
+ // (template_id, element_path, global-etag) with a 60s TTL. Survives
30
+ // across calls within a server lifetime; a write bumps the global
31
+ // etag and naturally invalidates the entry.
32
+ const inspectionCache = new InspectionCache();
27
33
  // W6.3 — per-handler resolveSiteOrError. The handlers consume a
28
34
  // single-field `MultiItemsHandlerDeps`, so we synthesise it inline
29
35
  // with the resolved client.
@@ -31,8 +37,17 @@ export function buildMultiItemsTools(pool) {
31
37
  defineTool({
32
38
  name: 'yootheme_builder_inspect_multi_items_binding',
33
39
  description: 'Reports Multi-Items binding state: container/item pair (grid↔grid_item, ' +
34
- 'slideshow↔slideshow_item, …), current binding level (none|container|item), ' +
35
- 'and a recommended_fix when the binding sits on the container instead of the child. ' +
40
+ 'slideshow↔slideshow_item, map↔map_item, …), current binding level ' +
41
+ '(none|container|item), and a recommended_fix when the binding sits on the ' +
42
+ 'container instead of the child. ' +
43
+ // F39 (2026-06-10): a bound map_item with NO `location` field
44
+ // renders 0 markers → blocking map_location_warning.
45
+ 'For map/map_item, a bound item without a `location` ("lat,lng") field is ' +
46
+ 'flagged as a blocking map_location_warning (renders 0 markers). ' +
47
+ // F189 (2026-06-12): a `…List` on a grid_item with nested children
48
+ // is render-dead (leaf renderer) → blocking iterator_is_leaf_renderer.
49
+ 'A List on a grid_item with nested children → blocking ' +
50
+ 'iterator_is_leaf_renderer (children never render). ' +
36
51
  'Operates on the default site unless site_id is provided.',
37
52
  inputSchema: {
38
53
  site_id: SITE_ID_SCHEMA,
@@ -42,7 +57,7 @@ export function buildMultiItemsTools(pool) {
42
57
  outputSchema: INSPECT_MULTI_ITEMS_OUTPUT_SCHEMA,
43
58
  annotations: readOnly('Inspect Multi-Items Binding'),
44
59
  handler: async ({ site_id, ...rest }) => withSiteRetry(pool, site_id, async (client, site) => {
45
- const deps = { client };
60
+ const deps = { client, cache: inspectionCache };
46
61
  return withSiteMeta(await handleInspectMultiItemsBinding(deps, rest), site);
47
62
  }),
48
63
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"builders.js","sourceRoot":"","sources":["../../../src/tools/multi-items/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,EACH,UAAU,EACV,WAAW,EACX,QAAQ,EACR,YAAY,GAEf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACH,2BAA2B,EAC3B,4BAA4B,GAC/B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACH,iCAAiC,EACjC,8BAA8B,GAEjC,MAAM,sBAAsB,CAAC;AAE9B,MAAM,UAAU,oBAAoB,CAAC,IAAgB;IACjD,gEAAgE;IAChE,mEAAmE;IACnE,4BAA4B;IAC5B,OAAO;QACH,UAAU,CAAC;YACP,IAAI,EAAE,8CAA8C;YACpD,WAAW,EACP,0EAA0E;gBAC1E,6EAA6E;gBAC7E,qFAAqF;gBACrF,0DAA0D;YAC9D,WAAW,EAAE;gBACT,OAAO,EAAE,cAAc;gBACvB,WAAW,EAAE,WAAW;gBACxB,YAAY,EAAE,YAAY;aAC7B;YACD,YAAY,EAAE,iCAAiC;YAC/C,WAAW,EAAE,QAAQ,CAAC,6BAA6B,CAAC;YACpD,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CACpC,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;gBAChD,MAAM,IAAI,GAA0B,EAAE,MAAM,EAAE,CAAC;gBAC/C,OAAO,YAAY,CAAC,MAAM,8BAA8B,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;YAChF,CAAC,CAAC;SACT,CAAC;QAEF,UAAU,CAAC;YACP,IAAI,EAAE,2CAA2C;YACjD,WAAW,EACP,4EAA4E;gBAC5E,2EAA2E;gBAC3E,0EAA0E;gBAC1E,wEAAwE;gBACxE,sEAAsE;gBACtE,0DAA0D;YAC9D,WAAW,EAAE;gBACT,OAAO,EAAE,cAAc;gBACvB,WAAW,EAAE,WAAW;gBACxB,YAAY,EAAE,YAAY;gBAC1B,IAAI,EAAE,IAAI;gBACV,OAAO,EAAE,CAAC;qBACL,OAAO,EAAE;qBACT,QAAQ,EAAE;qBACV,QAAQ,CACL,iEAAiE;oBAC7D,+DAA+D;oBAC/D,4CAA4C,CACnD;aACR;YACD,YAAY,EAAE,2BAA2B;YACzC,WAAW,EAAE,WAAW,CAAC,0BAA0B,CAAC;YACpD,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CACpC,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;gBAChD,MAAM,IAAI,GAA0B,EAAE,MAAM,EAAE,CAAC;gBAC/C,OAAO,YAAY,CAAC,MAAM,4BAA4B,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;YAC9E,CAAC,CAAC;SACT,CAAC;KACL,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"builders.js","sourceRoot":"","sources":["../../../src/tools/multi-items/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,EACH,UAAU,EACV,WAAW,EACX,QAAQ,EACR,YAAY,GAEf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACH,2BAA2B,EAC3B,4BAA4B,GAC/B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACH,iCAAiC,EACjC,8BAA8B,GAEjC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,UAAU,oBAAoB,CAAC,IAAgB;IACjD,6DAA6D;IAC7D,oEAAoE;IACpE,kEAAkE;IAClE,4CAA4C;IAC5C,MAAM,eAAe,GAAG,IAAI,eAAe,EAA2B,CAAC;IAEvE,gEAAgE;IAChE,mEAAmE;IACnE,4BAA4B;IAC5B,OAAO;QACH,UAAU,CAAC;YACP,IAAI,EAAE,8CAA8C;YACpD,WAAW,EACP,0EAA0E;gBAC1E,oEAAoE;gBACpE,4EAA4E;gBAC5E,kCAAkC;gBAClC,8DAA8D;gBAC9D,qDAAqD;gBACrD,2EAA2E;gBAC3E,kEAAkE;gBAClE,mEAAmE;gBACnE,uEAAuE;gBACvE,wDAAwD;gBACxD,qDAAqD;gBACrD,0DAA0D;YAC9D,WAAW,EAAE;gBACT,OAAO,EAAE,cAAc;gBACvB,WAAW,EAAE,WAAW;gBACxB,YAAY,EAAE,YAAY;aAC7B;YACD,YAAY,EAAE,iCAAiC;YAC/C,WAAW,EAAE,QAAQ,CAAC,6BAA6B,CAAC;YACpD,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CACpC,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;gBAChD,MAAM,IAAI,GAA0B,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;gBACvE,OAAO,YAAY,CAAC,MAAM,8BAA8B,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;YAChF,CAAC,CAAC;SACT,CAAC;QAEF,UAAU,CAAC;YACP,IAAI,EAAE,2CAA2C;YACjD,WAAW,EACP,4EAA4E;gBAC5E,2EAA2E;gBAC3E,0EAA0E;gBAC1E,wEAAwE;gBACxE,sEAAsE;gBACtE,0DAA0D;YAC9D,WAAW,EAAE;gBACT,OAAO,EAAE,cAAc;gBACvB,WAAW,EAAE,WAAW;gBACxB,YAAY,EAAE,YAAY;gBAC1B,IAAI,EAAE,IAAI;gBACV,OAAO,EAAE,CAAC;qBACL,OAAO,EAAE;qBACT,QAAQ,EAAE;qBACV,QAAQ,CACL,iEAAiE;oBAC7D,+DAA+D;oBAC/D,4CAA4C,CACnD;aACR;YACD,YAAY,EAAE,2BAA2B;YACzC,WAAW,EAAE,WAAW,CAAC,0BAA0B,CAAC;YACpD,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CACpC,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;gBAChD,MAAM,IAAI,GAA0B,EAAE,MAAM,EAAE,CAAC;gBAC/C,OAAO,YAAY,CAAC,MAAM,4BAA4B,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;YAC9E,CAAC,CAAC;SACT,CAAC;KACL,CAAC;AACN,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"clean-implode-handler.d.ts","sourceRoot":"","sources":["../../../src/tools/multi-items/clean-implode-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAKH,KAAK,UAAU,EAClB,MAAM,oBAAoB,CAAC;AAE5B,eAAO,MAAM,2BAA2B;;;;;;;;;iBAWtC,CAAC;AAEH,MAAM,WAAW,uBAAuB;IACpC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC/B;AAED,wBAAsB,4BAA4B,CAC9C,EAAE,MAAM,EAAE,EAAE,uBAAuB,EACnC,EACI,WAAW,EACX,YAAY,EACZ,IAAI,EACJ,OAAO,GACV,EAAE;IACC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,GACF,OAAO,CAAC,UAAU,CAAC,CAgCrB"}
1
+ {"version":3,"file":"clean-implode-handler.d.ts","sourceRoot":"","sources":["../../../src/tools/multi-items/clean-implode-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAuC,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,EAKH,KAAK,UAAU,EAClB,MAAM,oBAAoB,CAAC;AAE5B,eAAO,MAAM,2BAA2B;;;;;;;;;iBAWtC,CAAC;AAEH,MAAM,WAAW,uBAAuB;IACpC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC/B;AAED,wBAAsB,4BAA4B,CAC9C,EAAE,MAAM,EAAE,EAAE,uBAAuB,EACnC,EACI,WAAW,EACX,YAAY,EACZ,IAAI,EACJ,OAAO,GACV,EAAE;IACC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,GACF,OAAO,CAAC,UAAU,CAAC,CAgCrB"}
@@ -12,7 +12,7 @@
12
12
  * @license MIT
13
13
  */
14
14
  import { z } from 'zod';
15
- import { encodeElementPath } from '../../client.js';
15
+ import { encodeElementPath, encodeTemplateId } from '../../client.js';
16
16
  import { confirmGuard, errorResult, jsonResult, structuredResult, } from '../tool-builder.js';
17
17
  export const CLEAN_IMPLODE_OUTPUT_SCHEMA = z.object({
18
18
  template_id: z.string(),
@@ -37,7 +37,7 @@ export async function handleCleanImplodeDirectives({ client }, { template_id, el
37
37
  }
38
38
  const encoded = encodeElementPath(element_path);
39
39
  try {
40
- const data = await client.post(`/pages/${encodeURIComponent(template_id)}/elements/${encoded}/multi-items/clean-implode`, { body: {}, etag });
40
+ const data = await client.post(`/pages/${encodeTemplateId(template_id)}/elements/${encoded}/multi-items/clean-implode`, { body: {}, etag });
41
41
  // The REST endpoint returns the canonical CLEAN_IMPLODE_OUTPUT_SCHEMA
42
42
  // shape ({template_id, element_path, cleaned_count, removed_directives,
43
43
  // new_etag}) — pass it through as structuredContent so the declared
@@ -1 +1 @@
1
- {"version":3,"file":"clean-implode-handler.js","sourceRoot":"","sources":["../../../src/tools/multi-items/clean-implode-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAmB,MAAM,iBAAiB,CAAC;AACrE,OAAO,EACH,YAAY,EACZ,WAAW,EACX,UAAU,EACV,gBAAgB,GAEnB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,kBAAkB,EAAE,CAAC,CAAC,KAAK,CACvB,CAAC,CAAC,MAAM,CAAC;QACL,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;QACrB,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;KAC/C,CAAC,CACL;IACD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;CACvB,CAAC,CAAC;AAMH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAC9C,EAAE,MAAM,EAA2B,EACnC,EACI,WAAW,EACX,YAAY,EACZ,IAAI,EACJ,OAAO,GAMV;IAED,qEAAqE;IACrE,qEAAqE;IACrE,sEAAsE;IACtE,8EAA8E;IAC9E,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,YAAY,CAAC;YAChB,SAAS,EAAE,+CAA+C;YAC1D,OAAO,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE;SACzC,CAAC,CAAC;IACP,CAAC;IACD,MAAM,OAAO,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;IAChD,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAC1B,UAAU,kBAAkB,CAAC,WAAW,CAAC,aAAa,OAAO,4BAA4B,EACzF,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CACrB,CAAC;QACF,sEAAsE;QACtE,wEAAwE;QACxE,oEAAoE;QACpE,mEAAmE;QACnE,4DAA4D;QAC5D,OAAO,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,WAAW,CAAC;YACf,KAAK,EAAE,CAAC;YACR,OAAO,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE;YACtC,IAAI,EACA,4EAA4E;gBAC5E,iDAAiD;SACxD,CAAC,CAAC;IACP,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"clean-implode-handler.js","sourceRoot":"","sources":["../../../src/tools/multi-items/clean-implode-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAmB,MAAM,iBAAiB,CAAC;AACvF,OAAO,EACH,YAAY,EACZ,WAAW,EACX,UAAU,EACV,gBAAgB,GAEnB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,kBAAkB,EAAE,CAAC,CAAC,KAAK,CACvB,CAAC,CAAC,MAAM,CAAC;QACL,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;QACrB,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;KAC/C,CAAC,CACL;IACD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;CACvB,CAAC,CAAC;AAMH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAC9C,EAAE,MAAM,EAA2B,EACnC,EACI,WAAW,EACX,YAAY,EACZ,IAAI,EACJ,OAAO,GAMV;IAED,qEAAqE;IACrE,qEAAqE;IACrE,sEAAsE;IACtE,8EAA8E;IAC9E,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,YAAY,CAAC;YAChB,SAAS,EAAE,+CAA+C;YAC1D,OAAO,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE;SACzC,CAAC,CAAC;IACP,CAAC;IACD,MAAM,OAAO,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;IAChD,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAC1B,UAAU,gBAAgB,CAAC,WAAW,CAAC,aAAa,OAAO,4BAA4B,EACvF,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CACrB,CAAC;QACF,sEAAsE;QACtE,wEAAwE;QACxE,oEAAoE;QACpE,mEAAmE;QACnE,4DAA4D;QAC5D,OAAO,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,WAAW,CAAC;YACf,KAAK,EAAE,CAAC;YACR,OAAO,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE;YACtC,IAAI,EACA,4EAA4E;gBAC5E,iDAAiD;SACxD,CAAC,CAAC;IACP,CAAC;AACL,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Multi-Items inspection format-sidecar.
3
+ *
4
+ * Wave-16 #34 (6.1): the `inspect_multi_items_binding` report is passed
5
+ * through verbatim to `structuredContent` (which must stay schema-pure),
6
+ * but the human-readable text leg is serialized from the same payload.
7
+ * A deeply-nested report (e.g. a fully-qualified element subtree under
8
+ * `props` / `minimal_layout`, or a future `children` array) would balloon
9
+ * that text leg without bound. `capInspectionDepth` walks the value and
10
+ * truncates any object/array whose depth exceeds the cap, replacing it
11
+ * with an `…and N more` marker so the agent still sees that the subtree
12
+ * was elided rather than silently dropped.
13
+ *
14
+ * Pure / stateless. `structuredContent` is never passed through this —
15
+ * only the text-render copy — so output-schema validation is unaffected.
16
+ *
17
+ * @license MIT
18
+ */
19
+ /**
20
+ * Default recursion cap for the inspect text render. Objects/arrays at a
21
+ * depth strictly greater than this are collapsed to the `…and N more`
22
+ * marker. The root value sits at depth 0.
23
+ */
24
+ export declare const MAX_INSPECTION_DEPTH = 3;
25
+ /**
26
+ * Recursively cap the depth of a JSON-serializable value.
27
+ *
28
+ * - Primitives (string / number / boolean / null / undefined) pass
29
+ * through untouched at any depth.
30
+ * - An object or array sitting AT `maxDepth` is replaced by the
31
+ * `…and N more` marker (N = its immediate child count) instead of
32
+ * recursing further.
33
+ * - Otherwise the container is rebuilt with each child capped at
34
+ * `depth + 1`.
35
+ *
36
+ * @param value the value to cap.
37
+ * @param maxDepth recursion cap (defaults to {@link MAX_INSPECTION_DEPTH}).
38
+ * @param depth current depth (internal; callers omit it).
39
+ */
40
+ export declare function capInspectionDepth(value: unknown, maxDepth?: number, depth?: number): unknown;
41
+ //# sourceMappingURL=inspection-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspection-format.d.ts","sourceRoot":"","sources":["../../../../src/tools/multi-items/format/inspection-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAYtC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,OAAO,EACd,QAAQ,GAAE,MAA6B,EACvC,KAAK,SAAI,GACV,OAAO,CAeT"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Multi-Items inspection format-sidecar.
3
+ *
4
+ * Wave-16 #34 (6.1): the `inspect_multi_items_binding` report is passed
5
+ * through verbatim to `structuredContent` (which must stay schema-pure),
6
+ * but the human-readable text leg is serialized from the same payload.
7
+ * A deeply-nested report (e.g. a fully-qualified element subtree under
8
+ * `props` / `minimal_layout`, or a future `children` array) would balloon
9
+ * that text leg without bound. `capInspectionDepth` walks the value and
10
+ * truncates any object/array whose depth exceeds the cap, replacing it
11
+ * with an `…and N more` marker so the agent still sees that the subtree
12
+ * was elided rather than silently dropped.
13
+ *
14
+ * Pure / stateless. `structuredContent` is never passed through this —
15
+ * only the text-render copy — so output-schema validation is unaffected.
16
+ *
17
+ * @license MIT
18
+ */
19
+ /**
20
+ * Default recursion cap for the inspect text render. Objects/arrays at a
21
+ * depth strictly greater than this are collapsed to the `…and N more`
22
+ * marker. The root value sits at depth 0.
23
+ */
24
+ export const MAX_INSPECTION_DEPTH = 3;
25
+ /** Render the marker that replaces a truncated subtree. */
26
+ function truncationMarker(childCount, maxDepth) {
27
+ return `…and ${String(childCount)} more (truncated at depth ${String(maxDepth)})`;
28
+ }
29
+ /** Number of immediate children an object/array exposes. */
30
+ function childCountOf(value) {
31
+ return Array.isArray(value) ? value.length : Object.keys(value).length;
32
+ }
33
+ /**
34
+ * Recursively cap the depth of a JSON-serializable value.
35
+ *
36
+ * - Primitives (string / number / boolean / null / undefined) pass
37
+ * through untouched at any depth.
38
+ * - An object or array sitting AT `maxDepth` is replaced by the
39
+ * `…and N more` marker (N = its immediate child count) instead of
40
+ * recursing further.
41
+ * - Otherwise the container is rebuilt with each child capped at
42
+ * `depth + 1`.
43
+ *
44
+ * @param value the value to cap.
45
+ * @param maxDepth recursion cap (defaults to {@link MAX_INSPECTION_DEPTH}).
46
+ * @param depth current depth (internal; callers omit it).
47
+ */
48
+ export function capInspectionDepth(value, maxDepth = MAX_INSPECTION_DEPTH, depth = 0) {
49
+ if (value === null || typeof value !== 'object') {
50
+ return value;
51
+ }
52
+ if (depth >= maxDepth) {
53
+ return truncationMarker(childCountOf(value), maxDepth);
54
+ }
55
+ if (Array.isArray(value)) {
56
+ return value.map((item) => capInspectionDepth(item, maxDepth, depth + 1));
57
+ }
58
+ const out = {};
59
+ for (const [key, child] of Object.entries(value)) {
60
+ out[key] = capInspectionDepth(child, maxDepth, depth + 1);
61
+ }
62
+ return out;
63
+ }
64
+ //# sourceMappingURL=inspection-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspection-format.js","sourceRoot":"","sources":["../../../../src/tools/multi-items/format/inspection-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAEtC,2DAA2D;AAC3D,SAAS,gBAAgB,CAAC,UAAkB,EAAE,QAAgB;IAC1D,OAAO,QAAQ,MAAM,CAAC,UAAU,CAAC,6BAA6B,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;AACtF,CAAC;AAED,4DAA4D;AAC5D,SAAS,YAAY,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;AAC3E,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,kBAAkB,CAC9B,KAAc,EACd,WAAmB,oBAAoB,EACvC,KAAK,GAAG,CAAC;IAET,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,KAAK,IAAI,QAAQ,EAAE,CAAC;QACpB,OAAO,gBAAgB,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;QAC1E,GAAG,CAAC,GAAG,CAAC,GAAG,kBAAkB,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC"}
@@ -6,11 +6,27 @@
6
6
  * src/modules/builder-source-binding/src/MultiItemsInspector.php
7
7
  * for the report shape.
8
8
  *
9
+ * Wave-16 #34:
10
+ * - 6.1 depth-cap: the human-readable text leg is capped at
11
+ * {@link MAX_INSPECTION_DEPTH}; structuredContent stays verbatim so
12
+ * it keeps validating against the output schema.
13
+ * - 6.4 severity marker: the response carries a typed `hint.severity`
14
+ * ("advisory" | "blocking") so the agent can tell a structural
15
+ * container-level binding bug apart from informational guidance.
16
+ *
9
17
  * @license MIT
10
18
  */
11
19
  import { z } from 'zod';
12
20
  import { type RestClient } from '../../client.js';
13
21
  import { type ToolResult } from '../tool-builder.js';
22
+ import { InspectionCache } from './inspection-cache.js';
23
+ /**
24
+ * Severity of the advisory hint the inspector attaches to every report.
25
+ * `blocking` means the binding is structurally wrong (sits on the
26
+ * container instead of the `*_item` child) and the rendered output will
27
+ * be broken until fixed; `advisory` is informational guidance.
28
+ */
29
+ export type HintSeverity = 'advisory' | 'blocking';
14
30
  export declare const INSPECT_MULTI_ITEMS_OUTPUT_SCHEMA: z.ZodObject<{
15
31
  template_id: z.ZodString;
16
32
  report: z.ZodObject<{
@@ -21,21 +37,53 @@ export declare const INSPECT_MULTI_ITEMS_OUTPUT_SCHEMA: z.ZodObject<{
21
37
  container_type: z.ZodNullable<z.ZodString>;
22
38
  item_type: z.ZodNullable<z.ZodString>;
23
39
  current_binding_level: z.ZodEnum<{
24
- none: "none";
25
40
  container: "container";
26
41
  item: "item";
42
+ none: "none";
27
43
  }>;
44
+ item_child_binding_level: z.ZodOptional<z.ZodEnum<{
45
+ item: "item";
46
+ none: "none";
47
+ }>>;
48
+ is_bound: z.ZodOptional<z.ZodBoolean>;
28
49
  has_implode_directives: z.ZodBoolean;
50
+ bound_source_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
51
+ bound_source_exists: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
52
+ source_missing_warning: z.ZodOptional<z.ZodString>;
53
+ map_location_missing: z.ZodOptional<z.ZodBoolean>;
54
+ field_mapping_count: z.ZodOptional<z.ZodNumber>;
55
+ zero_field_mappings: z.ZodOptional<z.ZodBoolean>;
56
+ iterator_is_leaf_renderer: z.ZodOptional<z.ZodBoolean>;
57
+ map_location_warning: z.ZodOptional<z.ZodString>;
29
58
  warning: z.ZodOptional<z.ZodString>;
30
59
  recommended_fix: z.ZodOptional<z.ZodString>;
31
60
  }, z.core.$strip>;
32
61
  etag: z.ZodString;
62
+ hint: z.ZodOptional<z.ZodObject<{
63
+ severity: z.ZodEnum<{
64
+ advisory: "advisory";
65
+ blocking: "blocking";
66
+ }>;
67
+ message: z.ZodString;
68
+ }, z.core.$strip>>;
33
69
  }, z.core.$strip>;
70
+ /** The structured inspect payload the handler caches + emits. */
71
+ type InspectStructured = Record<string, unknown>;
34
72
  export interface MultiItemsHandlerDeps {
35
73
  readonly client: RestClient;
74
+ /**
75
+ * 6.2 — optional inspection cache. When provided, the handler keys
76
+ * results on (template_id, element_path, global-etag) with a 60s TTL.
77
+ * The builder injects one shared instance so repeat inspects within
78
+ * the TTL skip the REST round-trip; a write bumps the global etag and
79
+ * naturally invalidates the entry. Omit it to disable caching (e.g.
80
+ * the cold-AI shape-pin tests that assert the raw round-trip).
81
+ */
82
+ readonly cache?: InspectionCache<InspectStructured>;
36
83
  }
37
- export declare function handleInspectMultiItemsBinding({ client }: MultiItemsHandlerDeps, { template_id, element_path }: {
84
+ export declare function handleInspectMultiItemsBinding({ client, cache }: MultiItemsHandlerDeps, { template_id, element_path }: {
38
85
  template_id: string;
39
86
  element_path: string;
40
87
  }): Promise<ToolResult>;
88
+ export {};
41
89
  //# sourceMappingURL=inspect-handler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"inspect-handler.d.ts","sourceRoot":"","sources":["../../../src/tools/multi-items/inspect-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAA6C,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhG,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;iBAe5C,CAAC;AAEH,MAAM,WAAW,qBAAqB;IAClC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC/B;AAED,wBAAsB,8BAA8B,CAChD,EAAE,MAAM,EAAE,EAAE,qBAAqB,EACjC,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC7E,OAAO,CAAC,UAAU,CAAC,CAqBrB"}
1
+ {"version":3,"file":"inspect-handler.d.ts","sourceRoot":"","sources":["../../../src/tools/multi-items/inspect-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAuC,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,EAA6C,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC;AAEnD,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuD5C,CAAC;AAEH,iEAAiE;AACjE,KAAK,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjD,MAAM,WAAW,qBAAqB;IAClC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC,iBAAiB,CAAC,CAAC;CACvD;AA0MD,wBAAsB,8BAA8B,CAChD,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,qBAAqB,EACxC,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC7E,OAAO,CAAC,UAAU,CAAC,CAwCrB"}
@@ -6,11 +6,20 @@
6
6
  * src/modules/builder-source-binding/src/MultiItemsInspector.php
7
7
  * for the report shape.
8
8
  *
9
+ * Wave-16 #34:
10
+ * - 6.1 depth-cap: the human-readable text leg is capped at
11
+ * {@link MAX_INSPECTION_DEPTH}; structuredContent stays verbatim so
12
+ * it keeps validating against the output schema.
13
+ * - 6.4 severity marker: the response carries a typed `hint.severity`
14
+ * ("advisory" | "blocking") so the agent can tell a structural
15
+ * container-level binding bug apart from informational guidance.
16
+ *
9
17
  * @license MIT
10
18
  */
11
19
  import { z } from 'zod';
12
- import { encodeElementPath } from '../../client.js';
20
+ import { encodeElementPath, encodeTemplateId } from '../../client.js';
13
21
  import { errorResult, jsonResult, structuredResult } from '../tool-builder.js';
22
+ import { capInspectionDepth } from './format/inspection-format.js';
14
23
  export const INSPECT_MULTI_ITEMS_OUTPUT_SCHEMA = z.object({
15
24
  template_id: z.string(),
16
25
  report: z.object({
@@ -21,30 +30,248 @@ export const INSPECT_MULTI_ITEMS_OUTPUT_SCHEMA = z.object({
21
30
  container_type: z.string().nullable(),
22
31
  item_type: z.string().nullable(),
23
32
  current_binding_level: z.enum(['none', 'container', 'item']),
33
+ // C7 (2026-06-10) — binding level of the container's first `*_item`
34
+ // child. Optional so a pre-C7 backend's report still validates.
35
+ item_child_binding_level: z.enum(['none', 'item']).optional(),
36
+ // C7 — single honest "is anything bound (here or on the item child)"
37
+ // signal. Optional for back-compat with pre-C7 reports.
38
+ is_bound: z.boolean().optional(),
24
39
  has_implode_directives: z.boolean(),
40
+ // C7 — bound source name + live-registry existence cross-check.
41
+ // `bound_source_exists` is null when the registry is not wired.
42
+ bound_source_name: z.string().nullable().optional(),
43
+ bound_source_exists: z.boolean().nullable().optional(),
44
+ source_missing_warning: z.string().optional(),
45
+ // F143 — true when a bound map_item/map carries no resolved
46
+ // `location` leaf (the map renders 0 markers). Optional so reports
47
+ // for non-map elements (and pre-F143 backends) still validate.
48
+ map_location_missing: z.boolean().optional(),
49
+ // F174 — number of field mappings on the bound node (0 when unbound /
50
+ // mapping-less). Optional so a pre-F174 backend's report still validates.
51
+ field_mapping_count: z.number().int().nonnegative().optional(),
52
+ // F174 — true when the element IS bound but carries 0 field mappings
53
+ // (the N clones render only the template's static placeholder text).
54
+ // Optional for back-compat with pre-F174 reports.
55
+ zero_field_mappings: z.boolean().optional(),
56
+ // F189 — true when a `…List` source sits on a LEAF renderer (grid_item /
57
+ // any non-container) with non-empty children (the children never paint).
58
+ // Optional so reports for other shapes + pre-F189 backends still validate.
59
+ iterator_is_leaf_renderer: z.boolean().optional(),
60
+ // F39 (2026-06-10) — emitted when a map/map_item is bound without a
61
+ // `location` field mapping (renders 0 markers). Optional so non-map
62
+ // reports still validate. Companion human-readable signal to the
63
+ // structured `map_location_missing` boolean above.
64
+ map_location_warning: z.string().optional(),
25
65
  warning: z.string().optional(),
26
66
  recommended_fix: z.string().optional(),
27
67
  }),
28
68
  etag: z.string(),
69
+ // 6.4 — typed advisory/blocking marker. Optional so a verbatim REST
70
+ // passthrough that predates this field still validates, but the
71
+ // handler always populates it.
72
+ hint: z
73
+ .object({
74
+ severity: z.enum(['advisory', 'blocking']),
75
+ message: z.string(),
76
+ })
77
+ .optional(),
29
78
  });
30
- export async function handleInspectMultiItemsBinding({ client }, { template_id, element_path }) {
79
+ /**
80
+ * Classify the report into an advisory/blocking hint.
81
+ *
82
+ * C7 (2026-06-10) — the verdict now reflects what is ACTUALLY bound, not
83
+ * just the container-node's own binding level. Three structural bugs the
84
+ * pre-C7 single-axis (`current_binding_level`) classifier produced:
85
+ *
86
+ * 1. A container bound *through* its `*_item` child reported "none" + a
87
+ * reassuring "structurally correct" hint. Now `is_bound` /
88
+ * `item_child_binding_level` make the child binding visible.
89
+ * 2. A fully-unbound element was called "structurally correct". Now a
90
+ * false `is_bound` yields an honest "no source binding present" hint.
91
+ * 3. A binding to a since-deleted source looked fine. Now
92
+ * `bound_source_exists === false` is `blocking` with the missing-
93
+ * source message.
94
+ *
95
+ * Precedence: container-level binding (blocking) → deleted source
96
+ * (blocking) → nothing bound (advisory, honest) → bound + live (advisory,
97
+ * "structurally correct").
98
+ */
99
+ function buildHint(report) {
100
+ const r = (report ?? {});
101
+ // F143 — a bound map with no resolved `location` leaf renders 0
102
+ // markers. That is a render-breaking bug, not advisory: surface it as
103
+ // `blocking` even though the binding level itself is "item". This is the
104
+ // structured-boolean entry point; the human-readable `map_location_warning`
105
+ // (F39, branch 1b below) is the companion signal a different backend emits.
106
+ if (r.map_location_missing === true) {
107
+ const fix = typeof r.recommended_fix === 'string' && r.recommended_fix !== ''
108
+ ? r.recommended_fix
109
+ : 'Map a single `location` field holding a combined "lat,lng" string.';
110
+ return {
111
+ severity: 'blocking',
112
+ message: 'Map is bound but no `location` field is mapped — no markers will ' +
113
+ `render. ${fix}`,
114
+ };
115
+ }
116
+ // F189 — a `…List` source on a LEAF renderer (grid_item / any non-container)
117
+ // that carries non-empty children: repeatSource clones it per row but the
118
+ // template renders ONLY its own slots, never its nested children → the
119
+ // children are render-dead and the grid shows placeholders. Render-breaking
120
+ // tier → blocking. The PHP inspector ships the human-readable `warning` with
121
+ // both recipes; surface it verbatim. Runs before the zero-mappings / generic
122
+ // branches so the iterator-shape bug is named first.
123
+ if (r.iterator_is_leaf_renderer === true) {
124
+ const msg = typeof r.warning === 'string' && r.warning !== ''
125
+ ? r.warning
126
+ : 'This element iterates a list source but is a LEAF renderer ' +
127
+ '(grid_item / *_item) — its nested children are never rendered. ' +
128
+ 'Map fields onto the item\'s own slots (title/meta/content/image), ' +
129
+ 'or move the List onto a container (column/fragment/row) with #parent leaves.';
130
+ return { severity: 'blocking', message: msg };
131
+ }
132
+ // F174 — a bound element with ZERO field mappings clones the container N
133
+ // times but every clone renders only the template's static placeholder
134
+ // text ("Title" / "Lorem ipsum"), not real data. The binding is
135
+ // structurally item-level so every other signal reports healthy. Same
136
+ // render-breaking tier as map_location_missing → blocking. The PHP
137
+ // inspector ships the human-readable `warning`; surface it verbatim.
138
+ if (r.zero_field_mappings === true) {
139
+ const msg = typeof r.warning === 'string' && r.warning !== ''
140
+ ? r.warning
141
+ : 'Bound to a source but with 0 field mappings — the cloned items ' +
142
+ 'render the template\'s static placeholder text (Title / Lorem ipsum), ' +
143
+ 'not real data. Re-bind with field_mappings AT THIS ITEM ' +
144
+ '(element_bind_source on this same element with non-empty ' +
145
+ 'field_mappings). Do NOT bind the individual child leaves instead: ' +
146
+ 'on YT5 a "#parent" leaf bind written directly under an iterating ' +
147
+ 'item renders placeholder text.';
148
+ return { severity: 'blocking', message: msg };
149
+ }
150
+ // (1) Container-level binding — the original structural bug. Blocking.
151
+ if (r.current_binding_level === 'container') {
152
+ const fix = typeof r.recommended_fix === 'string' && r.recommended_fix !== ''
153
+ ? r.recommended_fix
154
+ : 'Move the binding to the first `*_item` child element.';
155
+ return { severity: 'blocking', message: fix };
156
+ }
157
+ // (1b) F39 — a map/map_item bound WITHOUT a `location` field mapping
158
+ // renders zero markers. The PHP inspector only emits map_location_warning
159
+ // for a genuinely-bound map pair, so its mere presence is the signal.
160
+ // Blocking, because the map looks healthy but shows nothing.
161
+ if (typeof r.map_location_warning === 'string' && r.map_location_warning !== '') {
162
+ return { severity: 'blocking', message: r.map_location_warning };
163
+ }
164
+ // (2) C7 bug 3 — bound source no longer exists in the live registry.
165
+ // `bound_source_exists` is only a hard `false` when the registry was
166
+ // wired AND the name was absent; `null`/`undefined` (unknown) never trips
167
+ // this branch.
168
+ if (r.bound_source_exists === false) {
169
+ const msg = typeof r.source_missing_warning === 'string' && r.source_missing_warning !== ''
170
+ ? r.source_missing_warning
171
+ : 'The bound source no longer exists in the live source registry — ' +
172
+ 'the frontend will render empty. Re-bind to a current source.';
173
+ return { severity: 'blocking', message: msg };
174
+ }
175
+ // (3) C7 bug 2 — nothing is actually bound (neither this node nor, for a
176
+ // container, its item child). `is_bound` is the authoritative signal;
177
+ // when a pre-C7 backend omits it, fall back to current_binding_level.
178
+ const isBound = typeof r.is_bound === 'boolean'
179
+ ? r.is_bound
180
+ : r.current_binding_level === 'item';
181
+ if (!isBound) {
182
+ return {
183
+ severity: 'advisory',
184
+ message: 'No source binding present on this element' +
185
+ (r.current_binding_level !== 'item' && r.item_child_binding_level !== 'item'
186
+ ? ' or its item child'
187
+ : '') +
188
+ '. Bind a source directly: yootheme_builder_element_bind_source({ ' +
189
+ 'template_id, element_path, source_name, field_mappings }) — for a ' +
190
+ 'Multi-Items container, bind on the first `*_item` child.',
191
+ };
192
+ }
193
+ // (4) C7 bug 1 — bound through the item child. Surface that explicitly so
194
+ // the agent does not mistake the container's own "none" level for "unbound".
195
+ if (r.item_child_binding_level === 'item') {
196
+ return {
197
+ severity: 'advisory',
198
+ message: 'Binding looks structurally correct — the source is bound at the ' +
199
+ 'item level (on the `*_item` child), which is the canonical ' +
200
+ 'Multi-Items shape. Verify element_path via ' +
201
+ 'yootheme_builder_element_list if the source still renders empty.',
202
+ };
203
+ }
204
+ // (5) Genuinely item-bound with a live (or unknown) source.
205
+ return {
206
+ severity: 'advisory',
207
+ message: 'Binding looks structurally correct. Verify element_path via ' +
208
+ 'yootheme_builder_element_list if the source still renders empty.',
209
+ };
210
+ }
211
+ /**
212
+ * Render a structured inspect payload into the ToolResult envelope.
213
+ * Shared by the cache-hit and cache-miss paths so both legs (text +
214
+ * structuredContent) are built identically.
215
+ *
216
+ * 6.1 — the text leg is depth-capped so a deeply-nested report cannot
217
+ * balloon the LLM context. structuredContent stays verbatim so it keeps
218
+ * validating against INSPECT_MULTI_ITEMS_OUTPUT_SCHEMA
219
+ * (additionalProperties:false).
220
+ */
221
+ function renderInspectResult(structured) {
222
+ const text = jsonResult(capInspectionDepth(structured));
223
+ return structuredResult(text, structured);
224
+ }
225
+ export async function handleInspectMultiItemsBinding({ client, cache }, { template_id, element_path }) {
31
226
  const encoded = encodeElementPath(element_path);
32
227
  try {
33
- const data = await client.get(`/pages/${encodeURIComponent(template_id)}/elements/${encoded}/multi-items/inspect`);
34
- // The REST endpoint already returns the canonical
35
- // {template_id, report, etag} shape pass it through as
36
- // structuredContent so the declared outputSchema is satisfied
37
- // (a tool with an outputSchema MUST emit structuredContent, else
38
- // the MCP SDK rejects the call with -32602).
39
- return structuredResult(jsonResult(data), data);
228
+ // 6.2 when a cache is wired, key on the GLOBAL state etag. Every
229
+ // write tool bumps it, so a mutated template surfaces a fresh etag
230
+ // a new key a guaranteed miss. Read-only repeats within the TTL
231
+ // skip the inspect round-trip below.
232
+ let cacheEtag;
233
+ if (cache !== undefined) {
234
+ cacheEtag = await fetchStateEtag(client);
235
+ if (cacheEtag !== undefined) {
236
+ const cached = cache.get(template_id, element_path, cacheEtag);
237
+ if (cached !== undefined) {
238
+ return renderInspectResult(cached);
239
+ }
240
+ }
241
+ }
242
+ const data = await client.get(`/pages/${encodeTemplateId(template_id)}/elements/${encoded}/multi-items/inspect`);
243
+ // 6.4 — attach the typed severity marker to the structured payload.
244
+ const hint = buildHint(data.report);
245
+ const structured = { ...data, hint };
246
+ if (cache !== undefined && cacheEtag !== undefined) {
247
+ cache.set(template_id, element_path, cacheEtag, structured);
248
+ }
249
+ return renderInspectResult(structured);
40
250
  }
41
251
  catch (e) {
42
252
  return errorResult({
43
253
  error: e,
44
254
  context: { template_id, element_path },
45
255
  hint: 'Verify element_path via yootheme_builder_element_list. Paths are JSON-Pointer ' +
46
- 'style ("/templates/<id>/layout/children/0").',
256
+ '(RFC-6901) style: /0/children/1. Use yootheme_builder_element_list to enumerate ' +
257
+ 'valid paths.',
47
258
  });
48
259
  }
49
260
  }
261
+ /**
262
+ * Read the global state ETag used as the cache-invalidation token.
263
+ * Returns `undefined` (cache disabled for this call) if the etag probe
264
+ * fails or returns a non-string — a missing etag must never poison the
265
+ * cache key, and a probe failure should fall through to a live inspect
266
+ * rather than abort the whole call.
267
+ */
268
+ async function fetchStateEtag(client) {
269
+ try {
270
+ const res = await client.get('/etag');
271
+ return typeof res.etag === 'string' && res.etag !== '' ? res.etag : undefined;
272
+ }
273
+ catch {
274
+ return undefined;
275
+ }
276
+ }
50
277
  //# sourceMappingURL=inspect-handler.js.map