@jxsuite/studio 6.1.1 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/chunks/2020-5wtzce5g.js +4 -0
- package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
- package/dist/chunks/adapter-5tphg7xe.js +4 -0
- package/dist/chunks/add-new-flow-psym14sn.js +4 -0
- package/dist/chunks/cf-account-picker-haqazq5r.js +4 -0
- package/dist/chunks/cf-settings-h2wrh6hq.js +4 -0
- package/dist/chunks/color-area-6rbra5dy.js +4 -0
- package/dist/chunks/color-field-gy56c94g.js +4 -0
- package/dist/chunks/color-m7r1vk54.js +4 -0
- package/dist/chunks/color-slider-sqqdyf6c.js +4 -0
- package/dist/chunks/combobox-72h32ejk.js +4 -0
- package/dist/chunks/components-r22xca09.js +4 -0
- package/dist/chunks/content-source-mmppmcyg.js +4 -0
- package/dist/chunks/convert-to-repeater-he70fc2b.js +4 -0
- package/dist/chunks/dialog-c4x05vyx.js +4 -0
- package/dist/chunks/editor-ccd9jwsa.js +4 -0
- package/dist/chunks/entry-commands-6qxz9e8p.js +4 -0
- package/dist/chunks/extension-sections-0egb88dm.js +4 -0
- package/dist/chunks/file-ops-qnab36ek.js +4 -0
- package/dist/chunks/files-rcn56qvm.js +4 -0
- package/dist/chunks/format-host-yxz0kjjs.js +4 -0
- package/dist/chunks/fs-events-d1qxq4z4.js +4 -0
- package/dist/chunks/grid-open-4z1g062t.js +4 -0
- package/dist/chunks/grid-view-qg1b5eqx.js +51 -0
- package/dist/chunks/icons-63bjtbs7.js +4 -0
- package/dist/chunks/iframe-entry-2zggzajv.js +5 -0
- package/dist/chunks/iframe-entry-76j8vwwx.js +5 -0
- package/dist/chunks/iframe-entry-99nr5zfb.js +5 -0
- package/dist/chunks/iframe-entry-pkgmcgp0.js +5 -0
- package/dist/chunks/iframe-host-ssv7kyj0.js +4 -0
- package/dist/chunks/{index-2veqmnhr.js → index-32eqzv1k.js} +3 -3
- package/dist/chunks/index-f0jn7nnp.js +4 -0
- package/dist/chunks/{javascript-8nbvs12s.js → javascript-pjp734q4.js} +3 -3
- package/dist/chunks/jsonMode-njkvsa02.js +13 -0
- package/dist/chunks/jx-validate-ttasrbh7.js +4 -0
- package/dist/chunks/layers-bgyr11tr.js +4 -0
- package/dist/chunks/layers-panel-7ez66zeq.js +4 -0
- package/dist/chunks/listbox-c421cf8c.js +4 -0
- package/dist/chunks/lit-html-v9gh687x.js +4 -0
- package/dist/chunks/media-library-sq468wts.js +4 -0
- package/dist/chunks/media-picker-shfe59pt.js +4 -0
- package/dist/chunks/menu-bdpzbfvs.js +4 -0
- package/dist/chunks/monaco-binding-vq1hgnn0.js +4 -0
- package/dist/chunks/monaco-buffer-3afgwvbp.js +4 -0
- package/dist/chunks/monaco-setup-xrd2cbkp.js +4 -0
- package/dist/chunks/notify-kzrjr3fv.js +4 -0
- package/dist/chunks/number-field-y62xq0ty.js +4 -0
- package/dist/chunks/parse-v77xtwv7.js +4 -0
- package/dist/chunks/platform-7v4rtd7m.js +4 -0
- package/dist/chunks/popover-b89sfej7.js +4 -0
- package/dist/chunks/publish-panel-2z9gw8ee.js +4 -0
- package/dist/chunks/publish-quick-qx2455cj.js +4 -0
- package/dist/chunks/publish-workspace-wrc1dgwx.js +4 -0
- package/dist/chunks/quick-search-n0t0eqxb.js +4 -0
- package/dist/chunks/references-9547rg5s.js +4 -0
- package/dist/chunks/right-panel-wsgnr9pn.js +4 -0
- package/dist/chunks/select-rzds841e.js +4 -0
- package/dist/chunks/source-control-kwktr9y6.js +4 -0
- package/dist/chunks/split-c9zfdgxf.js +4 -0
- package/dist/chunks/studio-03ct6yfv.js +9 -0
- package/dist/chunks/studio-07rcfje3.js +5 -0
- package/dist/chunks/studio-3e54qh39.js +7 -0
- package/dist/chunks/studio-3exxhz5g.js +5 -0
- package/dist/chunks/studio-3q40e3rj.js +5 -0
- package/dist/chunks/studio-3qeh9t0h.js +6 -0
- package/dist/chunks/studio-3qqjeep5.js +6 -0
- package/dist/chunks/studio-43sd2mam.js +4 -0
- package/dist/chunks/studio-4hp8pkyt.js +5 -0
- package/dist/chunks/studio-58xg6j2q.js +9 -0
- package/dist/chunks/studio-5g0rprdt.js +7 -0
- package/dist/chunks/studio-6m380wp7.js +5 -0
- package/dist/chunks/studio-80jyh1xh.js +4 -0
- package/dist/chunks/studio-83mk4bgg.js +9 -0
- package/dist/chunks/{studio-kggey1jt.js → studio-881z1xrx.js} +4 -4
- package/dist/chunks/studio-8m0y2qe7.js +5 -0
- package/dist/chunks/studio-8tr6cfrc.js +5 -0
- package/dist/chunks/studio-8vcvfs7r.js +6 -0
- package/dist/chunks/studio-9tmebf0s.js +5 -0
- package/dist/chunks/studio-a2bvaptz.js +5 -0
- package/dist/chunks/studio-b7y5mr30.js +5 -0
- package/dist/chunks/studio-bavb31r0.js +5 -0
- package/dist/chunks/studio-bbe4c90a.js +5 -0
- package/dist/chunks/studio-c05wdnt3.js +5 -0
- package/dist/chunks/studio-ccv2svc6.js +5 -0
- package/dist/chunks/studio-d5grtb9e.js +16 -0
- package/dist/chunks/studio-df0baea9.js +5 -0
- package/dist/chunks/studio-dgk4dqtx.js +7 -0
- package/dist/chunks/studio-e1g64q43.js +5 -0
- package/dist/chunks/studio-ed1hp6zf.js +6 -0
- package/dist/chunks/studio-ed3xx40h.js +7 -0
- package/dist/chunks/studio-f14e1zdj.js +5 -0
- package/dist/chunks/studio-fbhxxc5f.js +5 -0
- package/dist/chunks/studio-fyh0jc96.js +5 -0
- package/dist/chunks/studio-gcxk20n7.js +5 -0
- package/dist/chunks/studio-jaaz8ce9.js +5 -0
- package/dist/chunks/{studio-8grwxtqk.js → studio-jcnsdaep.js} +4 -4
- package/dist/chunks/studio-jsgf2q5k.js +7 -0
- package/dist/chunks/{studio-1q1sh2ax.js → studio-k3xxbagr.js} +3 -3
- package/dist/chunks/studio-k7evxqh4.js +5 -0
- package/dist/chunks/studio-kt3pjkwd.js +5 -0
- package/dist/chunks/studio-m8g16bgz.js +5 -0
- package/dist/chunks/studio-mn0476ag.js +5 -0
- package/dist/chunks/studio-mx1smyq0.js +5 -0
- package/dist/chunks/studio-n0c5h6mf.js +5 -0
- package/dist/chunks/{studio-rv11kfwa.js → studio-nh6d342n.js} +7 -7
- package/dist/chunks/studio-nqxqf8p2.js +4 -0
- package/dist/chunks/studio-p4nrkvqr.js +5 -0
- package/dist/chunks/{studio-h46vtzk8.js → studio-pbxa5fpc.js} +4 -4
- package/dist/chunks/studio-pgmvdv7z.js +7 -0
- package/dist/chunks/studio-ph84avkf.js +5 -0
- package/dist/chunks/{studio-wszjyh0j.js → studio-q0mvbaq6.js} +4 -4
- package/dist/chunks/studio-q0tccd43.js +5 -0
- package/dist/chunks/studio-q7rtx6zq.js +14 -0
- package/dist/chunks/{studio-pre0skq6.js → studio-qgh13jtz.js} +4 -4
- package/dist/chunks/studio-qmn1xc24.js +5 -0
- package/dist/chunks/studio-qwdqwkj0.js +5 -0
- package/dist/chunks/{studio-t6b6qe31.js → studio-r5qy30vx.js} +4 -4
- package/dist/chunks/studio-rj9eamf8.js +5 -0
- package/dist/chunks/studio-rptgsk96.js +5 -0
- package/dist/chunks/studio-rthyg42z.js +928 -0
- package/dist/chunks/studio-s19tp1xr.js +5 -0
- package/dist/chunks/studio-s32578pn.js +5 -0
- package/dist/chunks/studio-svb7yyve.js +5 -0
- package/dist/chunks/studio-syreb644.js +5 -0
- package/dist/chunks/studio-tf9jryb1.js +10 -0
- package/dist/chunks/studio-tfkznv39.js +5 -0
- package/dist/chunks/studio-tft6r105.js +5 -0
- package/dist/chunks/studio-txf2kysx.js +5 -0
- package/dist/chunks/studio-v8867ddv.js +12 -0
- package/dist/chunks/studio-vxq7fcvv.js +5 -0
- package/dist/chunks/studio-w4rz9hdk.js +5 -0
- package/dist/chunks/studio-wbcjbhy1.js +9 -0
- package/dist/chunks/studio-wc649wss.js +5 -0
- package/dist/chunks/studio-wys23mxz.js +5 -0
- package/dist/chunks/studio-x1x167jh.js +5 -0
- package/dist/chunks/studio-x9hsze61.js +5 -0
- package/dist/chunks/studio-y0n7yxea.js +9 -0
- package/dist/chunks/studio-y3ahhdpx.js +5 -0
- package/dist/chunks/studio-z97c48fk.js +5 -0
- package/dist/chunks/studio-zat62m0c.js +5 -0
- package/dist/chunks/studio-zcd2e7yz.js +5 -0
- package/dist/chunks/studio-zz9qe3rw.js +64 -0
- package/dist/chunks/swatch-group-ewh24n1f.js +4 -0
- package/dist/chunks/tabs-f5cw3tgp.js +4 -0
- package/dist/chunks/textfield-wewc8rq2.js +4 -0
- package/dist/chunks/toast-1gv0h53h.js +4 -0
- package/dist/chunks/toast-host-1yg5ar8d.js +4 -0
- package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
- package/dist/chunks/tooltip-yypz28gq.js +4 -0
- package/dist/chunks/tree-9xa4hm7n.js +4 -0
- package/dist/chunks/tsMode-epyfz1hv.js +14 -0
- package/dist/chunks/workspace-dz7nxfhv.js +4 -0
- package/dist/chunks/workspace-home-xsd7hkjw.js +4 -0
- package/dist/chunks/ws-client-bv552sfx.js +4 -0
- package/dist/iframe-entry.js +20 -16
- package/dist/manifest.json +77 -63
- package/dist/studio.js +106 -107
- package/dist/workers/ts.worker.js +3 -3
- package/package.json +17 -16
- package/src/about/about-modal.ts +4 -3
- package/src/account/action-flow.ts +45 -38
- package/src/account-status.ts +7 -2
- package/src/browse/component-examples.ts +272 -0
- package/src/browse/library-commands.ts +64 -104
- package/src/browse/library-layouts.ts +270 -53
- package/src/browse/library-model.ts +194 -134
- package/src/browse/library-pane.ts +748 -440
- package/src/browse/library-preview.ts +161 -26
- package/src/browse/library-source.ts +308 -41
- package/src/browse/preview-root.ts +78 -0
- package/src/browse/preview-style.ts +155 -0
- package/src/canvas/asset-refs.ts +40 -10
- package/src/canvas/asset-resolve.ts +19 -23
- package/src/canvas/canvas-helpers.ts +7 -6
- package/src/canvas/canvas-live-render.ts +260 -77
- package/src/canvas/canvas-origin.ts +37 -12
- package/src/canvas/canvas-page-context.ts +112 -0
- package/src/canvas/canvas-patcher.ts +30 -30
- package/src/canvas/canvas-perf.ts +11 -5
- package/src/canvas/canvas-render.ts +175 -148
- package/src/canvas/canvas-surface.ts +5 -3
- package/src/canvas/canvas-utils.ts +147 -61
- package/src/canvas/dialog-path.ts +9 -4
- package/src/canvas/dialog-state.ts +1 -2
- package/src/canvas/diff-marks.ts +9 -16
- package/src/canvas/diff-toolbar.ts +8 -7
- package/src/canvas/edit-width-drag.ts +4 -1
- package/src/canvas/edit-width.ts +1 -3
- package/src/canvas/iframe-channel.ts +27 -13
- package/src/canvas/iframe-drop.ts +120 -12
- package/src/canvas/iframe-editable-root.ts +29 -16
- package/src/canvas/iframe-entry.ts +104 -75
- package/src/canvas/iframe-eval.ts +73 -49
- package/src/canvas/iframe-host.ts +269 -158
- package/src/canvas/iframe-inline-edit.ts +49 -30
- package/src/canvas/iframe-insert.ts +5 -4
- package/src/canvas/iframe-interaction.ts +30 -25
- package/src/canvas/iframe-keys.ts +11 -0
- package/src/canvas/iframe-overlay.ts +1 -1
- package/src/canvas/iframe-patch.ts +25 -21
- package/src/canvas/iframe-position.ts +12 -6
- package/src/canvas/iframe-protocol.ts +36 -21
- package/src/canvas/iframe-render.ts +84 -35
- package/src/canvas/iframe-slash.ts +24 -11
- package/src/canvas/iframe-subtree.ts +10 -3
- package/src/canvas/npm-modules.ts +22 -0
- package/src/canvas/path-mapping.ts +19 -12
- package/src/canvas/popover-path.ts +7 -3
- package/src/canvas/popover-state.ts +1 -2
- package/src/canvas/preview-navigate.ts +16 -0
- package/src/canvas/repeater-sources.ts +200 -0
- package/src/canvas/serialize-scope.ts +13 -5
- package/src/canvas/stage-scrollbar.ts +7 -2
- package/src/canvas/surface-registry.ts +27 -3
- package/src/collab/collab-commands.ts +7 -2
- package/src/collab/collab-session.ts +84 -45
- package/src/collab/collab-state.ts +4 -3
- package/src/collab/monaco-binding.ts +16 -13
- package/src/collab/monaco-cursors.ts +5 -2
- package/src/commands/app-commands.ts +16 -6
- package/src/commands/budget.ts +13 -11
- package/src/commands/command-args.ts +103 -71
- package/src/commands/context.ts +55 -28
- package/src/commands/defaults.ts +69 -45
- package/src/commands/keymap.ts +56 -43
- package/src/commands/levels.ts +14 -8
- package/src/commands/live-context.ts +9 -7
- package/src/commands/reference.ts +2 -1
- package/src/commands/registry.ts +22 -11
- package/src/commands/run-reported.ts +15 -10
- package/src/component-props.ts +46 -30
- package/src/content/collection-match.ts +11 -9
- package/src/content/collection-pages.ts +412 -0
- package/src/content/content-collections.ts +270 -0
- package/src/content/draft-state.ts +4 -3
- package/src/content/entry-commands.ts +54 -62
- package/src/content/entry-editor.ts +137 -32
- package/src/content/entry-fields.ts +25 -8
- package/src/content/entry-inspector.ts +225 -0
- package/src/content/entry-model.ts +38 -15
- package/src/content/entry-open.ts +80 -0
- package/src/content/entry-summaries.ts +440 -0
- package/src/content/file-record-ids.ts +80 -0
- package/src/content/file-records.ts +125 -0
- package/src/content/page-summaries.ts +129 -0
- package/src/content/record-entry.ts +201 -0
- package/src/content/writing-banner.ts +177 -0
- package/src/create/add-new-commands.ts +185 -0
- package/src/create/add-new-flow.ts +1116 -0
- package/src/create/add-new.ts +1014 -0
- package/src/create/element-name.ts +121 -0
- package/src/editor/canvas-context-menu.ts +1 -2
- package/src/editor/canvas-slash-bridge.ts +3 -6
- package/src/editor/content-slice.ts +16 -14
- package/src/editor/context-menu.ts +35 -22
- package/src/editor/convert-targets.ts +30 -35
- package/src/editor/convert-to-component.ts +78 -48
- package/src/editor/convert-to-repeater.ts +34 -22
- package/src/editor/editable-tags.ts +17 -2
- package/src/editor/file-drop-action.ts +29 -22
- package/src/editor/inline-edit-apply.ts +79 -17
- package/src/editor/inline-edit.ts +76 -50
- package/src/editor/inline-format.ts +59 -56
- package/src/editor/inline-link.ts +40 -15
- package/src/editor/insert-component.ts +91 -0
- package/src/editor/insert-zone-action.ts +14 -5
- package/src/editor/merge-tags.ts +58 -19
- package/src/editor/repeater-scope.ts +39 -28
- package/src/editor/shortcuts.ts +76 -42
- package/src/editor/slash-menu.ts +52 -14
- package/src/files/asset-versions.ts +4 -4
- package/src/files/components.ts +89 -20
- package/src/files/elements.ts +5 -6
- package/src/files/file-ops.ts +92 -41
- package/src/files/files.ts +248 -239
- package/src/files/fs-events.ts +18 -7
- package/src/files/media-meta.ts +97 -2
- package/src/files/media-paths.ts +3 -0
- package/src/files/media-types.ts +55 -0
- package/src/files/media-upload.ts +209 -52
- package/src/files/new-file-name.ts +156 -0
- package/src/files/serialize-document.ts +15 -5
- package/src/format/constraints.ts +1 -1
- package/src/format/convert-file.ts +27 -13
- package/src/format/format-choices.ts +2 -1
- package/src/format/format-host.ts +91 -50
- package/src/github/github-auth-status.ts +27 -3
- package/src/github/github-auth.ts +21 -11
- package/src/github/github-publish.ts +28 -23
- package/src/grid/cell-editors.ts +46 -31
- package/src/grid/cell-popovers.ts +5 -3
- package/src/grid/edit-buffer.ts +10 -9
- package/src/grid/grid-controller.ts +25 -23
- package/src/grid/grid-layout.ts +21 -5
- package/src/grid/grid-open.ts +3 -33
- package/src/grid/grid-panel.ts +65 -6
- package/src/grid/grid-reveal.ts +34 -0
- package/src/grid/grid-source.ts +9 -31
- package/src/grid/grid-view.ts +45 -23
- package/src/grid/redirects-grid.ts +14 -5
- package/src/grid/redirects.ts +16 -14
- package/src/grid/schema-columns.ts +25 -19
- package/src/grid/sources/connector-source.ts +47 -20
- package/src/grid/sources/content-source.ts +100 -31
- package/src/grid/sources/csv-file-source.ts +2 -2
- package/src/grid/tabulator-tables.d.ts +61 -34
- package/src/hosting/document.ts +2 -2
- package/src/hosting/stage.ts +7 -7
- package/src/i18n/i18n-commands.ts +3 -3
- package/src/media/media-commands.ts +181 -0
- package/src/media/media-library-model.ts +232 -0
- package/src/media/media-library.ts +1283 -0
- package/src/media/media-pane.ts +51 -20
- package/src/new-project/add-repo-modal.ts +20 -19
- package/src/new-project/import-tab.ts +10 -14
- package/src/new-project/location-fields.ts +2 -1
- package/src/new-project/new-project-modal.ts +12 -9
- package/src/packages/jxsuite-update.ts +4 -3
- package/src/packages/pull-package-sync.ts +26 -25
- package/src/page-params.ts +97 -68
- package/src/panels/activity-panel.ts +38 -14
- package/src/panels/ai-chat/attached-context.ts +13 -7
- package/src/panels/ai-chat/chat-markdown.ts +8 -8
- package/src/panels/ai-chat/chat-view.ts +80 -73
- package/src/panels/ai-chat/composer.ts +30 -33
- package/src/panels/ai-chat/sessions-view.ts +1 -2
- package/src/panels/ai-panel.ts +23 -20
- package/src/panels/block-action-bar.ts +57 -46
- package/src/panels/bottom-dock.ts +5 -3
- package/src/panels/canvas-dnd-bridge.ts +36 -26
- package/src/panels/chat-panel.ts +6 -6
- package/src/panels/collections-panel.ts +306 -0
- package/src/panels/component-preview.ts +35 -13
- package/src/panels/data-explorer.ts +63 -26
- package/src/panels/data-grid.ts +18 -11
- package/src/panels/dnd.ts +115 -138
- package/src/panels/editors.ts +52 -21
- package/src/panels/elements-panel.ts +19 -5
- package/src/panels/empty-state.ts +2 -2
- package/src/panels/events-panel.ts +84 -69
- package/src/panels/formula-workspace.ts +78 -54
- package/src/panels/frontmatter-fields.ts +33 -28
- package/src/panels/git-diff-open.ts +10 -6
- package/src/panels/head-panel.ts +488 -202
- package/src/panels/i18n-panel.ts +20 -12
- package/src/panels/imports-panel.ts +25 -47
- package/src/panels/jump-bar.ts +75 -31
- package/src/panels/layers-panel.ts +130 -101
- package/src/panels/left-panel.ts +25 -11
- package/src/panels/navigator-panels.ts +23 -11
- package/src/panels/pane-context.ts +140 -49
- package/src/panels/pane-grid.ts +55 -26
- package/src/panels/panel-registry.ts +36 -46
- package/src/panels/properties-panel.ts +182 -124
- package/src/panels/quick-search.ts +53 -31
- package/src/panels/right-panel.ts +201 -45
- package/src/panels/seo-modal.ts +54 -125
- package/src/panels/settings-menu.ts +63 -61
- package/src/panels/settings-pane.ts +268 -162
- package/src/panels/signals-panel.ts +156 -135
- package/src/panels/site-model.ts +367 -0
- package/src/panels/site-panel.ts +638 -0
- package/src/panels/statement-editor.ts +230 -140
- package/src/panels/style-panel.ts +253 -206
- package/src/panels/style-utils.ts +114 -51
- package/src/panels/stylebook-doc.ts +195 -60
- package/src/panels/stylebook-layers-panel.ts +48 -89
- package/src/panels/stylebook-panel.ts +60 -27
- package/src/panels/styles-panel.ts +327 -0
- package/src/panels/tab-drop.ts +27 -11
- package/src/panels/tab-strip.ts +143 -49
- package/src/platform-errors.ts +57 -43
- package/src/platform.ts +59 -31
- package/src/platforms/cloud.ts +373 -176
- package/src/platforms/default-platform.ts +14 -8
- package/src/platforms/devserver.ts +180 -142
- package/src/platforms/read-batcher.ts +16 -8
- package/src/project-list.ts +2 -1
- package/src/publish/deploy-checklist.ts +20 -9
- package/src/publish/pages-service.ts +66 -27
- package/src/publish/publish-changes.ts +491 -0
- package/src/publish/publish-commands.ts +88 -22
- package/src/publish/publish-ids.ts +49 -0
- package/src/publish/publish-panel.ts +10 -6
- package/src/publish/publish-quick.ts +148 -0
- package/src/publish/publish-workspace.ts +926 -0
- package/src/publish/source-control.ts +907 -0
- package/src/recent-projects.ts +15 -8
- package/src/resize-edges.ts +26 -36
- package/src/services/a11y-report.ts +26 -19
- package/src/services/agent-seed.ts +23 -11
- package/src/services/ai-ask.ts +9 -12
- package/src/services/ai-command-tools.ts +68 -62
- package/src/services/ai-import-tools.ts +80 -67
- package/src/services/ai-models.ts +17 -13
- package/src/services/ai-project-tools.ts +68 -32
- package/src/services/ai-session-store.ts +19 -10
- package/src/services/ai-system-prompt.ts +46 -20
- package/src/services/ai-tools.ts +71 -27
- package/src/services/ai-write-report.ts +20 -12
- package/src/services/ai-writes.ts +4 -4
- package/src/services/automation.ts +74 -51
- package/src/services/cem-export.ts +149 -58
- package/src/services/cf-settings.ts +4 -4
- package/src/services/clock.ts +6 -1
- package/src/services/code-services.ts +37 -31
- package/src/services/connection.ts +2 -2
- package/src/services/context-manager.ts +14 -10
- package/src/services/context-resolver.ts +20 -8
- package/src/services/data-service.ts +19 -15
- package/src/services/directory-picker.ts +20 -14
- package/src/services/document-assistant.ts +39 -19
- package/src/services/gated-registry.ts +10 -6
- package/src/services/harness/chat-reducer.ts +23 -1
- package/src/services/import-client.ts +91 -38
- package/src/services/import-seed.ts +8 -2
- package/src/services/jx-validate.ts +28 -31
- package/src/services/live-preview.ts +0 -0
- package/src/services/live-surfaces.ts +6 -3
- package/src/services/model-uri.ts +10 -2
- package/src/services/module-preloads.ts +12 -8
- package/src/services/monaco-buffer.ts +43 -24
- package/src/services/monaco-lazy.ts +7 -8
- package/src/services/monaco-setup.ts +23 -16
- package/src/services/notify.ts +44 -17
- package/src/services/popover-report.ts +25 -10
- package/src/services/preview-eval.ts +20 -8
- package/src/services/profile.ts +13 -6
- package/src/services/project-path.ts +13 -10
- package/src/services/references.ts +0 -0
- package/src/services/render-critic.ts +29 -9
- package/src/services/settings/definitions.ts +25 -14
- package/src/services/settings/kernel.ts +13 -4
- package/src/services/settings/write-queue.ts +9 -9
- package/src/services/token-lint.ts +12 -10
- package/src/services/tool-executor.ts +17 -5
- package/src/services/tool-outcomes.ts +44 -24
- package/src/services/trusted-types.ts +24 -7
- package/src/settings/contexts-section.ts +11 -8
- package/src/settings/contributed-section.ts +128 -70
- package/src/settings/css-vars-editor.ts +119 -32
- package/src/settings/defs-editor.ts +38 -35
- package/src/settings/developer-panels.ts +43 -0
- package/src/settings/extension-rows.ts +16 -8
- package/src/settings/extension-sections.ts +42 -14
- package/src/settings/extensions-section.ts +4 -1
- package/src/settings/general-settings.ts +101 -28
- package/src/settings/locales-section.ts +20 -12
- package/src/settings/preferences-dialog.ts +17 -7
- package/src/settings/preferences-keymap.ts +7 -5
- package/src/settings/preferences-sections.ts +11 -5
- package/src/settings/project-sections.ts +28 -11
- package/src/settings/schema-field-ui.ts +12 -1
- package/src/settings/section-registry.ts +116 -11
- package/src/settings/settings-dialog.ts +192 -0
- package/src/settings/settings-document.ts +186 -166
- package/src/shell/tree.ts +6 -5
- package/src/shell.ts +536 -477
- package/src/site-context.ts +101 -32
- package/src/state.ts +68 -57
- package/src/store.ts +54 -34
- package/src/studio.ts +219 -116
- package/src/style/live-preview.ts +1 -1
- package/src/style/project-styles.ts +40 -7
- package/src/style/stylebook-specimens.ts +89 -0
- package/src/style/stylebook-target.ts +26 -0
- package/src/style/tag-inheritance.ts +105 -0
- package/src/style/token-ref.ts +5 -4
- package/src/style/variables-focus.ts +61 -0
- package/src/style/variables-view.ts +235 -0
- package/src/surfaces/about.ts +18 -19
- package/src/surfaces/add-new.json +1482 -0
- package/src/surfaces/add-new.ts +325 -0
- package/src/surfaces/add-repo.ts +17 -19
- package/src/surfaces/ai-chat.ts +33 -38
- package/src/surfaces/ai-credentials-form.ts +6 -16
- package/src/surfaces/ai-managed-connect.ts +3 -4
- package/src/surfaces/ai-model-picker.ts +3 -5
- package/src/surfaces/block-action-bar.ts +22 -11
- package/src/surfaces/boot-failure.json +4 -3
- package/src/surfaces/boot-failure.ts +4 -5
- package/src/surfaces/bottom-dock.json +1 -1
- package/src/surfaces/bottom-dock.ts +9 -18
- package/src/surfaces/canvas-stage.json +30 -19
- package/src/surfaces/canvas-stage.ts +17 -16
- package/src/surfaces/cf-account-picker.ts +17 -18
- package/src/surfaces/collections-panel.json +615 -0
- package/src/surfaces/collections-panel.ts +168 -0
- package/src/surfaces/commandbar.json +241 -96
- package/src/surfaces/commandbar.ts +145 -105
- package/src/surfaces/convert-repeater.ts +17 -19
- package/src/surfaces/data-actions.ts +9 -7
- package/src/surfaces/dialog.ts +26 -28
- package/src/surfaces/diff-toolbar.ts +9 -7
- package/src/surfaces/empty-state.json +1 -1
- package/src/surfaces/empty-state.ts +7 -10
- package/src/surfaces/entry-editor.json +136 -0
- package/src/surfaces/entry-editor.ts +35 -11
- package/src/surfaces/entry-inspector.json +371 -0
- package/src/surfaces/entry-inspector.ts +143 -0
- package/src/surfaces/expression-editor.ts +11 -25
- package/src/surfaces/files-panel.ts +27 -14
- package/src/surfaces/formula-palette.ts +4 -5
- package/src/surfaces/github-auth.ts +16 -20
- package/src/surfaces/github-publish.ts +17 -22
- package/src/surfaces/grid-cell.ts +30 -31
- package/src/surfaces/grid-open.ts +10 -14
- package/src/surfaces/grid-panel.ts +13 -9
- package/src/surfaces/grid-replace.ts +13 -13
- package/src/surfaces/grid-views.ts +15 -18
- package/src/surfaces/inspector-dock.json +162 -14
- package/src/surfaces/inspector-dock.ts +59 -31
- package/src/surfaces/jump-bar.ts +5 -6
- package/src/surfaces/jxsuite-update.ts +16 -22
- package/src/surfaces/library-pane.json +670 -437
- package/src/surfaces/library-pane.ts +111 -77
- package/src/surfaces/logic-panel.ts +17 -30
- package/src/surfaces/logic-workspace.ts +13 -15
- package/src/surfaces/media-browser.json +62 -6
- package/src/surfaces/media-browser.ts +26 -11
- package/src/surfaces/media-field.json +1 -1
- package/src/surfaces/media-field.ts +4 -5
- package/src/surfaces/media-library.json +1586 -0
- package/src/surfaces/media-library.ts +282 -0
- package/src/surfaces/media-pane.ts +8 -7
- package/src/surfaces/media-pick-dialog.json +71 -0
- package/src/surfaces/media-pick-dialog.ts +132 -0
- package/src/surfaces/menu.ts +47 -23
- package/src/surfaces/navigator-dock.ts +11 -12
- package/src/surfaces/new-project.ts +27 -26
- package/src/surfaces/pane-context.json +144 -77
- package/src/surfaces/pane-context.ts +44 -25
- package/src/surfaces/pane-grid.ts +15 -10
- package/src/surfaces/panel-activity.ts +5 -6
- package/src/surfaces/panel-data.ts +3 -4
- package/src/surfaces/panel-deploy-checklist.json +12 -6
- package/src/surfaces/panel-deploy-checklist.ts +8 -7
- package/src/surfaces/panel-elements.ts +5 -7
- package/src/surfaces/panel-i18n.ts +5 -7
- package/src/surfaces/panel-imports.ts +6 -13
- package/src/surfaces/panel-outline.ts +25 -19
- package/src/surfaces/panel-page.json +72 -2
- package/src/surfaces/panel-page.ts +49 -25
- package/src/surfaces/panel-problems.ts +5 -7
- package/src/surfaces/panel-signals.json +1 -1
- package/src/surfaces/panel-signals.ts +25 -39
- package/src/surfaces/panel-stylebook-layers.json +71 -204
- package/src/surfaces/panel-stylebook-layers.ts +5 -29
- package/src/surfaces/preferences.json +120 -48
- package/src/surfaces/preferences.ts +29 -11
- package/src/surfaces/progress-modal.ts +15 -9
- package/src/surfaces/properties-panel.json +1 -1
- package/src/surfaces/properties-panel.ts +20 -42
- package/src/surfaces/publish-quick.json +428 -0
- package/src/surfaces/publish-quick.ts +165 -0
- package/src/surfaces/publish-workspace.json +2892 -0
- package/src/surfaces/publish-workspace.ts +391 -0
- package/src/surfaces/publish.ts +18 -18
- package/src/surfaces/push-plan.ts +7 -8
- package/src/surfaces/rail.json +1 -159
- package/src/surfaces/rail.ts +22 -79
- package/src/surfaces/reference-field.ts +11 -15
- package/src/surfaces/schema-builder.ts +16 -22
- package/src/surfaces/schema-form.json +10 -2
- package/src/surfaces/schema-form.ts +17 -25
- package/src/surfaces/secret-field.ts +9 -6
- package/src/surfaces/seo.json +1 -1
- package/src/surfaces/seo.ts +21 -15
- package/src/surfaces/settings-contexts.ts +9 -7
- package/src/surfaces/settings-contributed.json +5 -5
- package/src/surfaces/settings-contributed.ts +32 -12
- package/src/surfaces/settings-css-vars.json +44 -36
- package/src/surfaces/settings-css-vars.ts +82 -16
- package/src/surfaces/settings-defs.json +2 -2
- package/src/surfaces/settings-defs.ts +17 -21
- package/src/surfaces/settings-deploy.json +2 -15
- package/src/surfaces/settings-deploy.ts +9 -16
- package/src/surfaces/settings-dialog.json +51 -0
- package/src/surfaces/settings-dialog.ts +169 -0
- package/src/surfaces/settings-extensions.ts +5 -6
- package/src/surfaces/settings-head.ts +33 -39
- package/src/surfaces/settings-locales.ts +8 -20
- package/src/surfaces/settings-overview.json +3 -3
- package/src/surfaces/settings-overview.ts +14 -8
- package/src/surfaces/settings-packages.ts +8 -7
- package/src/surfaces/settings-pane.json +269 -46
- package/src/surfaces/settings-pane.ts +88 -36
- package/src/surfaces/settings-rawjson.ts +5 -6
- package/src/surfaces/shell.json +2 -1
- package/src/surfaces/shell.ts +1 -2
- package/src/surfaces/site-panel.json +1029 -0
- package/src/surfaces/site-panel.ts +233 -0
- package/src/surfaces/slash-menu.json +63 -21
- package/src/surfaces/slash-menu.ts +42 -9
- package/src/surfaces/statements.ts +13 -18
- package/src/surfaces/statusbar.ts +56 -29
- package/src/surfaces/style-panel.ts +18 -31
- package/src/surfaces/stylebook-chrome.ts +3 -5
- package/src/surfaces/styles-panel.json +735 -0
- package/src/surfaces/styles-panel.ts +195 -0
- package/src/surfaces/styles-variables.json +149 -0
- package/src/surfaces/styles-variables.ts +145 -0
- package/src/surfaces/tab-strip.json +4 -4
- package/src/surfaces/tab-strip.ts +14 -13
- package/src/surfaces/target-line.ts +6 -7
- package/src/surfaces/welcome.ts +6 -8
- package/src/surfaces/writing-banner.json +94 -0
- package/src/surfaces/writing-banner.ts +80 -0
- package/src/tabs/bare-repeaters.ts +101 -0
- package/src/tabs/patch-ops.ts +4 -3
- package/src/tabs/project-config.ts +32 -21
- package/src/tabs/selection.ts +36 -8
- package/src/tabs/tab.ts +99 -48
- package/src/tabs/transact.ts +98 -53
- package/src/types.ts +53 -43
- package/src/ui/ai-credentials-form.ts +10 -13
- package/src/ui/ai-model-picker.ts +3 -3
- package/src/ui/cf-account-picker.ts +7 -9
- package/src/ui/color-selector.ts +9 -5
- package/src/ui/dynamic-slot.ts +7 -8
- package/src/ui/expression-editor.ts +112 -105
- package/src/ui/form-controls.ts +104 -56
- package/src/ui/formula-catalog.ts +239 -230
- package/src/ui/formula-chips.ts +33 -18
- package/src/ui/layers.ts +57 -31
- package/src/ui/media-picker.ts +300 -47
- package/src/ui/popover-surface.ts +20 -12
- package/src/ui/progress-modal.ts +13 -8
- package/src/ui/regions.ts +14 -12
- package/src/ui/schema-form.ts +372 -97
- package/src/ui/surface.ts +71 -8
- package/src/ui/timing.ts +9 -0
- package/src/ui/value-source.ts +44 -31
- package/src/ui/virtual-window.ts +29 -3
- package/src/utils/base64.ts +6 -4
- package/src/utils/edit-display.ts +366 -111
- package/src/utils/element-selectors.ts +3 -2
- package/src/utils/google-fonts.ts +15 -14
- package/src/utils/inherited-style.ts +18 -20
- package/src/utils/link-target.ts +1 -1
- package/src/utils/local-day.ts +18 -0
- package/src/utils/preview-format.ts +25 -3
- package/src/utils/strip-events.ts +49 -22
- package/src/utils/studio-utils.ts +29 -14
- package/src/view.ts +2 -3
- package/src/workspace/pane-derive.ts +14 -16
- package/src/workspace/session.ts +81 -50
- package/src/workspace/tab-workspace.ts +137 -0
- package/src/workspace/workspace-back.ts +189 -0
- package/src/workspace/workspace-home.ts +133 -0
- package/src/workspace/workspace-ids.ts +129 -0
- package/src/workspace/workspace-switch.ts +372 -0
- package/src/workspace/workspace.ts +165 -47
- package/styles/shell-frame.css +30 -7
- package/styles/shell-frame.json +15 -3
- package/dist/chunks/2020-va2wwra4.js +0 -4
- package/dist/chunks/adapter-f93pafd7.js +0 -4
- package/dist/chunks/cf-account-picker-af1h381v.js +0 -4
- package/dist/chunks/cf-settings-125tdm0w.js +0 -4
- package/dist/chunks/color-area-jqhna8zy.js +0 -4
- package/dist/chunks/color-field-embq5ctg.js +0 -4
- package/dist/chunks/color-fpezvnkt.js +0 -4
- package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
- package/dist/chunks/combobox-773hdzyj.js +0 -4
- package/dist/chunks/components-ax2f1fnn.js +0 -4
- package/dist/chunks/content-source-108aqtk1.js +0 -4
- package/dist/chunks/convert-to-repeater-ry5rmppr.js +0 -4
- package/dist/chunks/dialog-mtm9fq5t.js +0 -4
- package/dist/chunks/editor-pfgdmkb0.js +0 -4
- package/dist/chunks/entry-commands-t0k1q0kx.js +0 -4
- package/dist/chunks/extension-sections-6mwh2hf8.js +0 -4
- package/dist/chunks/file-ops-meej5mqf.js +0 -4
- package/dist/chunks/files-44vp8a2s.js +0 -4
- package/dist/chunks/format-host-7q1petb9.js +0 -4
- package/dist/chunks/fs-events-h2mwnxaz.js +0 -4
- package/dist/chunks/git-panel-zngbymvd.js +0 -4
- package/dist/chunks/grid-view-sx9vynsp.js +0 -51
- package/dist/chunks/icons-p44xhjf0.js +0 -4
- package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
- package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
- package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
- package/dist/chunks/iframe-host-qk3ycq87.js +0 -4
- package/dist/chunks/index-wkyfjeqz.js +0 -4
- package/dist/chunks/jsonMode-s8kt9dsj.js +0 -13
- package/dist/chunks/jx-validate-psgd7vsx.js +0 -4
- package/dist/chunks/layers-panel-1kq2jyfk.js +0 -4
- package/dist/chunks/layers-xd92fg8d.js +0 -4
- package/dist/chunks/listbox-s8fkmnq8.js +0 -4
- package/dist/chunks/lit-html-ac4cwwr4.js +0 -4
- package/dist/chunks/media-picker-0svzkdyb.js +0 -4
- package/dist/chunks/menu-37d07z9m.js +0 -4
- package/dist/chunks/menu-5c55ea3d.js +0 -4
- package/dist/chunks/monaco-binding-z6r70pdt.js +0 -4
- package/dist/chunks/monaco-buffer-fz6gq5y7.js +0 -4
- package/dist/chunks/monaco-setup-q4axkgj7.js +0 -4
- package/dist/chunks/notify-0xgtn8q1.js +0 -4
- package/dist/chunks/number-field-gw7sq8rn.js +0 -4
- package/dist/chunks/parse-897fvqah.js +0 -4
- package/dist/chunks/platform-v1qctbe6.js +0 -4
- package/dist/chunks/popover-8htra4er.js +0 -4
- package/dist/chunks/publish-panel-ym1fmgq5.js +0 -4
- package/dist/chunks/quick-search-a54e6t5n.js +0 -4
- package/dist/chunks/references-gmqp82fs.js +0 -4
- package/dist/chunks/right-panel-v7t9awbk.js +0 -4
- package/dist/chunks/section-registry-vhyf3zsr.js +0 -4
- package/dist/chunks/select-n3v7gwas.js +0 -4
- package/dist/chunks/split-pff8f3ze.js +0 -4
- package/dist/chunks/studio-0bhx5hz6.js +0 -5
- package/dist/chunks/studio-0k1ddnyy.js +0 -6
- package/dist/chunks/studio-1b04pd0j.js +0 -64
- package/dist/chunks/studio-4dwbj6gb.js +0 -5
- package/dist/chunks/studio-4tanh828.js +0 -5
- package/dist/chunks/studio-55h4mstj.js +0 -4
- package/dist/chunks/studio-5tnvjkz4.js +0 -5
- package/dist/chunks/studio-60dqgb0c.js +0 -5
- package/dist/chunks/studio-61dp09qg.js +0 -9
- package/dist/chunks/studio-63epcrj2.js +0 -5
- package/dist/chunks/studio-74k29dy9.js +0 -5
- package/dist/chunks/studio-7vg6jcd3.js +0 -5
- package/dist/chunks/studio-7zx31knw.js +0 -9
- package/dist/chunks/studio-8bxk97km.js +0 -5
- package/dist/chunks/studio-933e30n4.js +0 -5
- package/dist/chunks/studio-98wnwhbg.js +0 -5
- package/dist/chunks/studio-9mccjwjh.js +0 -14
- package/dist/chunks/studio-a2ke1e4t.js +0 -5
- package/dist/chunks/studio-e3a2a6v3.js +0 -4
- package/dist/chunks/studio-e81q1vb9.js +0 -5
- package/dist/chunks/studio-epgrmqqm.js +0 -5
- package/dist/chunks/studio-ery42sqr.js +0 -4
- package/dist/chunks/studio-g1shz58g.js +0 -5
- package/dist/chunks/studio-gf0fz03c.js +0 -5
- package/dist/chunks/studio-gjtpe62q.js +0 -6
- package/dist/chunks/studio-gkskhg7m.js +0 -5
- package/dist/chunks/studio-gx4dnjzd.js +0 -5
- package/dist/chunks/studio-j03zga3y.js +0 -9
- package/dist/chunks/studio-jhpxeckz.js +0 -5
- package/dist/chunks/studio-k01r7ykp.js +0 -5
- package/dist/chunks/studio-kk7h30ne.js +0 -7
- package/dist/chunks/studio-kt1zqney.js +0 -5
- package/dist/chunks/studio-m3cwhvye.js +0 -5
- package/dist/chunks/studio-mcayt6hz.js +0 -5
- package/dist/chunks/studio-myjcghv3.js +0 -5
- package/dist/chunks/studio-n8bxwc3y.js +0 -4
- package/dist/chunks/studio-ngm8gvpb.js +0 -5
- package/dist/chunks/studio-nj5a01jy.js +0 -928
- package/dist/chunks/studio-pcgz8heb.js +0 -5
- package/dist/chunks/studio-qcsq0t15.js +0 -5
- package/dist/chunks/studio-qkstvve9.js +0 -5
- package/dist/chunks/studio-qv1pwd3c.js +0 -5
- package/dist/chunks/studio-rc6dvxjb.js +0 -7
- package/dist/chunks/studio-s8dmmz66.js +0 -5
- package/dist/chunks/studio-sp5xzbj4.js +0 -6
- package/dist/chunks/studio-szsjbj0g.js +0 -5
- package/dist/chunks/studio-t1xzawhr.js +0 -16
- package/dist/chunks/studio-tdcprbqb.js +0 -5
- package/dist/chunks/studio-vrmcjf9g.js +0 -7
- package/dist/chunks/studio-vyc0b4he.js +0 -10
- package/dist/chunks/studio-w0cgf6jg.js +0 -5
- package/dist/chunks/studio-w3hskzqk.js +0 -5
- package/dist/chunks/studio-xgrgcdyh.js +0 -9
- package/dist/chunks/studio-xz2yxfcb.js +0 -5
- package/dist/chunks/studio-y6n42tgs.js +0 -5
- package/dist/chunks/studio-yb560vxr.js +0 -5
- package/dist/chunks/studio-yn9f8vtx.js +0 -5
- package/dist/chunks/studio-yw05w8f0.js +0 -7
- package/dist/chunks/studio-z16sgavc.js +0 -5
- package/dist/chunks/studio-zey7zsdw.js +0 -12
- package/dist/chunks/studio-zyqn40w4.js +0 -5
- package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
- package/dist/chunks/tabs-jwthg40w.js +0 -4
- package/dist/chunks/textfield-spy3hc77.js +0 -4
- package/dist/chunks/toast-4d35zd64.js +0 -4
- package/dist/chunks/toast-host-8sjmfed3.js +0 -4
- package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
- package/dist/chunks/tree-h19v1jfz.js +0 -4
- package/dist/chunks/tsMode-2frah6h1.js +0 -14
- package/dist/chunks/workspace-zt81g1ms.js +0 -4
- package/dist/chunks/ws-client-n2bh4hkf.js +0 -4
- package/src/panels/frontmatter-panel.ts +0 -701
- package/src/panels/git-panel.ts +0 -1120
- package/src/surfaces/doc-header.json +0 -776
- package/src/surfaces/doc-header.ts +0 -231
- package/src/surfaces/git-panel.json +0 -1880
- package/src/surfaces/git-panel.ts +0 -272
package/src/services/ai-tools.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import { createToolDefinition } from "@jxsuite/ai/tools";
|
|
12
12
|
import type { ToolRegistry, ToolResult, WriteLedger } from "@jxsuite/ai/tools";
|
|
13
|
-
import type { JxMutableNode, JxPath
|
|
13
|
+
import type { JsonObject, JxMutableNode, JxPath } from "@jxsuite/schema/types";
|
|
14
14
|
import { getNodeAtPath } from "../state";
|
|
15
15
|
import type { Tab } from "../tabs/tab";
|
|
16
16
|
import {
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
snapshotBeforeWrite,
|
|
33
33
|
translateValidationError,
|
|
34
34
|
} from "./ai-write-report";
|
|
35
|
-
import type { RenderVerdict } from "./ai-write-report";
|
|
35
|
+
import type { CandidateDocument, RenderVerdict } from "./ai-write-report";
|
|
36
36
|
|
|
37
37
|
/* Re-exported from its new home so `ai-project-tools.ts` and the tests keep their import: the
|
|
38
38
|
translation moved with the verdict it belongs to (`ai-write-report.ts`), where every document
|
|
@@ -43,6 +43,14 @@ const PATH_DESCRIPTION =
|
|
|
43
43
|
"Path to a node in the document, as a JSON array of keys/indices from the root " +
|
|
44
44
|
'(e.g. ["children", 0, "children", 1]). Use read_document to discover valid paths.';
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* The node at `path`, typed as what {@link getNodeAtPath} actually answers: a path the model made up
|
|
48
|
+
* runs off the tree, and that is `undefined`, which every tool here reports as "No node exists".
|
|
49
|
+
*/
|
|
50
|
+
function nodeAt(doc: JxMutableNode, path: JxPath): JxMutableNode | undefined {
|
|
51
|
+
return getNodeAtPath(doc, path);
|
|
52
|
+
}
|
|
53
|
+
|
|
46
54
|
/** Steering error for document tools called with no active tab. */
|
|
47
55
|
function noDocError(): ToolResult {
|
|
48
56
|
return {
|
|
@@ -64,8 +72,8 @@ function noDocError(): ToolResult {
|
|
|
64
72
|
* @param {import("../tabs/tab").Tab} tab
|
|
65
73
|
* @param {(t: import("../tabs/tab").Tab) => void} mutationFn
|
|
66
74
|
* @param {string} summary
|
|
67
|
-
* @param {(doc:
|
|
68
|
-
* @param {((doc:
|
|
75
|
+
* @param {(doc: CandidateDocument) => Promise<string[]>} validate
|
|
76
|
+
* @param {((doc: CandidateDocument) => Promise<RenderVerdict>) | undefined} renderCheck
|
|
69
77
|
* @param {Record<string, string> | undefined} projectStyle
|
|
70
78
|
* @returns {Promise<import("@jxsuite/ai/tools").ToolResult>}
|
|
71
79
|
*/
|
|
@@ -74,8 +82,8 @@ async function applyAndValidate(
|
|
|
74
82
|
tab: Tab,
|
|
75
83
|
mutationFn: (t: Tab) => void,
|
|
76
84
|
summary: string,
|
|
77
|
-
validate: (doc:
|
|
78
|
-
renderCheck: ((doc:
|
|
85
|
+
validate: (doc: CandidateDocument) => Promise<string[]>,
|
|
86
|
+
renderCheck: ((doc: CandidateDocument) => Promise<RenderVerdict>) | undefined,
|
|
79
87
|
projectStyle: Record<string, string> | undefined,
|
|
80
88
|
): Promise<ToolResult> {
|
|
81
89
|
const deps = { getProjectStyle: () => projectStyle, renderCheck, validate };
|
|
@@ -109,9 +117,9 @@ async function applyAndValidate(
|
|
|
109
117
|
* @param {import("@jxsuite/ai/tools").ToolRegistry} registry
|
|
110
118
|
* @param {{
|
|
111
119
|
* getTab: () => import("../tabs/tab").Tab | null;
|
|
112
|
-
* validate?: (doc:
|
|
120
|
+
* validate?: (doc: CandidateDocument) => Promise<string[]>;
|
|
113
121
|
* saveFile?: (relPath: string, content: string) => Promise<void>;
|
|
114
|
-
* renderCheck?: (doc:
|
|
122
|
+
* renderCheck?: (doc: CandidateDocument) => Promise<{ ok: true } | { ok: false; error: string }>;
|
|
115
123
|
* projectStyle?: Record<string, string>;
|
|
116
124
|
* getProjectStyle?: () => Record<string, string> | undefined;
|
|
117
125
|
* findOpenTab?: (path: string) => import("../tabs/tab").Tab | null;
|
|
@@ -131,9 +139,9 @@ export function registerAiTools(
|
|
|
131
139
|
reloadTab,
|
|
132
140
|
}: {
|
|
133
141
|
getTab: () => Tab | null;
|
|
134
|
-
validate?: (doc:
|
|
142
|
+
validate?: (doc: CandidateDocument) => Promise<string[]>;
|
|
135
143
|
saveFile?: (relPath: string, content: string) => Promise<void>;
|
|
136
|
-
renderCheck?: (doc:
|
|
144
|
+
renderCheck?: (doc: CandidateDocument) => Promise<{ ok: true } | { ok: false; error: string }>;
|
|
137
145
|
projectStyle?: Record<string, string> | undefined;
|
|
138
146
|
/**
|
|
139
147
|
* Live variant of `projectStyle` — takes precedence; re-read per tool call so a project
|
|
@@ -195,9 +203,11 @@ export function registerAiTools(
|
|
|
195
203
|
if (!tab) {
|
|
196
204
|
return noDocError();
|
|
197
205
|
}
|
|
206
|
+
/* SAFETY: a strict tool runs only after the registry's `validate()` passed, which refuses
|
|
207
|
+
a `path` that is present but not an array. Its items are not checked; a key that does
|
|
208
|
+
not resolve makes `nodeAt` answer undefined, reported just below. */
|
|
198
209
|
const { path } = args as { path?: JxPath };
|
|
199
|
-
const node =
|
|
200
|
-
path && path.length > 0 ? getNodeAtPath(tab.doc.document, path) : tab.doc.document;
|
|
210
|
+
const node = path && path.length > 0 ? nodeAt(tab.doc.document, path) : tab.doc.document;
|
|
201
211
|
if (node === undefined) {
|
|
202
212
|
return { success: false, error: `No node exists at path ${JSON.stringify(path)}.` };
|
|
203
213
|
}
|
|
@@ -239,8 +249,12 @@ export function registerAiTools(
|
|
|
239
249
|
if (!tab) {
|
|
240
250
|
return noDocError();
|
|
241
251
|
}
|
|
252
|
+
/* SAFETY: a strict tool runs only after the registry's `validate()` passed: `path` is a
|
|
253
|
+
present array and `key` a present string. `value` declares no type, so it is any JSON
|
|
254
|
+
value or absent, all of which `JxNodeValue` includes. A `path` whose items do not resolve
|
|
255
|
+
is caught by `nodeAt` just below. */
|
|
242
256
|
const { path, key, value } = args as { path: JxPath; key: string; value?: JxNodeValue };
|
|
243
|
-
const node =
|
|
257
|
+
const node = nodeAt(tab.doc.document, path);
|
|
244
258
|
if (node === undefined) {
|
|
245
259
|
return { success: false, error: `No node exists at path ${JSON.stringify(path)}.` };
|
|
246
260
|
}
|
|
@@ -286,6 +300,11 @@ export function registerAiTools(
|
|
|
286
300
|
if (!tab) {
|
|
287
301
|
return noDocError();
|
|
288
302
|
}
|
|
303
|
+
/* SAFETY: a strict tool runs only after the registry's `validate()` passed: `parentPath` is
|
|
304
|
+
a present array, `node` a present object, and `index` a present number — or a numeric
|
|
305
|
+
string, which the validator also admits for an integer and `splice` coerces alike.
|
|
306
|
+
`node` is a model-written tree whose shape the schema check after the write judges, and
|
|
307
|
+
a `parentPath` that does not resolve is caught just below. */
|
|
289
308
|
const {
|
|
290
309
|
parentPath,
|
|
291
310
|
index,
|
|
@@ -295,7 +314,7 @@ export function registerAiTools(
|
|
|
295
314
|
index: number;
|
|
296
315
|
node: JxMutableNode;
|
|
297
316
|
};
|
|
298
|
-
const parent =
|
|
317
|
+
const parent = nodeAt(tab.doc.document, parentPath);
|
|
299
318
|
if (parent === undefined) {
|
|
300
319
|
return { success: false, error: `No node exists at path ${JSON.stringify(parentPath)}.` };
|
|
301
320
|
}
|
|
@@ -373,12 +392,12 @@ export function registerAiTools(
|
|
|
373
392
|
if (!tab) {
|
|
374
393
|
return noDocError();
|
|
375
394
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
};
|
|
381
|
-
if (
|
|
395
|
+
/* SAFETY: a strict tool runs only after the registry's `validate()` passed: `path` is a
|
|
396
|
+
present array and `property` a present string; a `path` that does not resolve is caught
|
|
397
|
+
just below. `value` is read untyped and stringified. */
|
|
398
|
+
const { path, property } = args as { path: JxPath; property: string };
|
|
399
|
+
const { value } = args;
|
|
400
|
+
if (nodeAt(tab.doc.document, path) === undefined) {
|
|
382
401
|
return { success: false, error: `No node exists at path ${JSON.stringify(path)}.` };
|
|
383
402
|
}
|
|
384
403
|
const prop = property;
|
|
@@ -420,8 +439,11 @@ export function registerAiTools(
|
|
|
420
439
|
if (!tab) {
|
|
421
440
|
return noDocError();
|
|
422
441
|
}
|
|
442
|
+
/* SAFETY: a strict tool runs only after the registry's `validate()` passed: `path` is a
|
|
443
|
+
present array and `value` a present string; a `path` that does not resolve is caught
|
|
444
|
+
just below. */
|
|
423
445
|
const { path, value } = args as { path: JxPath; value: string };
|
|
424
|
-
if (
|
|
446
|
+
if (nodeAt(tab.doc.document, path) === undefined) {
|
|
425
447
|
return { success: false, error: `No node exists at path ${JSON.stringify(path)}.` };
|
|
426
448
|
}
|
|
427
449
|
return applyAndValidate(
|
|
@@ -469,7 +491,10 @@ export function registerAiTools(
|
|
|
469
491
|
if (!tab) {
|
|
470
492
|
return noDocError();
|
|
471
493
|
}
|
|
472
|
-
|
|
494
|
+
/* SAFETY: a strict tool runs only after the registry's `validate()` passed, so `key` is a
|
|
495
|
+
present string. */
|
|
496
|
+
const { key } = args as { key: string };
|
|
497
|
+
const { value } = args;
|
|
473
498
|
if (tab.doc.document.state && tab.doc.document.state[key] !== undefined) {
|
|
474
499
|
return {
|
|
475
500
|
success: false,
|
|
@@ -482,6 +507,10 @@ export function registerAiTools(
|
|
|
482
507
|
/* `mutateAddDef` rather than `mutateUpdateProperty`: the latter deletes on "", which is
|
|
483
508
|
wrong for a state default (`"title": ""`). It also records the op, so the canvas, the
|
|
484
509
|
history and collaborators each get the edit as an edit. */
|
|
510
|
+
/* SAFETY: `value` is required, so the registry refused it missing or null; it is the
|
|
511
|
+
model's state entry, possibly a scalar default (`0`, `""`) the schema admits.
|
|
512
|
+
`mutateAddDef` only clones `def` and stores it under `state[key]`, never reading it
|
|
513
|
+
as the object its parameter names. */
|
|
485
514
|
(t) => mutateAddDef(t, key, value as Record<string, JsonValue>),
|
|
486
515
|
`Added state "${key}".`,
|
|
487
516
|
validate,
|
|
@@ -519,7 +548,10 @@ export function registerAiTools(
|
|
|
519
548
|
if (!tab) {
|
|
520
549
|
return noDocError();
|
|
521
550
|
}
|
|
522
|
-
|
|
551
|
+
/* SAFETY: a strict tool runs only after the registry's `validate()` passed, so `key` is a
|
|
552
|
+
present string. */
|
|
553
|
+
const { key } = args as { key: string };
|
|
554
|
+
const { value } = args;
|
|
523
555
|
if (!tab.doc.document.state || tab.doc.document.state[key] === undefined) {
|
|
524
556
|
return {
|
|
525
557
|
success: false,
|
|
@@ -535,6 +567,9 @@ export function registerAiTools(
|
|
|
535
567
|
if (value == null) {
|
|
536
568
|
mutateRemoveDef(t, key);
|
|
537
569
|
} else {
|
|
570
|
+
/* SAFETY: the model's state entry, possibly a scalar default the schema admits.
|
|
571
|
+
`mutateAddDef` only clones `def` and stores it under `state[key]`, never reading
|
|
572
|
+
it as the object its parameter names. */
|
|
538
573
|
mutateAddDef(t, key, value as Record<string, JsonValue>);
|
|
539
574
|
}
|
|
540
575
|
},
|
|
@@ -580,6 +615,9 @@ export function registerAiTools(
|
|
|
580
615
|
if (!tab) {
|
|
581
616
|
return noDocError();
|
|
582
617
|
}
|
|
618
|
+
/* SAFETY: a strict tool runs only after the registry's `validate()` passed: both paths are
|
|
619
|
+
present arrays, and `toIndex` a present number or numeric string (the validator admits
|
|
620
|
+
both for an integer). Paths that do not resolve are caught just below. */
|
|
583
621
|
const { fromPath, toParentPath, toIndex } = args as {
|
|
584
622
|
fromPath: JxPath;
|
|
585
623
|
toParentPath: JxPath;
|
|
@@ -588,13 +626,13 @@ export function registerAiTools(
|
|
|
588
626
|
if (fromPath.length < 2) {
|
|
589
627
|
return { success: false, error: "Cannot move the document root." };
|
|
590
628
|
}
|
|
591
|
-
if (
|
|
629
|
+
if (nodeAt(tab.doc.document, fromPath) === undefined) {
|
|
592
630
|
return {
|
|
593
631
|
success: false,
|
|
594
632
|
error: `No node exists at fromPath ${JSON.stringify(fromPath)}.`,
|
|
595
633
|
};
|
|
596
634
|
}
|
|
597
|
-
if (
|
|
635
|
+
if (nodeAt(tab.doc.document, toParentPath) === undefined) {
|
|
598
636
|
return {
|
|
599
637
|
success: false,
|
|
600
638
|
error: `No node exists at toParentPath ${JSON.stringify(toParentPath)}.`,
|
|
@@ -644,7 +682,10 @@ export function registerAiTools(
|
|
|
644
682
|
error: "File operations are not available in this environment.",
|
|
645
683
|
};
|
|
646
684
|
}
|
|
647
|
-
|
|
685
|
+
/* SAFETY: a strict tool runs only after the registry's `validate()` passed: `path` is a
|
|
686
|
+
present string and `content` a present JSON object (not an array, not null). Whether that
|
|
687
|
+
object is a Jx document is what `validate` and `renderCheck` below decide. */
|
|
688
|
+
const { path, content } = args as { path: string; content: JsonObject };
|
|
648
689
|
// Inside the project or not at all (ai.md §4): the platform write is given this path.
|
|
649
690
|
const relPath = normalizeRelPath(path);
|
|
650
691
|
if (relPath === null) {
|
|
@@ -728,7 +769,10 @@ export function registerAiTools(
|
|
|
728
769
|
error: "File operations are not available in this environment.",
|
|
729
770
|
};
|
|
730
771
|
}
|
|
731
|
-
|
|
772
|
+
/* SAFETY: a strict tool runs only after the registry's `validate()` passed: `path` is a
|
|
773
|
+
present string and `content` a present JSON object (not an array, not null). Whether that
|
|
774
|
+
object is a Jx document is what `validate` and `renderCheck` below decide. */
|
|
775
|
+
const { path, content } = args as { path: string; content: JsonObject };
|
|
732
776
|
const relPath = normalizeRelPath(path);
|
|
733
777
|
if (relPath === null) {
|
|
734
778
|
return invalidPathResult(path);
|
|
@@ -2,26 +2,27 @@
|
|
|
2
2
|
* Ai-write-report.ts — what the model is told after a document write, whoever made it.
|
|
3
3
|
*
|
|
4
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
|
-
*
|
|
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
7
|
* `services/ai-command-tools.ts` — so it lives here, in two functions the caller brackets its write
|
|
8
8
|
* with:
|
|
9
9
|
*
|
|
10
|
-
* 1. {@link snapshotBeforeWrite} reads the document's schema errors and render state BEFORE the
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* 1. {@link snapshotBeforeWrite} reads the document's schema errors and render state BEFORE the write,
|
|
11
|
+
* because the loop's signal (specs/ai.md §3.1) is "what did this edit newly introduce", not "is
|
|
12
|
+
* the document valid": a page that was already broken must not make every subsequent edit read
|
|
13
|
+
* as the culprit.
|
|
14
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
|
-
*
|
|
15
|
+
* fix hint the model can act on, running the render check only when rendering worked before, and
|
|
16
|
+
* appending the soft token-discipline hints to a success.
|
|
17
17
|
*
|
|
18
|
-
* The change stays applied either way (optimistic apply + undo, specs/ai.md §3.1); reporting the
|
|
19
|
-
* the agent loop self-correct on the next round.
|
|
18
|
+
* The change stays applied either way (optimistic apply + undo, specs/ai.md §3.1); reporting the
|
|
19
|
+
* errors lets the agent loop self-correct on the next round.
|
|
20
20
|
*
|
|
21
21
|
* @license MIT
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
import type { ToolResult } from "@jxsuite/ai/tools";
|
|
25
|
+
import type { JsonValue, JxMutableNode } from "@jxsuite/schema/types";
|
|
25
26
|
import { toRaw } from "../reactivity";
|
|
26
27
|
import type { Tab } from "../tabs/tab";
|
|
27
28
|
import { flagHardcodedTokens, formatTokenHints } from "./token-lint";
|
|
@@ -29,12 +30,19 @@ import { flagHardcodedTokens, formatTokenHints } from "./token-lint";
|
|
|
29
30
|
/** A render probe's answer: rendered, or the message it threw. */
|
|
30
31
|
export type RenderVerdict = { ok: true } | { ok: false; error: string };
|
|
31
32
|
|
|
33
|
+
/**
|
|
34
|
+
* A document as the validator and the render probe receive it: the live tree of an open tab, or the
|
|
35
|
+
* JSON a tool was handed (a `create_page` argument, a parsed `write_file` body) before anything has
|
|
36
|
+
* said it is a document. Judging that is what the two of them are for.
|
|
37
|
+
*/
|
|
38
|
+
export type CandidateDocument = JxMutableNode | JsonValue;
|
|
39
|
+
|
|
32
40
|
/** What a write reporter needs. Every member is what `registerAiTools` already takes by injection. */
|
|
33
41
|
export interface WriteReportDeps {
|
|
34
42
|
/** Schema errors for a document, as raw ajv sentences. */
|
|
35
|
-
validate: (doc:
|
|
43
|
+
validate: (doc: CandidateDocument) => Promise<string[]>;
|
|
36
44
|
/** The detached-DOM render probe, when the host has one. */
|
|
37
|
-
renderCheck?: ((doc:
|
|
45
|
+
renderCheck?: ((doc: CandidateDocument) => Promise<RenderVerdict>) | undefined;
|
|
38
46
|
/** The project's design tokens, read per call so a project opened mid-session contributes. */
|
|
39
47
|
getProjectStyle?: (() => Record<string, string> | undefined) | undefined;
|
|
40
48
|
}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* @docs studio/ai/chat
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import type {
|
|
25
|
+
import type { LiveMessage } from "@jxsuite/ai/messages";
|
|
26
26
|
import { createLedger } from "@jxsuite/ai/tools";
|
|
27
27
|
import type { AiWrite, WriteLedger } from "@jxsuite/ai/tools";
|
|
28
28
|
|
|
@@ -113,7 +113,7 @@ export function summarizeWrites(writes: AiWrite[]): string {
|
|
|
113
113
|
return failed > 0 ? `${failed} change${failed === 1 ? "" : "s"} failed` : "";
|
|
114
114
|
}
|
|
115
115
|
const files = `Changed ${paths.size} file${paths.size === 1 ? "" : "s"}`;
|
|
116
|
-
const diskPaths = new Set(applied.
|
|
116
|
+
const diskPaths = new Set(applied.flatMap((w) => (w.disk ? [w.path] : [])));
|
|
117
117
|
const parts = [files];
|
|
118
118
|
if (diskPaths.size > 0) {
|
|
119
119
|
parts.push(
|
|
@@ -150,13 +150,13 @@ export function resetAiWrites(): void {
|
|
|
150
150
|
* message in it belongs to some other conversation: filing there would draw "Changed 1 file", and
|
|
151
151
|
* Restore, under a reply that changed nothing.
|
|
152
152
|
*
|
|
153
|
-
* @param {readonly
|
|
153
|
+
* @param {readonly LiveMessage[]} messages
|
|
154
154
|
* @param {string} [userId] - The id of the user message this turn answers; without one, the whole
|
|
155
155
|
* transcript is the turn
|
|
156
156
|
* @returns {string | null} Null when the turn drew nothing (so it ran no tool either), or when its
|
|
157
157
|
* user message has left the transcript
|
|
158
158
|
*/
|
|
159
|
-
export function turnAnchor(messages: readonly
|
|
159
|
+
export function turnAnchor(messages: readonly LiveMessage[], userId?: string): string | null {
|
|
160
160
|
let anchor: string | null = null;
|
|
161
161
|
for (let index = messages.length - 1; index >= 0; index--) {
|
|
162
162
|
const message = messages[index]!;
|
|
@@ -37,10 +37,12 @@ import { seedProjectList } from "../project-list";
|
|
|
37
37
|
import { activeTab } from "../workspace/workspace";
|
|
38
38
|
import { shell } from "../shell";
|
|
39
39
|
import { collabState } from "../collab/collab-state";
|
|
40
|
+
import { isNonNullObject, isString } from "@jxsuite/schema/guards";
|
|
40
41
|
import { canvasPointAt, revealCanvasPath } from "../canvas/iframe-host";
|
|
41
42
|
import { probeIdle } from "./idle";
|
|
42
43
|
import type { CanvasPoint } from "../canvas/iframe-host";
|
|
43
44
|
import type { IdleOptions } from "./idle";
|
|
45
|
+
import type { CommandArgValues } from "../commands/command-args";
|
|
44
46
|
import type { CommandContext } from "../commands/context";
|
|
45
47
|
import type { AnyCommand, CommandRegistry } from "../commands/registry";
|
|
46
48
|
import type { PeerPresence } from "../collab/collab-state";
|
|
@@ -50,9 +52,6 @@ import type { GitBranchesResult, GitStatusResult, ProjectListEntry } from "../ty
|
|
|
50
52
|
import type { GitLogEntry } from "../shell";
|
|
51
53
|
import type { JxPath } from "../state";
|
|
52
54
|
|
|
53
|
-
/** Loosely-typed arguments, as they arrive from a manifest step, a palette prompt or a tool call. */
|
|
54
|
-
export type AutomationArgs = Record<string, unknown>;
|
|
55
|
-
|
|
56
55
|
/**
|
|
57
56
|
* What the hook needs that it cannot import.
|
|
58
57
|
*
|
|
@@ -93,13 +92,14 @@ export function isScriptable(command: AnyCommand): boolean {
|
|
|
93
92
|
// ─── The registry-gap declaration ─────────────────────────────────────────────
|
|
94
93
|
|
|
95
94
|
/**
|
|
96
|
-
*
|
|
95
|
+
* Why a manifest id the registry does not declare will never be one.
|
|
97
96
|
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
97
|
+
* There were three fates. `command` (a thing a user does, so it becomes a registry record) emptied
|
|
98
|
+
* when `media.browse` landed in `media/media-commands.ts`, the last of them; `seed` (a remote's
|
|
99
|
+
* state) is answered from {@link seedIds}. What is left is `refused`: §13.5 says the app will never
|
|
100
|
+
* provide it, and the manifest step is deleted.
|
|
101
101
|
*/
|
|
102
|
-
export type GapDisposition = "
|
|
102
|
+
export type GapDisposition = "refused";
|
|
103
103
|
|
|
104
104
|
export interface ManifestId {
|
|
105
105
|
disposition: GapDisposition;
|
|
@@ -118,19 +118,18 @@ export interface ManifestId {
|
|
|
118
118
|
* — only to explain, when the registry refuses an id, which of the three fates that id has.
|
|
119
119
|
*
|
|
120
120
|
* This is a countdown, in the idiom of the checker's own `TOGGLE_DEBT`: it may only shrink. It went
|
|
121
|
-
* 39 → 8 when the manifest converted,
|
|
122
|
-
* (`canvas/canvas-render.ts`)
|
|
121
|
+
* 39 → 8 when the manifest converted, 8 → 7 when `element.insertData` became `insert.data`
|
|
122
|
+
* (`canvas/canvas-render.ts`), and down to five when `media.browse` became a record of its own
|
|
123
|
+
* (`media/media-commands.ts`). What left: every `seed` entry, now read off {@link seedIds} and
|
|
123
124
|
* answered from the live registry rather than from a hand-kept list; every `toggle*` entry, which
|
|
124
|
-
* {@link TOGGLE_ID} refuses before this map is ever consulted; and every `command` entry
|
|
125
|
-
*
|
|
125
|
+
* {@link TOGGLE_ID} refuses before this map is ever consulted; and every `command` entry, each of
|
|
126
|
+
* whose records has landed.
|
|
126
127
|
*
|
|
127
|
-
* What is left is
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
* the same debt. Five `refused` entries are NOT a countdown: they are §13.5's normative refusals,
|
|
131
|
-
* and they stay so that a caller reaching for one gets the reason instead of "unknown command".
|
|
128
|
+
* What is left is one kind, and it is NOT a countdown: five `refused` entries, §13.5's normative
|
|
129
|
+
* refusals, which stay so that a caller reaching for one gets the reason instead of "unknown
|
|
130
|
+
* command".
|
|
132
131
|
*/
|
|
133
|
-
export const AUTOMATION_COMMANDS
|
|
132
|
+
export const AUTOMATION_COMMANDS = {
|
|
134
133
|
"file.contextMenu": {
|
|
135
134
|
disposition: "refused",
|
|
136
135
|
note: "opening a menu to press an item names a control; the ITEM is the command",
|
|
@@ -139,20 +138,25 @@ export const AUTOMATION_COMMANDS: Readonly<Record<string, ManifestId>> = {
|
|
|
139
138
|
disposition: "refused",
|
|
140
139
|
note: "matched RENDERED TEXT, which R1 of scripts/screenshots/README.md forbids; a row is addressed by its data-jx-path",
|
|
141
140
|
},
|
|
142
|
-
"media.browse": { disposition: "command", note: "media.browse, site-architecture.md §9.4" },
|
|
143
141
|
"project.showWelcome": {
|
|
144
142
|
disposition: "refused",
|
|
145
143
|
note: "cold start is a startup profile (?profile=fresh), not an action",
|
|
146
144
|
},
|
|
147
145
|
"settings.setSection": {
|
|
148
146
|
disposition: "refused",
|
|
149
|
-
note: 'mirrored the section registry\'s LABELS; say settings.open { section: "
|
|
147
|
+
note: 'mirrored the section registry\'s LABELS; say settings.open { section: "contexts" }',
|
|
150
148
|
},
|
|
151
149
|
"view.setStatus": {
|
|
152
150
|
disposition: "refused",
|
|
153
151
|
note: "the status bar is not staged — if a capture needs a calm shell, the app must BE calm",
|
|
154
152
|
},
|
|
155
|
-
}
|
|
153
|
+
} as const satisfies Readonly<Record<string, ManifestId>>;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* {@link AUTOMATION_COMMANDS} keyed for lookup by an arbitrary id. A Map rather than an index into
|
|
157
|
+
* the object, so an id such as `"constructor"` finds nothing instead of `Object.prototype`'s.
|
|
158
|
+
*/
|
|
159
|
+
const COMMAND_GAPS: ReadonlyMap<string, ManifestId> = new Map(Object.entries(AUTOMATION_COMMANDS));
|
|
156
160
|
|
|
157
161
|
// ─── The seed registry, under the Remote Rule ─────────────────────────────────
|
|
158
162
|
|
|
@@ -161,7 +165,7 @@ export interface SeedDefinition {
|
|
|
161
165
|
id: string;
|
|
162
166
|
/** The network or IPC boundary this seed stands in for. The Remote Rule, written down per seed. */
|
|
163
167
|
boundary: string;
|
|
164
|
-
run: (args:
|
|
168
|
+
run: (args: CommandArgValues) => void | Promise<void>;
|
|
165
169
|
}
|
|
166
170
|
|
|
167
171
|
/**
|
|
@@ -170,7 +174,7 @@ export interface SeedDefinition {
|
|
|
170
174
|
* Every one of these was a method on the old surface. Each writes state a USER writes, so each is a
|
|
171
175
|
* COMMAND — and a fixture that stages it photographs a state no session could have reached.
|
|
172
176
|
*/
|
|
173
|
-
export const REFUSED_SEEDS
|
|
177
|
+
export const REFUSED_SEEDS = {
|
|
174
178
|
openSettings: 'a user opens Settings — run("settings.open")',
|
|
175
179
|
select: 'a user selects a node — run("selection.set", { path })',
|
|
176
180
|
setActivity: 'a user picks a Navigator panel — run("navigator.showPanel", { panel })',
|
|
@@ -178,9 +182,12 @@ export const REFUSED_SEEDS: Readonly<Record<string, string>> = {
|
|
|
178
182
|
setStatus:
|
|
179
183
|
"the status bar reports what the app just did; staging it is the one lie the Remote Rule (studio.md §13.5) names outright",
|
|
180
184
|
setZoom: 'a user zooms — run("canvas.setZoom", { zoom })',
|
|
181
|
-
}
|
|
185
|
+
} as const satisfies Readonly<Record<string, string>>;
|
|
186
|
+
|
|
187
|
+
/** {@link REFUSED_SEEDS} keyed for lookup by an arbitrary seed name, as {@link COMMAND_GAPS} is. */
|
|
188
|
+
const SEED_REFUSALS: ReadonlyMap<string, string> = new Map(Object.entries(REFUSED_SEEDS));
|
|
182
189
|
|
|
183
|
-
function arrayArg<T>(args:
|
|
190
|
+
function arrayArg<T>(args: CommandArgValues, key: string): T[] {
|
|
184
191
|
const value = args[key];
|
|
185
192
|
if (value === undefined) {
|
|
186
193
|
return [];
|
|
@@ -188,23 +195,28 @@ function arrayArg<T>(args: AutomationArgs, key: string): T[] {
|
|
|
188
195
|
if (!Array.isArray(value)) {
|
|
189
196
|
throw new TypeError(`seed argument "${key}" must be an array`);
|
|
190
197
|
}
|
|
198
|
+
/* SAFETY: a seed's arguments are a fixture written against the boundary type it stands in for
|
|
199
|
+
(the screenshot manifest's `seed` steps), so only the container is checked here — exactly as
|
|
200
|
+
much as the remote it replaces would have checked before handing its JSON over. */
|
|
191
201
|
return value as T[];
|
|
192
202
|
}
|
|
193
203
|
|
|
194
|
-
function requiredArg<T>(args:
|
|
204
|
+
function requiredArg<T>(args: CommandArgValues, key: string): T {
|
|
195
205
|
const value = args[key];
|
|
196
|
-
if (value
|
|
206
|
+
if (!isNonNullObject(value)) {
|
|
197
207
|
throw new TypeError(`seed argument "${key}" must be an object`);
|
|
198
208
|
}
|
|
209
|
+
/* SAFETY: as in `arrayArg`: a fixture written against the boundary type it stands in for, of
|
|
210
|
+
which only the object container is checked here. */
|
|
199
211
|
return value as T;
|
|
200
212
|
}
|
|
201
213
|
|
|
202
|
-
function optionalString(args:
|
|
214
|
+
function optionalString(args: CommandArgValues, key: string): string | undefined {
|
|
203
215
|
const value = args[key];
|
|
204
216
|
if (value === undefined) {
|
|
205
217
|
return undefined;
|
|
206
218
|
}
|
|
207
|
-
if (
|
|
219
|
+
if (!isString(value)) {
|
|
208
220
|
throw new TypeError(`seed argument "${key}" must be a string`);
|
|
209
221
|
}
|
|
210
222
|
return value;
|
|
@@ -216,7 +228,9 @@ function optionalString(args: AutomationArgs, key: string): string | undefined {
|
|
|
216
228
|
* Each one writes exactly what its named boundary would have written, and nothing else — the git
|
|
217
229
|
* seed does not also open the Source Control panel, because a user does that.
|
|
218
230
|
*/
|
|
219
|
-
export function createSeeds(
|
|
231
|
+
export function createSeeds(
|
|
232
|
+
deps: Pick<AutomationDeps, "seedAssistantMessages" | "seedPublishConnected">,
|
|
233
|
+
): SeedDefinition[] {
|
|
220
234
|
return [
|
|
221
235
|
{
|
|
222
236
|
boundary: "the assistant's model stream",
|
|
@@ -252,10 +266,13 @@ export function createSeeds(deps: AutomationDeps): SeedDefinition[] {
|
|
|
252
266
|
id: "seed.publish",
|
|
253
267
|
run: (args) => {
|
|
254
268
|
const accountId = optionalString(args, "accountId");
|
|
255
|
-
|
|
269
|
+
const connected: Parameters<AutomationDeps["seedPublishConnected"]>[0] = {
|
|
256
270
|
deployment: requiredArg<PagesDeploymentInfo>(args, "deployment"),
|
|
257
|
-
|
|
258
|
-
|
|
271
|
+
};
|
|
272
|
+
if (accountId) {
|
|
273
|
+
connected.accountId = accountId;
|
|
274
|
+
}
|
|
275
|
+
deps.seedPublishConnected(connected);
|
|
259
276
|
},
|
|
260
277
|
},
|
|
261
278
|
{
|
|
@@ -264,9 +281,16 @@ export function createSeeds(deps: AutomationDeps): SeedDefinition[] {
|
|
|
264
281
|
run: (args) => {
|
|
265
282
|
// The working tree really is a remote here: the git-panel shot photographs whatever the
|
|
266
283
|
// Author happened to have dirty, because its project lives inside this repository.
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
284
|
+
/* SAFETY: as in `arrayArg`: a fixture written against the platform's git route answers it
|
|
285
|
+
stands in for, passed on as the route's JSON would have been, unchecked. */
|
|
286
|
+
const { status, branches, log } = args as {
|
|
287
|
+
status?: GitStatusResult;
|
|
288
|
+
branches?: GitBranchesResult;
|
|
289
|
+
log?: GitLogEntry[];
|
|
290
|
+
};
|
|
291
|
+
shell.git.status = status ?? null;
|
|
292
|
+
shell.git.branches = branches ?? null;
|
|
293
|
+
shell.git.logEntries = log ?? null;
|
|
270
294
|
shell.git.loading = false;
|
|
271
295
|
shell.git.error = null;
|
|
272
296
|
render();
|
|
@@ -293,12 +317,9 @@ export function createSeeds(deps: AutomationDeps): SeedDefinition[] {
|
|
|
293
317
|
* its `run`, never while building it, so the no-op deps below can never be called.
|
|
294
318
|
*/
|
|
295
319
|
export function seedIds(): string[] {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
seedPublishConnected: () => {},
|
|
300
|
-
} satisfies AutomationDeps;
|
|
301
|
-
return createSeeds(inert).map((seed) => seed.id);
|
|
320
|
+
return createSeeds({ seedAssistantMessages: () => {}, seedPublishConnected: () => {} }).map(
|
|
321
|
+
(seed) => seed.id,
|
|
322
|
+
);
|
|
302
323
|
}
|
|
303
324
|
|
|
304
325
|
// ─── The API ──────────────────────────────────────────────────────────────────
|
|
@@ -340,8 +361,8 @@ export interface AutomationProbe {
|
|
|
340
361
|
}
|
|
341
362
|
|
|
342
363
|
export interface AutomationApi {
|
|
343
|
-
run: (id: string, args?:
|
|
344
|
-
seed: (id: string, args?:
|
|
364
|
+
run: (id: string, args?: CommandArgValues) => Promise<void>;
|
|
365
|
+
seed: (id: string, args?: CommandArgValues) => Promise<void>;
|
|
345
366
|
probe: AutomationProbe;
|
|
346
367
|
}
|
|
347
368
|
|
|
@@ -391,12 +412,9 @@ function unknownCommandMessage(
|
|
|
391
412
|
if (seeds.has(id)) {
|
|
392
413
|
return `"${id}" is a seed, not a command — call seed("${id}", …)`;
|
|
393
414
|
}
|
|
394
|
-
const gap =
|
|
395
|
-
if (gap?.disposition === "refused") {
|
|
396
|
-
return `"${id}" is refused by spec §13.5: ${gap.note}`;
|
|
397
|
-
}
|
|
415
|
+
const gap = COMMAND_GAPS.get(id);
|
|
398
416
|
if (gap) {
|
|
399
|
-
return `"${id}"
|
|
417
|
+
return `"${id}" is refused by spec §13.5: ${gap.note}`;
|
|
400
418
|
}
|
|
401
419
|
const known = registry
|
|
402
420
|
.list()
|
|
@@ -435,7 +453,7 @@ export function createAutomationApi(deps: AutomationDeps): AutomationApi {
|
|
|
435
453
|
},
|
|
436
454
|
async seed(id, args = {}) {
|
|
437
455
|
const bare = id.startsWith("seed.") ? id.slice(5) : id;
|
|
438
|
-
const refusal =
|
|
456
|
+
const refusal = SEED_REFUSALS.get(bare);
|
|
439
457
|
if (refusal) {
|
|
440
458
|
throw new AutomationRefusedError(
|
|
441
459
|
id,
|
|
@@ -453,6 +471,11 @@ export function createAutomationApi(deps: AutomationDeps): AutomationApi {
|
|
|
453
471
|
};
|
|
454
472
|
}
|
|
455
473
|
|
|
474
|
+
declare global {
|
|
475
|
+
/** The automation hook, installed only on a page load that opted in with `?automation=1`. */
|
|
476
|
+
var __jxAutomation: AutomationApi | undefined;
|
|
477
|
+
}
|
|
478
|
+
|
|
456
479
|
/** The hook is opt-in per page load: only `?automation=1` installs it. */
|
|
457
480
|
export function shouldInstallAutomation(search: string): boolean {
|
|
458
481
|
return new URLSearchParams(search).get("automation") === "1";
|
|
@@ -466,6 +489,6 @@ export function installAutomationHook(deps: AutomationDeps): boolean {
|
|
|
466
489
|
if (!shouldInstallAutomation(location.search)) {
|
|
467
490
|
return false;
|
|
468
491
|
}
|
|
469
|
-
|
|
492
|
+
globalThis.__jxAutomation = createAutomationApi(deps);
|
|
470
493
|
return true;
|
|
471
494
|
}
|