@jxsuite/studio 6.1.0 → 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-f2gkpy8d.js +4 -0
- 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-gybvv7a6.js → index-zpjmzqfk.js} +3 -3
- package/dist/chunks/{javascript-rnvdp3k4.js → javascript-m54mnwp6.js} +3 -3
- package/dist/chunks/jsonMode-w15cmrcm.js +13 -0
- 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-5g0ag7c0.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-pxg4ap1e.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-qbj760tx.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-anyrgzvb.js → studio-90pq9km1.js} +4 -4
- package/dist/chunks/studio-924p1tm1.js +6 -0
- package/dist/chunks/{studio-v2bvmbjj.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-txjjzrsm.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-0x3jyb8r.js → studio-tq0rtfwj.js} +4 -4
- package/dist/chunks/{studio-cpxkgjrj.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-y64hrt8p.js +12 -0
- 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-sf49ee9x.js +14 -0
- 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 +98 -98
- package/dist/workers/ts.worker.js +3 -3
- package/package.json +11 -11
- 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 +66 -42
- package/src/canvas/canvas-surface.ts +5 -3
- package/src/canvas/canvas-utils.ts +163 -64
- 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 +203 -118
- package/src/canvas/iframe-inline-edit.ts +69 -32
- package/src/canvas/iframe-insert.ts +5 -4
- package/src/canvas/iframe-interaction.ts +37 -26
- 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 +15 -16
- package/src/canvas/iframe-render.ts +41 -36
- 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/defaults.ts +4 -1
- package/src/commands/keymap.ts +47 -43
- package/src/commands/levels.ts +3 -3
- package/src/commands/live-context.ts +10 -8
- 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 +87 -47
- 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 +6 -1
- 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 +55 -22
- 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 +254 -216
- 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 +174 -127
- 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 +39 -77
- 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 +25 -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.json +126 -73
- package/src/surfaces/rail.ts +38 -12
- 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/tabs/typing.ts +31 -0
- 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 +103 -74
- 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 +47 -36
- package/dist/chunks/2020-nkxms0ay.js +0 -4
- package/dist/chunks/adapter-m948ab5f.js +0 -4
- package/dist/chunks/cf-account-picker-n8hr38v7.js +0 -4
- package/dist/chunks/cf-settings-356xdtne.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-yk3t844e.js +0 -4
- package/dist/chunks/content-source-bawmyc09.js +0 -4
- package/dist/chunks/convert-to-repeater-7wns8kf1.js +0 -4
- package/dist/chunks/dialog-mtm9fq5t.js +0 -4
- package/dist/chunks/editor-6sc8nacq.js +0 -4
- package/dist/chunks/entry-commands-8ay9fh81.js +0 -4
- package/dist/chunks/extension-sections-na7rj3nr.js +0 -4
- package/dist/chunks/file-ops-gye0qw56.js +0 -4
- package/dist/chunks/files-dmc2xvcq.js +0 -4
- package/dist/chunks/format-host-t76b53f8.js +0 -4
- package/dist/chunks/fs-events-cg4tpz06.js +0 -4
- package/dist/chunks/git-panel-yef7bshy.js +0 -4
- package/dist/chunks/grid-view-7tt4bxw1.js +0 -51
- package/dist/chunks/icons-qbh8akb1.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-tmz30gfp.js +0 -4
- package/dist/chunks/index-nag78a9h.js +0 -4
- package/dist/chunks/jsonMode-zhwsprqk.js +0 -13
- package/dist/chunks/jx-validate-3gbp5nkn.js +0 -4
- package/dist/chunks/layers-fvz99859.js +0 -4
- package/dist/chunks/layers-panel-gchmbf9p.js +0 -4
- package/dist/chunks/listbox-s8fkmnq8.js +0 -4
- package/dist/chunks/lit-html-9agdspkt.js +0 -4
- package/dist/chunks/media-picker-rhjvyy00.js +0 -4
- package/dist/chunks/menu-2e4y9j7b.js +0 -4
- package/dist/chunks/menu-37d07z9m.js +0 -4
- package/dist/chunks/monaco-binding-2jnhjjvr.js +0 -4
- package/dist/chunks/monaco-buffer-rp21359g.js +0 -4
- package/dist/chunks/monaco-setup-vhh7gayr.js +0 -4
- package/dist/chunks/notify-h3www560.js +0 -4
- package/dist/chunks/number-field-gw7sq8rn.js +0 -4
- package/dist/chunks/parse-897fvqah.js +0 -4
- package/dist/chunks/platform-hz34wcd7.js +0 -4
- package/dist/chunks/popover-8htra4er.js +0 -4
- package/dist/chunks/publish-panel-exsmjzyj.js +0 -4
- package/dist/chunks/quick-search-pgaqeh0m.js +0 -4
- package/dist/chunks/references-2cgdxnb8.js +0 -4
- package/dist/chunks/right-panel-jf856w5w.js +0 -4
- package/dist/chunks/section-registry-jnf8r5gy.js +0 -4
- package/dist/chunks/select-n3v7gwas.js +0 -4
- package/dist/chunks/split-pff8f3ze.js +0 -4
- package/dist/chunks/studio-0f55h9ye.js +0 -5
- package/dist/chunks/studio-0sqdhnew.js +0 -12
- package/dist/chunks/studio-19x1c75w.js +0 -5
- package/dist/chunks/studio-2sqcndak.js +0 -5
- package/dist/chunks/studio-3aey7dd3.js +0 -5
- package/dist/chunks/studio-3bpdkq2s.js +0 -5
- package/dist/chunks/studio-47y6fbpf.js +0 -5
- package/dist/chunks/studio-4m3826v2.js +0 -5
- package/dist/chunks/studio-4nx2dj1g.js +0 -4
- package/dist/chunks/studio-4xv5s47r.js +0 -9
- package/dist/chunks/studio-5g4t8v6w.js +0 -5
- package/dist/chunks/studio-5py436sf.js +0 -5
- package/dist/chunks/studio-77kt594t.js +0 -5
- package/dist/chunks/studio-8f87n763.js +0 -10
- package/dist/chunks/studio-8mb00b84.js +0 -5
- package/dist/chunks/studio-8p51gq2h.js +0 -6
- package/dist/chunks/studio-954ds834.js +0 -5
- package/dist/chunks/studio-9ft45c83.js +0 -9
- package/dist/chunks/studio-a2138x5k.js +0 -7
- package/dist/chunks/studio-a9yzstqj.js +0 -5
- package/dist/chunks/studio-acdksxx6.js +0 -5
- package/dist/chunks/studio-ar8jcf2y.js +0 -5
- package/dist/chunks/studio-bmn4mn9j.js +0 -7
- package/dist/chunks/studio-e7xxa0sj.js +0 -5
- package/dist/chunks/studio-ecaz25vk.js +0 -5
- package/dist/chunks/studio-ery42sqr.js +0 -4
- package/dist/chunks/studio-fzdywr6p.js +0 -9
- package/dist/chunks/studio-g5fmf0c1.js +0 -5
- package/dist/chunks/studio-g7nse7zb.js +0 -5
- package/dist/chunks/studio-geq1ea6k.js +0 -14
- package/dist/chunks/studio-ghkb32r8.js +0 -5
- package/dist/chunks/studio-ghrhy2y7.js +0 -5
- package/dist/chunks/studio-grawhey1.js +0 -5
- package/dist/chunks/studio-h0xgswew.js +0 -5
- package/dist/chunks/studio-h9c4p2tx.js +0 -5
- package/dist/chunks/studio-jyzj5cxs.js +0 -5
- package/dist/chunks/studio-mgx8yhnz.js +0 -64
- package/dist/chunks/studio-mpb04y1d.js +0 -6
- package/dist/chunks/studio-n17mty64.js +0 -5
- package/dist/chunks/studio-nwh2eqsk.js +0 -6
- package/dist/chunks/studio-q1h883bt.js +0 -16
- package/dist/chunks/studio-q4tv82h7.js +0 -9
- package/dist/chunks/studio-qpqa7vk3.js +0 -5
- package/dist/chunks/studio-qqz8e5gk.js +0 -5
- package/dist/chunks/studio-qvasen3f.js +0 -5
- package/dist/chunks/studio-rggdb3hm.js +0 -5
- package/dist/chunks/studio-sghy936h.js +0 -4
- package/dist/chunks/studio-skprc6ef.js +0 -5
- package/dist/chunks/studio-tt2nactf.js +0 -5
- package/dist/chunks/studio-tyasmc39.js +0 -5
- package/dist/chunks/studio-vk9ezads.js +0 -5
- package/dist/chunks/studio-vzacdfsc.js +0 -4
- package/dist/chunks/studio-w4c0xmrw.js +0 -5
- package/dist/chunks/studio-wfjqhhbk.js +0 -5
- package/dist/chunks/studio-wgh5kxpj.js +0 -5
- package/dist/chunks/studio-xasj0796.js +0 -5
- package/dist/chunks/studio-y78s8r2n.js +0 -5
- package/dist/chunks/studio-z8w183sh.js +0 -5
- package/dist/chunks/studio-zscd9ty4.js +0 -928
- package/dist/chunks/studio-zxp13sss.js +0 -7
- package/dist/chunks/studio-zygnmm01.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-gr0m4dzr.js +0 -14
- package/dist/chunks/workspace-m15qtcqp.js +0 -4
- package/dist/chunks/ws-client-nf61frr1.js +0 -4
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
|
|
34
34
|
import { LOCATION_ID_FILE } from "@jxsuite/protocol/routes";
|
|
35
|
+
import { isNonNullObject, isString } from "@jxsuite/schema/guards";
|
|
35
36
|
import { errorMessage } from "@jxsuite/schema/parse";
|
|
36
37
|
|
|
37
38
|
/** Re-exported so a caller wiring up `locate` need not also reach into the protocol package. */
|
|
@@ -57,11 +58,20 @@ type ShowDirectoryPicker = (opts?: {
|
|
|
57
58
|
startIn?: string;
|
|
58
59
|
}) => Promise<DirectoryHandle>;
|
|
59
60
|
|
|
61
|
+
/** A realm that exposes the File System Access API's folder chooser. */
|
|
62
|
+
type DirectoryPickerRealm = typeof globalThis & { showDirectoryPicker: ShowDirectoryPicker };
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Whether a realm carries `showDirectoryPicker`. The DOM lib this package compiles against does not
|
|
66
|
+
* declare it (the API is Chromium-only), so the global is probed rather than read.
|
|
67
|
+
*/
|
|
68
|
+
function hasDirectoryPicker(realm: typeof globalThis): realm is DirectoryPickerRealm {
|
|
69
|
+
return "showDirectoryPicker" in realm && typeof realm.showDirectoryPicker === "function";
|
|
70
|
+
}
|
|
71
|
+
|
|
60
72
|
/** Whether this browser can open a native folder chooser at all. */
|
|
61
73
|
export function canPickDirectory(): boolean {
|
|
62
|
-
return (
|
|
63
|
-
typeof (globalThis as { showDirectoryPicker?: unknown }).showDirectoryPicker === "function"
|
|
64
|
-
);
|
|
74
|
+
return hasDirectoryPicker(globalThis);
|
|
65
75
|
}
|
|
66
76
|
|
|
67
77
|
/** A location id: URL-safe, unguessable enough that a concurrent pick cannot collide. */
|
|
@@ -76,13 +86,8 @@ function newLocationId(): string {
|
|
|
76
86
|
* `showDirectoryPicker`, a test double) is not `instanceof Error` here, but it still says what it
|
|
77
87
|
* is.
|
|
78
88
|
*/
|
|
79
|
-
function nameOf(
|
|
80
|
-
return
|
|
81
|
-
error !== null &&
|
|
82
|
-
"name" in error &&
|
|
83
|
-
typeof error.name === "string"
|
|
84
|
-
? error.name
|
|
85
|
-
: "";
|
|
89
|
+
function nameOf(cause: unknown): string {
|
|
90
|
+
return isNonNullObject(cause) && "name" in cause && isString(cause.name) ? cause.name : "";
|
|
86
91
|
}
|
|
87
92
|
|
|
88
93
|
/**
|
|
@@ -111,12 +116,13 @@ function nameOf(error: unknown): string {
|
|
|
111
116
|
export async function pickDirectoryPath(
|
|
112
117
|
locate: (query: { name: string; id: string }) => Promise<string | null>,
|
|
113
118
|
): Promise<string | null> {
|
|
114
|
-
const
|
|
115
|
-
if (
|
|
119
|
+
const realm = globalThis;
|
|
120
|
+
if (!hasDirectoryPicker(realm)) {
|
|
116
121
|
throw new TypeError(
|
|
117
122
|
"This browser has no folder chooser. Type the folder's path into Location instead.",
|
|
118
123
|
);
|
|
119
124
|
}
|
|
125
|
+
const show = realm.showDirectoryPicker;
|
|
120
126
|
|
|
121
127
|
let handle: DirectoryHandle;
|
|
122
128
|
try {
|
|
@@ -42,6 +42,7 @@ import { getBaseUrl, getOpenAiKey } from "./ai-settings";
|
|
|
42
42
|
import { preferredModel } from "./ai-models";
|
|
43
43
|
import { pruneOrphanToolMessages, trimContext } from "./context-manager";
|
|
44
44
|
import { renderCheck } from "./render-critic";
|
|
45
|
+
import type { CandidateDocument, RenderVerdict } from "./ai-write-report";
|
|
45
46
|
import { validateDoc } from "./jx-validate";
|
|
46
47
|
import { reloadFileInTab } from "../files/files";
|
|
47
48
|
import { getExtensionCatalog, refreshExtensionUi } from "../format/format-host";
|
|
@@ -59,6 +60,20 @@ function projectRoot() {
|
|
|
59
60
|
return workspace.projectRoot || "";
|
|
60
61
|
}
|
|
61
62
|
|
|
63
|
+
/**
|
|
64
|
+
* The open project's configuration.
|
|
65
|
+
*
|
|
66
|
+
* @returns {ProjectConfig | null}
|
|
67
|
+
*/
|
|
68
|
+
function projectConfig(): ProjectConfig | null {
|
|
69
|
+
return workspace.projectConfig;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* SAFETY: renderCheck runs the whole render inside a try and answers `{ ok: false, error }` for
|
|
73
|
+
anything it cannot render, so JSON that is not (yet) a valid document is exactly what it is safe
|
|
74
|
+
to hand; its JxDocument parameter names what renders, not what may be probed. */
|
|
75
|
+
const probeRender = renderCheck as (doc: CandidateDocument) => Promise<RenderVerdict>;
|
|
76
|
+
|
|
62
77
|
/**
|
|
63
78
|
* Create a document-assistant session bound to the currently active tab.
|
|
64
79
|
*
|
|
@@ -82,8 +97,10 @@ export function createDocumentAssistant() {
|
|
|
82
97
|
`ctx.session`. New Chat starts over; a new session id keeps what the conversation knew. */
|
|
83
98
|
let sessionFacts = createSessionFacts();
|
|
84
99
|
|
|
85
|
-
|
|
86
|
-
|
|
100
|
+
/* SAFETY: the token tools read only the top-level `--*` keys of the project style block, and skip
|
|
101
|
+
any whose value is not a string, so the nested rule blocks a JxStyle may also hold are never
|
|
102
|
+
read as tokens. */
|
|
103
|
+
const getProjectStyle = () => projectConfig()?.style as Record<string, string> | undefined;
|
|
87
104
|
|
|
88
105
|
const findOpenTab = (path: string): Tab | null => {
|
|
89
106
|
for (const tab of workspace.tabs.values()) {
|
|
@@ -106,9 +123,7 @@ export function createDocumentAssistant() {
|
|
|
106
123
|
const plat = getPlatform();
|
|
107
124
|
await plat.writeFile(relPath, content);
|
|
108
125
|
},
|
|
109
|
-
renderCheck:
|
|
110
|
-
doc: unknown,
|
|
111
|
-
) => Promise<{ ok: true } | { ok: false; error: string }>,
|
|
126
|
+
renderCheck: probeRender,
|
|
112
127
|
getProjectStyle,
|
|
113
128
|
findOpenTab,
|
|
114
129
|
reloadTab: reloadFileInTab,
|
|
@@ -126,9 +141,7 @@ export function createDocumentAssistant() {
|
|
|
126
141
|
});
|
|
127
142
|
registerProjectTools(innerRegistry, {
|
|
128
143
|
getTab: () => activeTab.value,
|
|
129
|
-
renderCheck:
|
|
130
|
-
doc: unknown,
|
|
131
|
-
) => Promise<{ ok: true } | { ok: false; error: string }>,
|
|
144
|
+
renderCheck: probeRender,
|
|
132
145
|
getProjectStyle,
|
|
133
146
|
findOpenTab,
|
|
134
147
|
reloadTab: reloadFileInTab,
|
|
@@ -221,9 +234,7 @@ export function createDocumentAssistant() {
|
|
|
221
234
|
const commandTools = createCommandToolRegistry({
|
|
222
235
|
getProjectStyle,
|
|
223
236
|
getTab: () => activeTab.value,
|
|
224
|
-
renderCheck:
|
|
225
|
-
doc: unknown,
|
|
226
|
-
) => Promise<{ ok: true } | { ok: false; error: string }>,
|
|
237
|
+
renderCheck: probeRender,
|
|
227
238
|
validate: validateDoc,
|
|
228
239
|
});
|
|
229
240
|
const toolRegistry = composeToolRegistries(
|
|
@@ -263,16 +274,21 @@ export function createDocumentAssistant() {
|
|
|
263
274
|
be two answers to "what can this project turn on". */
|
|
264
275
|
const catalog: ExtensionCatalogSummary[] = [];
|
|
265
276
|
for (const entry of getExtensionCatalog()) {
|
|
266
|
-
|
|
277
|
+
const summary: ExtensionCatalogSummary = {
|
|
267
278
|
name: entry.name,
|
|
268
279
|
sections: entry.sections.map((section) => section.key),
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
280
|
+
};
|
|
281
|
+
if (entry.title !== undefined) {
|
|
282
|
+
summary.title = entry.title;
|
|
283
|
+
}
|
|
284
|
+
if (entry.description !== undefined) {
|
|
285
|
+
summary.description = entry.description;
|
|
286
|
+
}
|
|
287
|
+
catalog.push(summary);
|
|
272
288
|
}
|
|
273
289
|
return buildSystemPrompt({
|
|
274
290
|
document: tab ? toRaw(tab.doc.document) : undefined,
|
|
275
|
-
projectConfig: (
|
|
291
|
+
projectConfig: projectConfig() || undefined,
|
|
276
292
|
components: componentRegistry.length > 0 ? componentRegistry : undefined,
|
|
277
293
|
projectRoot: workspace.projectRoot || undefined,
|
|
278
294
|
hasProject: Boolean(workspace.projectRoot),
|
|
@@ -285,8 +301,9 @@ export function createDocumentAssistant() {
|
|
|
285
301
|
/* Read per turn from the live registry — a projected tool the gate will honour this round is
|
|
286
302
|
listed this round, and one it will not is not. */
|
|
287
303
|
commandTools: commandToolBlurbs(activeRegistry()),
|
|
288
|
-
|
|
289
|
-
|
|
304
|
+
// Absent and undefined read the same: every option is destructured without a default.
|
|
305
|
+
fileInventory: inventory && inventory.length > 0 ? inventory : undefined,
|
|
306
|
+
extensionCatalog: catalog.length > 0 ? catalog : undefined,
|
|
290
307
|
});
|
|
291
308
|
}
|
|
292
309
|
|
|
@@ -347,7 +364,7 @@ export function createDocumentAssistant() {
|
|
|
347
364
|
baseUrl: getBaseUrl() || undefined,
|
|
348
365
|
/* The persisted conversation, so the backend can keep its rounds on one warm prompt cache.
|
|
349
366
|
Sent to the backend only, which hashes it before any provider sees it (specs/ai.md §2.5). */
|
|
350
|
-
sessionId
|
|
367
|
+
sessionId,
|
|
351
368
|
});
|
|
352
369
|
|
|
353
370
|
if (sessionFacts.sessionId !== sessionId) {
|
|
@@ -480,6 +497,9 @@ export function createDocumentAssistant() {
|
|
|
480
497
|
*/
|
|
481
498
|
function pushRestoredMessages(msgs: sessionStore.PersistedMessage[]) {
|
|
482
499
|
for (const m of backfillToolResults(msgs)) {
|
|
500
|
+
/* SAFETY: every persisted message was written by persistChat from a live message (its role,
|
|
501
|
+
tool calls and timestamp included) and its call results were restored by
|
|
502
|
+
backfillToolResults above; only the id a legacy entry may lack is synthesized here. */
|
|
483
503
|
chatState.messages.push({
|
|
484
504
|
...m,
|
|
485
505
|
id: m.id || `restored_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* @license MIT
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import type { ToolContext, ToolDefinition, ToolRegistry } from "@jxsuite/ai/tools";
|
|
16
|
+
import type { ToolArguments, ToolContext, ToolDefinition, ToolRegistry } from "@jxsuite/ai/tools";
|
|
17
17
|
|
|
18
18
|
export interface ToolAvailability {
|
|
19
19
|
/** Whether the tool is currently advertised/executable. */
|
|
@@ -48,17 +48,21 @@ export function createGatedToolRegistry(
|
|
|
48
48
|
},
|
|
49
49
|
listForLLM() {
|
|
50
50
|
const available = new Set(this.list().map((t) => t.name));
|
|
51
|
-
return inner
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
return inner.listForLLM().filter((t) => {
|
|
52
|
+
/* SAFETY: a @jxsuite/ai registry lists each tool in OpenAI function-calling form,
|
|
53
|
+
`{ type: "function", function: { name, … } }`; the registry interface types the entries
|
|
54
|
+
as bare objects, and the optional chain still answers "" for any other shape. */
|
|
55
|
+
const tool = t as { function?: { name?: string } };
|
|
56
|
+
return available.has(tool.function?.name ?? "");
|
|
57
|
+
});
|
|
54
58
|
},
|
|
55
59
|
getDefinition(toolName: string) {
|
|
56
60
|
return inner.getDefinition(toolName);
|
|
57
61
|
},
|
|
58
|
-
validate(toolName: string, args:
|
|
62
|
+
validate(toolName: string, args: ToolArguments) {
|
|
59
63
|
return inner.validate(toolName, args);
|
|
60
64
|
},
|
|
61
|
-
async execute(toolName: string, args:
|
|
65
|
+
async execute(toolName: string, args: ToolArguments, ctx?: ToolContext) {
|
|
62
66
|
if (inner.getDefinition(toolName) && !isAvailable(toolName)) {
|
|
63
67
|
const gate = availability.get(toolName);
|
|
64
68
|
return {
|
|
@@ -11,11 +11,30 @@
|
|
|
11
11
|
|
|
12
12
|
import type { createChatState } from "@jxsuite/ai/chat-state";
|
|
13
13
|
import type { HarnessEvent, TurnOutcome } from "@jxsuite/ai/harness";
|
|
14
|
+
import { isJsonObject, isNumber, isString } from "@jxsuite/schema/guards";
|
|
14
15
|
import type { ImportProgressEvent } from "../../types";
|
|
15
16
|
import { recordImportProgress } from "../import-run";
|
|
16
17
|
|
|
17
18
|
type ChatStore = ReturnType<typeof createChatState>;
|
|
18
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Whether a tool's progress payload is an import progress line. The engine carries progress as
|
|
22
|
+
* opaque JSON; only the import tool reports any, and only in this shape. Exported so the test
|
|
23
|
+
* harness's tool context records exactly what this reducer records.
|
|
24
|
+
*/
|
|
25
|
+
export function isImportProgressEvent(value: unknown): value is ImportProgressEvent {
|
|
26
|
+
if (!isJsonObject(value)) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
const { phase, message, current, total } = value;
|
|
30
|
+
return (
|
|
31
|
+
isString(phase) &&
|
|
32
|
+
isString(message) &&
|
|
33
|
+
(current === undefined || isNumber(current)) &&
|
|
34
|
+
(total === undefined || isNumber(total))
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
19
38
|
/** How a turn's end reads in the transcript: the cap message, an error row, or nothing more. */
|
|
20
39
|
function applyOutcome(chat: ChatStore, outcome: TurnOutcome): void {
|
|
21
40
|
switch (outcome.kind) {
|
|
@@ -96,7 +115,10 @@ export function applyHarnessEvent(chat: ChatStore, event: HarnessEvent): void {
|
|
|
96
115
|
break;
|
|
97
116
|
}
|
|
98
117
|
case "tool_progress": {
|
|
99
|
-
|
|
118
|
+
// A call that is not an import run has no record to update either way.
|
|
119
|
+
if (isImportProgressEvent(event.progress)) {
|
|
120
|
+
recordImportProgress(event.callId, event.progress);
|
|
121
|
+
}
|
|
100
122
|
break;
|
|
101
123
|
}
|
|
102
124
|
case "tool_result": {
|
|
@@ -18,6 +18,7 @@ import type {
|
|
|
18
18
|
ImportSiteOptions,
|
|
19
19
|
ImportSiteSummary,
|
|
20
20
|
} from "../types";
|
|
21
|
+
import { isJsonObject } from "@jxsuite/schema/guards";
|
|
21
22
|
import type { ProjectConfig } from "@jxsuite/schema/types";
|
|
22
23
|
|
|
23
24
|
/**
|
|
@@ -29,6 +30,34 @@ import type { ProjectConfig } from "@jxsuite/schema/types";
|
|
|
29
30
|
*/
|
|
30
31
|
export const IMPORT_WARNING_PHASE = "warning";
|
|
31
32
|
|
|
33
|
+
/** The request headers: JSON, plus the caller's AI credentials when it has them. */
|
|
34
|
+
interface ImportRequestHeaders {
|
|
35
|
+
"Content-Type": string;
|
|
36
|
+
"X-Api-Key"?: string;
|
|
37
|
+
"X-Api-Base-URL"?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** The JSON body the import-site route reads; `model` travels as `aiModel`. */
|
|
41
|
+
interface ImportRequestBody {
|
|
42
|
+
url: string;
|
|
43
|
+
directory: string;
|
|
44
|
+
depth: number;
|
|
45
|
+
maxPages: number;
|
|
46
|
+
aiComponents: boolean;
|
|
47
|
+
breakpoints?: ImportSiteOptions["breakpoints"];
|
|
48
|
+
aiModel?: ImportSiteOptions["model"];
|
|
49
|
+
verify?: boolean;
|
|
50
|
+
verifyThreshold?: number;
|
|
51
|
+
verifyMinFidelity?: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** What a `done` line settles the stream with. */
|
|
55
|
+
export interface ImportStreamResult {
|
|
56
|
+
root: string;
|
|
57
|
+
config: ProjectConfig;
|
|
58
|
+
result?: ImportSiteSummary;
|
|
59
|
+
}
|
|
60
|
+
|
|
32
61
|
interface StreamLine {
|
|
33
62
|
type: string;
|
|
34
63
|
phase?: string;
|
|
@@ -58,8 +87,8 @@ export async function streamImport(
|
|
|
58
87
|
onProgress: (evt: ImportProgressEvent) => void,
|
|
59
88
|
signal?: AbortSignal,
|
|
60
89
|
onReady?: (evt: ImportReadyEvent) => void,
|
|
61
|
-
): Promise<
|
|
62
|
-
const headers:
|
|
90
|
+
): Promise<ImportStreamResult> {
|
|
91
|
+
const headers: ImportRequestHeaders = { "Content-Type": "application/json" };
|
|
63
92
|
if (opts.apiKey) {
|
|
64
93
|
headers["X-Api-Key"] = opts.apiKey;
|
|
65
94
|
}
|
|
@@ -67,32 +96,46 @@ export async function streamImport(
|
|
|
67
96
|
headers["X-Api-Base-URL"] = opts.baseUrl;
|
|
68
97
|
}
|
|
69
98
|
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
99
|
+
const request: ImportRequestBody = {
|
|
100
|
+
url: opts.url,
|
|
101
|
+
directory: opts.directory,
|
|
102
|
+
depth: opts.depth,
|
|
103
|
+
maxPages: opts.maxPages,
|
|
104
|
+
aiComponents: opts.aiComponents,
|
|
105
|
+
};
|
|
106
|
+
if (opts.breakpoints !== undefined) {
|
|
107
|
+
request.breakpoints = opts.breakpoints;
|
|
108
|
+
}
|
|
109
|
+
if (opts.model !== undefined) {
|
|
110
|
+
request.aiModel = opts.model;
|
|
111
|
+
}
|
|
112
|
+
if (opts.verify !== undefined) {
|
|
113
|
+
request.verify = opts.verify;
|
|
114
|
+
}
|
|
115
|
+
if (opts.verifyThreshold !== undefined) {
|
|
116
|
+
request.verifyThreshold = opts.verifyThreshold;
|
|
117
|
+
}
|
|
118
|
+
if (opts.verifyMinFidelity !== undefined) {
|
|
119
|
+
request.verifyMinFidelity = opts.verifyMinFidelity;
|
|
120
|
+
}
|
|
121
|
+
// The spread is a plain record copy: an interface is not assignable to the `HeadersInit` record.
|
|
122
|
+
const init: RequestInit = {
|
|
123
|
+
body: JSON.stringify(request),
|
|
124
|
+
headers: { ...headers },
|
|
86
125
|
method: "POST",
|
|
87
|
-
|
|
88
|
-
|
|
126
|
+
};
|
|
127
|
+
if (signal !== undefined) {
|
|
128
|
+
init.signal = signal;
|
|
129
|
+
}
|
|
130
|
+
const res = await fetch(endpoint, init);
|
|
89
131
|
|
|
90
132
|
if (!res.ok) {
|
|
91
133
|
let message = `Import failed (${res.status})`;
|
|
92
134
|
try {
|
|
93
|
-
const body =
|
|
94
|
-
|
|
95
|
-
|
|
135
|
+
const body: unknown = await res.json();
|
|
136
|
+
// `new Error()` stringifies a non-string message, so String() keeps any `error` value's text.
|
|
137
|
+
if (isJsonObject(body) && body.error) {
|
|
138
|
+
message = String(body.error);
|
|
96
139
|
}
|
|
97
140
|
} catch {
|
|
98
141
|
/* Non-JSON error body — keep the status message. */
|
|
@@ -106,7 +149,7 @@ export async function streamImport(
|
|
|
106
149
|
const reader = res.body.getReader();
|
|
107
150
|
const decoder = new TextDecoder();
|
|
108
151
|
let buffer = "";
|
|
109
|
-
let result:
|
|
152
|
+
let result: ImportStreamResult | null = null;
|
|
110
153
|
/*
|
|
111
154
|
* Lines the parser could not read. Tolerating one is right — an import that ran for two minutes
|
|
112
155
|
* should not die on a garbled progress line — but doing it *silently* is not: the import then
|
|
@@ -115,37 +158,47 @@ export async function streamImport(
|
|
|
115
158
|
*/
|
|
116
159
|
let unreadable = 0;
|
|
117
160
|
|
|
118
|
-
|
|
161
|
+
/** Apply one line; a `done` line's result is returned for the read loop to keep. */
|
|
162
|
+
const handleLine = (line: string): ImportStreamResult | undefined => {
|
|
119
163
|
const trimmed = line.trim();
|
|
120
164
|
if (!trimmed) {
|
|
121
|
-
return;
|
|
165
|
+
return undefined;
|
|
122
166
|
}
|
|
123
167
|
let parsed: StreamLine;
|
|
124
168
|
try {
|
|
169
|
+
/* SAFETY: the import-site route writes every line as JSON.stringify of one stream line
|
|
170
|
+
object with a string `type`, and every other member is optional; each branch below
|
|
171
|
+
compares `type` to a literal and checks the members it reads before using them. */
|
|
125
172
|
parsed = JSON.parse(trimmed) as StreamLine;
|
|
126
173
|
} catch {
|
|
127
174
|
unreadable += 1;
|
|
128
|
-
return; // Tolerate a mangled line rather than killing the whole import.
|
|
175
|
+
return undefined; // Tolerate a mangled line rather than killing the whole import.
|
|
129
176
|
}
|
|
130
177
|
if (parsed.type === "progress") {
|
|
131
|
-
|
|
178
|
+
const progress: ImportProgressEvent = {
|
|
132
179
|
phase: parsed.phase ?? "",
|
|
133
180
|
message: parsed.message ?? "",
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
181
|
+
};
|
|
182
|
+
if (parsed.current !== undefined) {
|
|
183
|
+
progress.current = parsed.current;
|
|
184
|
+
}
|
|
185
|
+
if (parsed.total !== undefined) {
|
|
186
|
+
progress.total = parsed.total;
|
|
187
|
+
}
|
|
188
|
+
onProgress(progress);
|
|
137
189
|
} else if (parsed.type === "ready" && parsed.root !== undefined) {
|
|
138
190
|
onReady?.({ root: parsed.root });
|
|
139
191
|
} else if (parsed.type === "done" && parsed.root !== undefined && parsed.config) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
192
|
+
const settled: ImportStreamResult = { root: parsed.root, config: parsed.config };
|
|
193
|
+
if (parsed.result !== undefined) {
|
|
194
|
+
settled.result = parsed.result;
|
|
195
|
+
}
|
|
196
|
+
return settled;
|
|
145
197
|
} else if (parsed.type === "error") {
|
|
146
198
|
throw new Error(parsed.error || "Import failed");
|
|
147
199
|
}
|
|
148
200
|
// Heartbeats and unknown line types are ignored.
|
|
201
|
+
return undefined;
|
|
149
202
|
};
|
|
150
203
|
|
|
151
204
|
try {
|
|
@@ -159,10 +212,10 @@ export async function streamImport(
|
|
|
159
212
|
const lines = buffer.split("\n");
|
|
160
213
|
buffer = lines.pop() ?? "";
|
|
161
214
|
for (const line of lines) {
|
|
162
|
-
handleLine(line);
|
|
215
|
+
result = handleLine(line) ?? result;
|
|
163
216
|
}
|
|
164
217
|
}
|
|
165
|
-
handleLine(buffer);
|
|
218
|
+
result = handleLine(buffer) ?? result;
|
|
166
219
|
} finally {
|
|
167
220
|
try {
|
|
168
221
|
await reader.cancel();
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* the turn and runs the import as a tool call. This holds what the form gathered for the one turn
|
|
6
6
|
* that consumes it.
|
|
7
7
|
*
|
|
8
|
-
* **Module state, and deliberately NOT a copy of `agent-seed.ts`.** That one uses localStorage
|
|
9
|
-
* by project root because the project it seeds opens in a NEW WINDOW, and the key is the
|
|
8
|
+
* **Module state, and deliberately NOT a copy of `agent-seed.ts`.** That one uses localStorage
|
|
9
|
+
* keyed by project root because the project it seeds opens in a NEW WINDOW, and the key is the
|
|
10
10
|
* cross-window channel. Neither half of that applies here: the project does not exist yet at
|
|
11
11
|
* hand-off time, so there is no root to key on, and the assistant taking the turn is in this window
|
|
12
12
|
* — `import_site` is `no-project` tiered precisely because it runs before there is a project. A
|
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
|
|
19
19
|
import type { ImportBreakpointPolicy } from "../types";
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* The deepest crawl the import pipeline accepts: the bound `packages/server/src/import-api.ts`
|
|
23
|
+
* clamps to, which both the wizard's depth field and `import_site` honour.
|
|
24
|
+
*/
|
|
25
|
+
export const MAX_IMPORT_DEPTH = 5;
|
|
26
|
+
|
|
21
27
|
/** What the wizard gathered, as the tool needs it. */
|
|
22
28
|
export interface ImportBrief {
|
|
23
29
|
/** Absolute http(s) URL of the site to clone. */
|
|
@@ -19,21 +19,21 @@
|
|
|
19
19
|
|
|
20
20
|
import coreDocumentSchema from "@jxsuite/schema/schema.json";
|
|
21
21
|
import coreProjectSchema from "@jxsuite/schema/project-schema.json";
|
|
22
|
-
|
|
23
|
-
type
|
|
24
|
-
|
|
25
|
-
};
|
|
22
|
+
import { isJsonObject, isString } from "@jxsuite/schema/guards";
|
|
23
|
+
import type { JsonObject, JsonValue, ProjectConfig } from "@jxsuite/schema/types";
|
|
24
|
+
import type { ValidateFunction } from "ajv/dist/2020.js";
|
|
25
|
+
import type { CandidateDocument } from "./ai-write-report";
|
|
26
26
|
|
|
27
27
|
/** Which of the two entry documents a validator covers. */
|
|
28
28
|
type SchemaKind = "document" | "project";
|
|
29
29
|
|
|
30
|
-
const CORE: Record<SchemaKind,
|
|
31
|
-
document: coreDocumentSchema
|
|
32
|
-
project: coreProjectSchema
|
|
30
|
+
const CORE: Record<SchemaKind, JsonObject> = {
|
|
31
|
+
document: coreDocumentSchema,
|
|
32
|
+
project: coreProjectSchema,
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
const active: Record<SchemaKind,
|
|
36
|
-
const compiling: Record<SchemaKind, Promise<
|
|
35
|
+
const active: Record<SchemaKind, JsonObject> = { ...CORE };
|
|
36
|
+
const compiling: Record<SchemaKind, Promise<ValidateFunction | null> | null> = {
|
|
37
37
|
document: null,
|
|
38
38
|
project: null,
|
|
39
39
|
};
|
|
@@ -49,9 +49,9 @@ let reportedFailure = false;
|
|
|
49
49
|
* unavailable or the schema will not compile.
|
|
50
50
|
*
|
|
51
51
|
* @param {SchemaKind} kind - Which entry document to compile
|
|
52
|
-
* @returns {Promise<
|
|
52
|
+
* @returns {Promise<ValidateFunction | null>} The compiled validator, or null when unavailable
|
|
53
53
|
*/
|
|
54
|
-
function getValidator(kind: SchemaKind): Promise<
|
|
54
|
+
function getValidator(kind: SchemaKind): Promise<ValidateFunction | null> {
|
|
55
55
|
compiling[kind] ??= (async () => {
|
|
56
56
|
try {
|
|
57
57
|
// The generated schemas are JSON Schema draft 2020-12, so they need Ajv's 2020 build —
|
|
@@ -62,7 +62,7 @@ function getValidator(kind: SchemaKind): Promise<ValidateFn | null> {
|
|
|
62
62
|
const { default: addFormats } = await import("ajv-formats");
|
|
63
63
|
const ajv = new Ajv2020({ allErrors: true, strict: false, allowUnionTypes: true });
|
|
64
64
|
addFormats(ajv);
|
|
65
|
-
return ajv.compile(active[kind])
|
|
65
|
+
return ajv.compile(active[kind]);
|
|
66
66
|
} catch (error) {
|
|
67
67
|
if (!reportedFailure) {
|
|
68
68
|
reportedFailure = true;
|
|
@@ -78,14 +78,9 @@ function getValidator(kind: SchemaKind): Promise<ValidateFn | null> {
|
|
|
78
78
|
return compiling[kind];
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
/**
|
|
82
|
-
function
|
|
83
|
-
return
|
|
84
|
-
value !== null &&
|
|
85
|
-
!Array.isArray(value) &&
|
|
86
|
-
Object.keys(value).length > 0
|
|
87
|
-
? (value as object)
|
|
88
|
-
: undefined;
|
|
81
|
+
/** Whether a payload half is usable as a JSON Schema — a non-empty, non-array object. */
|
|
82
|
+
function isSchemaObject(value: unknown): value is JsonObject {
|
|
83
|
+
return isJsonObject(value) && Object.keys(value).length > 0;
|
|
89
84
|
}
|
|
90
85
|
|
|
91
86
|
/**
|
|
@@ -107,8 +102,10 @@ export function applyProjectSchemas(
|
|
|
107
102
|
* an error envelope under `document` would not fail loudly — it would install a validator that
|
|
108
103
|
* calls every document valid, and every consumer would go on trusting it.
|
|
109
104
|
*/
|
|
110
|
-
const
|
|
111
|
-
const
|
|
105
|
+
const documentHalf = schemas?.document;
|
|
106
|
+
const projectHalf = schemas?.project;
|
|
107
|
+
const document = isSchemaObject(documentHalf) ? documentHalf : CORE.document;
|
|
108
|
+
const project = isSchemaObject(projectHalf) ? projectHalf : CORE.project;
|
|
112
109
|
const applied = document !== CORE.document || project !== CORE.project;
|
|
113
110
|
if (document === active.document && project === active.project) {
|
|
114
111
|
return applied;
|
|
@@ -140,13 +137,13 @@ const ERROR_PROPERTY_KEYS = ["unevaluatedProperty", "additionalProperty", "missi
|
|
|
140
137
|
* Format ajv errors the way the agent loop consumes them (see ai-tools.ts
|
|
141
138
|
* `translateValidationError`).
|
|
142
139
|
*
|
|
143
|
-
* @param {
|
|
140
|
+
* @param {ValidateFunction} validate - The validator that just ran
|
|
144
141
|
* @returns {string[]} One formatted string per error
|
|
145
142
|
*/
|
|
146
|
-
function formatErrors(validate:
|
|
143
|
+
function formatErrors(validate: ValidateFunction): string[] {
|
|
147
144
|
return (validate.errors || []).map((e) => {
|
|
148
|
-
const key = ERROR_PROPERTY_KEYS.find((name) =>
|
|
149
|
-
const property = key ? ` (${String(e.params
|
|
145
|
+
const key = ERROR_PROPERTY_KEYS.find((name) => isString(e.params[name]));
|
|
146
|
+
const property = key ? ` (${String(e.params[key])})` : "";
|
|
150
147
|
return `${e.instancePath || "(root)"}: ${e.message}${property}`;
|
|
151
148
|
});
|
|
152
149
|
}
|
|
@@ -154,10 +151,10 @@ function formatErrors(validate: ValidateFn): string[] {
|
|
|
154
151
|
/**
|
|
155
152
|
* Validate a Jx document against the active document schema.
|
|
156
153
|
*
|
|
157
|
-
* @param {
|
|
154
|
+
* @param {CandidateDocument} doc - Parsed document
|
|
158
155
|
* @returns {Promise<string[]>} Formatted error strings; empty when valid or validation unavailable
|
|
159
156
|
*/
|
|
160
|
-
export async function validateDoc(doc:
|
|
157
|
+
export async function validateDoc(doc: CandidateDocument): Promise<string[]> {
|
|
161
158
|
const validate = await getValidator("document");
|
|
162
159
|
if (!validate || validate(doc)) {
|
|
163
160
|
return [];
|
|
@@ -176,7 +173,7 @@ export async function validateDoc(doc: unknown): Promise<string[]> {
|
|
|
176
173
|
* @param doc - Parsed document
|
|
177
174
|
* @returns The errors, `[]` when valid, or `null` when no validator could be compiled
|
|
178
175
|
*/
|
|
179
|
-
export async function validateDocOrNull(doc:
|
|
176
|
+
export async function validateDocOrNull(doc: CandidateDocument): Promise<string[] | null> {
|
|
180
177
|
const validate = await getValidator("document");
|
|
181
178
|
if (!validate) {
|
|
182
179
|
return null;
|
|
@@ -190,10 +187,10 @@ export async function validateDocOrNull(doc: unknown): Promise<string[] | null>
|
|
|
190
187
|
* extension's fragment), so this is the only gate that catches a typo'd section key or a misshapen
|
|
191
188
|
* extension section before the write lands.
|
|
192
189
|
*
|
|
193
|
-
* @param {
|
|
190
|
+
* @param {ProjectConfig | JsonValue} config - Parsed project.json
|
|
194
191
|
* @returns {Promise<string[]>} Formatted error strings; empty when valid or validation unavailable
|
|
195
192
|
*/
|
|
196
|
-
export async function validateProjectConfig(config:
|
|
193
|
+
export async function validateProjectConfig(config: ProjectConfig | JsonValue): Promise<string[]> {
|
|
197
194
|
const validate = await getValidator("project");
|
|
198
195
|
if (!validate || validate(config)) {
|
|
199
196
|
return [];
|
|
Binary file
|
|
@@ -173,12 +173,15 @@ export interface LiveSurfaceDeps {
|
|
|
173
173
|
redefineOnCanvases: (doc: JxDocument, base: string) => number;
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
/**
|
|
177
|
-
export
|
|
176
|
+
/** How a save's result is announced: the toast key it replaces, its level and its sentence. */
|
|
177
|
+
export interface LiveSaveNotice {
|
|
178
178
|
key: string;
|
|
179
179
|
level: "info" | "warn";
|
|
180
180
|
message: string;
|
|
181
|
-
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** The sentence a result is said in. Exported so the wording is tested, not only the branch. */
|
|
184
|
+
export function liveSaveNotice(result: LiveSurfaceResult): LiveSaveNotice {
|
|
182
185
|
const what =
|
|
183
186
|
result.target.kind === "surface" ? `surface ${result.target.name}` : result.target.tag;
|
|
184
187
|
const key = `live-chrome:${what}`;
|