@jxsuite/studio 4.1.0 → 5.1.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 (612) hide show
  1. package/README.md +1 -1
  2. package/data/elements-meta.json +5 -15
  3. package/data/html-meta.json +51 -6
  4. package/dist/chunks/{2020-n6tfwnda.js → 2020-g79n01v9.js} +14 -14
  5. package/dist/chunks/action-group-sp6tna8v.js +118 -0
  6. package/dist/chunks/adapter-nj7tnjfn.js +13 -0
  7. package/dist/chunks/cf-account-picker-qwkm9zrf.js +495 -0
  8. package/dist/chunks/cf-settings-71bv5zn9.js +20 -0
  9. package/dist/chunks/color-area-v17df7b8.js +154 -0
  10. package/dist/chunks/color-field-anwybnkn.js +208 -0
  11. package/dist/chunks/color-slider-44ez96fc.js +79 -0
  12. package/dist/chunks/color-xgg3kfw7.js +35 -0
  13. package/dist/chunks/combobox-5e7jev23.js +236 -0
  14. package/dist/chunks/components-vj72gqtq.js +20 -0
  15. package/dist/chunks/content-source-5mex4x1h.js +46 -0
  16. package/dist/chunks/convert-to-repeater-n64h8znc.js +639 -0
  17. package/dist/chunks/dialog-s890b918.js +85 -0
  18. package/dist/chunks/editor-3qhbg51x.js +35 -0
  19. package/dist/chunks/entry-commands-234hjnqw.js +42 -0
  20. package/dist/chunks/extension-sections-3hpcambp.js +651 -0
  21. package/dist/chunks/file-ops-8yhd83xr.js +47 -0
  22. package/dist/chunks/files-hnxqxtsg.js +72 -0
  23. package/dist/chunks/format-host-779sfp2n.js +40 -0
  24. package/dist/chunks/fs-events-b88z7g4h.js +18 -0
  25. package/dist/chunks/git-panel-xwj8fpab.js +49 -0
  26. package/dist/chunks/icons-yy10wk9r.js +402 -0
  27. package/dist/chunks/iframe-entry-15g3n6xv.js +114 -0
  28. package/dist/chunks/iframe-entry-b27vq81n.js +203 -0
  29. package/dist/chunks/iframe-entry-nbyxee1y.js +154 -0
  30. package/dist/chunks/iframe-host-syr0f9sb.js +115 -0
  31. package/dist/chunks/{index-wcnt3r9g.js → index-mdmyx6s2.js} +11 -11
  32. package/dist/chunks/index-n4j7qxyr.js +109 -0
  33. package/dist/chunks/{javascript-q8kpmfah.js → javascript-xvrfrpkb.js} +8 -9
  34. package/dist/chunks/{jsonMode-dkr040ga.js → jsonMode-tyx2kj6p.js} +526 -527
  35. package/dist/chunks/jx-validate-j0wxk72w.js +15 -0
  36. package/dist/chunks/layers-ff81wthn.js +30 -0
  37. package/dist/chunks/layers-panel-pnnghw12.js +40 -0
  38. package/dist/chunks/listbox-6v2ac08j.js +44 -0
  39. package/dist/chunks/lit-html-m244w9nh.js +17 -0
  40. package/dist/chunks/media-picker-cqhhxhhe.js +33 -0
  41. package/dist/chunks/menu-9p2w46gj.js +15 -0
  42. package/dist/chunks/menu-q99sy9rf.js +285 -0
  43. package/dist/chunks/{monaco-binding-rj6xpx9y.js → monaco-binding-sw6en4dw.js} +12 -15
  44. package/dist/chunks/monaco-buffer-bhy3hb6m.js +24 -0
  45. package/dist/chunks/{monaco-setup-vx9bhp1d.js → monaco-setup-8r62fj6y.js} +27 -37
  46. package/dist/chunks/notify-628t0anh.js +21 -0
  47. package/dist/chunks/number-field-5cndyft8.js +72 -0
  48. package/dist/chunks/parse-0zx14y15.js +10 -0
  49. package/dist/chunks/platform-ts9cg1a4.js +15 -0
  50. package/dist/chunks/popover-47z3ytva.js +25 -0
  51. package/dist/chunks/publish-panel-5zt840sy.js +27 -0
  52. package/dist/chunks/quick-search-3748564r.js +45 -0
  53. package/dist/chunks/references-qvvxej7h.js +26 -0
  54. package/dist/chunks/right-panel-eccz92qt.js +45 -0
  55. package/dist/chunks/section-registry-5pq32t0q.js +25 -0
  56. package/dist/chunks/select-2r16ez41.js +49 -0
  57. package/dist/chunks/split-g7nm1rgb.js +191 -0
  58. package/dist/chunks/studio-0hqbpbd0.js +62 -0
  59. package/dist/chunks/{studio-kryvsw6j.js → studio-1k325pwf.js} +48 -48
  60. package/dist/chunks/{studio-b55y6ewx.js → studio-1knfqgy7.js} +58 -58
  61. package/dist/chunks/{studio-2b946z26.js → studio-1z1kcjv4.js} +3628 -6095
  62. package/dist/chunks/studio-3773086z.js +111 -0
  63. package/dist/chunks/{studio-4r1pv6zf.js → studio-38emantv.js} +22 -5
  64. package/dist/chunks/{studio-x813zp48.js → studio-3rz5md06.js} +30 -30
  65. package/dist/chunks/{studio-ynxwkrzd.js → studio-4wbb9ct0.js} +1953 -1785
  66. package/dist/chunks/studio-5te5tqng.js +81 -0
  67. package/dist/chunks/studio-5wt9nvhd.js +4763 -0
  68. package/dist/chunks/{studio-p4ngc046.js → studio-6ewqv390.js} +9 -9
  69. package/dist/chunks/{studio-9ab8gqsm.js → studio-6nzaktvy.js} +7 -7
  70. package/dist/chunks/studio-6xa21ej9.js +28 -0
  71. package/dist/chunks/{studio-5ehhackm.js → studio-727xh0e3.js} +19 -19
  72. package/dist/chunks/{studio-gcye7qka.js → studio-7e11jpa9.js} +21 -21
  73. package/dist/chunks/{studio-q7v10cg2.js → studio-7r42c6ca.js} +17 -7
  74. package/dist/chunks/studio-7xnmgv66.js +13615 -0
  75. package/dist/chunks/studio-8scdew0e.js +258 -0
  76. package/dist/chunks/{studio-fbf92ckf.js → studio-93zafjcm.js} +275 -163
  77. package/dist/chunks/{studio-dg7zyt5x.js → studio-98b3z07n.js} +1 -1
  78. package/dist/chunks/studio-a79k90n9.js +1162 -0
  79. package/dist/chunks/studio-aj37eer3.js +422 -0
  80. package/dist/chunks/studio-b0k5tqgp.js +2432 -0
  81. package/dist/chunks/studio-b4s9eykd.js +2811 -0
  82. package/dist/chunks/{studio-f3wqjtk5.js → studio-d0300636.js} +5076 -18
  83. package/dist/chunks/{studio-b9b6t1dg.js → studio-e1f24eff.js} +5664 -5666
  84. package/dist/chunks/studio-e1pgga3k.js +839 -0
  85. package/dist/chunks/{studio-g1wdche0.js → studio-esrxgwh6.js} +80 -80
  86. package/dist/chunks/{studio-q43a5y9h.js → studio-g3jevyjt.js} +16 -16
  87. package/dist/chunks/studio-gb13095a.js +2806 -0
  88. package/dist/chunks/{studio-3n4ndrzh.js → studio-h4nvnjvz.js} +303 -303
  89. package/dist/chunks/{studio-dm19q43r.js → studio-hhvs4sdg.js} +10 -10
  90. package/dist/chunks/{studio-x4qkdat5.js → studio-js8nv53n.js} +1749 -2481
  91. package/dist/chunks/{studio-qjy2z9bv.js → studio-jxp12rnj.js} +32 -137
  92. package/dist/chunks/{studio-trxrabqf.js → studio-k75n7vhp.js} +527 -283
  93. package/dist/chunks/{studio-q9jd1a60.js → studio-kcgff4r0.js} +15 -18
  94. package/dist/chunks/studio-kkqkcp3d.js +17668 -0
  95. package/dist/chunks/studio-mhhyamxf.js +763 -0
  96. package/dist/chunks/{studio-cft9r4r7.js → studio-nq5yf5mp.js} +22 -22
  97. package/dist/chunks/{studio-685s0ytq.js → studio-nqgawfks.js} +572 -572
  98. package/dist/chunks/studio-nzzpvzx9.js +185 -0
  99. package/dist/chunks/{studio-xrapxwwc.js → studio-p1dw8wfw.js} +55 -29
  100. package/dist/chunks/{studio-3bqpr0zh.js → studio-pxbgypmg.js} +299 -110
  101. package/dist/chunks/studio-q0a3yk4n.js +33 -0
  102. package/dist/chunks/{studio-wcy8trfx.js → studio-q3x06vmj.js} +23 -22
  103. package/dist/chunks/{studio-6yw4y3my.js → studio-qhhm6hbt.js} +8 -8
  104. package/dist/chunks/studio-qk4bfsq2.js +362 -0
  105. package/dist/chunks/{studio-msd847zn.js → studio-qk90fgqm.js} +361 -90
  106. package/dist/chunks/{studio-jkftxyvz.js → studio-r6nvacqs.js} +5861 -2154
  107. package/dist/chunks/{studio-53n8bp04.js → studio-r6xmmtfh.js} +1 -1
  108. package/dist/chunks/{studio-tvgyw9xw.js → studio-rnyf3f8e.js} +83 -250
  109. package/dist/chunks/studio-rs76k67r.js +12 -0
  110. package/dist/chunks/studio-sbjyc8bt.js +954 -0
  111. package/dist/chunks/{studio-1wagb550.js → studio-syg2tadj.js} +11 -11
  112. package/dist/chunks/{studio-t5wqwzdh.js → studio-tjjk7jvk.js} +1 -1
  113. package/dist/chunks/studio-tqgryxwg.js +1171 -0
  114. package/dist/chunks/studio-try13h8c.js +8448 -0
  115. package/dist/chunks/studio-vfq8qpjt.js +1219 -0
  116. package/dist/chunks/studio-vhv5tgxm.js +51 -0
  117. package/dist/chunks/{studio-ahn3pdgx.js → studio-vw7mzp6z.js} +52 -38
  118. package/dist/chunks/studio-wqpngpsk.js +174 -0
  119. package/dist/chunks/studio-wqz6dggm.js +1356 -0
  120. package/dist/chunks/{studio-92ab2jqe.js → studio-y9zedyjn.js} +14 -14
  121. package/dist/chunks/studio-yxa81f45.js +12 -0
  122. package/dist/chunks/studio-zdn2g6dt.js +148 -0
  123. package/dist/chunks/swatch-group-t0n6h2rn.js +139 -0
  124. package/dist/chunks/tabs-wbp1cdws.js +156 -0
  125. package/dist/chunks/textfield-abk6qyee.js +73 -0
  126. package/dist/chunks/toast-780pvfbv.js +27 -0
  127. package/dist/chunks/toast-host-3sqv46sn.js +116 -0
  128. package/dist/chunks/toolbar-xbh5bhtr.js +194 -0
  129. package/dist/chunks/tooltip-eptb614w.js +369 -0
  130. package/dist/chunks/tree-a73p0pqm.js +367 -0
  131. package/dist/chunks/{tsMode-76kr53q0.js → tsMode-jy4m86rv.js} +83 -85
  132. package/dist/chunks/workspace-t55jdjbx.js +69 -0
  133. package/dist/chunks/{ws-client-6shc5rze.js → ws-client-ny4zc51r.js} +20 -22
  134. package/dist/iframe-entry.js +1873 -673
  135. package/dist/studio.js +52757 -36535
  136. package/dist/workers/editor.worker.js +1040 -1085
  137. package/dist/workers/json.worker.js +1946 -1991
  138. package/dist/workers/ts.worker.js +4960 -5005
  139. package/index.html +1 -0
  140. package/package.json +18 -52
  141. package/src/about/about-modal.ts +72 -123
  142. package/src/browse/library-commands.ts +20 -49
  143. package/src/browse/library-layouts.ts +87 -218
  144. package/src/browse/library-pane.ts +406 -438
  145. package/src/canvas/canvas-helpers.ts +0 -49
  146. package/src/canvas/canvas-live-render.ts +25 -2
  147. package/src/canvas/canvas-render.ts +666 -231
  148. package/src/canvas/canvas-surface.ts +0 -1
  149. package/src/canvas/canvas-utils.ts +333 -113
  150. package/src/canvas/dialog-path.ts +76 -0
  151. package/src/canvas/dialog-state.ts +67 -0
  152. package/src/canvas/diff-marks.ts +252 -0
  153. package/src/canvas/diff-toolbar.ts +349 -0
  154. package/src/canvas/diff-view.ts +123 -0
  155. package/src/canvas/edit-width-drag.ts +187 -0
  156. package/src/canvas/edit-width.ts +150 -0
  157. package/src/canvas/iframe-entry.ts +125 -8
  158. package/src/canvas/iframe-host.ts +271 -15
  159. package/src/canvas/iframe-interaction.ts +133 -13
  160. package/src/canvas/iframe-patch.ts +7 -1
  161. package/src/canvas/iframe-position.ts +5 -6
  162. package/src/canvas/iframe-protocol.ts +106 -5
  163. package/src/canvas/iframe-render.ts +373 -5
  164. package/src/canvas/iframe-slash.ts +2 -2
  165. package/src/canvas/iframe-subtree.ts +5 -8
  166. package/src/canvas/path-mapping.ts +25 -3
  167. package/src/canvas/popover-path.ts +106 -0
  168. package/src/canvas/popover-state.ts +155 -0
  169. package/src/canvas/surface-registry.ts +21 -10
  170. package/src/collab/presence-chips.ts +51 -73
  171. package/src/commands/app-commands.ts +10 -0
  172. package/src/commands/budget.ts +12 -0
  173. package/src/commands/command-args.ts +404 -6
  174. package/src/commands/defaults.ts +44 -14
  175. package/src/commands/live-context.ts +11 -5
  176. package/src/commands/reference.ts +12 -2
  177. package/src/commands/registry.ts +177 -10
  178. package/src/commands/run-reported.ts +120 -0
  179. package/src/content/entry-commands.ts +16 -23
  180. package/src/content/entry-editor.ts +144 -101
  181. package/src/editor/canvas-slash-bridge.ts +2 -2
  182. package/src/editor/context-menu.ts +49 -200
  183. package/src/editor/convert-to-component.ts +42 -82
  184. package/src/editor/convert-to-repeater.ts +132 -173
  185. package/src/editor/inline-edit.ts +11 -0
  186. package/src/editor/shortcuts.ts +76 -49
  187. package/src/editor/slash-menu.ts +150 -157
  188. package/src/files/components.ts +39 -0
  189. package/src/files/file-ops.ts +117 -11
  190. package/src/files/files.ts +944 -660
  191. package/src/files/json-layout.ts +474 -0
  192. package/src/files/serialize-document.ts +8 -1
  193. package/src/format/convert-file.ts +16 -10
  194. package/src/format/format-host.ts +50 -1
  195. package/src/github/github-auth.ts +71 -29
  196. package/src/github/github-publish.ts +57 -65
  197. package/src/grid/cell-editors.ts +46 -4
  198. package/src/grid/cell-popovers.ts +65 -62
  199. package/src/grid/grid-open.ts +86 -64
  200. package/src/grid/grid-panel.ts +390 -469
  201. package/src/grid/redirects-grid.ts +40 -44
  202. package/src/hosting/layout.ts +2 -0
  203. package/src/i18n/i18n-commands.ts +137 -62
  204. package/src/media/media-pane.ts +83 -133
  205. package/src/new-project/add-repo-modal.ts +125 -176
  206. package/src/new-project/import-tab.ts +181 -252
  207. package/src/new-project/location-fields.ts +93 -160
  208. package/src/new-project/new-project-modal.ts +376 -367
  209. package/src/packages/jxsuite-update.ts +76 -18
  210. package/src/packages/pull-package-sync.ts +5 -1
  211. package/src/panels/activity-panel.ts +137 -104
  212. package/src/panels/ai-chat/chat-markdown.ts +15 -13
  213. package/src/panels/ai-chat/chat-view.ts +307 -472
  214. package/src/panels/ai-chat/composer.ts +175 -163
  215. package/src/panels/ai-chat/sessions-view.ts +31 -62
  216. package/src/panels/ai-panel.ts +213 -185
  217. package/src/panels/block-action-bar.ts +444 -645
  218. package/src/panels/bottom-dock.ts +112 -47
  219. package/src/panels/chat-panel.ts +19 -14
  220. package/src/panels/data-explorer.ts +141 -102
  221. package/src/panels/data-grid.ts +183 -150
  222. package/src/panels/dnd.ts +75 -20
  223. package/src/panels/editors.ts +26 -19
  224. package/src/panels/elements-panel.ts +243 -186
  225. package/src/panels/empty-state.ts +26 -42
  226. package/src/panels/events-panel.ts +950 -729
  227. package/src/panels/formula-workspace.ts +434 -207
  228. package/src/panels/frontmatter-fields.ts +185 -153
  229. package/src/panels/frontmatter-panel.ts +411 -187
  230. package/src/panels/git-diff-open.ts +148 -0
  231. package/src/panels/git-panel.ts +679 -605
  232. package/src/panels/head-panel.ts +617 -435
  233. package/src/panels/i18n-panel.ts +148 -135
  234. package/src/panels/imports-panel.ts +388 -414
  235. package/src/panels/jump-bar.ts +175 -147
  236. package/src/panels/layers-panel.ts +785 -671
  237. package/src/panels/left-panel.ts +166 -94
  238. package/src/panels/navigator-panels.ts +1 -1
  239. package/src/panels/pane-context.ts +529 -677
  240. package/src/panels/pane-grid.ts +265 -241
  241. package/src/panels/panel-registry.ts +15 -4
  242. package/src/panels/problems-panel.ts +181 -99
  243. package/src/panels/properties-panel.ts +1525 -966
  244. package/src/panels/provenance.ts +31 -113
  245. package/src/panels/quick-search.ts +223 -184
  246. package/src/panels/right-panel.ts +135 -169
  247. package/src/panels/seo-modal.ts +346 -167
  248. package/src/panels/settings-menu.ts +114 -661
  249. package/src/panels/settings-pane.ts +102 -86
  250. package/src/panels/signals-panel.ts +1318 -1172
  251. package/src/panels/statement-editor.ts +556 -428
  252. package/src/panels/style-panel.ts +1367 -630
  253. package/src/panels/style-utils.ts +36 -32
  254. package/src/panels/stylebook-doc.ts +30 -73
  255. package/src/panels/stylebook-layers-panel.ts +202 -109
  256. package/src/panels/stylebook-panel.ts +124 -88
  257. package/src/panels/tab-strip.ts +386 -288
  258. package/src/platforms/cloud.ts +106 -16
  259. package/src/platforms/devserver.ts +13 -0
  260. package/src/publish/deploy-checklist.ts +124 -78
  261. package/src/publish/publish-commands.ts +4 -12
  262. package/src/publish/publish-panel.ts +134 -328
  263. package/src/services/a11y-report.ts +100 -43
  264. package/src/services/ai-command-tools.ts +538 -0
  265. package/src/services/ai-project-tools.ts +8 -2
  266. package/src/services/ai-session-store.ts +6 -0
  267. package/src/services/ai-system-prompt.ts +112 -24
  268. package/src/services/ai-tools.ts +36 -212
  269. package/src/services/ai-write-report.ts +174 -0
  270. package/src/services/document-assistant.ts +59 -8
  271. package/src/services/idle.ts +16 -14
  272. package/src/services/live-surfaces.ts +237 -0
  273. package/src/services/model-uri.ts +75 -0
  274. package/src/services/notify.ts +63 -6
  275. package/src/services/popover-report.ts +325 -0
  276. package/src/services/surface-registry.ts +56 -0
  277. package/src/services/tool-executor.ts +6 -0
  278. package/src/settings/contexts-section.ts +301 -299
  279. package/src/settings/contributed-section.ts +361 -222
  280. package/src/settings/css-vars-editor.ts +320 -325
  281. package/src/settings/defs-editor.ts +572 -535
  282. package/src/settings/dependencies-editor.ts +79 -107
  283. package/src/settings/extension-commands.ts +379 -0
  284. package/src/settings/extension-rows.ts +113 -0
  285. package/src/settings/extensions-section.ts +287 -0
  286. package/src/settings/general-settings.ts +130 -181
  287. package/src/settings/head-editor.ts +10 -305
  288. package/src/settings/locales-section.ts +146 -196
  289. package/src/settings/preferences-accounts.ts +1 -1
  290. package/src/settings/preferences-dialog.ts +350 -330
  291. package/src/settings/project-sections.ts +108 -181
  292. package/src/settings/schema-field-ui.ts +11 -399
  293. package/src/settings/section-registry.ts +8 -1
  294. package/src/settings/settings-document.ts +31 -29
  295. package/src/shell/tree.ts +42 -87
  296. package/src/shell.ts +48 -36
  297. package/src/studio.ts +104 -69
  298. package/src/style/token-ref.ts +0 -39
  299. package/src/surfaces/about.json +263 -0
  300. package/src/surfaces/about.ts +163 -0
  301. package/src/surfaces/add-repo.json +486 -0
  302. package/src/surfaces/add-repo.ts +236 -0
  303. package/src/surfaces/ai-chat.json +2185 -0
  304. package/src/surfaces/ai-chat.ts +549 -0
  305. package/src/surfaces/ai-credentials-form.json +332 -0
  306. package/src/surfaces/ai-credentials-form.ts +151 -0
  307. package/src/surfaces/ai-managed-connect.json +108 -0
  308. package/src/surfaces/ai-managed-connect.ts +123 -0
  309. package/src/surfaces/ai-model-picker.json +114 -0
  310. package/src/surfaces/ai-model-picker.ts +139 -0
  311. package/src/surfaces/block-action-bar.json +640 -0
  312. package/src/surfaces/block-action-bar.ts +368 -0
  313. package/src/surfaces/bottom-dock.json +154 -0
  314. package/src/surfaces/bottom-dock.ts +125 -0
  315. package/src/surfaces/canvas-stage.json +444 -0
  316. package/src/surfaces/canvas-stage.ts +253 -0
  317. package/src/surfaces/cf-account-picker.json +300 -0
  318. package/src/surfaces/cf-account-picker.ts +214 -0
  319. package/src/surfaces/commandbar.json +985 -0
  320. package/src/{panels/toolbar.ts → surfaces/commandbar.ts} +417 -391
  321. package/src/surfaces/convert-repeater.json +309 -0
  322. package/src/surfaces/convert-repeater.ts +276 -0
  323. package/src/surfaces/data-actions.json +157 -0
  324. package/src/surfaces/data-actions.ts +115 -0
  325. package/src/surfaces/dialog.json +289 -0
  326. package/src/surfaces/dialog.ts +343 -0
  327. package/src/surfaces/diff-toolbar.json +266 -0
  328. package/src/surfaces/diff-toolbar.ts +139 -0
  329. package/src/surfaces/doc-header.json +739 -0
  330. package/src/surfaces/doc-header.ts +223 -0
  331. package/src/surfaces/empty-state.json +152 -0
  332. package/src/surfaces/empty-state.ts +173 -0
  333. package/src/surfaces/entry-editor.json +281 -0
  334. package/src/surfaces/entry-editor.ts +191 -0
  335. package/src/surfaces/expression-editor.json +977 -0
  336. package/src/surfaces/expression-editor.ts +266 -0
  337. package/src/surfaces/files-panel.json +592 -0
  338. package/src/surfaces/files-panel.ts +301 -0
  339. package/src/surfaces/formula-palette.json +364 -0
  340. package/src/surfaces/formula-palette.ts +340 -0
  341. package/src/surfaces/git-panel.json +1822 -0
  342. package/src/surfaces/git-panel.ts +272 -0
  343. package/src/surfaces/github-auth.json +112 -0
  344. package/src/surfaces/github-auth.ts +139 -0
  345. package/src/surfaces/github-publish.json +206 -0
  346. package/src/surfaces/github-publish.ts +169 -0
  347. package/src/surfaces/grid-cell.json +218 -0
  348. package/src/surfaces/grid-cell.ts +120 -0
  349. package/src/surfaces/grid-open.json +147 -0
  350. package/src/surfaces/grid-open.ts +87 -0
  351. package/src/surfaces/grid-panel.json +706 -0
  352. package/src/surfaces/grid-panel.ts +206 -0
  353. package/src/surfaces/grid-replace.json +179 -0
  354. package/src/surfaces/grid-replace.ts +89 -0
  355. package/src/surfaces/grid-views.json +446 -0
  356. package/src/surfaces/grid-views.ts +172 -0
  357. package/src/surfaces/inspector-dock.json +187 -0
  358. package/src/surfaces/inspector-dock.ts +161 -0
  359. package/src/surfaces/jump-bar.json +243 -0
  360. package/src/surfaces/jump-bar.ts +129 -0
  361. package/src/surfaces/jxsuite-update.json +146 -0
  362. package/src/surfaces/jxsuite-update.ts +149 -0
  363. package/src/surfaces/library-pane.json +1509 -0
  364. package/src/surfaces/library-pane.ts +363 -0
  365. package/src/surfaces/logic-panel.json +1949 -0
  366. package/src/surfaces/logic-panel.ts +369 -0
  367. package/src/surfaces/logic-workspace.json +685 -0
  368. package/src/surfaces/logic-workspace.ts +238 -0
  369. package/src/surfaces/media-browser.json +303 -0
  370. package/src/surfaces/media-browser.ts +145 -0
  371. package/src/surfaces/media-field.json +163 -0
  372. package/src/surfaces/media-field.ts +116 -0
  373. package/src/surfaces/media-pane.json +513 -0
  374. package/src/surfaces/media-pane.ts +197 -0
  375. package/src/surfaces/menu.json +232 -0
  376. package/src/surfaces/menu.ts +375 -0
  377. package/src/surfaces/navigator-dock.json +113 -0
  378. package/src/surfaces/navigator-dock.ts +130 -0
  379. package/src/surfaces/new-project.json +1654 -0
  380. package/src/surfaces/new-project.ts +411 -0
  381. package/src/surfaces/palette.json +535 -0
  382. package/src/surfaces/pane-context.json +1497 -0
  383. package/src/surfaces/pane-context.ts +513 -0
  384. package/src/surfaces/pane-grid.json +188 -0
  385. package/src/surfaces/pane-grid.ts +250 -0
  386. package/src/surfaces/panel-activity.json +563 -0
  387. package/src/surfaces/panel-activity.ts +187 -0
  388. package/src/surfaces/panel-data.json +141 -0
  389. package/src/surfaces/panel-data.ts +156 -0
  390. package/src/surfaces/panel-deploy-checklist.json +283 -0
  391. package/src/surfaces/panel-deploy-checklist.ts +175 -0
  392. package/src/surfaces/panel-elements.json +367 -0
  393. package/src/surfaces/panel-elements.ts +175 -0
  394. package/src/surfaces/panel-i18n.json +569 -0
  395. package/src/surfaces/panel-i18n.ts +212 -0
  396. package/src/surfaces/panel-imports.json +780 -0
  397. package/src/surfaces/panel-imports.ts +209 -0
  398. package/src/surfaces/panel-outline.json +734 -0
  399. package/src/surfaces/panel-outline.ts +326 -0
  400. package/src/surfaces/panel-page.json +1017 -0
  401. package/src/surfaces/panel-page.ts +240 -0
  402. package/src/surfaces/panel-problems.json +497 -0
  403. package/src/surfaces/panel-problems.ts +157 -0
  404. package/src/surfaces/panel-signals.json +1973 -0
  405. package/src/surfaces/panel-signals.ts +436 -0
  406. package/src/surfaces/panel-stylebook-layers.json +317 -0
  407. package/src/surfaces/panel-stylebook-layers.ts +155 -0
  408. package/src/surfaces/preferences.json +850 -0
  409. package/src/surfaces/preferences.ts +332 -0
  410. package/src/surfaces/progress-modal.json +110 -0
  411. package/src/surfaces/progress-modal.ts +150 -0
  412. package/src/surfaces/properties-panel.json +1578 -0
  413. package/src/surfaces/properties-panel.ts +337 -0
  414. package/src/surfaces/publish.json +945 -0
  415. package/src/surfaces/publish.ts +392 -0
  416. package/src/surfaces/push-plan.json +110 -0
  417. package/src/surfaces/push-plan.ts +87 -0
  418. package/src/surfaces/rail.json +255 -0
  419. package/src/surfaces/rail.ts +206 -0
  420. package/src/surfaces/reference-field.json +191 -0
  421. package/src/surfaces/reference-field.ts +168 -0
  422. package/src/surfaces/schema-builder.json +1011 -0
  423. package/src/surfaces/schema-builder.ts +181 -0
  424. package/src/surfaces/schema-form.json +1013 -0
  425. package/src/surfaces/schema-form.ts +287 -0
  426. package/src/surfaces/secret-field.json +60 -0
  427. package/src/surfaces/secret-field.ts +146 -0
  428. package/src/surfaces/seo.json +932 -0
  429. package/src/surfaces/seo.ts +334 -0
  430. package/src/surfaces/settings-contexts.json +538 -0
  431. package/src/surfaces/settings-contexts.ts +196 -0
  432. package/src/surfaces/settings-contributed.json +489 -0
  433. package/src/surfaces/settings-contributed.ts +199 -0
  434. package/src/surfaces/settings-css-vars.json +820 -0
  435. package/src/surfaces/settings-css-vars.ts +199 -0
  436. package/src/surfaces/settings-defs.json +1363 -0
  437. package/src/surfaces/settings-defs.ts +232 -0
  438. package/src/surfaces/settings-deploy.json +108 -0
  439. package/src/surfaces/settings-deploy.ts +135 -0
  440. package/src/surfaces/settings-extensions.json +486 -0
  441. package/src/surfaces/settings-extensions.ts +201 -0
  442. package/src/surfaces/settings-head.json +779 -0
  443. package/src/surfaces/settings-head.ts +397 -0
  444. package/src/surfaces/settings-locales.json +420 -0
  445. package/src/surfaces/settings-locales.ts +137 -0
  446. package/src/surfaces/settings-overview.json +423 -0
  447. package/src/surfaces/settings-overview.ts +218 -0
  448. package/src/surfaces/settings-packages.json +549 -0
  449. package/src/surfaces/settings-packages.ts +158 -0
  450. package/src/surfaces/settings-pane.json +147 -0
  451. package/src/surfaces/settings-pane.ts +150 -0
  452. package/src/surfaces/settings-rawjson.json +104 -0
  453. package/src/surfaces/settings-rawjson.ts +107 -0
  454. package/src/surfaces/shell.json +99 -0
  455. package/src/surfaces/shell.ts +30 -0
  456. package/src/surfaces/slash-menu.json +180 -0
  457. package/src/surfaces/slash-menu.ts +272 -0
  458. package/src/surfaces/statements.json +607 -0
  459. package/src/surfaces/statements.ts +238 -0
  460. package/src/surfaces/statusbar.json +94 -0
  461. package/src/{panels → surfaces}/statusbar.ts +164 -90
  462. package/src/surfaces/style-panel.json +1643 -0
  463. package/src/surfaces/style-panel.ts +338 -0
  464. package/src/surfaces/stylebook-chrome.json +122 -0
  465. package/src/surfaces/stylebook-chrome.ts +122 -0
  466. package/src/surfaces/tab-strip.json +448 -0
  467. package/src/surfaces/tab-strip.ts +200 -0
  468. package/src/surfaces/target-line.json +419 -0
  469. package/src/surfaces/target-line.ts +349 -0
  470. package/src/surfaces/toasts.json +189 -0
  471. package/src/surfaces/welcome.json +571 -0
  472. package/src/surfaces/welcome.ts +338 -0
  473. package/src/tabs/project-config.ts +111 -21
  474. package/src/tabs/tab.ts +52 -1
  475. package/src/types.ts +22 -0
  476. package/src/ui/ai-credentials-form.ts +104 -100
  477. package/src/ui/ai-managed-connect.ts +54 -36
  478. package/src/ui/ai-model-picker.ts +75 -47
  479. package/src/ui/cf-account-picker.ts +76 -141
  480. package/src/ui/color-selector.ts +80 -301
  481. package/src/ui/dynamic-slot.ts +43 -283
  482. package/src/ui/expression-editor.ts +797 -576
  483. package/src/ui/field-input.ts +8 -181
  484. package/src/ui/form-controls.ts +838 -366
  485. package/src/ui/formula-chips.ts +80 -85
  486. package/src/ui/kit.ts +33 -0
  487. package/src/ui/layers.ts +296 -593
  488. package/src/ui/media-picker.ts +203 -284
  489. package/src/ui/panel-resize.ts +251 -64
  490. package/src/ui/popover-surface.ts +153 -0
  491. package/src/ui/progress-modal.ts +22 -60
  492. package/src/ui/regions.ts +13 -7
  493. package/src/ui/schema-form.ts +906 -440
  494. package/src/ui/surface.ts +122 -0
  495. package/src/ui/unit-selector.ts +15 -131
  496. package/src/ui/value-source.ts +14 -0
  497. package/src/ui/virtual-window.ts +88 -9
  498. package/src/utils/canvas-media.ts +72 -0
  499. package/src/utils/edit-display.ts +7 -2
  500. package/src/utils/element-selectors.ts +69 -0
  501. package/src/utils/link-target.ts +2 -2
  502. package/src/utils/studio-utils.ts +0 -10
  503. package/src/view.ts +15 -0
  504. package/src/workspace/pane-derive.ts +36 -14
  505. package/src/workspace/workspace.ts +75 -6
  506. package/styles/canvas.css +72 -467
  507. package/styles/forced-colors.css +48 -82
  508. package/styles/forced-colors.json +41 -0
  509. package/styles/inspector.css +2 -1301
  510. package/styles/overlays.css +96 -2823
  511. package/styles/panels.css +6 -1423
  512. package/styles/shell-frame.css +272 -0
  513. package/styles/shell-frame.json +227 -0
  514. package/styles/shell.css +0 -1568
  515. package/styles/tokens.css +65 -136
  516. package/styles/tokens.json +84 -0
  517. package/dist/chunks/Overlay.dev-etqjwyf9.js +0 -23
  518. package/dist/chunks/adapter-jkcyhgtr.js +0 -14
  519. package/dist/chunks/cf-account-picker-en86v7x7.js +0 -163
  520. package/dist/chunks/cf-settings-45fgyx8y.js +0 -21
  521. package/dist/chunks/components-zmx10t62.js +0 -21
  522. package/dist/chunks/content-source-48xg86wj.js +0 -49
  523. package/dist/chunks/convert-to-repeater-43tfn7cs.js +0 -268
  524. package/dist/chunks/editor-cptq5jp1.js +0 -37
  525. package/dist/chunks/entry-commands-e63f1xc0.js +0 -46
  526. package/dist/chunks/extension-sections-txv08xxg.js +0 -311
  527. package/dist/chunks/file-ops-wbh4hhsx.js +0 -48
  528. package/dist/chunks/files-3kfkwhk4.js +0 -93
  529. package/dist/chunks/flow-qbfgrpeh.js +0 -634
  530. package/dist/chunks/focus-trap.esm-9t2drp0g.js +0 -1025
  531. package/dist/chunks/focus-visible-6eg70z18.js +0 -167
  532. package/dist/chunks/format-host-w16q81tf.js +0 -43
  533. package/dist/chunks/fs-events-hrrg328g.js +0 -21
  534. package/dist/chunks/git-panel-532whr1y.js +0 -59
  535. package/dist/chunks/index-zqxmqxmh.js +0 -109
  536. package/dist/chunks/jx-validate-8er6gbxy.js +0 -19
  537. package/dist/chunks/layers-panel-07hm7g5j.js +0 -67
  538. package/dist/chunks/layers-q75tj2mf.js +0 -45
  539. package/dist/chunks/lit-html-j055mkh8.js +0 -22
  540. package/dist/chunks/monaco-buffer-dqw0xxpx.js +0 -25
  541. package/dist/chunks/notify-yjm79n4s.js +0 -30
  542. package/dist/chunks/parse-24d0gay3.js +0 -19
  543. package/dist/chunks/platform-ba1j1gbh.js +0 -16
  544. package/dist/chunks/publish-panel-v9st96ja.js +0 -29
  545. package/dist/chunks/quick-search-zccjp6gv.js +0 -66
  546. package/dist/chunks/references-3qx8fkyp.js +0 -29
  547. package/dist/chunks/right-panel-vm3b6kwy.js +0 -46
  548. package/dist/chunks/section-registry-sx1ykvkw.js +0 -30
  549. package/dist/chunks/sp-overlay.dev-qgvhnxf4.js +0 -18
  550. package/dist/chunks/sp-popover.dev-n2etmqdp.js +0 -9
  551. package/dist/chunks/sp-progress-circle.dev-hryhj0es.js +0 -15
  552. package/dist/chunks/sp-tooltip.dev-4sastdnw.js +0 -15
  553. package/dist/chunks/sp-tray.dev-tkbscm06.js +0 -199
  554. package/dist/chunks/studio-0a5qrh01.js +0 -3
  555. package/dist/chunks/studio-0bq6eh7v.js +0 -12
  556. package/dist/chunks/studio-18j3bmcz.js +0 -14
  557. package/dist/chunks/studio-1ngbejft.js +0 -181
  558. package/dist/chunks/studio-4b5z1x43.js +0 -424
  559. package/dist/chunks/studio-4n2b5gzb.js +0 -357
  560. package/dist/chunks/studio-4rzyrtjz.js +0 -426
  561. package/dist/chunks/studio-5fx3g9jg.js +0 -4325
  562. package/dist/chunks/studio-5myknm0a.js +0 -1903
  563. package/dist/chunks/studio-7afd21nw.js +0 -67
  564. package/dist/chunks/studio-7nte2hj4.js +0 -613
  565. package/dist/chunks/studio-8jpzqk5s.js +0 -128
  566. package/dist/chunks/studio-8q517dfr.js +0 -24
  567. package/dist/chunks/studio-950k0dx6.js +0 -6939
  568. package/dist/chunks/studio-9n4mrmnb.js +0 -184
  569. package/dist/chunks/studio-a0tswy0w.js +0 -58
  570. package/dist/chunks/studio-ahnzd9rg.js +0 -23
  571. package/dist/chunks/studio-bgxt93ga.js +0 -62
  572. package/dist/chunks/studio-cmb03bg5.js +0 -13890
  573. package/dist/chunks/studio-d1ks410h.js +0 -175
  574. package/dist/chunks/studio-ef49pnzx.js +0 -387
  575. package/dist/chunks/studio-eqq1w638.js +0 -113
  576. package/dist/chunks/studio-ew0djmhg.js +0 -341
  577. package/dist/chunks/studio-gfgb8pe6.js +0 -1652
  578. package/dist/chunks/studio-h4rxscfc.js +0 -10
  579. package/dist/chunks/studio-jc994dnr.js +0 -1066
  580. package/dist/chunks/studio-kyh9avvv.js +0 -28
  581. package/dist/chunks/studio-m3hwn7y1.js +0 -120
  582. package/dist/chunks/studio-mtfnaqs9.js +0 -659
  583. package/dist/chunks/studio-n6j9t10q.js +0 -318
  584. package/dist/chunks/studio-n8b9wqwy.js +0 -291
  585. package/dist/chunks/studio-qcy05dp8.js +0 -1743
  586. package/dist/chunks/studio-qq6jym04.js +0 -53
  587. package/dist/chunks/studio-rdx8jcxy.js +0 -83
  588. package/dist/chunks/studio-rn9ta2mz.js +0 -111
  589. package/dist/chunks/studio-t7qb9db8.js +0 -665
  590. package/dist/chunks/studio-tmc5emrw.js +0 -8
  591. package/dist/chunks/studio-z6nw2ek2.js +0 -18
  592. package/dist/chunks/studio-zczps70q.js +0 -378
  593. package/dist/chunks/studio-zqazsct2.js +0 -1823
  594. package/dist/chunks/workspace-fjx52ryv.js +0 -89
  595. package/src/panels/activity-bar.ts +0 -251
  596. package/src/panels/panel-scheduler.ts +0 -219
  597. package/src/panels/style-inputs.ts +0 -237
  598. package/src/panels/target-line.ts +0 -274
  599. package/src/panels/welcome-screen.ts +0 -346
  600. package/src/ui/button-group.ts +0 -102
  601. package/src/ui/choice-field.ts +0 -72
  602. package/src/ui/field-row.ts +0 -249
  603. package/src/ui/formula-palette.ts +0 -213
  604. package/src/ui/icons.ts +0 -52
  605. package/src/ui/jx-theme.ts +0 -130
  606. package/src/ui/spectrum.ts +0 -340
  607. package/src/ui/value-selector.ts +0 -174
  608. package/src/ui/widgets.ts +0 -172
  609. /package/dist/chunks/{javascript-s56a8dpk.css → javascript-4abzjcy9.css} +0 -0
  610. /package/dist/chunks/{jsonMode-zr9sw0c7.css → jsonMode-vvmpmk34.css} +0 -0
  611. /package/dist/chunks/{monaco-setup-pav68602.css → monaco-setup-8vbyqnhr.css} +0 -0
  612. /package/dist/chunks/{tsMode-ef187txx.css → tsMode-hnxxb73h.css} +0 -0
@@ -29,6 +29,14 @@ interface BuildSystemPromptOptions {
29
29
  * prompt-shape tests — advertises the same list it always did.
30
30
  */
31
31
  treeEditable?: boolean | undefined;
32
+ /**
33
+ * The blurbs of the tools projected from command records this round —
34
+ * `services/ai-command-tools.ts`'s `commandToolBlurbs(activeRegistry())`. Rendered after the hand
35
+ * tools under every "Tools available right now" heading, one line each. Passed in rather than
36
+ * read here so this stays a pure function of its options: a caller that passes none sees the hand
37
+ * list it always did, and only `document-assistant.ts`, which holds the registry, adds them.
38
+ */
39
+ commandTools?: readonly string[] | undefined;
32
40
  /**
33
41
  * Whether the platform can import a site. Defaults TRUE so this stays a pure function of what it
34
42
  * is given — a caller that knows nothing about the platform gets the full list, and only
@@ -37,11 +45,32 @@ interface BuildSystemPromptOptions {
37
45
  canImport?: boolean | undefined;
38
46
  /** Project-relative file paths for the inventory section (project modes; capped). */
39
47
  fileInventory?: string[] | undefined;
48
+ /**
49
+ * What this backend can run, enabled or not.
50
+ *
51
+ * Passed in rather than read here, because it comes from the PLATFORM and this builder is a pure
52
+ * function of its options. Without it the model can only discover an extension by being told
53
+ * about one, which is how a request for a blog gets a hand-built Markdown pipeline instead of
54
+ * `@jxsuite/parser`.
55
+ */
56
+ extensionCatalog?: readonly ExtensionCatalogSummary[] | undefined;
57
+ }
58
+
59
+ /** One extension this backend can run — the prompt's view of a catalogue entry. */
60
+ export interface ExtensionCatalogSummary {
61
+ name: string;
62
+ title?: string | undefined;
63
+ description?: string | undefined;
64
+ /** `project.json` keys that become legal once it is enabled. */
65
+ sections?: readonly string[] | undefined;
40
66
  }
41
67
 
42
68
  /** Max file paths embedded in the prompt's inventory section. */
43
69
  const FILE_INVENTORY_CAP = 100;
44
70
 
71
+ /** Max catalogue entries listed in the prompt. */
72
+ const EXTENSION_CATALOG_CAP = 20;
73
+
45
74
  // ─── Tool tiers (single source of truth for prompt AND gating) ──────────────
46
75
 
47
76
  /** Studio state a tool tier requires. Used by the gating registry AND the prompt tool list. */
@@ -54,9 +83,14 @@ const FILE_INVENTORY_CAP = 100;
54
83
  * with Project Settings open, `project.json` drawn as a layer tree. The assistant's tier asked only
55
84
  * whether a tab existed, so in that exact state the agent was advertised `remove_node` and
56
85
  * `move_node` and executed them against the file that defines the project, while the human's
57
- * `delete_node` was refused. `remove_node` self-refuses only the document root (`path.length < 2`),
86
+ * `delete_node` was refused. `remove_node` self-refused only the document root (`path.length < 2`),
58
87
  * a weaker test than `structurallyEditable`, so a repeater template or `$switch` case was removable
59
- * by the agent and not by the person.
88
+ * by the agent and not by the person. A tier was the first fix; the second predicate went with
89
+ * `remove_node` itself, which is now `delete_node`, the projection of `selection.delete`
90
+ * (`services/ai-command-tools.ts`) — one record, one gate, and no tier row here at all.
91
+ *
92
+ * This union is the HAND table's vocabulary and nothing a record declares: a projected command's
93
+ * tier is derived from its `level` by the bridge.
60
94
  */
61
95
  export type AiToolTier = "always" | "no-project" | "project" | "document" | "document-tree";
62
96
 
@@ -76,9 +110,15 @@ export interface AiToolInfo {
76
110
  }
77
111
 
78
112
  /**
79
- * Every assistant tool with its availability tier and prompt blurb. document-assistant.ts derives
80
- * the gating predicates from the same rows, so the advertised tool list and the executable tool
81
- * list cannot drift (a test asserts the names match the registered tools).
113
+ * Every HAND-REGISTERED assistant tool with its availability tier and prompt blurb.
114
+ * document-assistant.ts derives the gating predicates from the same rows, so the advertised tool
115
+ * list and the executable tool list cannot drift (a test asserts the names match the registered
116
+ * tools, and that none is also a command record's projection).
117
+ *
118
+ * The other kind of tool is not here and must not be added here: a command record that declares
119
+ * `aiTool` is projected by `services/ai-command-tools.ts`, gated by the record's own `when` /
120
+ * `enablement`, and described by the record. `enable_extension`, `disable_extension`, `delete_node`
121
+ * (né `remove_node`) and `open_document` left this table for that one.
82
122
  */
83
123
  export const AI_TOOL_TIERS: AiToolInfo[] = [
84
124
  // Always — a question is not gated on what happens to be open
@@ -145,12 +185,8 @@ export const AI_TOOL_TIERS: AiToolInfo[] = [
145
185
  tier: "project",
146
186
  blurb: "create_page(path, content) — create a new .json page file on disk.",
147
187
  },
148
- {
149
- name: "open_document",
150
- tier: "project",
151
- blurb:
152
- "open_document(path) — open a file on the canvas as the active document; the document tools then operate on it. Use when the user should SEE the page, or for iterative visual refinement.",
153
- },
188
+ /* `open_document` is not a row: it is the projection of the `document.open` record
189
+ (`workspace/workspace.ts`), advertised by the record's own gate and described by the record. */
154
190
  // Document (an active document on the canvas)
155
191
  {
156
192
  name: "read_document",
@@ -181,11 +217,6 @@ export const AI_TOOL_TIERS: AiToolInfo[] = [
181
217
  blurb:
182
218
  "add_child(parentPath, index, node) — insert a new node into the children of parentPath at index.",
183
219
  },
184
- {
185
- name: "remove_node",
186
- tier: "document-tree",
187
- blurb: "remove_node(path) — remove the node at path.",
188
- },
189
220
  {
190
221
  name: "move_node",
191
222
  tier: "document-tree",
@@ -644,17 +675,24 @@ export function buildSystemPrompt({
644
675
  hasProject = Boolean(projectRoot),
645
676
  treeEditable = true,
646
677
  canImport = true,
678
+ commandTools = [],
647
679
  fileInventory,
680
+ extensionCatalog,
648
681
  }: BuildSystemPromptOptions = {}) {
649
682
  const hasDocument = Boolean(document);
650
683
 
651
684
  // 1. Role, state-appropriate workflow, and the tool list for the current state.
652
685
  // The list the model is TOLD about and the list the gate will honour are the same filter, so a
653
- // Refusal is never a surprise to it.
654
- const toolList = AI_TOOL_TIERS.filter((t) =>
655
- toolActive(t, { canImport, hasDocument, hasProject, treeEditable }),
656
- )
657
- .map((t) => `- ${t.blurb}`)
686
+ // Refusal is never a surprise to it. The command-projected tools arrive already filtered by
687
+ // Their records' own gates, for the same reason — one function answers both the prompt and the
688
+ // Executor (`advertisedCommandTools`).
689
+ const toolList = [
690
+ ...AI_TOOL_TIERS.filter((t) =>
691
+ toolActive(t, { canImport, hasDocument, hasProject, treeEditable }),
692
+ ).map((t) => t.blurb),
693
+ ...commandTools,
694
+ ]
695
+ .map((blurb) => `- ${blurb}`)
658
696
  .join("\n");
659
697
 
660
698
  const role = `You are an expert Jx builder assistant embedded in Jx Studio. You help users build websites, components, pages, and layouts using the Jx JSON schema. The live jxsuite.com marketing site is built entirely with Jx — you can produce production-quality Jx code.`;
@@ -722,7 +760,12 @@ Be concise. Don't explain what Jx is unless asked. Just build.`;
722
760
 
723
761
  // 6. Project context
724
762
  if (hasProject && (projectConfig || components || projectRoot)) {
725
- const projectSummary = buildProjectSummary({ projectConfig, components, projectRoot });
763
+ const projectSummary = buildProjectSummary({
764
+ components,
765
+ extensionCatalog,
766
+ projectConfig,
767
+ projectRoot,
768
+ });
726
769
  if (projectSummary) {
727
770
  sections.push(`## Project Context\n\n${projectSummary}`);
728
771
  }
@@ -744,7 +787,7 @@ Be concise. Don't explain what Jx is unless asked. Just build.`;
744
787
  If a tool call fails (returns { success: false }):
745
788
  1. Read the error message carefully — it includes a "→ Fix:" hint telling you exactly how to correct the error.
746
789
  2. Each error points to a specific path in the document and a specific rule violation.
747
- 3. Apply the suggested fix using set_property, remove_node, or add_child as appropriate.
790
+ 3. Apply the suggested fix using set_property, delete_node, or add_child as appropriate.
748
791
  4. Do NOT re-issue the exact same tool call with the same arguments — you must CHANGE something.
749
792
  5. If you see the SAME error after 2 attempts, try a completely different approach (e.g., remove and re-add the node instead of patching it).
750
793
 
@@ -762,7 +805,7 @@ If a tool call fails (returns { success: false }):
762
805
 
763
806
  ### If you keep getting errors:
764
807
  - Call read_document again — the document may have changed since you last read it.
765
- - Remove the problematic node entirely with remove_node, then re-create it correctly with add_child.
808
+ - Remove the problematic node entirely with delete_node, then re-create it correctly with add_child.
766
809
  - If the error message points to a different path than you expected, the node might have moved due to previous edits.`);
767
810
 
768
811
  return sections.join("\n\n---\n\n");
@@ -841,6 +884,7 @@ function buildProjectSummary({
841
884
  projectConfig,
842
885
  components,
843
886
  projectRoot,
887
+ extensionCatalog,
844
888
  }: Omit<BuildSystemPromptOptions, "document">) {
845
889
  const lines: string[] = [];
846
890
 
@@ -852,6 +896,13 @@ function buildProjectSummary({
852
896
  lines.push(`Root: ${projectRoot}`);
853
897
  }
854
898
 
899
+ /* One line, closing a gap that was pure oversight: this function has always received the whole
900
+ `projectConfig`, `extensions` included, and dropped it on the floor. */
901
+ const enabled = projectConfig?.extensions ?? [];
902
+ if (enabled.length > 0) {
903
+ lines.push(`Extensions enabled: ${enabled.join(", ")}`);
904
+ }
905
+
855
906
  // Available components — tag + purpose so the model can reuse them
856
907
  if (components && components.length > 0) {
857
908
  lines.push(`Available components (reuse these instead of rebuilding):`);
@@ -898,6 +949,43 @@ function buildProjectSummary({
898
949
  }
899
950
  }
900
951
 
952
+ /*
953
+ * The catalogue, last, so the design-token block keeps its prominence. The guidance names
954
+ * CAPABILITIES rather than packages on purpose: the capability-to-package mapping is what each
955
+ * entry's own description is for, and hardcoding "@jxsuite/parser" here would be a second,
956
+ * staler copy of the backend's answer.
957
+ */
958
+ if (extensionCatalog && extensionCatalog.length > 0) {
959
+ const enabledSet = new Set(enabled);
960
+ lines.push(
961
+ `Extensions available. Turn one on with enable_extension BEFORE writing the project.json ` +
962
+ `section it owns: a section belonging to a disabled extension is a schema error, and an ` +
963
+ `"extensions" entry whose package is not installed fails the build. When a request needs ` +
964
+ `a capability the core does not have (a blog or any folder of Markdown, a search box, a ` +
965
+ `feed, sign-ins, a database table), look for it below rather than hand-building it.`,
966
+ );
967
+ for (const entry of extensionCatalog.slice(0, EXTENSION_CATALOG_CAP)) {
968
+ const parts = [` ${entry.name}`];
969
+ if (entry.title) {
970
+ parts.push(` — ${entry.title}.`);
971
+ }
972
+ if (entry.description) {
973
+ parts.push(` ${entry.description}`);
974
+ }
975
+ if (entry.sections && entry.sections.length > 0) {
976
+ parts.push(` Contributes: ${entry.sections.join(", ")}.`);
977
+ }
978
+ if (enabledSet.has(entry.name)) {
979
+ parts.push(" [enabled]");
980
+ }
981
+ lines.push(parts.join(""));
982
+ }
983
+ if (extensionCatalog.length > EXTENSION_CATALOG_CAP) {
984
+ const more = extensionCatalog.length - EXTENSION_CATALOG_CAP;
985
+ lines.push(` … and ${more} more (open_settings { section: "extensions" })`);
986
+ }
987
+ }
988
+
901
989
  // Breakpoints — surfaced prominently so the model uses @--breakpoint responsive overrides
902
990
  if (projectConfig?.$media) {
903
991
  const breakpoints = Object.entries(projectConfig.$media)
@@ -12,15 +12,10 @@ import { createToolDefinition } from "@jxsuite/ai/tools";
12
12
  import type { ToolRegistry, ToolResult } from "@jxsuite/ai/tools";
13
13
  import type { JxMutableNode, JxPath, JxStateDefinition } from "@jxsuite/schema/types";
14
14
  import { getNodeAtPath } from "../state";
15
- import { toRaw } from "../reactivity";
16
15
  import type { Tab } from "../tabs/tab";
17
16
  import {
18
- beginBatch,
19
- endBatch,
20
- isBatching,
21
17
  mutateInsertNode,
22
18
  mutateMoveNode,
23
- mutateRemoveNode,
24
19
  mutateUpdateProperty,
25
20
  mutateUpdateStyle,
26
21
  transactDoc,
@@ -28,7 +23,18 @@ import {
28
23
  import type { JxNodeValue } from "../tabs/transact";
29
24
  import { validateDoc } from "./jx-validate";
30
25
  import { recordWrite } from "./ai-writes";
31
- import { flagHardcodedTokens, formatTokenHints } from "./token-lint";
26
+ import { serializeJson } from "../files/json-layout";
27
+ import {
28
+ reportDocumentWrite,
29
+ snapshotBeforeWrite,
30
+ translateValidationError,
31
+ } from "./ai-write-report";
32
+ import type { RenderVerdict } from "./ai-write-report";
33
+
34
+ /* Re-exported from its new home so `ai-project-tools.ts` and the tests keep their import: the
35
+ translation moved with the verdict it belongs to (`ai-write-report.ts`), where every document
36
+ write — hand-registered or projected from a command record — now reads it. */
37
+ export { translateValidationError } from "./ai-write-report";
32
38
 
33
39
  const PATH_DESCRIPTION =
34
40
  "Path to a node in the document, as a JSON array of keys/indices from the root " +
@@ -45,74 +51,17 @@ function noDocError(): ToolResult {
45
51
  }
46
52
 
47
53
  /**
48
- * Translate a raw JSON Schema validation error into a Jx-specific actionable message. The LLM needs
49
- * concrete guidance on HOW to fix errors, not just what rule was violated. Shared with the
50
- * project-level file tools (ai-project-tools.ts), which pre-validate Jx documents before writing.
51
- *
52
- * @param {string} rawError - Message from ajv (e.g. "/children/0/style: must NOT have additional
53
- * property")
54
- * @returns {string}
55
- */
56
- export function translateValidationError(rawError: string): string {
57
- const lower = rawError.toLowerCase();
58
-
59
- // Additional property — extract the offending key from the message if present
60
- if (
61
- lower.includes("must not have additional property") ||
62
- lower.includes("additional properties")
63
- ) {
64
- return `${rawError}\n → Fix: Remove or move the unexpected property. Style properties must be camelCase (e.g. "backgroundColor", not "background-color"). Non-IDL HTML attributes (aria-*, data-*, role, ...) must go inside an "attributes" object: { "attributes": { "aria-label": "..." } }.`;
65
- }
66
-
67
- // Pattern — usually tagName hyphen rule
68
- if (lower.includes("must match pattern")) {
69
- return `${rawError}\n → Fix: Custom element tag names must contain a hyphen (e.g. "newsletter-form", "feature-card"). Standard HTML elements use their exact name (e.g. "div", "input", "button").`;
70
- }
71
-
72
- // Type error
73
- if (lower.includes("must be string")) {
74
- return `${rawError}\n → Fix: Wrap the value in quotes — all Jx property values should be strings. For example, use "10px" (string) not 10px (unquoted).`;
75
- }
76
-
77
- if (lower.includes("must be number") || lower.includes("must be integer")) {
78
- return `${rawError}\n → Fix: Remove quotes from the numeric value — it should be a plain number, not a string.`;
79
- }
80
-
81
- if (lower.includes("must be object") || lower.includes("must be array")) {
82
- return `${rawError}\n → Fix: The value must be an object/array (use {} or []), not a string or number.`;
83
- }
84
-
85
- if (lower.includes("must be boolean")) {
86
- return `${rawError}\n → Fix: Use true or false without quotes for boolean values.`;
87
- }
88
-
89
- // Required property
90
- if (lower.includes("must have required property")) {
91
- return `${rawError}\n → Fix: Add the missing required property. Every Jx element must have at least a "tagName" field.`;
92
- }
93
-
94
- // Enum / allowed values
95
- if (lower.includes("must be equal to one of the allowed values")) {
96
- return `${rawError}\n → Fix: Change the value to one of the allowed options listed in the error.`;
97
- }
98
-
99
- return rawError;
100
- }
101
-
102
- /**
103
- * Apply a mutation, then validate the document and report only the schema errors the edit newly
104
- * introduced (the eval signal — ADR §6b). The change stays applied either way (optimistic apply +
105
- * undo, ADR §5); reporting the errors lets the agent loop self-correct on the next round.
106
- *
107
- * When a renderCheck function is provided, a second gate runs after schema validation passes: the
108
- * mutated document is rendered in a detached DOM context and any render-time throws are surfaced as
109
- * tool errors (same contract as schema errors).
54
+ * Apply a mutation, then hand the verdict to `ai-write-report.ts`: only the schema errors the edit
55
+ * NEWLY introduced are reported (the eval signal — ADR §6b), the render check runs when a
56
+ * renderCheck was provided and rendering worked before, and a success carries the token hints. The
57
+ * change stays applied either way (optimistic apply + undo, ADR §5); reporting the errors lets the
58
+ * agent loop self-correct on the next round.
110
59
  *
111
60
  * @param {import("../tabs/tab").Tab} tab
112
61
  * @param {(t: import("../tabs/tab").Tab) => void} mutationFn
113
62
  * @param {string} summary
114
63
  * @param {(doc: unknown) => Promise<string[]>} validate
115
- * @param {((doc: unknown) => Promise<{ ok: true } | { ok: false; error: string }>) | undefined} renderCheck
64
+ * @param {((doc: unknown) => Promise<RenderVerdict>) | undefined} renderCheck
116
65
  * @param {Record<string, string> | undefined} projectStyle
117
66
  * @returns {Promise<import("@jxsuite/ai/tools").ToolResult>}
118
67
  */
@@ -121,12 +70,11 @@ async function applyAndValidate(
121
70
  mutationFn: (t: Tab) => void,
122
71
  summary: string,
123
72
  validate: (doc: unknown) => Promise<string[]>,
124
- renderCheck: ((doc: unknown) => Promise<{ ok: true } | { ok: false; error: string }>) | undefined,
73
+ renderCheck: ((doc: unknown) => Promise<RenderVerdict>) | undefined,
125
74
  projectStyle: Record<string, string> | undefined,
126
75
  ): Promise<ToolResult> {
127
- const rawBefore = toRaw(tab.doc.document);
128
- const before = new Set(await validate(rawBefore));
129
- const renderOkBefore = renderCheck ? await renderCheck(rawBefore) : { ok: true };
76
+ const deps = { getProjectStyle: () => projectStyle, renderCheck, validate };
77
+ const before = await snapshotBeforeWrite(tab, deps);
130
78
 
131
79
  /* AND THE WRITE CAN BE REFUSED, in which case the model must be told rather than congratulated.
132
80
  The collab gate pauses structural editing while source is canonical, and this went on to
@@ -147,37 +95,7 @@ async function applyAndValidate(
147
95
  went through transactDoc, so the tab's history — and "Restore to here" — can reach it. */
148
96
  recordWrite({ disk: false, ok: true, path: tab.documentPath ?? "(untitled)", tool: summary });
149
97
 
150
- const rawAfter = toRaw(tab.doc.document);
151
- const after = await validate(rawAfter);
152
- const newErrors = after.filter((e) => !before.has(e));
153
- if (newErrors.length > 0) {
154
- const formatted = newErrors.map((e) => `- ${translateValidationError(e)}`).join("\n");
155
- return {
156
- success: false,
157
- error: `Change applied, but it introduced schema errors. Fix these issues with follow-up edits:\n${formatted}`,
158
- };
159
- }
160
-
161
- if (renderCheck && renderOkBefore.ok) {
162
- const renderResult = await renderCheck(rawAfter);
163
- if (!renderResult.ok) {
164
- return {
165
- success: false,
166
- error: `Change applied and schema-valid, but it broke rendering. Fix with follow-up edits:\n- ${renderResult.error}`,
167
- };
168
- }
169
- }
170
-
171
- // Soft token-discipline hints (never fail the mutation)
172
- if (projectStyle) {
173
- const findings = flagHardcodedTokens(rawAfter, projectStyle);
174
- const hints = formatTokenHints(findings);
175
- if (hints) {
176
- return { success: true, summary: `${summary}\n\n${hints}` };
177
- }
178
- }
179
-
180
- return { success: true, summary };
98
+ return reportDocumentWrite(tab, before, summary, deps);
181
99
  }
182
100
 
183
101
  /**
@@ -189,7 +107,6 @@ async function applyAndValidate(
189
107
  * validate?: (doc: unknown) => Promise<string[]>;
190
108
  * saveFile?: (relPath: string, content: string) => Promise<void>;
191
109
  * renderCheck?: (doc: unknown) => Promise<{ ok: true } | { ok: false; error: string }>;
192
- * openDocument?: (path: string) => Promise<void>;
193
110
  * projectStyle?: Record<string, string>;
194
111
  * getProjectStyle?: () => Record<string, string> | undefined;
195
112
  * findOpenTab?: (path: string) => import("../tabs/tab").Tab | null;
@@ -203,7 +120,6 @@ export function registerAiTools(
203
120
  validate = validateDoc,
204
121
  saveFile,
205
122
  renderCheck,
206
- openDocument,
207
123
  projectStyle,
208
124
  getProjectStyle,
209
125
  findOpenTab,
@@ -213,7 +129,6 @@ export function registerAiTools(
213
129
  validate?: (doc: unknown) => Promise<string[]>;
214
130
  saveFile?: (relPath: string, content: string) => Promise<void>;
215
131
  renderCheck?: (doc: unknown) => Promise<{ ok: true } | { ok: false; error: string }>;
216
- openDocument?: (path: string) => Promise<void>;
217
132
  projectStyle?: Record<string, string> | undefined;
218
133
  /**
219
134
  * Live variant of `projectStyle` — takes precedence; re-read per tool call so a project
@@ -258,7 +173,7 @@ export function registerAiTools(
258
173
  name: "read_document",
259
174
  description:
260
175
  "Read the current Jx document, or the subtree at a given path. Use this to discover " +
261
- "node paths before calling set_property, add_child, or remove_node.",
176
+ "node paths before calling set_property, add_child, or delete_node.",
262
177
  parameters: {
263
178
  type: "object",
264
179
  properties: {
@@ -751,7 +666,9 @@ export function registerAiTools(
751
666
  }
752
667
  }
753
668
  try {
754
- await saveFile(relPath, JSON.stringify(content, null, 2));
669
+ // The save serializer, layout-less (`files/json-layout.ts`): the assistant supplied a
670
+ // Value, not a text, so the formatter's layout for fresh output is the right one.
671
+ await saveFile(relPath, serializeJson(content, null));
755
672
  recordWrite({ disk: true, ok: true, path: relPath, tool: "create_component" });
756
673
  return {
757
674
  success: true,
@@ -828,7 +745,8 @@ export function registerAiTools(
828
745
  }
829
746
  }
830
747
  try {
831
- await saveFile(relPath, JSON.stringify(content, null, 2));
748
+ // As `create_component`: a value the assistant supplied, written in the formatter's layout.
749
+ await saveFile(relPath, serializeJson(content, null));
832
750
  recordWrite({ disk: true, ok: true, path: relPath, tool: "create_page" });
833
751
  return {
834
752
  success: true,
@@ -852,106 +770,12 @@ export function registerAiTools(
852
770
  }),
853
771
  );
854
772
 
855
- // ── open_document ─────────────────────────────────────────────────────
856
-
857
- registry.register(
858
- createToolDefinition({
859
- name: "open_document",
860
- description:
861
- "Switch the active document to another file in the project. After opening, all " +
862
- "tools (read_document, set_property, add_child, etc.) operate on the newly-active " +
863
- "document. Use this to iteratively refine pages or components after creating them " +
864
- "with create_page or create_component.",
865
- parameters: {
866
- type: "object",
867
- properties: {
868
- path: {
869
- type: "string",
870
- description:
871
- 'File path relative to the project root, e.g. "pages/about.json" or ' +
872
- '"components/nav-bar.json". Must be an existing file.',
873
- },
874
- },
875
- required: ["path"],
876
- },
877
- async execute(args) {
878
- if (!openDocument) {
879
- return {
880
- success: false,
881
- error: "File navigation is not available in this environment.",
882
- };
883
- }
884
- const { path: relPath } = args as { path: string };
885
- try {
886
- await openDocument(relPath);
887
- const tab = getTab();
888
- if (!tab) {
889
- return {
890
- success: false,
891
- error: `File "${relPath}" could not be opened — no active tab after navigation.`,
892
- };
893
- }
894
- /*
895
- * The agent loop opens a single undo batch on the tab that was active at loop start
896
- * (tool-executor.js → beginBatch). Switching the active document mid-loop would strand
897
- * the new tab's edits with no history snapshot — undo would have nothing to roll back.
898
- * Flush the previous tab's batch and re-open one on the newly-active tab so edits in
899
- * each document remain individually undoable.
900
- */
901
- if (isBatching()) {
902
- endBatch();
903
- beginBatch(tab);
904
- }
905
- return {
906
- success: true,
907
- summary: `Switched to "${relPath}". All tools now operate on this document.`,
908
- };
909
- } catch (error) {
910
- return {
911
- success: false,
912
- error: `Failed to open "${relPath}": ${error instanceof Error ? error.message : String(error)}`,
913
- };
914
- }
915
- },
916
- }),
917
- );
918
-
919
- registry.register(
920
- createToolDefinition({
921
- name: "remove_node",
922
- description: "Remove the node at the given path from its parent's children array.",
923
- parameters: {
924
- type: "object",
925
- properties: {
926
- path: {
927
- type: "array",
928
- description: `${PATH_DESCRIPTION} Cannot be the document root.`,
929
- items: { type: ["string", "number"] },
930
- },
931
- },
932
- required: ["path"],
933
- },
934
- async execute(args) {
935
- const tab = getTab();
936
- if (!tab) {
937
- return noDocError();
938
- }
939
- const { path } = args as { path: JxPath };
940
- if (path.length < 2) {
941
- return { success: false, error: "Cannot remove the document root." };
942
- }
943
- if (getNodeAtPath(tab.doc.document, path) === undefined) {
944
- return { success: false, error: `No node exists at path ${JSON.stringify(path)}.` };
945
- }
946
- return applyAndValidate(
947
- tab,
948
- (t) => mutateRemoveNode(t, path),
949
- `Removed node at ${JSON.stringify(path)}.`,
950
- validate,
951
- renderCheck,
952
- styleOf(),
953
- );
954
- },
955
- }),
956
- );
773
+ /*
774
+ * `open_document` is NOT here any more. It is the projection of the `document.open` record
775
+ * (`workspace/workspace.ts`'s `tabCommands`), so the person's palette row and the model's tool
776
+ * are one `run` and one gate (§12.4). The hand tool read `getTab()` after the open and called
777
+ * whatever it found a success — a missing file left the previous document active and reported
778
+ * "Switched to" — and it re-anchored the undo batch itself, which `tool-executor.ts` has done
779
+ * after EVERY tool since project adoption started replacing tabs mid-loop.
780
+ */
957
781
  }