@jxsuite/studio 4.1.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/data/elements-meta.json +5 -15
- package/data/html-meta.json +51 -6
- package/dist/chunks/{2020-n6tfwnda.js → 2020-g79n01v9.js} +14 -14
- package/dist/chunks/action-group-sp6tna8v.js +118 -0
- package/dist/chunks/adapter-nj7tnjfn.js +13 -0
- package/dist/chunks/cf-account-picker-fyf63pmy.js +495 -0
- package/dist/chunks/cf-settings-71bv5zn9.js +20 -0
- package/dist/chunks/color-area-v17df7b8.js +154 -0
- package/dist/chunks/color-field-anwybnkn.js +208 -0
- package/dist/chunks/color-slider-44ez96fc.js +79 -0
- package/dist/chunks/color-xgg3kfw7.js +35 -0
- package/dist/chunks/combobox-5e7jev23.js +236 -0
- package/dist/chunks/components-2w1f35qs.js +18 -0
- package/dist/chunks/content-source-3wqeas45.js +46 -0
- package/dist/chunks/convert-to-repeater-d0cgnb6d.js +639 -0
- package/dist/chunks/dialog-s890b918.js +85 -0
- package/dist/chunks/editor-3qhbg51x.js +35 -0
- package/dist/chunks/entry-commands-d6g50j7s.js +42 -0
- package/dist/chunks/extension-sections-fy7q4fe9.js +651 -0
- package/dist/chunks/file-ops-3btj6st0.js +47 -0
- package/dist/chunks/files-ef8fgs3w.js +72 -0
- package/dist/chunks/format-host-3c33nwr8.js +40 -0
- package/dist/chunks/fs-events-13tj6sex.js +18 -0
- package/dist/chunks/git-panel-4wp2rn9b.js +49 -0
- package/dist/chunks/icons-yy10wk9r.js +402 -0
- package/dist/chunks/iframe-entry-15g3n6xv.js +114 -0
- package/dist/chunks/iframe-entry-b27vq81n.js +203 -0
- package/dist/chunks/iframe-entry-nbyxee1y.js +154 -0
- package/dist/chunks/iframe-host-jgesd924.js +115 -0
- package/dist/chunks/{index-wcnt3r9g.js → index-mdmyx6s2.js} +11 -11
- package/dist/chunks/index-n4j7qxyr.js +109 -0
- package/dist/chunks/{javascript-q8kpmfah.js → javascript-xvrfrpkb.js} +8 -9
- package/dist/chunks/{jsonMode-dkr040ga.js → jsonMode-tyx2kj6p.js} +526 -527
- package/dist/chunks/jx-validate-j0wxk72w.js +15 -0
- package/dist/chunks/layers-1nq5evsh.js +29 -0
- package/dist/chunks/layers-panel-ar2gh90g.js +40 -0
- package/dist/chunks/listbox-6v2ac08j.js +44 -0
- package/dist/chunks/lit-html-m244w9nh.js +17 -0
- package/dist/chunks/media-picker-2qbetq73.js +33 -0
- package/dist/chunks/menu-q99sy9rf.js +285 -0
- package/dist/chunks/menu-rf7n72mf.js +14 -0
- package/dist/chunks/{monaco-binding-rj6xpx9y.js → monaco-binding-sw6en4dw.js} +12 -15
- package/dist/chunks/monaco-buffer-bhy3hb6m.js +24 -0
- package/dist/chunks/{monaco-setup-vx9bhp1d.js → monaco-setup-8r62fj6y.js} +27 -37
- package/dist/chunks/notify-628t0anh.js +21 -0
- package/dist/chunks/number-field-5cndyft8.js +72 -0
- package/dist/chunks/parse-0zx14y15.js +10 -0
- package/dist/chunks/platform-ts9cg1a4.js +15 -0
- package/dist/chunks/popover-47z3ytva.js +25 -0
- package/dist/chunks/publish-panel-98f7sr3g.js +27 -0
- package/dist/chunks/quick-search-srzz83k2.js +45 -0
- package/dist/chunks/references-n553f0e1.js +26 -0
- package/dist/chunks/right-panel-rrgx2dn3.js +45 -0
- package/dist/chunks/section-registry-5pq32t0q.js +25 -0
- package/dist/chunks/select-2r16ez41.js +49 -0
- package/dist/chunks/split-g7nm1rgb.js +191 -0
- package/dist/chunks/studio-0hqbpbd0.js +62 -0
- package/dist/chunks/studio-18avnhjp.js +2430 -0
- package/dist/chunks/{studio-kryvsw6j.js → studio-1k325pwf.js} +48 -48
- package/dist/chunks/{studio-msd847zn.js → studio-25hkdrkw.js} +357 -86
- package/dist/chunks/studio-26d7myd1.js +258 -0
- package/dist/chunks/{studio-4r1pv6zf.js → studio-38emantv.js} +22 -5
- package/dist/chunks/studio-3gxv60tn.js +422 -0
- package/dist/chunks/{studio-fbf92ckf.js → studio-3hxkd92t.js} +275 -163
- package/dist/chunks/studio-4m0haseg.js +185 -0
- package/dist/chunks/{studio-ynxwkrzd.js → studio-4wbb9ct0.js} +1953 -1785
- package/dist/chunks/{studio-1wagb550.js → studio-5523bpzt.js} +11 -11
- package/dist/chunks/{studio-x4qkdat5.js → studio-57mf66w2.js} +1749 -2481
- package/dist/chunks/studio-5jy81t3s.js +17463 -0
- package/dist/chunks/studio-5rt7sqa0.js +1168 -0
- package/dist/chunks/studio-5te5tqng.js +81 -0
- package/dist/chunks/{studio-p4ngc046.js → studio-6ewqv390.js} +9 -9
- package/dist/chunks/{studio-9ab8gqsm.js → studio-6nzaktvy.js} +7 -7
- package/dist/chunks/studio-6xa21ej9.js +28 -0
- package/dist/chunks/{studio-5ehhackm.js → studio-727xh0e3.js} +19 -19
- package/dist/chunks/{studio-ahn3pdgx.js → studio-79y5sz51.js} +52 -38
- package/dist/chunks/{studio-gcye7qka.js → studio-7e11jpa9.js} +21 -21
- package/dist/chunks/{studio-q7v10cg2.js → studio-7r42c6ca.js} +17 -7
- package/dist/chunks/studio-7xptrg0j.js +954 -0
- package/dist/chunks/{studio-cft9r4r7.js → studio-81390n6f.js} +22 -22
- package/dist/chunks/{studio-q43a5y9h.js → studio-8jn5yhyn.js} +16 -16
- package/dist/chunks/studio-8qtrpzr3.js +839 -0
- package/dist/chunks/{studio-dg7zyt5x.js → studio-98b3z07n.js} +1 -1
- package/dist/chunks/studio-9xxz1q69.js +1356 -0
- package/dist/chunks/studio-akbww0j5.js +13615 -0
- package/dist/chunks/{studio-x813zp48.js → studio-arfpe389.js} +30 -30
- package/dist/chunks/{studio-trxrabqf.js → studio-az3zd49t.js} +475 -283
- package/dist/chunks/studio-cpvb2ed1.js +1171 -0
- package/dist/chunks/{studio-f3wqjtk5.js → studio-d0300636.js} +5076 -18
- package/dist/chunks/{studio-bgxt93ga.js → studio-d055c37e.js} +13 -13
- package/dist/chunks/studio-d1ja2x9r.js +362 -0
- package/dist/chunks/{studio-b9b6t1dg.js → studio-e1f24eff.js} +5664 -5666
- package/dist/chunks/{studio-3bqpr0zh.js → studio-em9nw8eh.js} +299 -110
- package/dist/chunks/studio-erdatzvp.js +1190 -0
- package/dist/chunks/{studio-g1wdche0.js → studio-esrxgwh6.js} +80 -80
- package/dist/chunks/studio-fabxk6r9.js +2811 -0
- package/dist/chunks/{studio-3n4ndrzh.js → studio-h4nvnjvz.js} +303 -303
- package/dist/chunks/{studio-dm19q43r.js → studio-hhvs4sdg.js} +10 -10
- package/dist/chunks/{studio-q9jd1a60.js → studio-kcgff4r0.js} +15 -18
- package/dist/chunks/{studio-685s0ytq.js → studio-nqgawfks.js} +572 -572
- package/dist/chunks/{studio-xrapxwwc.js → studio-p1dw8wfw.js} +55 -29
- package/dist/chunks/studio-pm6hgy7r.js +4763 -0
- package/dist/chunks/studio-q0a3yk4n.js +33 -0
- package/dist/chunks/{studio-wcy8trfx.js → studio-q3x06vmj.js} +23 -22
- package/dist/chunks/studio-qahxvnan.js +111 -0
- package/dist/chunks/{studio-53n8bp04.js → studio-r6xmmtfh.js} +1 -1
- package/dist/chunks/{studio-2b946z26.js → studio-rkstz940.js} +3658 -6134
- package/dist/chunks/{studio-tvgyw9xw.js → studio-rnyf3f8e.js} +83 -250
- package/dist/chunks/studio-rpyah2ew.js +2805 -0
- package/dist/chunks/studio-rs76k67r.js +12 -0
- package/dist/chunks/{studio-jkftxyvz.js → studio-s6z853aq.js} +5858 -2152
- package/dist/chunks/{studio-6yw4y3my.js → studio-sgdc5pfc.js} +8 -8
- package/dist/chunks/studio-tb3ev01j.js +763 -0
- package/dist/chunks/{studio-t5wqwzdh.js → studio-tjjk7jvk.js} +1 -1
- package/dist/chunks/studio-vhv5tgxm.js +51 -0
- package/dist/chunks/{studio-qjy2z9bv.js → studio-vz68yn9e.js} +32 -137
- package/dist/chunks/studio-wqpngpsk.js +174 -0
- package/dist/chunks/{studio-b55y6ewx.js → studio-x3rty6tr.js} +58 -58
- package/dist/chunks/studio-xsykpvsh.js +8448 -0
- package/dist/chunks/{studio-92ab2jqe.js → studio-y9zedyjn.js} +14 -14
- package/dist/chunks/studio-yxa81f45.js +12 -0
- package/dist/chunks/swatch-group-t0n6h2rn.js +139 -0
- package/dist/chunks/tabs-wbp1cdws.js +156 -0
- package/dist/chunks/textfield-abk6qyee.js +73 -0
- package/dist/chunks/toast-780pvfbv.js +27 -0
- package/dist/chunks/toast-host-3sqv46sn.js +116 -0
- package/dist/chunks/toolbar-xbh5bhtr.js +194 -0
- package/dist/chunks/tooltip-eptb614w.js +369 -0
- package/dist/chunks/tree-a73p0pqm.js +367 -0
- package/dist/chunks/{tsMode-76kr53q0.js → tsMode-jy4m86rv.js} +83 -85
- package/dist/chunks/workspace-wrew8zk4.js +69 -0
- package/dist/chunks/{ws-client-6shc5rze.js → ws-client-ny4zc51r.js} +20 -22
- package/dist/iframe-entry.js +1780 -667
- package/dist/studio.js +52819 -36480
- package/dist/workers/editor.worker.js +1040 -1085
- package/dist/workers/json.worker.js +1946 -1991
- package/dist/workers/ts.worker.js +4960 -5005
- package/index.html +1 -0
- package/package.json +18 -52
- package/src/about/about-modal.ts +72 -123
- package/src/browse/library-commands.ts +20 -49
- package/src/browse/library-layouts.ts +87 -218
- package/src/browse/library-pane.ts +406 -438
- package/src/canvas/canvas-helpers.ts +0 -49
- package/src/canvas/canvas-live-render.ts +25 -2
- package/src/canvas/canvas-render.ts +666 -231
- package/src/canvas/canvas-surface.ts +0 -1
- package/src/canvas/canvas-utils.ts +310 -117
- package/src/canvas/dialog-path.ts +76 -0
- package/src/canvas/dialog-state.ts +67 -0
- package/src/canvas/diff-marks.ts +252 -0
- package/src/canvas/diff-toolbar.ts +349 -0
- package/src/canvas/diff-view.ts +123 -0
- package/src/canvas/edit-width-drag.ts +187 -0
- package/src/canvas/edit-width.ts +150 -0
- package/src/canvas/iframe-entry.ts +125 -8
- package/src/canvas/iframe-host.ts +271 -15
- package/src/canvas/iframe-interaction.ts +133 -13
- package/src/canvas/iframe-patch.ts +7 -1
- package/src/canvas/iframe-position.ts +5 -6
- package/src/canvas/iframe-protocol.ts +106 -5
- package/src/canvas/iframe-render.ts +373 -5
- package/src/canvas/iframe-slash.ts +2 -2
- package/src/canvas/iframe-subtree.ts +5 -8
- package/src/canvas/path-mapping.ts +25 -3
- package/src/canvas/popover-path.ts +106 -0
- package/src/canvas/popover-state.ts +155 -0
- package/src/canvas/surface-registry.ts +21 -10
- package/src/collab/presence-chips.ts +51 -73
- package/src/commands/app-commands.ts +10 -0
- package/src/commands/budget.ts +12 -0
- package/src/commands/command-args.ts +369 -6
- package/src/commands/defaults.ts +44 -14
- package/src/commands/live-context.ts +11 -5
- package/src/commands/reference.ts +12 -2
- package/src/commands/registry.ts +165 -8
- package/src/content/entry-commands.ts +16 -23
- package/src/content/entry-editor.ts +144 -101
- package/src/editor/canvas-slash-bridge.ts +2 -2
- package/src/editor/context-menu.ts +49 -200
- package/src/editor/convert-to-component.ts +42 -82
- package/src/editor/convert-to-repeater.ts +132 -173
- package/src/editor/inline-edit.ts +11 -0
- package/src/editor/shortcuts.ts +65 -26
- package/src/editor/slash-menu.ts +150 -157
- package/src/files/file-ops.ts +117 -11
- package/src/files/files.ts +943 -660
- package/src/files/json-layout.ts +474 -0
- package/src/files/serialize-document.ts +8 -1
- package/src/format/convert-file.ts +16 -10
- package/src/format/format-host.ts +50 -1
- package/src/github/github-auth.ts +71 -29
- package/src/github/github-publish.ts +57 -65
- package/src/grid/cell-editors.ts +46 -4
- package/src/grid/cell-popovers.ts +65 -62
- package/src/grid/grid-open.ts +86 -64
- package/src/grid/grid-panel.ts +390 -469
- package/src/grid/redirects-grid.ts +40 -44
- package/src/hosting/layout.ts +2 -0
- package/src/i18n/i18n-commands.ts +127 -62
- package/src/media/media-pane.ts +83 -133
- package/src/new-project/add-repo-modal.ts +125 -176
- package/src/new-project/import-tab.ts +181 -252
- package/src/new-project/location-fields.ts +93 -160
- package/src/new-project/new-project-modal.ts +376 -367
- package/src/packages/jxsuite-update.ts +76 -18
- package/src/panels/activity-panel.ts +137 -104
- package/src/panels/ai-chat/chat-markdown.ts +15 -13
- package/src/panels/ai-chat/chat-view.ts +307 -472
- package/src/panels/ai-chat/composer.ts +175 -163
- package/src/panels/ai-chat/sessions-view.ts +31 -62
- package/src/panels/ai-panel.ts +210 -185
- package/src/panels/block-action-bar.ts +437 -643
- package/src/panels/bottom-dock.ts +112 -47
- package/src/panels/chat-panel.ts +19 -14
- package/src/panels/data-explorer.ts +141 -102
- package/src/panels/data-grid.ts +183 -150
- package/src/panels/dnd.ts +75 -20
- package/src/panels/editors.ts +26 -19
- package/src/panels/elements-panel.ts +243 -186
- package/src/panels/empty-state.ts +26 -42
- package/src/panels/events-panel.ts +950 -729
- package/src/panels/formula-workspace.ts +434 -207
- package/src/panels/frontmatter-fields.ts +185 -153
- package/src/panels/frontmatter-panel.ts +411 -187
- package/src/panels/git-diff-open.ts +148 -0
- package/src/panels/git-panel.ts +679 -605
- package/src/panels/head-panel.ts +617 -435
- package/src/panels/i18n-panel.ts +153 -133
- package/src/panels/imports-panel.ts +388 -414
- package/src/panels/jump-bar.ts +174 -147
- package/src/panels/layers-panel.ts +785 -671
- package/src/panels/left-panel.ts +166 -94
- package/src/panels/navigator-panels.ts +1 -1
- package/src/panels/pane-context.ts +529 -677
- package/src/panels/pane-grid.ts +265 -241
- package/src/panels/panel-registry.ts +15 -4
- package/src/panels/problems-panel.ts +177 -99
- package/src/panels/properties-panel.ts +1525 -966
- package/src/panels/provenance.ts +31 -113
- package/src/panels/quick-search.ts +217 -172
- package/src/panels/right-panel.ts +135 -169
- package/src/panels/seo-modal.ts +346 -167
- package/src/panels/settings-menu.ts +109 -646
- package/src/panels/settings-pane.ts +102 -86
- package/src/panels/signals-panel.ts +1318 -1172
- package/src/panels/statement-editor.ts +556 -428
- package/src/panels/style-panel.ts +1367 -630
- package/src/panels/style-utils.ts +36 -32
- package/src/panels/stylebook-doc.ts +30 -73
- package/src/panels/stylebook-layers-panel.ts +202 -109
- package/src/panels/stylebook-panel.ts +124 -88
- package/src/panels/tab-strip.ts +385 -287
- package/src/platforms/cloud.ts +106 -16
- package/src/platforms/devserver.ts +13 -0
- package/src/publish/deploy-checklist.ts +124 -78
- package/src/publish/publish-commands.ts +4 -12
- package/src/publish/publish-panel.ts +134 -328
- package/src/services/a11y-report.ts +100 -43
- package/src/services/ai-command-tools.ts +468 -0
- package/src/services/ai-session-store.ts +6 -0
- package/src/services/ai-system-prompt.ts +110 -18
- package/src/services/ai-tools.ts +28 -143
- package/src/services/ai-write-report.ts +174 -0
- package/src/services/document-assistant.ts +50 -2
- package/src/services/idle.ts +16 -14
- package/src/services/live-surfaces.ts +237 -0
- package/src/services/model-uri.ts +75 -0
- package/src/services/notify.ts +63 -6
- package/src/services/popover-report.ts +325 -0
- package/src/services/surface-registry.ts +56 -0
- package/src/services/tool-executor.ts +6 -0
- package/src/settings/contexts-section.ts +301 -299
- package/src/settings/contributed-section.ts +361 -222
- package/src/settings/css-vars-editor.ts +320 -325
- package/src/settings/defs-editor.ts +572 -535
- package/src/settings/dependencies-editor.ts +79 -107
- package/src/settings/extension-commands.ts +379 -0
- package/src/settings/extension-rows.ts +113 -0
- package/src/settings/extensions-section.ts +287 -0
- package/src/settings/general-settings.ts +130 -181
- package/src/settings/head-editor.ts +10 -305
- package/src/settings/locales-section.ts +146 -196
- package/src/settings/preferences-accounts.ts +1 -1
- package/src/settings/preferences-dialog.ts +350 -330
- package/src/settings/project-sections.ts +108 -181
- package/src/settings/schema-field-ui.ts +11 -399
- package/src/settings/section-registry.ts +8 -1
- package/src/settings/settings-document.ts +31 -29
- package/src/shell/tree.ts +42 -87
- package/src/shell.ts +48 -36
- package/src/studio.ts +90 -67
- package/src/style/token-ref.ts +0 -39
- package/src/surfaces/about.json +263 -0
- package/src/surfaces/about.ts +163 -0
- package/src/surfaces/add-repo.json +486 -0
- package/src/surfaces/add-repo.ts +236 -0
- package/src/surfaces/ai-chat.json +2185 -0
- package/src/surfaces/ai-chat.ts +549 -0
- package/src/surfaces/ai-credentials-form.json +332 -0
- package/src/surfaces/ai-credentials-form.ts +151 -0
- package/src/surfaces/ai-managed-connect.json +108 -0
- package/src/surfaces/ai-managed-connect.ts +123 -0
- package/src/surfaces/ai-model-picker.json +114 -0
- package/src/surfaces/ai-model-picker.ts +139 -0
- package/src/surfaces/block-action-bar.json +640 -0
- package/src/surfaces/block-action-bar.ts +368 -0
- package/src/surfaces/bottom-dock.json +154 -0
- package/src/surfaces/bottom-dock.ts +125 -0
- package/src/surfaces/canvas-stage.json +444 -0
- package/src/surfaces/canvas-stage.ts +253 -0
- package/src/surfaces/cf-account-picker.json +300 -0
- package/src/surfaces/cf-account-picker.ts +214 -0
- package/src/surfaces/commandbar.json +984 -0
- package/src/{panels/toolbar.ts → surfaces/commandbar.ts} +414 -389
- package/src/surfaces/convert-repeater.json +309 -0
- package/src/surfaces/convert-repeater.ts +276 -0
- package/src/surfaces/data-actions.json +157 -0
- package/src/surfaces/data-actions.ts +115 -0
- package/src/surfaces/dialog.json +289 -0
- package/src/surfaces/dialog.ts +343 -0
- package/src/surfaces/diff-toolbar.json +266 -0
- package/src/surfaces/diff-toolbar.ts +139 -0
- package/src/surfaces/doc-header.json +739 -0
- package/src/surfaces/doc-header.ts +223 -0
- package/src/surfaces/empty-state.json +152 -0
- package/src/surfaces/empty-state.ts +173 -0
- package/src/surfaces/entry-editor.json +281 -0
- package/src/surfaces/entry-editor.ts +191 -0
- package/src/surfaces/expression-editor.json +977 -0
- package/src/surfaces/expression-editor.ts +266 -0
- package/src/surfaces/files-panel.json +592 -0
- package/src/surfaces/files-panel.ts +301 -0
- package/src/surfaces/formula-palette.json +364 -0
- package/src/surfaces/formula-palette.ts +340 -0
- package/src/surfaces/git-panel.json +1822 -0
- package/src/surfaces/git-panel.ts +272 -0
- package/src/surfaces/github-auth.json +112 -0
- package/src/surfaces/github-auth.ts +139 -0
- package/src/surfaces/github-publish.json +206 -0
- package/src/surfaces/github-publish.ts +169 -0
- package/src/surfaces/grid-cell.json +218 -0
- package/src/surfaces/grid-cell.ts +120 -0
- package/src/surfaces/grid-open.json +147 -0
- package/src/surfaces/grid-open.ts +87 -0
- package/src/surfaces/grid-panel.json +706 -0
- package/src/surfaces/grid-panel.ts +206 -0
- package/src/surfaces/grid-replace.json +179 -0
- package/src/surfaces/grid-replace.ts +89 -0
- package/src/surfaces/grid-views.json +446 -0
- package/src/surfaces/grid-views.ts +172 -0
- package/src/surfaces/inspector-dock.json +187 -0
- package/src/surfaces/inspector-dock.ts +161 -0
- package/src/surfaces/jump-bar.json +243 -0
- package/src/surfaces/jump-bar.ts +129 -0
- package/src/surfaces/jxsuite-update.json +146 -0
- package/src/surfaces/jxsuite-update.ts +149 -0
- package/src/surfaces/library-pane.json +1509 -0
- package/src/surfaces/library-pane.ts +363 -0
- package/src/surfaces/logic-panel.json +1949 -0
- package/src/surfaces/logic-panel.ts +369 -0
- package/src/surfaces/logic-workspace.json +685 -0
- package/src/surfaces/logic-workspace.ts +238 -0
- package/src/surfaces/media-browser.json +303 -0
- package/src/surfaces/media-browser.ts +145 -0
- package/src/surfaces/media-field.json +163 -0
- package/src/surfaces/media-field.ts +116 -0
- package/src/surfaces/media-pane.json +513 -0
- package/src/surfaces/media-pane.ts +197 -0
- package/src/surfaces/menu.json +232 -0
- package/src/surfaces/menu.ts +375 -0
- package/src/surfaces/navigator-dock.json +113 -0
- package/src/surfaces/navigator-dock.ts +130 -0
- package/src/surfaces/new-project.json +1654 -0
- package/src/surfaces/new-project.ts +411 -0
- package/src/surfaces/palette.json +535 -0
- package/src/surfaces/pane-context.json +1497 -0
- package/src/surfaces/pane-context.ts +513 -0
- package/src/surfaces/pane-grid.json +188 -0
- package/src/surfaces/pane-grid.ts +250 -0
- package/src/surfaces/panel-activity.json +563 -0
- package/src/surfaces/panel-activity.ts +187 -0
- package/src/surfaces/panel-data.json +141 -0
- package/src/surfaces/panel-data.ts +156 -0
- package/src/surfaces/panel-deploy-checklist.json +283 -0
- package/src/surfaces/panel-deploy-checklist.ts +175 -0
- package/src/surfaces/panel-elements.json +367 -0
- package/src/surfaces/panel-elements.ts +175 -0
- package/src/surfaces/panel-i18n.json +569 -0
- package/src/surfaces/panel-i18n.ts +212 -0
- package/src/surfaces/panel-imports.json +780 -0
- package/src/surfaces/panel-imports.ts +209 -0
- package/src/surfaces/panel-outline.json +734 -0
- package/src/surfaces/panel-outline.ts +326 -0
- package/src/surfaces/panel-page.json +1017 -0
- package/src/surfaces/panel-page.ts +240 -0
- package/src/surfaces/panel-problems.json +497 -0
- package/src/surfaces/panel-problems.ts +157 -0
- package/src/surfaces/panel-signals.json +1973 -0
- package/src/surfaces/panel-signals.ts +436 -0
- package/src/surfaces/panel-stylebook-layers.json +317 -0
- package/src/surfaces/panel-stylebook-layers.ts +155 -0
- package/src/surfaces/preferences.json +850 -0
- package/src/surfaces/preferences.ts +332 -0
- package/src/surfaces/progress-modal.json +110 -0
- package/src/surfaces/progress-modal.ts +150 -0
- package/src/surfaces/properties-panel.json +1578 -0
- package/src/surfaces/properties-panel.ts +337 -0
- package/src/surfaces/publish.json +945 -0
- package/src/surfaces/publish.ts +392 -0
- package/src/surfaces/push-plan.json +110 -0
- package/src/surfaces/push-plan.ts +87 -0
- package/src/surfaces/rail.json +255 -0
- package/src/surfaces/rail.ts +206 -0
- package/src/surfaces/reference-field.json +191 -0
- package/src/surfaces/reference-field.ts +168 -0
- package/src/surfaces/schema-builder.json +1011 -0
- package/src/surfaces/schema-builder.ts +181 -0
- package/src/surfaces/schema-form.json +1013 -0
- package/src/surfaces/schema-form.ts +287 -0
- package/src/surfaces/secret-field.json +60 -0
- package/src/surfaces/secret-field.ts +146 -0
- package/src/surfaces/seo.json +932 -0
- package/src/surfaces/seo.ts +334 -0
- package/src/surfaces/settings-contexts.json +538 -0
- package/src/surfaces/settings-contexts.ts +196 -0
- package/src/surfaces/settings-contributed.json +489 -0
- package/src/surfaces/settings-contributed.ts +199 -0
- package/src/surfaces/settings-css-vars.json +820 -0
- package/src/surfaces/settings-css-vars.ts +199 -0
- package/src/surfaces/settings-defs.json +1363 -0
- package/src/surfaces/settings-defs.ts +232 -0
- package/src/surfaces/settings-deploy.json +108 -0
- package/src/surfaces/settings-deploy.ts +135 -0
- package/src/surfaces/settings-extensions.json +486 -0
- package/src/surfaces/settings-extensions.ts +201 -0
- package/src/surfaces/settings-head.json +779 -0
- package/src/surfaces/settings-head.ts +397 -0
- package/src/surfaces/settings-locales.json +420 -0
- package/src/surfaces/settings-locales.ts +137 -0
- package/src/surfaces/settings-overview.json +423 -0
- package/src/surfaces/settings-overview.ts +218 -0
- package/src/surfaces/settings-packages.json +549 -0
- package/src/surfaces/settings-packages.ts +158 -0
- package/src/surfaces/settings-pane.json +147 -0
- package/src/surfaces/settings-pane.ts +150 -0
- package/src/surfaces/settings-rawjson.json +104 -0
- package/src/surfaces/settings-rawjson.ts +107 -0
- package/src/surfaces/shell.json +99 -0
- package/src/surfaces/shell.ts +30 -0
- package/src/surfaces/slash-menu.json +180 -0
- package/src/surfaces/slash-menu.ts +272 -0
- package/src/surfaces/statements.json +607 -0
- package/src/surfaces/statements.ts +238 -0
- package/src/surfaces/statusbar.json +94 -0
- package/src/{panels → surfaces}/statusbar.ts +163 -90
- package/src/surfaces/style-panel.json +1643 -0
- package/src/surfaces/style-panel.ts +338 -0
- package/src/surfaces/stylebook-chrome.json +122 -0
- package/src/surfaces/stylebook-chrome.ts +122 -0
- package/src/surfaces/tab-strip.json +448 -0
- package/src/surfaces/tab-strip.ts +200 -0
- package/src/surfaces/target-line.json +419 -0
- package/src/surfaces/target-line.ts +349 -0
- package/src/surfaces/toasts.json +189 -0
- package/src/surfaces/welcome.json +571 -0
- package/src/surfaces/welcome.ts +338 -0
- package/src/tabs/project-config.ts +71 -15
- package/src/tabs/tab.ts +52 -1
- package/src/types.ts +22 -0
- package/src/ui/ai-credentials-form.ts +104 -100
- package/src/ui/ai-managed-connect.ts +54 -36
- package/src/ui/ai-model-picker.ts +75 -47
- package/src/ui/cf-account-picker.ts +76 -141
- package/src/ui/color-selector.ts +80 -301
- package/src/ui/dynamic-slot.ts +43 -283
- package/src/ui/expression-editor.ts +797 -576
- package/src/ui/field-input.ts +8 -181
- package/src/ui/form-controls.ts +838 -366
- package/src/ui/formula-chips.ts +80 -85
- package/src/ui/kit.ts +33 -0
- package/src/ui/layers.ts +293 -593
- package/src/ui/media-picker.ts +203 -284
- package/src/ui/panel-resize.ts +251 -64
- package/src/ui/popover-surface.ts +153 -0
- package/src/ui/progress-modal.ts +22 -60
- package/src/ui/regions.ts +13 -7
- package/src/ui/schema-form.ts +906 -440
- package/src/ui/surface.ts +122 -0
- package/src/ui/unit-selector.ts +15 -131
- package/src/ui/value-source.ts +14 -0
- package/src/ui/virtual-window.ts +88 -9
- package/src/utils/canvas-media.ts +72 -0
- package/src/utils/edit-display.ts +7 -2
- package/src/utils/element-selectors.ts +69 -0
- package/src/utils/link-target.ts +2 -2
- package/src/utils/studio-utils.ts +0 -10
- package/src/view.ts +15 -0
- package/src/workspace/pane-derive.ts +36 -14
- package/src/workspace/workspace.ts +15 -6
- package/styles/canvas.css +72 -467
- package/styles/forced-colors.css +48 -82
- package/styles/forced-colors.json +41 -0
- package/styles/inspector.css +2 -1301
- package/styles/overlays.css +96 -2823
- package/styles/panels.css +6 -1423
- package/styles/shell-frame.css +272 -0
- package/styles/shell-frame.json +227 -0
- package/styles/shell.css +0 -1568
- package/styles/tokens.css +65 -136
- package/styles/tokens.json +84 -0
- package/dist/chunks/Overlay.dev-etqjwyf9.js +0 -23
- package/dist/chunks/adapter-jkcyhgtr.js +0 -14
- package/dist/chunks/cf-account-picker-en86v7x7.js +0 -163
- package/dist/chunks/cf-settings-45fgyx8y.js +0 -21
- package/dist/chunks/components-zmx10t62.js +0 -21
- package/dist/chunks/content-source-48xg86wj.js +0 -49
- package/dist/chunks/convert-to-repeater-43tfn7cs.js +0 -268
- package/dist/chunks/editor-cptq5jp1.js +0 -37
- package/dist/chunks/entry-commands-e63f1xc0.js +0 -46
- package/dist/chunks/extension-sections-txv08xxg.js +0 -311
- package/dist/chunks/file-ops-wbh4hhsx.js +0 -48
- package/dist/chunks/files-3kfkwhk4.js +0 -93
- package/dist/chunks/flow-qbfgrpeh.js +0 -634
- package/dist/chunks/focus-trap.esm-9t2drp0g.js +0 -1025
- package/dist/chunks/focus-visible-6eg70z18.js +0 -167
- package/dist/chunks/format-host-w16q81tf.js +0 -43
- package/dist/chunks/fs-events-hrrg328g.js +0 -21
- package/dist/chunks/git-panel-532whr1y.js +0 -59
- package/dist/chunks/index-zqxmqxmh.js +0 -109
- package/dist/chunks/jx-validate-8er6gbxy.js +0 -19
- package/dist/chunks/layers-panel-07hm7g5j.js +0 -67
- package/dist/chunks/layers-q75tj2mf.js +0 -45
- package/dist/chunks/lit-html-j055mkh8.js +0 -22
- package/dist/chunks/monaco-buffer-dqw0xxpx.js +0 -25
- package/dist/chunks/notify-yjm79n4s.js +0 -30
- package/dist/chunks/parse-24d0gay3.js +0 -19
- package/dist/chunks/platform-ba1j1gbh.js +0 -16
- package/dist/chunks/publish-panel-v9st96ja.js +0 -29
- package/dist/chunks/quick-search-zccjp6gv.js +0 -66
- package/dist/chunks/references-3qx8fkyp.js +0 -29
- package/dist/chunks/right-panel-vm3b6kwy.js +0 -46
- package/dist/chunks/section-registry-sx1ykvkw.js +0 -30
- package/dist/chunks/sp-overlay.dev-qgvhnxf4.js +0 -18
- package/dist/chunks/sp-popover.dev-n2etmqdp.js +0 -9
- package/dist/chunks/sp-progress-circle.dev-hryhj0es.js +0 -15
- package/dist/chunks/sp-tooltip.dev-4sastdnw.js +0 -15
- package/dist/chunks/sp-tray.dev-tkbscm06.js +0 -199
- package/dist/chunks/studio-0a5qrh01.js +0 -3
- package/dist/chunks/studio-0bq6eh7v.js +0 -12
- package/dist/chunks/studio-18j3bmcz.js +0 -14
- package/dist/chunks/studio-1ngbejft.js +0 -181
- package/dist/chunks/studio-4b5z1x43.js +0 -424
- package/dist/chunks/studio-4n2b5gzb.js +0 -357
- package/dist/chunks/studio-4rzyrtjz.js +0 -426
- package/dist/chunks/studio-5fx3g9jg.js +0 -4325
- package/dist/chunks/studio-5myknm0a.js +0 -1903
- package/dist/chunks/studio-7afd21nw.js +0 -67
- package/dist/chunks/studio-7nte2hj4.js +0 -613
- package/dist/chunks/studio-8jpzqk5s.js +0 -128
- package/dist/chunks/studio-8q517dfr.js +0 -24
- package/dist/chunks/studio-950k0dx6.js +0 -6939
- package/dist/chunks/studio-9n4mrmnb.js +0 -184
- package/dist/chunks/studio-a0tswy0w.js +0 -58
- package/dist/chunks/studio-ahnzd9rg.js +0 -23
- package/dist/chunks/studio-cmb03bg5.js +0 -13890
- package/dist/chunks/studio-d1ks410h.js +0 -175
- package/dist/chunks/studio-ef49pnzx.js +0 -387
- package/dist/chunks/studio-eqq1w638.js +0 -113
- package/dist/chunks/studio-ew0djmhg.js +0 -341
- package/dist/chunks/studio-gfgb8pe6.js +0 -1652
- package/dist/chunks/studio-h4rxscfc.js +0 -10
- package/dist/chunks/studio-jc994dnr.js +0 -1066
- package/dist/chunks/studio-kyh9avvv.js +0 -28
- package/dist/chunks/studio-m3hwn7y1.js +0 -120
- package/dist/chunks/studio-mtfnaqs9.js +0 -659
- package/dist/chunks/studio-n6j9t10q.js +0 -318
- package/dist/chunks/studio-n8b9wqwy.js +0 -291
- package/dist/chunks/studio-qcy05dp8.js +0 -1743
- package/dist/chunks/studio-qq6jym04.js +0 -53
- package/dist/chunks/studio-rdx8jcxy.js +0 -83
- package/dist/chunks/studio-rn9ta2mz.js +0 -111
- package/dist/chunks/studio-t7qb9db8.js +0 -665
- package/dist/chunks/studio-tmc5emrw.js +0 -8
- package/dist/chunks/studio-z6nw2ek2.js +0 -18
- package/dist/chunks/studio-zczps70q.js +0 -378
- package/dist/chunks/studio-zqazsct2.js +0 -1823
- package/dist/chunks/workspace-fjx52ryv.js +0 -89
- package/src/panels/activity-bar.ts +0 -251
- package/src/panels/panel-scheduler.ts +0 -219
- package/src/panels/style-inputs.ts +0 -237
- package/src/panels/target-line.ts +0 -274
- package/src/panels/welcome-screen.ts +0 -346
- package/src/ui/button-group.ts +0 -102
- package/src/ui/choice-field.ts +0 -72
- package/src/ui/field-row.ts +0 -249
- package/src/ui/formula-palette.ts +0 -213
- package/src/ui/icons.ts +0 -52
- package/src/ui/jx-theme.ts +0 -130
- package/src/ui/spectrum.ts +0 -340
- package/src/ui/value-selector.ts +0 -174
- package/src/ui/widgets.ts +0 -172
- /package/dist/chunks/{javascript-s56a8dpk.css → javascript-4abzjcy9.css} +0 -0
- /package/dist/chunks/{jsonMode-zr9sw0c7.css → jsonMode-vvmpmk34.css} +0 -0
- /package/dist/chunks/{monaco-setup-pav68602.css → monaco-setup-8vbyqnhr.css} +0 -0
- /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-
|
|
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.
|
|
80
|
-
* the gating predicates from the same rows, so the advertised tool
|
|
81
|
-
* list cannot drift (a test asserts the names match the registered
|
|
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` and
|
|
121
|
+
* `delete_node` (né `remove_node`) 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
|
|
@@ -181,11 +221,6 @@ export const AI_TOOL_TIERS: AiToolInfo[] = [
|
|
|
181
221
|
blurb:
|
|
182
222
|
"add_child(parentPath, index, node) — insert a new node into the children of parentPath at index.",
|
|
183
223
|
},
|
|
184
|
-
{
|
|
185
|
-
name: "remove_node",
|
|
186
|
-
tier: "document-tree",
|
|
187
|
-
blurb: "remove_node(path) — remove the node at path.",
|
|
188
|
-
},
|
|
189
224
|
{
|
|
190
225
|
name: "move_node",
|
|
191
226
|
tier: "document-tree",
|
|
@@ -644,17 +679,24 @@ export function buildSystemPrompt({
|
|
|
644
679
|
hasProject = Boolean(projectRoot),
|
|
645
680
|
treeEditable = true,
|
|
646
681
|
canImport = true,
|
|
682
|
+
commandTools = [],
|
|
647
683
|
fileInventory,
|
|
684
|
+
extensionCatalog,
|
|
648
685
|
}: BuildSystemPromptOptions = {}) {
|
|
649
686
|
const hasDocument = Boolean(document);
|
|
650
687
|
|
|
651
688
|
// 1. Role, state-appropriate workflow, and the tool list for the current state.
|
|
652
689
|
// 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
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
.
|
|
690
|
+
// Refusal is never a surprise to it. The command-projected tools arrive already filtered by
|
|
691
|
+
// Their records' own gates, for the same reason — one function answers both the prompt and the
|
|
692
|
+
// Executor (`advertisedCommandTools`).
|
|
693
|
+
const toolList = [
|
|
694
|
+
...AI_TOOL_TIERS.filter((t) =>
|
|
695
|
+
toolActive(t, { canImport, hasDocument, hasProject, treeEditable }),
|
|
696
|
+
).map((t) => t.blurb),
|
|
697
|
+
...commandTools,
|
|
698
|
+
]
|
|
699
|
+
.map((blurb) => `- ${blurb}`)
|
|
658
700
|
.join("\n");
|
|
659
701
|
|
|
660
702
|
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 +764,12 @@ Be concise. Don't explain what Jx is unless asked. Just build.`;
|
|
|
722
764
|
|
|
723
765
|
// 6. Project context
|
|
724
766
|
if (hasProject && (projectConfig || components || projectRoot)) {
|
|
725
|
-
const projectSummary = buildProjectSummary({
|
|
767
|
+
const projectSummary = buildProjectSummary({
|
|
768
|
+
components,
|
|
769
|
+
extensionCatalog,
|
|
770
|
+
projectConfig,
|
|
771
|
+
projectRoot,
|
|
772
|
+
});
|
|
726
773
|
if (projectSummary) {
|
|
727
774
|
sections.push(`## Project Context\n\n${projectSummary}`);
|
|
728
775
|
}
|
|
@@ -744,7 +791,7 @@ Be concise. Don't explain what Jx is unless asked. Just build.`;
|
|
|
744
791
|
If a tool call fails (returns { success: false }):
|
|
745
792
|
1. Read the error message carefully — it includes a "→ Fix:" hint telling you exactly how to correct the error.
|
|
746
793
|
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,
|
|
794
|
+
3. Apply the suggested fix using set_property, delete_node, or add_child as appropriate.
|
|
748
795
|
4. Do NOT re-issue the exact same tool call with the same arguments — you must CHANGE something.
|
|
749
796
|
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
797
|
|
|
@@ -762,7 +809,7 @@ If a tool call fails (returns { success: false }):
|
|
|
762
809
|
|
|
763
810
|
### If you keep getting errors:
|
|
764
811
|
- Call read_document again — the document may have changed since you last read it.
|
|
765
|
-
- Remove the problematic node entirely with
|
|
812
|
+
- Remove the problematic node entirely with delete_node, then re-create it correctly with add_child.
|
|
766
813
|
- If the error message points to a different path than you expected, the node might have moved due to previous edits.`);
|
|
767
814
|
|
|
768
815
|
return sections.join("\n\n---\n\n");
|
|
@@ -841,6 +888,7 @@ function buildProjectSummary({
|
|
|
841
888
|
projectConfig,
|
|
842
889
|
components,
|
|
843
890
|
projectRoot,
|
|
891
|
+
extensionCatalog,
|
|
844
892
|
}: Omit<BuildSystemPromptOptions, "document">) {
|
|
845
893
|
const lines: string[] = [];
|
|
846
894
|
|
|
@@ -852,6 +900,13 @@ function buildProjectSummary({
|
|
|
852
900
|
lines.push(`Root: ${projectRoot}`);
|
|
853
901
|
}
|
|
854
902
|
|
|
903
|
+
/* One line, closing a gap that was pure oversight: this function has always received the whole
|
|
904
|
+
`projectConfig`, `extensions` included, and dropped it on the floor. */
|
|
905
|
+
const enabled = projectConfig?.extensions ?? [];
|
|
906
|
+
if (enabled.length > 0) {
|
|
907
|
+
lines.push(`Extensions enabled: ${enabled.join(", ")}`);
|
|
908
|
+
}
|
|
909
|
+
|
|
855
910
|
// Available components — tag + purpose so the model can reuse them
|
|
856
911
|
if (components && components.length > 0) {
|
|
857
912
|
lines.push(`Available components (reuse these instead of rebuilding):`);
|
|
@@ -898,6 +953,43 @@ function buildProjectSummary({
|
|
|
898
953
|
}
|
|
899
954
|
}
|
|
900
955
|
|
|
956
|
+
/*
|
|
957
|
+
* The catalogue, last, so the design-token block keeps its prominence. The guidance names
|
|
958
|
+
* CAPABILITIES rather than packages on purpose: the capability-to-package mapping is what each
|
|
959
|
+
* entry's own description is for, and hardcoding "@jxsuite/parser" here would be a second,
|
|
960
|
+
* staler copy of the backend's answer.
|
|
961
|
+
*/
|
|
962
|
+
if (extensionCatalog && extensionCatalog.length > 0) {
|
|
963
|
+
const enabledSet = new Set(enabled);
|
|
964
|
+
lines.push(
|
|
965
|
+
`Extensions available. Turn one on with enable_extension BEFORE writing the project.json ` +
|
|
966
|
+
`section it owns: a section belonging to a disabled extension is a schema error, and an ` +
|
|
967
|
+
`"extensions" entry whose package is not installed fails the build. When a request needs ` +
|
|
968
|
+
`a capability the core does not have (a blog or any folder of Markdown, a search box, a ` +
|
|
969
|
+
`feed, sign-ins, a database table), look for it below rather than hand-building it.`,
|
|
970
|
+
);
|
|
971
|
+
for (const entry of extensionCatalog.slice(0, EXTENSION_CATALOG_CAP)) {
|
|
972
|
+
const parts = [` ${entry.name}`];
|
|
973
|
+
if (entry.title) {
|
|
974
|
+
parts.push(` — ${entry.title}.`);
|
|
975
|
+
}
|
|
976
|
+
if (entry.description) {
|
|
977
|
+
parts.push(` ${entry.description}`);
|
|
978
|
+
}
|
|
979
|
+
if (entry.sections && entry.sections.length > 0) {
|
|
980
|
+
parts.push(` Contributes: ${entry.sections.join(", ")}.`);
|
|
981
|
+
}
|
|
982
|
+
if (enabledSet.has(entry.name)) {
|
|
983
|
+
parts.push(" [enabled]");
|
|
984
|
+
}
|
|
985
|
+
lines.push(parts.join(""));
|
|
986
|
+
}
|
|
987
|
+
if (extensionCatalog.length > EXTENSION_CATALOG_CAP) {
|
|
988
|
+
const more = extensionCatalog.length - EXTENSION_CATALOG_CAP;
|
|
989
|
+
lines.push(` … and ${more} more (open_settings { section: "extensions" })`);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
|
|
901
993
|
// Breakpoints — surfaced prominently so the model uses @--breakpoint responsive overrides
|
|
902
994
|
if (projectConfig?.$media) {
|
|
903
995
|
const breakpoints = Object.entries(projectConfig.$media)
|
package/src/services/ai-tools.ts
CHANGED
|
@@ -12,7 +12,6 @@ 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
17
|
beginBatch,
|
|
@@ -20,7 +19,6 @@ import {
|
|
|
20
19
|
isBatching,
|
|
21
20
|
mutateInsertNode,
|
|
22
21
|
mutateMoveNode,
|
|
23
|
-
mutateRemoveNode,
|
|
24
22
|
mutateUpdateProperty,
|
|
25
23
|
mutateUpdateStyle,
|
|
26
24
|
transactDoc,
|
|
@@ -28,7 +26,18 @@ import {
|
|
|
28
26
|
import type { JxNodeValue } from "../tabs/transact";
|
|
29
27
|
import { validateDoc } from "./jx-validate";
|
|
30
28
|
import { recordWrite } from "./ai-writes";
|
|
31
|
-
import {
|
|
29
|
+
import { serializeJson } from "../files/json-layout";
|
|
30
|
+
import {
|
|
31
|
+
reportDocumentWrite,
|
|
32
|
+
snapshotBeforeWrite,
|
|
33
|
+
translateValidationError,
|
|
34
|
+
} from "./ai-write-report";
|
|
35
|
+
import type { RenderVerdict } from "./ai-write-report";
|
|
36
|
+
|
|
37
|
+
/* Re-exported from its new home so `ai-project-tools.ts` and the tests keep their import: the
|
|
38
|
+
translation moved with the verdict it belongs to (`ai-write-report.ts`), where every document
|
|
39
|
+
write — hand-registered or projected from a command record — now reads it. */
|
|
40
|
+
export { translateValidationError } from "./ai-write-report";
|
|
32
41
|
|
|
33
42
|
const PATH_DESCRIPTION =
|
|
34
43
|
"Path to a node in the document, as a JSON array of keys/indices from the root " +
|
|
@@ -45,74 +54,17 @@ function noDocError(): ToolResult {
|
|
|
45
54
|
}
|
|
46
55
|
|
|
47
56
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
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).
|
|
57
|
+
* Apply a mutation, then hand the verdict to `ai-write-report.ts`: only the schema errors the edit
|
|
58
|
+
* NEWLY introduced are reported (the eval signal — ADR §6b), the render check runs when a
|
|
59
|
+
* renderCheck was provided and rendering worked before, and a success carries the token hints. The
|
|
60
|
+
* change stays applied either way (optimistic apply + undo, ADR §5); reporting the errors lets the
|
|
61
|
+
* agent loop self-correct on the next round.
|
|
110
62
|
*
|
|
111
63
|
* @param {import("../tabs/tab").Tab} tab
|
|
112
64
|
* @param {(t: import("../tabs/tab").Tab) => void} mutationFn
|
|
113
65
|
* @param {string} summary
|
|
114
66
|
* @param {(doc: unknown) => Promise<string[]>} validate
|
|
115
|
-
* @param {((doc: unknown) => Promise<
|
|
67
|
+
* @param {((doc: unknown) => Promise<RenderVerdict>) | undefined} renderCheck
|
|
116
68
|
* @param {Record<string, string> | undefined} projectStyle
|
|
117
69
|
* @returns {Promise<import("@jxsuite/ai/tools").ToolResult>}
|
|
118
70
|
*/
|
|
@@ -121,12 +73,11 @@ async function applyAndValidate(
|
|
|
121
73
|
mutationFn: (t: Tab) => void,
|
|
122
74
|
summary: string,
|
|
123
75
|
validate: (doc: unknown) => Promise<string[]>,
|
|
124
|
-
renderCheck: ((doc: unknown) => Promise<
|
|
76
|
+
renderCheck: ((doc: unknown) => Promise<RenderVerdict>) | undefined,
|
|
125
77
|
projectStyle: Record<string, string> | undefined,
|
|
126
78
|
): Promise<ToolResult> {
|
|
127
|
-
const
|
|
128
|
-
const before =
|
|
129
|
-
const renderOkBefore = renderCheck ? await renderCheck(rawBefore) : { ok: true };
|
|
79
|
+
const deps = { getProjectStyle: () => projectStyle, renderCheck, validate };
|
|
80
|
+
const before = await snapshotBeforeWrite(tab, deps);
|
|
130
81
|
|
|
131
82
|
/* AND THE WRITE CAN BE REFUSED, in which case the model must be told rather than congratulated.
|
|
132
83
|
The collab gate pauses structural editing while source is canonical, and this went on to
|
|
@@ -147,37 +98,7 @@ async function applyAndValidate(
|
|
|
147
98
|
went through transactDoc, so the tab's history — and "Restore to here" — can reach it. */
|
|
148
99
|
recordWrite({ disk: false, ok: true, path: tab.documentPath ?? "(untitled)", tool: summary });
|
|
149
100
|
|
|
150
|
-
|
|
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 };
|
|
101
|
+
return reportDocumentWrite(tab, before, summary, deps);
|
|
181
102
|
}
|
|
182
103
|
|
|
183
104
|
/**
|
|
@@ -258,7 +179,7 @@ export function registerAiTools(
|
|
|
258
179
|
name: "read_document",
|
|
259
180
|
description:
|
|
260
181
|
"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
|
|
182
|
+
"node paths before calling set_property, add_child, or delete_node.",
|
|
262
183
|
parameters: {
|
|
263
184
|
type: "object",
|
|
264
185
|
properties: {
|
|
@@ -751,7 +672,9 @@ export function registerAiTools(
|
|
|
751
672
|
}
|
|
752
673
|
}
|
|
753
674
|
try {
|
|
754
|
-
|
|
675
|
+
// The save serializer, layout-less (`files/json-layout.ts`): the assistant supplied a
|
|
676
|
+
// Value, not a text, so the formatter's layout for fresh output is the right one.
|
|
677
|
+
await saveFile(relPath, serializeJson(content, null));
|
|
755
678
|
recordWrite({ disk: true, ok: true, path: relPath, tool: "create_component" });
|
|
756
679
|
return {
|
|
757
680
|
success: true,
|
|
@@ -828,7 +751,8 @@ export function registerAiTools(
|
|
|
828
751
|
}
|
|
829
752
|
}
|
|
830
753
|
try {
|
|
831
|
-
|
|
754
|
+
// As `create_component`: a value the assistant supplied, written in the formatter's layout.
|
|
755
|
+
await saveFile(relPath, serializeJson(content, null));
|
|
832
756
|
recordWrite({ disk: true, ok: true, path: relPath, tool: "create_page" });
|
|
833
757
|
return {
|
|
834
758
|
success: true,
|
|
@@ -915,43 +839,4 @@ export function registerAiTools(
|
|
|
915
839
|
},
|
|
916
840
|
}),
|
|
917
841
|
);
|
|
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
|
-
);
|
|
957
842
|
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ai-write-report.ts — what the model is told after a document write, whoever made it.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from `ai-tools.ts`'s `applyAndValidate`, which used to own both halves of a document
|
|
5
|
+
* tool: the transaction and the verdict on it. The verdict is the half every document write needs
|
|
6
|
+
* — the seven hand-registered tree tools AND every command the assistant runs through
|
|
7
|
+
* `services/ai-command-tools.ts` — so it lives here, in two functions the caller brackets its write
|
|
8
|
+
* with:
|
|
9
|
+
*
|
|
10
|
+
* 1. {@link snapshotBeforeWrite} reads the document's schema errors and render state BEFORE the
|
|
11
|
+
* write, because the eval signal (ADR docs/ai-assistant-decision.md §6b) is "what did this edit
|
|
12
|
+
* newly introduce", not "is the document valid": a page that was already broken must not make
|
|
13
|
+
* every subsequent edit read as the culprit.
|
|
14
|
+
* 2. {@link reportDocumentWrite} compares AFTER the write, translating each new schema error into a
|
|
15
|
+
* fix hint the model can act on, running the render check only when rendering worked before,
|
|
16
|
+
* and appending the soft token-discipline hints to a success.
|
|
17
|
+
*
|
|
18
|
+
* The change stays applied either way (optimistic apply + undo, ADR §5); reporting the errors lets
|
|
19
|
+
* the agent loop self-correct on the next round.
|
|
20
|
+
*
|
|
21
|
+
* @license MIT
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import type { ToolResult } from "@jxsuite/ai/tools";
|
|
25
|
+
import { toRaw } from "../reactivity";
|
|
26
|
+
import type { Tab } from "../tabs/tab";
|
|
27
|
+
import { flagHardcodedTokens, formatTokenHints } from "./token-lint";
|
|
28
|
+
|
|
29
|
+
/** A render probe's answer: rendered, or the message it threw. */
|
|
30
|
+
export type RenderVerdict = { ok: true } | { ok: false; error: string };
|
|
31
|
+
|
|
32
|
+
/** What a write reporter needs. Every member is what `registerAiTools` already takes by injection. */
|
|
33
|
+
export interface WriteReportDeps {
|
|
34
|
+
/** Schema errors for a document, as raw ajv sentences. */
|
|
35
|
+
validate: (doc: unknown) => Promise<string[]>;
|
|
36
|
+
/** The detached-DOM render probe, when the host has one. */
|
|
37
|
+
renderCheck?: ((doc: unknown) => Promise<RenderVerdict>) | undefined;
|
|
38
|
+
/** The project's design tokens, read per call so a project opened mid-session contributes. */
|
|
39
|
+
getProjectStyle?: (() => Record<string, string> | undefined) | undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** The document as it stood before a write, in the two respects the verdict compares. */
|
|
43
|
+
export interface WriteSnapshot {
|
|
44
|
+
errors: Set<string>;
|
|
45
|
+
renderOk: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Translate a raw JSON Schema validation error into a Jx-specific actionable message. The LLM needs
|
|
50
|
+
* concrete guidance on HOW to fix errors, not just what rule was violated. Shared with the
|
|
51
|
+
* project-level file tools (ai-project-tools.ts), which pre-validate Jx documents before writing.
|
|
52
|
+
*
|
|
53
|
+
* @param {string} rawError - Message from ajv (e.g. "/children/0/style: must NOT have additional
|
|
54
|
+
* property")
|
|
55
|
+
* @returns {string}
|
|
56
|
+
*/
|
|
57
|
+
export function translateValidationError(rawError: string): string {
|
|
58
|
+
const lower = rawError.toLowerCase();
|
|
59
|
+
|
|
60
|
+
// Additional property — extract the offending key from the message if present
|
|
61
|
+
if (
|
|
62
|
+
lower.includes("must not have additional property") ||
|
|
63
|
+
lower.includes("additional properties")
|
|
64
|
+
) {
|
|
65
|
+
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": "..." } }.`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Pattern — usually tagName hyphen rule
|
|
69
|
+
if (lower.includes("must match pattern")) {
|
|
70
|
+
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").`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Type error
|
|
74
|
+
if (lower.includes("must be string")) {
|
|
75
|
+
return `${rawError}\n → Fix: Wrap the value in quotes — all Jx property values should be strings. For example, use "10px" (string) not 10px (unquoted).`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (lower.includes("must be number") || lower.includes("must be integer")) {
|
|
79
|
+
return `${rawError}\n → Fix: Remove quotes from the numeric value — it should be a plain number, not a string.`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (lower.includes("must be object") || lower.includes("must be array")) {
|
|
83
|
+
return `${rawError}\n → Fix: The value must be an object/array (use {} or []), not a string or number.`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (lower.includes("must be boolean")) {
|
|
87
|
+
return `${rawError}\n → Fix: Use true or false without quotes for boolean values.`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Required property
|
|
91
|
+
if (lower.includes("must have required property")) {
|
|
92
|
+
return `${rawError}\n → Fix: Add the missing required property. Every Jx element must have at least a "tagName" field.`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Enum / allowed values
|
|
96
|
+
if (lower.includes("must be equal to one of the allowed values")) {
|
|
97
|
+
return `${rawError}\n → Fix: Change the value to one of the allowed options listed in the error.`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return rawError;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Read the document's standing BEFORE a write: its schema errors and whether it renders.
|
|
105
|
+
*
|
|
106
|
+
* Reads the RAW document, not the reactive proxy, for the same reason `applyAndValidate` always
|
|
107
|
+
* did: the validator walks the whole tree, and walking a proxy subscribes whichever effect is
|
|
108
|
+
* running to every key of it.
|
|
109
|
+
*
|
|
110
|
+
* @param {Tab} tab
|
|
111
|
+
* @param {WriteReportDeps} deps
|
|
112
|
+
* @returns {Promise<WriteSnapshot>}
|
|
113
|
+
*/
|
|
114
|
+
export async function snapshotBeforeWrite(tab: Tab, deps: WriteReportDeps): Promise<WriteSnapshot> {
|
|
115
|
+
const rawBefore = toRaw(tab.doc.document);
|
|
116
|
+
const errors = new Set(await deps.validate(rawBefore));
|
|
117
|
+
const rendered = deps.renderCheck ? await deps.renderCheck(rawBefore) : { ok: true };
|
|
118
|
+
return { errors, renderOk: rendered.ok };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The verdict on a write that has been applied: the NEW schema errors with fix hints, the render
|
|
123
|
+
* check (only when rendering worked before — a page that already failed to render is not this
|
|
124
|
+
* edit's fault), or a success carrying `summary` plus any token-discipline hints.
|
|
125
|
+
*
|
|
126
|
+
* The three sentences here are the ones the model has read since the tools were written; every
|
|
127
|
+
* bridged document command now answers with the same ones, which is what lets the prompt's error
|
|
128
|
+
* recovery guidance stay generic.
|
|
129
|
+
*
|
|
130
|
+
* @param {Tab} tab
|
|
131
|
+
* @param {WriteSnapshot} before - What {@link snapshotBeforeWrite} read.
|
|
132
|
+
* @param {string} summary - The sentence to return on success.
|
|
133
|
+
* @param {WriteReportDeps} deps
|
|
134
|
+
* @returns {Promise<ToolResult>}
|
|
135
|
+
*/
|
|
136
|
+
export async function reportDocumentWrite(
|
|
137
|
+
tab: Tab,
|
|
138
|
+
before: WriteSnapshot,
|
|
139
|
+
summary: string,
|
|
140
|
+
deps: WriteReportDeps,
|
|
141
|
+
): Promise<ToolResult> {
|
|
142
|
+
const rawAfter = toRaw(tab.doc.document);
|
|
143
|
+
const after = await deps.validate(rawAfter);
|
|
144
|
+
const newErrors = after.filter((e) => !before.errors.has(e));
|
|
145
|
+
if (newErrors.length > 0) {
|
|
146
|
+
const formatted = newErrors.map((e) => `- ${translateValidationError(e)}`).join("\n");
|
|
147
|
+
return {
|
|
148
|
+
success: false,
|
|
149
|
+
error: `Change applied, but it introduced schema errors. Fix these issues with follow-up edits:\n${formatted}`,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (deps.renderCheck && before.renderOk) {
|
|
154
|
+
const renderResult = await deps.renderCheck(rawAfter);
|
|
155
|
+
if (!renderResult.ok) {
|
|
156
|
+
return {
|
|
157
|
+
success: false,
|
|
158
|
+
error: `Change applied and schema-valid, but it broke rendering. Fix with follow-up edits:\n- ${renderResult.error}`,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Soft token-discipline hints (never fail the mutation)
|
|
164
|
+
const projectStyle = deps.getProjectStyle?.();
|
|
165
|
+
if (projectStyle) {
|
|
166
|
+
const findings = flagHardcodedTokens(rawAfter, projectStyle);
|
|
167
|
+
const hints = formatTokenHints(findings);
|
|
168
|
+
if (hints) {
|
|
169
|
+
return { success: true, summary: `${summary}\n\n${hints}` };
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return { success: true, summary };
|
|
174
|
+
}
|