@jxsuite/studio 6.1.1 → 6.1.2
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/dist/chunks/{2020-va2wwra4.js → 2020-f2gkpy8d.js} +3 -3
- package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
- package/dist/chunks/adapter-4912g339.js +4 -0
- package/dist/chunks/cf-account-picker-wccaenh6.js +4 -0
- package/dist/chunks/cf-settings-br6105tr.js +4 -0
- package/dist/chunks/color-28ksk2qm.js +4 -0
- package/dist/chunks/color-area-0fj8a4ga.js +4 -0
- package/dist/chunks/color-field-xch8kx2g.js +4 -0
- package/dist/chunks/color-slider-jxd8v350.js +4 -0
- package/dist/chunks/combobox-p0efwjke.js +4 -0
- package/dist/chunks/components-db68vsn7.js +4 -0
- package/dist/chunks/content-source-1449qesq.js +4 -0
- package/dist/chunks/convert-to-repeater-5h457egj.js +4 -0
- package/dist/chunks/dialog-c4x05vyx.js +4 -0
- package/dist/chunks/editor-x9jn86a7.js +4 -0
- package/dist/chunks/entry-commands-may24cpt.js +4 -0
- package/dist/chunks/extension-sections-pvr14vxr.js +4 -0
- package/dist/chunks/file-ops-x9v54pcj.js +4 -0
- package/dist/chunks/files-j3knqf0s.js +4 -0
- package/dist/chunks/format-host-tyre2trb.js +4 -0
- package/dist/chunks/fs-events-64ma9htc.js +4 -0
- package/dist/chunks/git-panel-84ps5dex.js +4 -0
- package/dist/chunks/grid-view-d2wq9ezg.js +51 -0
- package/dist/chunks/icons-pnfz478q.js +4 -0
- package/dist/chunks/iframe-entry-fvbk89gm.js +5 -0
- package/dist/chunks/iframe-entry-jdcktez8.js +5 -0
- package/dist/chunks/iframe-entry-x0ygf2yr.js +5 -0
- package/dist/chunks/iframe-entry-zap785cw.js +5 -0
- package/dist/chunks/iframe-host-ck6vejt5.js +4 -0
- package/dist/chunks/index-b8xw3vy9.js +4 -0
- package/dist/chunks/{index-2veqmnhr.js → index-zpjmzqfk.js} +3 -3
- package/dist/chunks/{javascript-8nbvs12s.js → javascript-m54mnwp6.js} +3 -3
- package/dist/chunks/{jsonMode-s8kt9dsj.js → jsonMode-w15cmrcm.js} +8 -8
- package/dist/chunks/jx-validate-at3zn8wa.js +4 -0
- package/dist/chunks/layers-h4xp1pss.js +4 -0
- package/dist/chunks/layers-panel-m5hw1d7g.js +4 -0
- package/dist/chunks/listbox-e74qjyq6.js +4 -0
- package/dist/chunks/lit-html-8t8t3dnr.js +4 -0
- package/dist/chunks/media-picker-2cweexc5.js +4 -0
- package/dist/chunks/menu-n6yzswmy.js +4 -0
- package/dist/chunks/menu-ynw13y0s.js +4 -0
- package/dist/chunks/monaco-binding-7gx83x3r.js +4 -0
- package/dist/chunks/monaco-buffer-qzxn567r.js +4 -0
- package/dist/chunks/monaco-setup-gxf6656g.js +4 -0
- package/dist/chunks/notify-cj5zbrs2.js +4 -0
- package/dist/chunks/number-field-y62xq0ty.js +4 -0
- package/dist/chunks/parse-b7ddhr8m.js +4 -0
- package/dist/chunks/platform-3dfws9js.js +4 -0
- package/dist/chunks/popover-jt2gxmzs.js +4 -0
- package/dist/chunks/publish-panel-1gvxbj21.js +4 -0
- package/dist/chunks/quick-search-0dajrwqg.js +4 -0
- package/dist/chunks/references-49qgt404.js +4 -0
- package/dist/chunks/right-panel-jm1bwe53.js +4 -0
- package/dist/chunks/section-registry-6kwc4fky.js +4 -0
- package/dist/chunks/select-rzds841e.js +4 -0
- package/dist/chunks/split-n2gfpm5m.js +4 -0
- package/dist/chunks/{studio-1q1sh2ax.js → studio-0q988f9w.js} +3 -3
- package/dist/chunks/studio-0rt52vpq.js +5 -0
- package/dist/chunks/studio-18vgbhs5.js +5 -0
- package/dist/chunks/{studio-h46vtzk8.js → studio-1fxkaaea.js} +4 -4
- package/dist/chunks/studio-24mccdrj.js +5 -0
- package/dist/chunks/studio-2eh507zk.js +9 -0
- package/dist/chunks/studio-2hcbccfv.js +5 -0
- package/dist/chunks/studio-2j1cb95x.js +5 -0
- package/dist/chunks/studio-2jbs3rxv.js +5 -0
- package/dist/chunks/{studio-rv11kfwa.js → studio-485046te.js} +7 -7
- package/dist/chunks/studio-4h8k4dw9.js +5 -0
- package/dist/chunks/studio-5f6n18kx.js +5 -0
- package/dist/chunks/studio-5gthpky6.js +5 -0
- package/dist/chunks/studio-5ve6bbep.js +5 -0
- package/dist/chunks/studio-6ep3js6b.js +9 -0
- package/dist/chunks/studio-6wkmf3wz.js +9 -0
- package/dist/chunks/studio-841rf3cg.js +5 -0
- package/dist/chunks/studio-8gmwgheg.js +5 -0
- package/dist/chunks/studio-8qm0ep50.js +5 -0
- package/dist/chunks/{studio-8grwxtqk.js → studio-90pq9km1.js} +4 -4
- package/dist/chunks/studio-924p1tm1.js +6 -0
- package/dist/chunks/{studio-pre0skq6.js → studio-a3g98wjr.js} +4 -4
- package/dist/chunks/studio-a3shpz9y.js +5 -0
- package/dist/chunks/studio-amsbaaar.js +6 -0
- package/dist/chunks/studio-at5spjbc.js +7 -0
- package/dist/chunks/studio-b2xv945e.js +5 -0
- package/dist/chunks/studio-bn5nkafw.js +5 -0
- package/dist/chunks/studio-bw6q5xjf.js +9 -0
- package/dist/chunks/studio-c7q0t9x1.js +5 -0
- package/dist/chunks/studio-camnhc96.js +6 -0
- package/dist/chunks/studio-cffqvnzd.js +5 -0
- package/dist/chunks/studio-d81xfh1g.js +5 -0
- package/dist/chunks/studio-dgz8d0c1.js +5 -0
- package/dist/chunks/studio-efvfrsf8.js +5 -0
- package/dist/chunks/studio-er30bpcx.js +5 -0
- package/dist/chunks/studio-ezscgr64.js +5 -0
- package/dist/chunks/studio-ffrrncvz.js +5 -0
- package/dist/chunks/studio-fpphgn8y.js +10 -0
- package/dist/chunks/studio-j1kvhdjk.js +4 -0
- package/dist/chunks/{studio-vrmcjf9g.js → studio-j430n16g.js} +5 -5
- package/dist/chunks/studio-jjkg84nj.js +5 -0
- package/dist/chunks/studio-m0q32ars.js +4 -0
- package/dist/chunks/studio-m6bdst11.js +5 -0
- package/dist/chunks/studio-nv2cptd4.js +64 -0
- package/dist/chunks/studio-nwfrc98n.js +5 -0
- package/dist/chunks/studio-p1wgvp7r.js +5 -0
- package/dist/chunks/studio-pag2wncm.js +5 -0
- package/dist/chunks/studio-qvanvzfd.js +5 -0
- package/dist/chunks/studio-qwa64kt7.js +5 -0
- package/dist/chunks/studio-rk1zc4x3.js +928 -0
- package/dist/chunks/studio-se2r3ptc.js +5 -0
- package/dist/chunks/studio-sg2a0dh0.js +5 -0
- package/dist/chunks/studio-tjzjhe68.js +5 -0
- package/dist/chunks/{studio-wszjyh0j.js → studio-tq0rtfwj.js} +4 -4
- package/dist/chunks/{studio-kggey1jt.js → studio-v0jzqdjm.js} +4 -4
- package/dist/chunks/studio-v2w7q8r1.js +7 -0
- package/dist/chunks/studio-v5vjq1h0.js +4 -0
- package/dist/chunks/studio-v8aga3vp.js +14 -0
- package/dist/chunks/studio-vfcdrfmv.js +5 -0
- package/dist/chunks/studio-vmfkgdjf.js +5 -0
- package/dist/chunks/studio-wt1816jj.js +5 -0
- package/dist/chunks/studio-wz73q5kq.js +4 -0
- package/dist/chunks/studio-y04qtxvp.js +7 -0
- package/dist/chunks/studio-y21g8zzg.js +5 -0
- package/dist/chunks/{studio-zey7zsdw.js → studio-y64hrt8p.js} +7 -7
- package/dist/chunks/studio-ynn90f58.js +16 -0
- package/dist/chunks/studio-yxz682sx.js +5 -0
- package/dist/chunks/studio-zp7snvkq.js +5 -0
- package/dist/chunks/studio-zq4z6tm6.js +5 -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-c9fn075p.js +4 -0
- package/dist/chunks/toast-host-ke5z4ng7.js +4 -0
- package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
- package/dist/chunks/tooltip-5v8ngwj2.js +4 -0
- package/dist/chunks/tree-mdq3v5cw.js +4 -0
- package/dist/chunks/{tsMode-2frah6h1.js → tsMode-sf49ee9x.js} +7 -7
- package/dist/chunks/workspace-jtfahpee.js +4 -0
- package/dist/chunks/ws-client-nze0k6mv.js +4 -0
- package/dist/iframe-entry.js +16 -16
- package/dist/manifest.json +63 -63
- package/dist/studio.js +97 -97
- package/package.json +6 -6
- 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/library-layouts.ts +8 -5
- package/src/browse/library-model.ts +18 -6
- package/src/browse/library-pane.ts +37 -21
- package/src/browse/library-preview.ts +14 -9
- package/src/browse/library-source.ts +1 -1
- package/src/canvas/asset-refs.ts +24 -9
- package/src/canvas/asset-resolve.ts +19 -23
- package/src/canvas/canvas-helpers.ts +7 -6
- package/src/canvas/canvas-live-render.ts +44 -53
- package/src/canvas/canvas-patcher.ts +30 -30
- package/src/canvas/canvas-perf.ts +11 -5
- package/src/canvas/canvas-render.ts +62 -41
- package/src/canvas/canvas-surface.ts +5 -3
- package/src/canvas/canvas-utils.ts +90 -49
- 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 +13 -12
- package/src/canvas/iframe-editable-root.ts +29 -16
- package/src/canvas/iframe-entry.ts +80 -63
- package/src/canvas/iframe-eval.ts +73 -49
- package/src/canvas/iframe-host.ts +135 -96
- 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-overlay.ts +1 -1
- package/src/canvas/iframe-patch.ts +18 -15
- package/src/canvas/iframe-position.ts +12 -6
- package/src/canvas/iframe-protocol.ts +12 -16
- package/src/canvas/iframe-render.ts +36 -34
- package/src/canvas/iframe-slash.ts +24 -11
- package/src/canvas/iframe-subtree.ts +6 -2
- 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/serialize-scope.ts +13 -5
- package/src/canvas/stage-scrollbar.ts +2 -1
- package/src/canvas/surface-registry.ts +21 -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/budget.ts +3 -3
- package/src/commands/command-args.ts +103 -71
- package/src/commands/context.ts +22 -20
- package/src/commands/keymap.ts +47 -43
- package/src/commands/levels.ts +3 -3
- package/src/commands/live-context.ts +7 -7
- package/src/commands/reference.ts +2 -1
- package/src/commands/registry.ts +12 -10
- package/src/commands/run-reported.ts +15 -10
- package/src/component-props.ts +46 -30
- package/src/content/collection-match.ts +5 -4
- package/src/content/draft-state.ts +4 -3
- package/src/content/entry-commands.ts +3 -2
- package/src/content/entry-editor.ts +29 -17
- package/src/content/entry-fields.ts +12 -7
- package/src/content/entry-model.ts +21 -12
- 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 +11 -5
- package/src/editor/convert-to-repeater.ts +34 -22
- package/src/editor/editable-tags.ts +17 -2
- package/src/editor/file-drop-action.ts +21 -22
- package/src/editor/inline-edit-apply.ts +35 -17
- package/src/editor/inline-edit.ts +66 -50
- package/src/editor/inline-format.ts +59 -56
- package/src/editor/inline-link.ts +40 -15
- package/src/editor/insert-zone-action.ts +1 -1
- package/src/editor/merge-tags.ts +58 -19
- package/src/editor/repeater-scope.ts +39 -28
- package/src/editor/shortcuts.ts +32 -20
- package/src/editor/slash-menu.ts +1 -6
- package/src/files/asset-versions.ts +4 -4
- package/src/files/components.ts +15 -10
- package/src/files/elements.ts +5 -6
- package/src/files/file-ops.ts +77 -36
- package/src/files/files.ts +90 -95
- package/src/files/media-meta.ts +2 -1
- package/src/files/media-paths.ts +3 -0
- package/src/files/serialize-document.ts +2 -2
- 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 +76 -50
- package/src/github/github-auth-status.ts +27 -3
- package/src/github/github-auth.ts +19 -9
- package/src/github/github-publish.ts +24 -20
- 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 +20 -22
- package/src/grid/grid-layout.ts +21 -5
- package/src/grid/grid-open.ts +3 -6
- package/src/grid/grid-panel.ts +11 -4
- package/src/grid/grid-source.ts +8 -8
- package/src/grid/grid-view.ts +14 -17
- 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 +25 -24
- package/src/grid/sources/csv-file-source.ts +2 -2
- package/src/grid/tabulator-tables.d.ts +55 -34
- package/src/hosting/stage.ts +7 -7
- package/src/i18n/i18n-commands.ts +1 -2
- package/src/media/media-pane.ts +4 -1
- 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 +17 -9
- package/src/panels/ai-chat/attached-context.ts +13 -7
- 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 +46 -35
- package/src/panels/bottom-dock.ts +5 -3
- package/src/panels/canvas-dnd-bridge.ts +31 -24
- package/src/panels/data-explorer.ts +62 -25
- package/src/panels/data-grid.ts +14 -11
- package/src/panels/dnd.ts +108 -118
- package/src/panels/editors.ts +52 -21
- package/src/panels/elements-panel.ts +10 -3
- package/src/panels/events-panel.ts +84 -69
- package/src/panels/formula-workspace.ts +76 -51
- package/src/panels/frontmatter-fields.ts +24 -19
- package/src/panels/frontmatter-panel.ts +44 -34
- package/src/panels/git-diff-open.ts +4 -4
- package/src/panels/git-panel.ts +49 -61
- package/src/panels/head-panel.ts +131 -111
- package/src/panels/i18n-panel.ts +10 -3
- package/src/panels/imports-panel.ts +23 -47
- package/src/panels/jump-bar.ts +48 -29
- package/src/panels/layers-panel.ts +97 -74
- package/src/panels/left-panel.ts +3 -3
- package/src/panels/pane-context.ts +31 -22
- package/src/panels/pane-grid.ts +49 -20
- package/src/panels/panel-registry.ts +22 -37
- package/src/panels/properties-panel.ts +175 -121
- package/src/panels/quick-search.ts +53 -31
- package/src/panels/right-panel.ts +3 -3
- package/src/panels/seo-modal.ts +13 -17
- package/src/panels/settings-menu.ts +15 -15
- package/src/panels/signals-panel.ts +153 -131
- package/src/panels/statement-editor.ts +230 -140
- package/src/panels/style-panel.ts +218 -205
- package/src/panels/style-utils.ts +114 -51
- package/src/panels/stylebook-doc.ts +57 -54
- package/src/panels/stylebook-layers-panel.ts +9 -9
- package/src/panels/stylebook-panel.ts +13 -17
- package/src/panels/tab-drop.ts +27 -11
- package/src/panels/tab-strip.ts +36 -26
- package/src/platform-errors.ts +57 -43
- package/src/platform.ts +58 -30
- package/src/platforms/cloud.ts +345 -175
- package/src/platforms/default-platform.ts +10 -4
- package/src/platforms/devserver.ts +129 -117
- package/src/platforms/read-batcher.ts +16 -8
- package/src/project-list.ts +2 -1
- package/src/publish/deploy-checklist.ts +8 -2
- package/src/publish/pages-service.ts +28 -13
- package/src/publish/publish-commands.ts +5 -4
- package/src/publish/publish-panel.ts +10 -6
- 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 +58 -31
- package/src/services/cem-export.ts +149 -58
- package/src/services/clock.ts +6 -1
- package/src/services/code-services.ts +37 -31
- 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 +18 -12
- 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 +8 -7
- 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 +79 -60
- package/src/settings/css-vars-editor.ts +37 -16
- package/src/settings/defs-editor.ts +38 -35
- package/src/settings/extension-rows.ts +16 -8
- package/src/settings/extension-sections.ts +23 -13
- package/src/settings/extensions-section.ts +4 -1
- package/src/settings/general-settings.ts +11 -8
- package/src/settings/locales-section.ts +20 -12
- package/src/settings/preferences-dialog.ts +9 -6
- package/src/settings/preferences-keymap.ts +7 -5
- package/src/settings/preferences-sections.ts +11 -5
- package/src/settings/project-sections.ts +1 -1
- package/src/settings/schema-field-ui.ts +9 -0
- package/src/settings/settings-document.ts +5 -5
- package/src/shell/tree.ts +6 -5
- package/src/shell.ts +104 -81
- package/src/site-context.ts +37 -22
- package/src/state.ts +41 -49
- package/src/store.ts +54 -34
- package/src/studio.ts +25 -75
- package/src/style/live-preview.ts +1 -1
- package/src/style/project-styles.ts +6 -7
- package/src/style/token-ref.ts +5 -4
- package/src/surfaces/about.ts +18 -19
- package/src/surfaces/add-repo.ts +17 -19
- package/src/surfaces/ai-chat.ts +31 -36
- 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.ts +4 -5
- package/src/surfaces/bottom-dock.ts +9 -18
- package/src/surfaces/canvas-stage.ts +12 -11
- package/src/surfaces/cf-account-picker.ts +17 -18
- package/src/surfaces/commandbar.ts +14 -9
- 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/doc-header.ts +10 -19
- package/src/surfaces/empty-state.ts +7 -10
- package/src/surfaces/entry-editor.ts +14 -11
- 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/git-panel.ts +7 -15
- 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.ts +13 -12
- package/src/surfaces/jump-bar.ts +5 -6
- package/src/surfaces/jxsuite-update.ts +16 -22
- package/src/surfaces/library-pane.ts +19 -20
- package/src/surfaces/logic-panel.ts +17 -30
- package/src/surfaces/logic-workspace.ts +13 -15
- package/src/surfaces/media-browser.ts +11 -10
- package/src/surfaces/media-field.ts +4 -5
- package/src/surfaces/media-pane.ts +8 -7
- package/src/surfaces/menu.ts +29 -23
- package/src/surfaces/navigator-dock.ts +11 -12
- package/src/surfaces/new-project.ts +27 -26
- package/src/surfaces/pane-context.ts +20 -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.ts +5 -6
- 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.ts +11 -18
- package/src/surfaces/panel-problems.ts +5 -7
- package/src/surfaces/panel-signals.ts +20 -34
- package/src/surfaces/panel-stylebook-layers.ts +5 -8
- package/src/surfaces/preferences.ts +21 -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.ts +18 -18
- package/src/surfaces/push-plan.ts +7 -8
- package/src/surfaces/rail.ts +13 -13
- package/src/surfaces/reference-field.ts +11 -15
- package/src/surfaces/schema-builder.ts +16 -22
- package/src/surfaces/schema-form.ts +15 -25
- package/src/surfaces/secret-field.ts +9 -6
- package/src/surfaces/seo.ts +21 -15
- package/src/surfaces/settings-contexts.ts +9 -7
- package/src/surfaces/settings-contributed.ts +14 -10
- package/src/surfaces/settings-css-vars.ts +5 -12
- package/src/surfaces/settings-defs.json +2 -2
- package/src/surfaces/settings-defs.ts +17 -21
- package/src/surfaces/settings-deploy.ts +8 -15
- 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.ts +5 -6
- package/src/surfaces/settings-packages.ts +8 -7
- package/src/surfaces/settings-pane.ts +9 -18
- package/src/surfaces/settings-rawjson.ts +5 -6
- package/src/surfaces/shell.ts +1 -2
- package/src/surfaces/slash-menu.ts +19 -9
- package/src/surfaces/statements.ts +13 -18
- package/src/surfaces/statusbar.ts +17 -14
- package/src/surfaces/style-panel.ts +18 -31
- package/src/surfaces/stylebook-chrome.ts +3 -5
- package/src/surfaces/tab-strip.ts +14 -13
- package/src/surfaces/target-line.ts +6 -7
- package/src/surfaces/welcome.ts +5 -7
- 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 +52 -41
- package/src/tabs/transact.ts +98 -53
- package/src/types.ts +32 -17
- 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 +57 -48
- package/src/ui/formula-catalog.ts +239 -230
- package/src/ui/formula-chips.ts +33 -18
- package/src/ui/layers.ts +44 -31
- package/src/ui/media-picker.ts +18 -9
- package/src/ui/popover-surface.ts +20 -12
- package/src/ui/progress-modal.ts +13 -8
- package/src/ui/regions.ts +7 -6
- package/src/ui/schema-form.ts +113 -70
- 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 +3 -2
- package/src/utils/base64.ts +3 -1
- package/src/utils/edit-display.ts +73 -73
- 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/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 +10 -12
- package/src/workspace/session.ts +53 -43
- package/src/workspace/workspace.ts +40 -36
- 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/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-t6b6qe31.js +0 -5
- package/dist/chunks/studio-tdcprbqb.js +0 -5
- 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-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/workspace-zt81g1ms.js +0 -4
- package/dist/chunks/ws-client-n2bh4hkf.js +0 -4
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
|
*
|
|
@@ -130,7 +129,7 @@ export interface ManifestId {
|
|
|
130
129
|
* the same debt. Five `refused` entries are NOT a countdown: they are §13.5's normative refusals,
|
|
131
130
|
* and they stay so that a caller reaching for one gets the reason instead of "unknown 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",
|
|
@@ -152,7 +151,13 @@ export const AUTOMATION_COMMANDS: Readonly<Record<string, ManifestId>> = {
|
|
|
152
151
|
disposition: "refused",
|
|
153
152
|
note: "the status bar is not staged — if a capture needs a calm shell, the app must BE calm",
|
|
154
153
|
},
|
|
155
|
-
}
|
|
154
|
+
} as const satisfies Readonly<Record<string, ManifestId>>;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* {@link AUTOMATION_COMMANDS} keyed for lookup by an arbitrary id. A Map rather than an index into
|
|
158
|
+
* the object, so an id such as `"constructor"` finds nothing instead of `Object.prototype`'s.
|
|
159
|
+
*/
|
|
160
|
+
const COMMAND_GAPS: ReadonlyMap<string, ManifestId> = new Map(Object.entries(AUTOMATION_COMMANDS));
|
|
156
161
|
|
|
157
162
|
// ─── The seed registry, under the Remote Rule ─────────────────────────────────
|
|
158
163
|
|
|
@@ -161,7 +166,7 @@ export interface SeedDefinition {
|
|
|
161
166
|
id: string;
|
|
162
167
|
/** The network or IPC boundary this seed stands in for. The Remote Rule, written down per seed. */
|
|
163
168
|
boundary: string;
|
|
164
|
-
run: (args:
|
|
169
|
+
run: (args: CommandArgValues) => void | Promise<void>;
|
|
165
170
|
}
|
|
166
171
|
|
|
167
172
|
/**
|
|
@@ -170,7 +175,7 @@ export interface SeedDefinition {
|
|
|
170
175
|
* Every one of these was a method on the old surface. Each writes state a USER writes, so each is a
|
|
171
176
|
* COMMAND — and a fixture that stages it photographs a state no session could have reached.
|
|
172
177
|
*/
|
|
173
|
-
export const REFUSED_SEEDS
|
|
178
|
+
export const REFUSED_SEEDS = {
|
|
174
179
|
openSettings: 'a user opens Settings — run("settings.open")',
|
|
175
180
|
select: 'a user selects a node — run("selection.set", { path })',
|
|
176
181
|
setActivity: 'a user picks a Navigator panel — run("navigator.showPanel", { panel })',
|
|
@@ -178,9 +183,12 @@ export const REFUSED_SEEDS: Readonly<Record<string, string>> = {
|
|
|
178
183
|
setStatus:
|
|
179
184
|
"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
185
|
setZoom: 'a user zooms — run("canvas.setZoom", { zoom })',
|
|
181
|
-
}
|
|
186
|
+
} as const satisfies Readonly<Record<string, string>>;
|
|
182
187
|
|
|
183
|
-
|
|
188
|
+
/** {@link REFUSED_SEEDS} keyed for lookup by an arbitrary seed name, as {@link COMMAND_GAPS} is. */
|
|
189
|
+
const SEED_REFUSALS: ReadonlyMap<string, string> = new Map(Object.entries(REFUSED_SEEDS));
|
|
190
|
+
|
|
191
|
+
function arrayArg<T>(args: CommandArgValues, key: string): T[] {
|
|
184
192
|
const value = args[key];
|
|
185
193
|
if (value === undefined) {
|
|
186
194
|
return [];
|
|
@@ -188,23 +196,28 @@ function arrayArg<T>(args: AutomationArgs, key: string): T[] {
|
|
|
188
196
|
if (!Array.isArray(value)) {
|
|
189
197
|
throw new TypeError(`seed argument "${key}" must be an array`);
|
|
190
198
|
}
|
|
199
|
+
/* SAFETY: a seed's arguments are a fixture written against the boundary type it stands in for
|
|
200
|
+
(the screenshot manifest's `seed` steps), so only the container is checked here — exactly as
|
|
201
|
+
much as the remote it replaces would have checked before handing its JSON over. */
|
|
191
202
|
return value as T[];
|
|
192
203
|
}
|
|
193
204
|
|
|
194
|
-
function requiredArg<T>(args:
|
|
205
|
+
function requiredArg<T>(args: CommandArgValues, key: string): T {
|
|
195
206
|
const value = args[key];
|
|
196
|
-
if (value
|
|
207
|
+
if (!isNonNullObject(value)) {
|
|
197
208
|
throw new TypeError(`seed argument "${key}" must be an object`);
|
|
198
209
|
}
|
|
210
|
+
/* SAFETY: as in `arrayArg`: a fixture written against the boundary type it stands in for, of
|
|
211
|
+
which only the object container is checked here. */
|
|
199
212
|
return value as T;
|
|
200
213
|
}
|
|
201
214
|
|
|
202
|
-
function optionalString(args:
|
|
215
|
+
function optionalString(args: CommandArgValues, key: string): string | undefined {
|
|
203
216
|
const value = args[key];
|
|
204
217
|
if (value === undefined) {
|
|
205
218
|
return undefined;
|
|
206
219
|
}
|
|
207
|
-
if (
|
|
220
|
+
if (!isString(value)) {
|
|
208
221
|
throw new TypeError(`seed argument "${key}" must be a string`);
|
|
209
222
|
}
|
|
210
223
|
return value;
|
|
@@ -216,7 +229,9 @@ function optionalString(args: AutomationArgs, key: string): string | undefined {
|
|
|
216
229
|
* Each one writes exactly what its named boundary would have written, and nothing else — the git
|
|
217
230
|
* seed does not also open the Source Control panel, because a user does that.
|
|
218
231
|
*/
|
|
219
|
-
export function createSeeds(
|
|
232
|
+
export function createSeeds(
|
|
233
|
+
deps: Pick<AutomationDeps, "seedAssistantMessages" | "seedPublishConnected">,
|
|
234
|
+
): SeedDefinition[] {
|
|
220
235
|
return [
|
|
221
236
|
{
|
|
222
237
|
boundary: "the assistant's model stream",
|
|
@@ -252,10 +267,13 @@ export function createSeeds(deps: AutomationDeps): SeedDefinition[] {
|
|
|
252
267
|
id: "seed.publish",
|
|
253
268
|
run: (args) => {
|
|
254
269
|
const accountId = optionalString(args, "accountId");
|
|
255
|
-
|
|
270
|
+
const connected: Parameters<AutomationDeps["seedPublishConnected"]>[0] = {
|
|
256
271
|
deployment: requiredArg<PagesDeploymentInfo>(args, "deployment"),
|
|
257
|
-
|
|
258
|
-
|
|
272
|
+
};
|
|
273
|
+
if (accountId) {
|
|
274
|
+
connected.accountId = accountId;
|
|
275
|
+
}
|
|
276
|
+
deps.seedPublishConnected(connected);
|
|
259
277
|
},
|
|
260
278
|
},
|
|
261
279
|
{
|
|
@@ -264,9 +282,16 @@ export function createSeeds(deps: AutomationDeps): SeedDefinition[] {
|
|
|
264
282
|
run: (args) => {
|
|
265
283
|
// The working tree really is a remote here: the git-panel shot photographs whatever the
|
|
266
284
|
// Author happened to have dirty, because its project lives inside this repository.
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
285
|
+
/* SAFETY: as in `arrayArg`: a fixture written against the platform's git route answers it
|
|
286
|
+
stands in for, passed on as the route's JSON would have been, unchecked. */
|
|
287
|
+
const { status, branches, log } = args as {
|
|
288
|
+
status?: GitStatusResult;
|
|
289
|
+
branches?: GitBranchesResult;
|
|
290
|
+
log?: GitLogEntry[];
|
|
291
|
+
};
|
|
292
|
+
shell.git.status = status ?? null;
|
|
293
|
+
shell.git.branches = branches ?? null;
|
|
294
|
+
shell.git.logEntries = log ?? null;
|
|
270
295
|
shell.git.loading = false;
|
|
271
296
|
shell.git.error = null;
|
|
272
297
|
render();
|
|
@@ -293,12 +318,9 @@ export function createSeeds(deps: AutomationDeps): SeedDefinition[] {
|
|
|
293
318
|
* its `run`, never while building it, so the no-op deps below can never be called.
|
|
294
319
|
*/
|
|
295
320
|
export function seedIds(): string[] {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
seedPublishConnected: () => {},
|
|
300
|
-
} satisfies AutomationDeps;
|
|
301
|
-
return createSeeds(inert).map((seed) => seed.id);
|
|
321
|
+
return createSeeds({ seedAssistantMessages: () => {}, seedPublishConnected: () => {} }).map(
|
|
322
|
+
(seed) => seed.id,
|
|
323
|
+
);
|
|
302
324
|
}
|
|
303
325
|
|
|
304
326
|
// ─── The API ──────────────────────────────────────────────────────────────────
|
|
@@ -340,8 +362,8 @@ export interface AutomationProbe {
|
|
|
340
362
|
}
|
|
341
363
|
|
|
342
364
|
export interface AutomationApi {
|
|
343
|
-
run: (id: string, args?:
|
|
344
|
-
seed: (id: string, args?:
|
|
365
|
+
run: (id: string, args?: CommandArgValues) => Promise<void>;
|
|
366
|
+
seed: (id: string, args?: CommandArgValues) => Promise<void>;
|
|
345
367
|
probe: AutomationProbe;
|
|
346
368
|
}
|
|
347
369
|
|
|
@@ -391,7 +413,7 @@ function unknownCommandMessage(
|
|
|
391
413
|
if (seeds.has(id)) {
|
|
392
414
|
return `"${id}" is a seed, not a command — call seed("${id}", …)`;
|
|
393
415
|
}
|
|
394
|
-
const gap =
|
|
416
|
+
const gap = COMMAND_GAPS.get(id);
|
|
395
417
|
if (gap?.disposition === "refused") {
|
|
396
418
|
return `"${id}" is refused by spec §13.5: ${gap.note}`;
|
|
397
419
|
}
|
|
@@ -435,7 +457,7 @@ export function createAutomationApi(deps: AutomationDeps): AutomationApi {
|
|
|
435
457
|
},
|
|
436
458
|
async seed(id, args = {}) {
|
|
437
459
|
const bare = id.startsWith("seed.") ? id.slice(5) : id;
|
|
438
|
-
const refusal =
|
|
460
|
+
const refusal = SEED_REFUSALS.get(bare);
|
|
439
461
|
if (refusal) {
|
|
440
462
|
throw new AutomationRefusedError(
|
|
441
463
|
id,
|
|
@@ -453,6 +475,11 @@ export function createAutomationApi(deps: AutomationDeps): AutomationApi {
|
|
|
453
475
|
};
|
|
454
476
|
}
|
|
455
477
|
|
|
478
|
+
declare global {
|
|
479
|
+
/** The automation hook, installed only on a page load that opted in with `?automation=1`. */
|
|
480
|
+
var __jxAutomation: AutomationApi | undefined;
|
|
481
|
+
}
|
|
482
|
+
|
|
456
483
|
/** The hook is opt-in per page load: only `?automation=1` installs it. */
|
|
457
484
|
export function shouldInstallAutomation(search: string): boolean {
|
|
458
485
|
return new URLSearchParams(search).get("automation") === "1";
|
|
@@ -466,6 +493,6 @@ export function installAutomationHook(deps: AutomationDeps): boolean {
|
|
|
466
493
|
if (!shouldInstallAutomation(location.search)) {
|
|
467
494
|
return false;
|
|
468
495
|
}
|
|
469
|
-
|
|
496
|
+
globalThis.__jxAutomation = createAutomationApi(deps);
|
|
470
497
|
return true;
|
|
471
498
|
}
|