@jxsuite/studio 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/canvas.html +21 -0
- package/dist/chunks/Overlay.dev-qfjzkms8.js +23 -0
- package/dist/chunks/{Overlay.dev-cszx7yn5.js.map → Overlay.dev-qfjzkms8.js.map} +1 -1
- package/dist/chunks/{adapter-z8fkmbmv.js → adapter-qfnesn5v.js} +2 -2
- package/dist/chunks/{cf-settings-mmyv436d.js → cf-settings-73sh5z4p.js} +3 -3
- package/dist/chunks/{components-0hzentwq.js → components-2bpqp4mq.js} +5 -7
- package/dist/chunks/{components-0hzentwq.js.map → components-2bpqp4mq.js.map} +1 -1
- package/dist/chunks/content-source-34gnkbnn.js +38 -0
- package/dist/chunks/content-source-34gnkbnn.js.map +9 -0
- package/dist/chunks/convert-to-repeater-t8kxre5s.js +258 -0
- package/dist/chunks/convert-to-repeater-t8kxre5s.js.map +10 -0
- package/dist/chunks/extension-sections-6mqydz35.js +301 -0
- package/dist/chunks/extension-sections-6mqydz35.js.map +11 -0
- package/dist/chunks/files-8kn321h1.js +70 -0
- package/dist/chunks/files-8kn321h1.js.map +9 -0
- package/dist/chunks/{format-host-2c188n41.js → format-host-mkwsmt8d.js} +3 -3
- package/dist/chunks/git-panel-tjbr191d.js +51 -0
- package/dist/chunks/git-panel-tjbr191d.js.map +9 -0
- package/dist/chunks/{index-baeg2x3y.js → index-7pxchcce.js} +4 -3
- package/dist/chunks/{index-baeg2x3y.js.map → index-7pxchcce.js.map} +3 -3
- package/dist/chunks/{jx-validate-qx8degj7.js → jx-validate-v6qgknrs.js} +3 -3
- package/dist/chunks/layers-panel-87pb25km.js +58 -0
- package/dist/chunks/layers-panel-87pb25km.js.map +9 -0
- package/dist/chunks/{monaco-setup-zjdp9zdw.js → monaco-setup-e0yh25j4.js} +4 -75
- package/dist/chunks/{monaco-setup-zjdp9zdw.js.map → monaco-setup-e0yh25j4.js.map} +3 -4
- package/dist/chunks/publish-panel-m0fcgdrt.js +21 -0
- package/dist/chunks/publish-panel-m0fcgdrt.js.map +9 -0
- package/dist/chunks/quick-search-rhs6cbsb.js +53 -0
- package/dist/chunks/quick-search-rhs6cbsb.js.map +9 -0
- package/dist/chunks/right-panel-zpdxd98t.js +37 -0
- package/dist/chunks/right-panel-zpdxd98t.js.map +9 -0
- package/dist/chunks/section-registry-zmckaxf4.js +30 -0
- package/dist/chunks/section-registry-zmckaxf4.js.map +9 -0
- package/dist/chunks/sp-overlay.dev-9ran0sfq.js +18 -0
- package/dist/chunks/sp-overlay.dev-9ran0sfq.js.map +9 -0
- package/dist/chunks/sp-popover.dev-rebmdncr.js +9 -0
- package/dist/chunks/sp-popover.dev-rebmdncr.js.map +9 -0
- package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js +15 -0
- package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js.map +9 -0
- package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js +15 -0
- package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js.map +9 -0
- package/dist/chunks/{sp-tray.dev-pb2fsd65.js → sp-tray.dev-ey59vfh7.js} +10 -8
- package/dist/chunks/{sp-tray.dev-pb2fsd65.js.map → sp-tray.dev-ey59vfh7.js.map} +2 -2
- package/dist/chunks/{studio-9qr6fq7p.js → studio-0rqqhrdy.js} +10 -378
- package/dist/chunks/{studio-9qr6fq7p.js.map → studio-0rqqhrdy.js.map} +4 -14
- package/dist/chunks/{studio-5x6tqqec.js → studio-2sj1jj3v.js} +10 -8
- package/dist/chunks/{studio-5x6tqqec.js.map → studio-2sj1jj3v.js.map} +2 -2
- package/dist/chunks/{studio-h3fw0wn8.js → studio-3fk1ac9z.js} +6 -4
- package/dist/chunks/{studio-h3fw0wn8.js.map → studio-3fk1ac9z.js.map} +2 -2
- package/dist/chunks/studio-41exgzhq.js +6690 -0
- package/dist/chunks/studio-41exgzhq.js.map +38 -0
- package/dist/chunks/{studio-7v2bpweq.js → studio-4mqb9a0j.js} +6 -4
- package/dist/chunks/{studio-7v2bpweq.js.map → studio-4mqb9a0j.js.map} +2 -2
- package/dist/chunks/studio-50k77cca.js +1787 -0
- package/dist/chunks/studio-50k77cca.js.map +18 -0
- package/dist/chunks/{studio-56v3zwk6.js → studio-6a0h7sne.js} +10 -8
- package/dist/chunks/{studio-56v3zwk6.js.map → studio-6a0h7sne.js.map} +2 -2
- package/dist/chunks/studio-6f0am8f2.js +53 -0
- package/dist/chunks/studio-6f0am8f2.js.map +10 -0
- package/dist/chunks/studio-6nmjc5qk.js +7002 -0
- package/dist/chunks/studio-6nmjc5qk.js.map +32 -0
- package/dist/chunks/studio-7afd21nw.js +67 -0
- package/dist/chunks/studio-7afd21nw.js.map +10 -0
- package/dist/chunks/{studio-xze4zrs1.js → studio-7bmdvzne.js} +2 -2
- package/dist/chunks/studio-7bmdvzne.js.map +10 -0
- package/dist/chunks/studio-8jpzqk5s.js +128 -0
- package/dist/chunks/studio-8jpzqk5s.js.map +10 -0
- package/dist/chunks/studio-94m77tgk.js +1482 -0
- package/dist/chunks/studio-94m77tgk.js.map +13 -0
- package/dist/chunks/studio-9je6w5sq.js +1000 -0
- package/dist/chunks/studio-9je6w5sq.js.map +16 -0
- package/dist/chunks/{studio-w7c6kvk7.js → studio-a7pzveq1.js} +2 -2
- package/dist/chunks/{studio-97qcgvdn.js → studio-adn0z1k3.js} +14 -8
- package/dist/chunks/{studio-97qcgvdn.js.map → studio-adn0z1k3.js.map} +3 -3
- package/dist/chunks/{studio-kr88ryr7.js → studio-bsxxx3x2.js} +17 -15
- package/dist/chunks/{studio-kr88ryr7.js.map → studio-bsxxx3x2.js.map} +7 -6
- package/dist/chunks/studio-bw5dz6km.js +608 -0
- package/dist/chunks/studio-bw5dz6km.js.map +21 -0
- package/dist/chunks/studio-c6s5getc.js +4232 -0
- package/dist/chunks/studio-c6s5getc.js.map +39 -0
- package/dist/chunks/studio-cjm7fdjf.js +451 -0
- package/dist/chunks/studio-cjm7fdjf.js.map +14 -0
- package/dist/chunks/{studio-cx91mnh8.js → studio-ckwz4d3x.js} +53 -53
- package/dist/chunks/{studio-cx91mnh8.js.map → studio-ckwz4d3x.js.map} +5 -5
- package/dist/chunks/studio-dg7zyt5x.js +28 -0
- package/dist/chunks/studio-dg7zyt5x.js.map +10 -0
- package/dist/chunks/studio-dzcyvvvz.js +166 -0
- package/dist/chunks/studio-dzcyvvvz.js.map +10 -0
- package/dist/chunks/{studio-7kqe41sa.js → studio-evkr5d3b.js} +15 -7
- package/dist/chunks/{studio-7kqe41sa.js.map → studio-evkr5d3b.js.map} +5 -4
- package/dist/chunks/studio-f12h6177.js +411 -0
- package/dist/chunks/studio-f12h6177.js.map +13 -0
- package/dist/chunks/studio-hbp1s8m9.js +1817 -0
- package/dist/chunks/studio-hbp1s8m9.js.map +14 -0
- package/dist/chunks/studio-k2sxjph5.js +15295 -0
- package/dist/chunks/studio-k2sxjph5.js.map +235 -0
- package/dist/chunks/studio-myje51t3.js +385 -0
- package/dist/chunks/studio-myje51t3.js.map +12 -0
- package/dist/chunks/studio-na6rwzhw.js +353 -0
- package/dist/chunks/studio-na6rwzhw.js.map +11 -0
- package/dist/chunks/{studio-4k0m4fmp.js → studio-p471gg5n.js} +126 -3
- package/dist/chunks/studio-p471gg5n.js.map +14 -0
- package/dist/chunks/{studio-9bjwf0d4.js → studio-rgwcpast.js} +5 -46
- package/dist/chunks/{studio-9bjwf0d4.js.map → studio-rgwcpast.js.map} +4 -5
- package/dist/chunks/{studio-hhj92gcr.js → studio-s519zc99.js} +3 -3
- package/dist/chunks/studio-sas7mt3k.js +75 -0
- package/dist/chunks/studio-sas7mt3k.js.map +10 -0
- package/dist/chunks/studio-t5wqwzdh.js +74 -0
- package/dist/chunks/studio-t5wqwzdh.js.map +10 -0
- package/dist/chunks/{studio-9qpspwfn.js → studio-temv5bw4.js} +5 -5
- package/dist/chunks/{studio-9qpspwfn.js.map → studio-temv5bw4.js.map} +1 -1
- package/dist/chunks/{studio-qkvt37c0.js → studio-tr20m8g8.js} +669 -18
- package/dist/chunks/studio-tr20m8g8.js.map +9 -0
- package/dist/chunks/{studio-ygzav7z5.js → studio-v96qfnww.js} +5514 -4291
- package/dist/chunks/studio-v96qfnww.js.map +54 -0
- package/dist/chunks/studio-vcetc91k.js +659 -0
- package/dist/chunks/studio-vcetc91k.js.map +10 -0
- package/dist/chunks/{studio-n9zmpxjg.js → studio-vmymjefp.js} +2972 -4937
- package/dist/chunks/studio-vmymjefp.js.map +98 -0
- package/dist/chunks/{studio-bghqfmea.js → studio-wwseqyw0.js} +2 -2
- package/dist/chunks/studio-x9hmy5kr.js +390 -0
- package/dist/chunks/studio-x9hmy5kr.js.map +10 -0
- package/dist/chunks/studio-xa0ce0n7.js +335 -0
- package/dist/chunks/studio-xa0ce0n7.js.map +10 -0
- package/dist/chunks/studio-xm3dbxvn.js +378 -0
- package/dist/chunks/studio-xm3dbxvn.js.map +19 -0
- package/dist/chunks/{studio-nqw433kv.js → studio-xmvbhg31.js} +2 -2
- package/dist/chunks/studio-zv37yrfa.js +1054 -0
- package/dist/chunks/studio-zv37yrfa.js.map +13 -0
- package/dist/chunks/{ws-client-q7hkz3j9.js → ws-client-654ts66j.js} +6 -4
- package/dist/chunks/ws-client-654ts66j.js.map +11 -0
- package/dist/iframe-entry.js +668 -230
- package/dist/studio.js +23711 -35185
- package/index.html +35 -4685
- package/package.json +17 -15
- package/src/about/about-modal.ts +42 -11
- package/src/browse/library-commands.ts +240 -0
- package/src/browse/library-layouts.ts +369 -0
- package/src/browse/library-model.ts +396 -0
- package/src/browse/library-pane.ts +1049 -0
- package/src/browse/library-preview.ts +252 -0
- package/src/browse/library-source.ts +150 -0
- package/src/canvas/canvas-helpers.ts +33 -9
- package/src/canvas/canvas-live-render.ts +45 -29
- package/src/canvas/canvas-patcher.ts +151 -31
- package/src/canvas/canvas-perf.ts +46 -7
- package/src/canvas/canvas-render.ts +1092 -220
- package/src/canvas/canvas-surface.ts +240 -0
- package/src/canvas/canvas-utils.ts +1166 -124
- package/src/canvas/iframe-drop.ts +2 -1
- package/src/canvas/iframe-entry.ts +241 -4
- package/src/canvas/iframe-host.ts +1226 -143
- package/src/canvas/iframe-inline-edit.ts +31 -0
- package/src/canvas/iframe-interaction.ts +76 -16
- package/src/canvas/iframe-keys.ts +107 -45
- package/src/canvas/iframe-overlay.ts +38 -1
- package/src/canvas/iframe-protocol.ts +137 -2
- package/src/canvas/iframe-render.ts +70 -2
- package/src/canvas/iframe-slash.ts +6 -0
- package/src/canvas/path-mapping.ts +56 -6
- package/src/canvas/surface-registry.ts +292 -0
- package/src/collab/collab-commands.ts +244 -0
- package/src/collab/collab-session.ts +198 -32
- package/src/collab/collab-state.ts +28 -2
- package/src/collab/presence-chips.ts +100 -9
- package/src/commands/active-registry.ts +42 -0
- package/src/commands/app-commands.ts +176 -0
- package/src/commands/budget.ts +158 -0
- package/src/commands/command-args.ts +253 -0
- package/src/commands/context.ts +387 -0
- package/src/commands/defaults.ts +580 -0
- package/src/commands/keymap.ts +571 -0
- package/src/commands/levels.ts +345 -0
- package/src/commands/live-context.ts +193 -0
- package/src/commands/reference.ts +227 -0
- package/src/commands/registry.ts +293 -0
- package/src/component-props.ts +3 -2
- package/src/content/draft-state.ts +106 -0
- package/src/content/entry-commands.ts +282 -0
- package/src/content/entry-editor.ts +327 -0
- package/src/content/entry-fields.ts +116 -0
- package/src/content/entry-model.ts +175 -0
- package/src/editor/canvas-context-menu.ts +17 -11
- package/src/editor/canvas-slash-bridge.ts +11 -4
- package/src/editor/context-menu.ts +804 -204
- package/src/editor/convert-to-component.ts +31 -10
- package/src/editor/convert-to-repeater.ts +3 -2
- package/src/editor/inline-edit-apply.ts +5 -5
- package/src/editor/inline-edit.ts +86 -50
- package/src/editor/insert-zone-action.ts +1 -1
- package/src/editor/shortcuts.ts +1043 -329
- package/src/editor/slash-menu.ts +1 -0
- package/src/files/elements.ts +166 -0
- package/src/files/file-ops.ts +178 -31
- package/src/files/files.ts +898 -268
- package/src/files/fs-events.ts +21 -0
- package/src/files/media-meta.ts +203 -0
- package/src/files/media-paths.ts +141 -0
- package/src/files/media-upload.ts +7 -3
- package/src/files/media-usage.ts +189 -0
- package/src/github/github-auth.ts +235 -33
- package/src/github/github-publish.ts +80 -21
- package/src/grid/grid-controller.ts +152 -12
- package/src/grid/grid-layout.ts +225 -20
- package/src/grid/grid-open.ts +120 -0
- package/src/grid/grid-panel.ts +554 -39
- package/src/grid/grid-source.ts +27 -1
- package/src/grid/redirects-grid.ts +599 -0
- package/src/grid/redirects.ts +398 -0
- package/src/grid/sources/content-source.ts +108 -2
- package/src/i18n/i18n-commands.ts +322 -0
- package/src/new-project/add-repo-modal.ts +8 -10
- package/src/new-project/import-tab.ts +34 -9
- package/src/new-project/location-fields.ts +9 -1
- package/src/new-project/new-project-modal.ts +270 -262
- package/src/packages/jxsuite-update.ts +97 -48
- package/src/packages/pull-package-sync.ts +18 -9
- package/src/page-params.ts +2 -1
- package/src/panels/activity-bar.ts +152 -91
- package/src/panels/activity-panel.ts +481 -0
- package/src/panels/ai-chat/chat-markdown.ts +8 -3
- package/src/panels/ai-chat/chat-view.ts +245 -18
- package/src/panels/ai-chat/composer.ts +31 -5
- package/src/panels/ai-chat/sessions-view.ts +17 -10
- package/src/panels/ai-panel.ts +279 -120
- package/src/panels/block-action-bar.ts +1115 -224
- package/src/panels/bottom-dock.ts +337 -0
- package/src/panels/canvas-dnd-bridge.ts +37 -8
- package/src/panels/chat-panel.ts +29 -12
- package/src/panels/data-explorer.ts +254 -112
- package/src/panels/data-grid.ts +10 -4
- package/src/panels/dnd.ts +28 -51
- package/src/panels/editors.ts +434 -107
- package/src/panels/elements-panel.ts +66 -2
- package/src/panels/empty-state.ts +112 -0
- package/src/panels/events-panel.ts +596 -82
- package/src/panels/formula-workspace.ts +408 -218
- package/src/panels/frontmatter-fields.ts +51 -10
- package/src/panels/frontmatter-panel.ts +357 -79
- package/src/panels/git-panel.ts +375 -164
- package/src/panels/head-panel.ts +791 -85
- package/src/panels/i18n-panel.ts +592 -0
- package/src/panels/imports-panel.ts +95 -85
- package/src/panels/jump-bar.ts +584 -0
- package/src/panels/layers-panel.ts +1106 -328
- package/src/panels/left-panel.ts +109 -204
- package/src/panels/navigator-panels.ts +131 -0
- package/src/panels/overlays.ts +7 -2
- package/src/panels/pane-context.ts +1477 -0
- package/src/panels/pane-grid.ts +406 -0
- package/src/panels/panel-registry.ts +340 -0
- package/src/panels/panel-scheduler.ts +75 -0
- package/src/panels/problems-panel.ts +234 -0
- package/src/panels/properties-panel.ts +946 -1139
- package/src/panels/provenance.ts +258 -0
- package/src/panels/quick-search.ts +791 -122
- package/src/panels/right-panel.ts +228 -102
- package/src/panels/seo-modal.ts +395 -0
- package/src/panels/settings-pane.ts +203 -0
- package/src/panels/signals-panel.ts +354 -137
- package/src/panels/statement-editor.ts +41 -25
- package/src/panels/statusbar.ts +342 -106
- package/src/panels/style-panel.ts +974 -463
- package/src/panels/style-utils.ts +3 -3
- package/src/panels/stylebook-doc.ts +4 -2
- package/src/panels/stylebook-layers-panel.ts +3 -2
- package/src/panels/stylebook-panel.ts +51 -26
- package/src/panels/tab-strip.ts +1058 -78
- package/src/panels/target-line.ts +274 -0
- package/src/panels/toolbar.ts +631 -484
- package/src/panels/welcome-screen.ts +301 -198
- package/src/platform-errors.ts +26 -3
- package/src/platform.ts +96 -2
- package/src/platforms/cloud.ts +71 -8
- package/src/platforms/devserver.ts +92 -29
- package/src/publish/deploy-checklist.ts +383 -0
- package/src/publish/pages-service.ts +10 -1
- package/src/publish/publish-commands.ts +218 -0
- package/src/publish/publish-panel.ts +110 -16
- package/src/recent-projects.ts +3 -2
- package/src/services/a11y-report.ts +505 -0
- package/src/services/ai-models.ts +75 -2
- package/src/services/ai-project-tools.ts +29 -10
- package/src/services/ai-system-prompt.ts +53 -14
- package/src/services/ai-tools.ts +39 -3
- package/src/services/ai-writes.ts +154 -0
- package/src/services/announce.ts +97 -0
- package/src/services/automation.ts +424 -175
- package/src/services/cem-export.ts +9 -4
- package/src/services/clock.ts +61 -0
- package/src/services/document-assistant.ts +36 -8
- package/src/services/idle.ts +179 -0
- package/src/services/import-client.ts +26 -0
- package/src/services/monaco-buffer.ts +627 -0
- package/src/services/monaco-lazy.ts +36 -0
- package/src/services/notify.ts +271 -0
- package/src/services/profile.ts +155 -0
- package/src/services/references.ts +0 -0
- package/src/services/token-lint.ts +3 -2
- package/src/services/tool-executor.ts +53 -7
- package/src/services/trusted-types.ts +123 -0
- package/src/settings/contexts-section.ts +427 -0
- package/src/settings/contributed-section.ts +149 -11
- package/src/settings/css-vars-editor.ts +306 -349
- package/src/settings/defs-editor.ts +93 -34
- package/src/settings/dependencies-editor.ts +7 -7
- package/src/settings/extension-sections.ts +37 -5
- package/src/settings/general-settings.ts +204 -121
- package/src/settings/locales-section.ts +347 -0
- package/src/settings/preferences-accounts.ts +140 -0
- package/src/settings/preferences-dialog.ts +620 -0
- package/src/settings/preferences-keymap.ts +270 -0
- package/src/settings/project-sections.ts +260 -0
- package/src/settings/section-registry.ts +169 -0
- package/src/settings/settings-document.ts +385 -0
- package/src/shell.ts +1549 -0
- package/src/site-context.ts +45 -20
- package/src/state.ts +14 -275
- package/src/store.ts +88 -43
- package/src/studio.ts +790 -346
- package/src/style/live-preview.ts +36 -0
- package/src/style/project-styles.ts +349 -0
- package/src/style/token-ref.ts +123 -0
- package/src/tabs/patch-ops.ts +16 -4
- package/src/tabs/project-config.ts +416 -0
- package/src/tabs/selection.ts +323 -0
- package/src/tabs/tab.ts +182 -47
- package/src/tabs/transact.ts +209 -28
- package/src/types.ts +68 -13
- package/src/ui/ai-credentials-form.ts +39 -35
- package/src/ui/ai-managed-connect.ts +113 -0
- package/src/ui/dynamic-slot.ts +224 -81
- package/src/ui/expression-editor.ts +71 -63
- package/src/ui/field-input.ts +4 -6
- package/src/ui/field-row.ts +215 -38
- package/src/ui/form-controls.ts +194 -7
- package/src/ui/layers.ts +492 -69
- package/src/ui/media-picker.ts +115 -25
- package/src/ui/panel-resize.ts +109 -91
- package/src/ui/progress-modal.ts +131 -50
- package/src/ui/regions.ts +462 -0
- package/src/ui/schema-form.ts +229 -45
- package/src/ui/spectrum.ts +24 -8
- package/src/ui/timing.ts +49 -0
- package/src/ui/value-selector.ts +20 -0
- package/src/ui/value-source.ts +348 -0
- package/src/ui/virtual-window.ts +400 -0
- package/src/utils/edit-display.ts +3 -2
- package/src/utils/inherited-style.ts +67 -37
- package/src/view.ts +64 -78
- package/src/workspace/pane-derive.ts +1258 -0
- package/src/workspace/session.ts +317 -0
- package/src/workspace/workspace.ts +1345 -23
- package/styles/canvas.css +653 -0
- package/styles/forced-colors.css +106 -0
- package/styles/inspector.css +1454 -0
- package/styles/overlays.css +2704 -0
- package/styles/panels.css +1701 -0
- package/styles/shell.css +1423 -0
- package/styles/tokens.css +151 -0
- package/dist/chunks/Overlay.dev-cszx7yn5.js +0 -22
- package/dist/chunks/extension-sections-qct0gt8f.js +0 -531
- package/dist/chunks/extension-sections-qct0gt8f.js.map +0 -12
- package/dist/chunks/files-02zn5y24.js +0 -50
- package/dist/chunks/files-02zn5y24.js.map +0 -9
- package/dist/chunks/git-panel-mbb0y0hz.js +0 -28
- package/dist/chunks/git-panel-mbb0y0hz.js.map +0 -9
- package/dist/chunks/layers-panel-9qekmqk1.js +0 -26
- package/dist/chunks/layers-panel-9qekmqk1.js.map +0 -9
- package/dist/chunks/settings-modal-gj0hrah4.js +0 -29
- package/dist/chunks/settings-modal-gj0hrah4.js.map +0 -9
- package/dist/chunks/sp-overlay.dev-earn5as8.js +0 -17
- package/dist/chunks/sp-overlay.dev-earn5as8.js.map +0 -9
- package/dist/chunks/sp-popover.dev-frxtfejn.js +0 -8
- package/dist/chunks/sp-popover.dev-frxtfejn.js.map +0 -9
- package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js +0 -14
- package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js.map +0 -9
- package/dist/chunks/sp-tooltip.dev-a9fywesm.js +0 -21
- package/dist/chunks/sp-tooltip.dev-a9fywesm.js.map +0 -10
- package/dist/chunks/studio-4k0m4fmp.js.map +0 -13
- package/dist/chunks/studio-568nx4t5.js +0 -469
- package/dist/chunks/studio-568nx4t5.js.map +0 -14
- package/dist/chunks/studio-9smfzqhc.js +0 -19
- package/dist/chunks/studio-9smfzqhc.js.map +0 -10
- package/dist/chunks/studio-asvf0j9e.js +0 -429
- package/dist/chunks/studio-asvf0j9e.js.map +0 -13
- package/dist/chunks/studio-d77qm3pk.js +0 -3427
- package/dist/chunks/studio-d77qm3pk.js.map +0 -26
- package/dist/chunks/studio-j6gqyjf4.js +0 -1854
- package/dist/chunks/studio-j6gqyjf4.js.map +0 -18
- package/dist/chunks/studio-n9zmpxjg.js.map +0 -115
- package/dist/chunks/studio-qkvt37c0.js.map +0 -9
- package/dist/chunks/studio-rq0vxb19.js +0 -3744
- package/dist/chunks/studio-rq0vxb19.js.map +0 -22
- package/dist/chunks/studio-wd6ewdvd.js +0 -853
- package/dist/chunks/studio-wd6ewdvd.js.map +0 -12
- package/dist/chunks/studio-xq0t7n5t.js +0 -140
- package/dist/chunks/studio-xq0t7n5t.js.map +0 -10
- package/dist/chunks/studio-xze4zrs1.js.map +0 -10
- package/dist/chunks/studio-ygzav7z5.js.map +0 -46
- package/dist/chunks/studio-zmy7241e.js +0 -399
- package/dist/chunks/studio-zmy7241e.js.map +0 -12
- package/dist/chunks/ws-client-q7hkz3j9.js.map +0 -11
- package/src/browse/browse-modal.ts +0 -69
- package/src/browse/browse.ts +0 -904
- package/src/canvas/canvas-diff.ts +0 -216
- package/src/canvas/nested-site-style.ts +0 -58
- package/src/new-project/design-fields.ts +0 -264
- package/src/new-project/templates.ts +0 -61
- package/src/panels/tab-bar.ts +0 -548
- package/src/settings/settings-modal.ts +0 -203
- /package/dist/chunks/{adapter-z8fkmbmv.js.map → adapter-qfnesn5v.js.map} +0 -0
- /package/dist/chunks/{cf-settings-mmyv436d.js.map → cf-settings-73sh5z4p.js.map} +0 -0
- /package/dist/chunks/{format-host-2c188n41.js.map → format-host-mkwsmt8d.js.map} +0 -0
- /package/dist/chunks/{jx-validate-qx8degj7.js.map → jx-validate-v6qgknrs.js.map} +0 -0
- /package/dist/chunks/{studio-w7c6kvk7.js.map → studio-a7pzveq1.js.map} +0 -0
- /package/dist/chunks/{studio-hhj92gcr.js.map → studio-s519zc99.js.map} +0 -0
- /package/dist/chunks/{studio-bghqfmea.js.map → studio-wwseqyw0.js.map} +0 -0
- /package/dist/chunks/{studio-nqw433kv.js.map → studio-xmvbhg31.js.map} +0 -0
|
@@ -6,7 +6,27 @@
|
|
|
6
6
|
* blocks become chips), assistant messages render sanitized markdown plus tool-call
|
|
7
7
|
* chips, tool messages surface failures only (ADR §11.3), the streaming tail renders
|
|
8
8
|
* as plain text with a cursor (markdown parses once on finalize), and chat errors get
|
|
9
|
-
* a danger row with recovery advice.
|
|
9
|
+
* a danger row with recovery advice and a Retry. Templates only — chat state lives in ai-panel, and
|
|
10
|
+
* the three buttons are records the registry holds (see below).
|
|
11
|
+
*
|
|
12
|
+
* §7.4 (AI honesty) is why three things here are not what they were:
|
|
13
|
+
*
|
|
14
|
+
* - **A chip renders its OUTCOME.** `ToolCallRecord.result` has always been populated by the loop
|
|
15
|
+
* and ignored by this renderer, so a chip that said `update_style: ["children",0]` said exactly
|
|
16
|
+
* as much when the edit had been refused as when it had landed.
|
|
17
|
+
* - **A turn renders what it CHANGED.** The changed-files summary comes off the write ledger
|
|
18
|
+
* (`services/ai-writes.ts`), which records whether each change went through a transaction or
|
|
19
|
+
* straight to disk — so the undo caveat is rendered to the human holding ⌘Z instead of being
|
|
20
|
+
* appended to the model-facing tool summary.
|
|
21
|
+
* - **An error offers Retry.** `chatState.retryLast()` has been implemented, exported and called by
|
|
22
|
+
* nobody; the error row is where it belongs.
|
|
23
|
+
*
|
|
24
|
+
* §11.1 is why the three buttons here are not callbacks any more. History, New Chat and Retry were
|
|
25
|
+
* closures this module received and invoked, so the capabilities existed ONLY as buttons: the
|
|
26
|
+
* `Assistant` category held zero records, and nothing could reach them from the palette, a chord,
|
|
27
|
+
* the automation runner or the generated commands sheet. They run {@link commandButton} now, in the
|
|
28
|
+
* idiom `panels/statusbar.ts` established — the record is the definition site, and this file only
|
|
29
|
+
* decides where it is drawn.
|
|
10
30
|
*
|
|
11
31
|
* @license MIT
|
|
12
32
|
*/
|
|
@@ -17,6 +37,8 @@ import { ref } from "lit-html/directives/ref.js";
|
|
|
17
37
|
import type { Message, ToolCallRecord } from "@jxsuite/ai/chat-state";
|
|
18
38
|
import { splitAttachedContext } from "./attached-context";
|
|
19
39
|
import { renderMarkdown } from "./chat-markdown";
|
|
40
|
+
import { summarizeWrites, writesForTurn } from "../../services/ai-writes";
|
|
41
|
+
import { activeRegistry } from "../../commands/active-registry";
|
|
20
42
|
|
|
21
43
|
// ─── Helpers (moved from ai-panel.ts) ────────────────────────────────────────
|
|
22
44
|
|
|
@@ -89,33 +111,125 @@ export function formatErrorAdvice(error: string): string {
|
|
|
89
111
|
return "";
|
|
90
112
|
}
|
|
91
113
|
|
|
114
|
+
// ─── Commands as buttons ────────────────────────────────────────────────────
|
|
115
|
+
|
|
116
|
+
/** What {@link commandButton} draws inside the button, and how. */
|
|
117
|
+
export interface CommandButtonOptions {
|
|
118
|
+
/** Slotted content — an icon element for the header, a label for the error row's Retry. */
|
|
119
|
+
content: TemplateResult | string;
|
|
120
|
+
/** Extra class, so the CSS that already targets `.ai-msg-retry` keeps landing. */
|
|
121
|
+
className?: string;
|
|
122
|
+
/** Quiet chrome. The header's icon buttons are quiet; the labelled Retry is not. */
|
|
123
|
+
quiet?: boolean;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* One control that IS a command — `panels/statusbar.ts`'s `itemTpl`, for the assistant.
|
|
128
|
+
*
|
|
129
|
+
* A command the registry does not hold, or whose `when` is false, renders NOTHING rather than a
|
|
130
|
+
* dead button; a visible-but-refused one renders disabled with its `requires` sentence in the
|
|
131
|
+
* tooltip. That is what keeps this file a rendering of the registry instead of a second place the
|
|
132
|
+
* assistant's capabilities are decided — and it is why `tests/ai-chat-view.test.ts` asserts the
|
|
133
|
+
* ids, exactly as `tests/statusbar.test.ts` does: an id is not an interface between two files
|
|
134
|
+
* unless something checks it.
|
|
135
|
+
*
|
|
136
|
+
* Before any registry exists (the bootstrap composes one at the END of `studio.ts`, and a reduced
|
|
137
|
+
* test fixture may compose none) the button is simply absent. The chat is still readable, which is
|
|
138
|
+
* the same bargain the status bar strikes for the frame it paints early.
|
|
139
|
+
*/
|
|
140
|
+
export function commandButton(
|
|
141
|
+
id: string,
|
|
142
|
+
opts: CommandButtonOptions,
|
|
143
|
+
): TemplateResult | typeof nothing {
|
|
144
|
+
const registry = activeRegistry();
|
|
145
|
+
const command = registry?.get(id);
|
|
146
|
+
if (!registry || !command || !registry.isVisible(id)) {
|
|
147
|
+
return nothing;
|
|
148
|
+
}
|
|
149
|
+
const reason = registry.disabledReason(id);
|
|
150
|
+
const chord = registry.keymap.formatBinding(id);
|
|
151
|
+
const title = reason
|
|
152
|
+
? `${command.title} — requires ${reason}`
|
|
153
|
+
: chord
|
|
154
|
+
? `${command.title} (${chord})`
|
|
155
|
+
: command.title;
|
|
156
|
+
return html`<sp-action-button
|
|
157
|
+
size="s"
|
|
158
|
+
?quiet=${opts.quiet ?? false}
|
|
159
|
+
class=${opts.className ?? ""}
|
|
160
|
+
?disabled=${reason !== undefined}
|
|
161
|
+
title=${title}
|
|
162
|
+
@click=${() => {
|
|
163
|
+
/* Re-asked at click time, not trusted from the render: state moves between the two, and
|
|
164
|
+
`registry.run` THROWS on a refusal. Same bargain `registry.handleKeyEvent` strikes for a
|
|
165
|
+
chord bound to a disabled command — swallow it here rather than make every surface wrap a
|
|
166
|
+
dispatch in try/catch. */
|
|
167
|
+
if (registry.isEnabled(id)) {
|
|
168
|
+
void registry.run(id);
|
|
169
|
+
}
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
${opts.content}
|
|
173
|
+
</sp-action-button>`;
|
|
174
|
+
}
|
|
175
|
+
|
|
92
176
|
// ─── Header ─────────────────────────────────────────────────────────────────
|
|
93
177
|
|
|
94
178
|
export interface ChatHeaderOptions {
|
|
95
179
|
/** The open session's title, or null for a fresh unsaved chat. */
|
|
96
180
|
title: string | null;
|
|
97
181
|
streaming: boolean;
|
|
98
|
-
|
|
99
|
-
|
|
182
|
+
/**
|
|
183
|
+
* The conversation's estimated token count, and whether it is over the warning line.
|
|
184
|
+
*
|
|
185
|
+
* `services/context-manager.ts` has computed both on every turn since it was written, and
|
|
186
|
+
* `chat-state.ts` has stored them — with NO READER anywhere. Plan §11.6: "Context budget manager
|
|
187
|
+
* → tokenCount / contextWarning actually rendered". So a conversation was silently trimmed, the
|
|
188
|
+
* assistant forgot what you told it ten turns ago, and the two numbers that would have explained
|
|
189
|
+
* why sat in the store.
|
|
190
|
+
*/
|
|
191
|
+
tokens: number;
|
|
192
|
+
overBudget: boolean;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Compact token count: 18400 → "18.4k". A four-digit number in a 28px header is noise. */
|
|
196
|
+
function tokenLabel(tokens: number): string {
|
|
197
|
+
return tokens >= 1000 ? `${(tokens / 1000).toFixed(1)}k` : String(tokens);
|
|
100
198
|
}
|
|
101
199
|
|
|
102
|
-
/** The chat header: history button, session title,
|
|
200
|
+
/** The chat header: history button, session title, the context budget, spinner, New Chat. */
|
|
103
201
|
export function renderChatHeader(opts: ChatHeaderOptions): TemplateResult {
|
|
104
202
|
return html`
|
|
105
203
|
<div class="ai-chat-header">
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
204
|
+
${commandButton("assistant.history", {
|
|
205
|
+
content: html`<sp-icon-history slot="icon"></sp-icon-history>`,
|
|
206
|
+
quiet: true,
|
|
207
|
+
})}
|
|
109
208
|
<span class="ai-chat-title">${opts.title ?? "New chat"}</span>
|
|
110
209
|
<span class="ai-header-spacer"></span>
|
|
210
|
+
${
|
|
211
|
+
opts.tokens > 0
|
|
212
|
+
? html`<span
|
|
213
|
+
class=${opts.overBudget ? "ai-tokens ai-tokens--warn" : "ai-tokens"}
|
|
214
|
+
title=${
|
|
215
|
+
opts.overBudget
|
|
216
|
+
? `About ${opts.tokens.toLocaleString()} tokens — past half the model's context. ` +
|
|
217
|
+
`The oldest turns are dropped as this grows; start a new chat to keep them.`
|
|
218
|
+
: `About ${opts.tokens.toLocaleString()} tokens of the model's context in use`
|
|
219
|
+
}
|
|
220
|
+
>${tokenLabel(opts.tokens)}</span
|
|
221
|
+
>`
|
|
222
|
+
: nothing
|
|
223
|
+
}
|
|
111
224
|
${
|
|
112
225
|
opts.streaming
|
|
113
226
|
? html`<sp-progress-circle size="s" indeterminate></sp-progress-circle>`
|
|
114
227
|
: nothing
|
|
115
228
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
229
|
+
${commandButton("assistant.newChat", {
|
|
230
|
+
content: html`<sp-icon-add slot="icon"></sp-icon-add>`,
|
|
231
|
+
quiet: true,
|
|
232
|
+
})}
|
|
119
233
|
</div>
|
|
120
234
|
`;
|
|
121
235
|
}
|
|
@@ -140,25 +254,125 @@ function renderUserMessage(msg: Message): TemplateResult {
|
|
|
140
254
|
`;
|
|
141
255
|
}
|
|
142
256
|
|
|
257
|
+
/**
|
|
258
|
+
* What became of one tool call: `"pending"` while the loop has not reported, else ok/failed.
|
|
259
|
+
*
|
|
260
|
+
* @param {ToolCallRecord} tc
|
|
261
|
+
* @returns {"pending" | "ok" | "failed"}
|
|
262
|
+
*/
|
|
263
|
+
export function toolOutcome(tc: ToolCallRecord): "pending" | "ok" | "failed" {
|
|
264
|
+
if (!tc.result) {
|
|
265
|
+
return "pending";
|
|
266
|
+
}
|
|
267
|
+
return tc.result.success ? "ok" : "failed";
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* The one line a chip says about its outcome — the tool's own words where it has any.
|
|
272
|
+
*
|
|
273
|
+
* A tool that succeeded already writes a human sentence into `summary` for the model to read; there
|
|
274
|
+
* is no reason the human could not have been reading it all along. A tool that failed writes
|
|
275
|
+
* `error`, which was surfaced only through the separate tool-message row and only after the fact.
|
|
276
|
+
*
|
|
277
|
+
* @param {ToolCallRecord} tc
|
|
278
|
+
* @returns {string}
|
|
279
|
+
*/
|
|
280
|
+
export function toolOutcomeText(tc: ToolCallRecord): string {
|
|
281
|
+
const { result } = tc;
|
|
282
|
+
if (!result) {
|
|
283
|
+
return "";
|
|
284
|
+
}
|
|
285
|
+
return (result.success ? result.summary : result.error) ?? "";
|
|
286
|
+
}
|
|
287
|
+
|
|
143
288
|
function renderToolChips(toolCalls: ToolCallRecord[]): TemplateResult | typeof nothing {
|
|
144
289
|
if (toolCalls.length === 0) {
|
|
145
290
|
return nothing;
|
|
146
291
|
}
|
|
147
292
|
return html`
|
|
148
293
|
<div class="ai-msg-tools">
|
|
149
|
-
${toolCalls.map(
|
|
150
|
-
(tc)
|
|
151
|
-
|
|
294
|
+
${toolCalls.map((tc) => {
|
|
295
|
+
const outcome = toolOutcome(tc);
|
|
296
|
+
const text = toolOutcomeText(tc);
|
|
297
|
+
return html`
|
|
298
|
+
<span class="ai-tool-chip" data-outcome=${outcome} title=${text || formatToolLabel(tc)}>
|
|
152
299
|
<sp-icon-gears size="xs"></sp-icon-gears>
|
|
153
|
-
|
|
300
|
+
<span class="ai-tool-chip-name">${formatToolLabel(tc)}</span>
|
|
301
|
+
${
|
|
302
|
+
outcome === "pending"
|
|
303
|
+
? nothing
|
|
304
|
+
: html`<span class="ai-tool-chip-outcome"
|
|
305
|
+
>${outcome === "ok" ? "✓" : "✗"} ${text}</span
|
|
306
|
+
>`
|
|
307
|
+
}
|
|
154
308
|
</span>
|
|
155
|
-
|
|
156
|
-
)}
|
|
309
|
+
`;
|
|
310
|
+
})}
|
|
157
311
|
</div>
|
|
158
312
|
`;
|
|
159
313
|
}
|
|
160
314
|
|
|
161
|
-
|
|
315
|
+
/**
|
|
316
|
+
* The turn's changed-files summary, with the two things it can honestly offer.
|
|
317
|
+
*
|
|
318
|
+
* Rendered only for a turn that changed something — "Changed 0 files" is noise, and a turn that
|
|
319
|
+
* only read is the common case. **Restore to here** is offered only when every recorded change went
|
|
320
|
+
* through a transaction: a disk write has no history behind it, so a button that claimed to restore
|
|
321
|
+
* one would be the same lie the model-facing caveat used to be.
|
|
322
|
+
*/
|
|
323
|
+
function renderChangedFiles(
|
|
324
|
+
msg: Message,
|
|
325
|
+
onRestore?: (messageId: string) => void,
|
|
326
|
+
): TemplateResult | typeof nothing {
|
|
327
|
+
const writes = writesForTurn(msg.id);
|
|
328
|
+
if (writes.length === 0) {
|
|
329
|
+
return nothing;
|
|
330
|
+
}
|
|
331
|
+
const summary = summarizeWrites(writes);
|
|
332
|
+
if (!summary) {
|
|
333
|
+
return nothing;
|
|
334
|
+
}
|
|
335
|
+
const restorable = writes.every((w) => !w.disk);
|
|
336
|
+
return html`
|
|
337
|
+
<details class="ai-msg-changes">
|
|
338
|
+
<summary>
|
|
339
|
+
${summary}
|
|
340
|
+
${
|
|
341
|
+
onRestore && restorable
|
|
342
|
+
? html`<sp-action-button
|
|
343
|
+
size="xs"
|
|
344
|
+
quiet
|
|
345
|
+
title="Undo everything this turn changed"
|
|
346
|
+
@click=${(e: Event) => {
|
|
347
|
+
e.preventDefault();
|
|
348
|
+
e.stopPropagation();
|
|
349
|
+
onRestore(msg.id);
|
|
350
|
+
}}
|
|
351
|
+
>
|
|
352
|
+
Restore to here
|
|
353
|
+
</sp-action-button>`
|
|
354
|
+
: nothing
|
|
355
|
+
}
|
|
356
|
+
</summary>
|
|
357
|
+
<ul class="ai-msg-changes-list">
|
|
358
|
+
${writes.map(
|
|
359
|
+
(w) => html`
|
|
360
|
+
<li data-disk=${String(w.disk)} data-ok=${String(w.ok)}>
|
|
361
|
+
<code>${w.path}</code>
|
|
362
|
+
<span>${w.ok ? w.tool : `failed — ${w.error ?? w.tool}`}</span>
|
|
363
|
+
${w.disk ? html`<em>written to disk — undo cannot reach it</em>` : nothing}
|
|
364
|
+
</li>
|
|
365
|
+
`,
|
|
366
|
+
)}
|
|
367
|
+
</ul>
|
|
368
|
+
</details>
|
|
369
|
+
`;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function renderAssistantMessage(
|
|
373
|
+
msg: Message,
|
|
374
|
+
onRestore?: (messageId: string) => void,
|
|
375
|
+
): TemplateResult | typeof nothing {
|
|
162
376
|
const toolCalls = msg.toolCalls ?? [];
|
|
163
377
|
if (!msg.content && toolCalls.length === 0) {
|
|
164
378
|
return nothing;
|
|
@@ -166,6 +380,7 @@ function renderAssistantMessage(msg: Message): TemplateResult | typeof nothing {
|
|
|
166
380
|
return html`
|
|
167
381
|
<div class="ai-msg-assistant">
|
|
168
382
|
${msg.content ? renderMarkdown(msg.id, msg.content) : nothing} ${renderToolChips(toolCalls)}
|
|
383
|
+
${renderChangedFiles(msg, onRestore)}
|
|
169
384
|
</div>
|
|
170
385
|
`;
|
|
171
386
|
}
|
|
@@ -208,6 +423,8 @@ export interface MessageListOptions {
|
|
|
208
423
|
onScroll: (e: Event) => void;
|
|
209
424
|
/** Ref to the scrolling element, for stick-to-bottom maintenance. */
|
|
210
425
|
listRef: (el: Element | undefined) => void;
|
|
426
|
+
/** Undo everything one turn changed. Offered only for turns whose changes are all transactional. */
|
|
427
|
+
onRestore?: ((messageId: string) => void) | undefined;
|
|
211
428
|
}
|
|
212
429
|
|
|
213
430
|
/** The scrollable message list — THE scroller of the chat view. */
|
|
@@ -237,7 +454,7 @@ export function renderMessageList(opts: MessageListOptions): TemplateResult {
|
|
|
237
454
|
if (status === "streaming" && i === lastIdx) {
|
|
238
455
|
return renderStreamingTail(msg);
|
|
239
456
|
}
|
|
240
|
-
return renderAssistantMessage(msg);
|
|
457
|
+
return renderAssistantMessage(msg, opts.onRestore);
|
|
241
458
|
}
|
|
242
459
|
return nothing;
|
|
243
460
|
})}
|
|
@@ -251,6 +468,16 @@ export function renderMessageList(opts: MessageListOptions): TemplateResult {
|
|
|
251
468
|
? html`<div class="ai-msg-error-advice">${formatErrorAdvice(opts.error)}</div>`
|
|
252
469
|
: nothing
|
|
253
470
|
}
|
|
471
|
+
${
|
|
472
|
+
/* `assistant.retry`, not a closure. Its `enablement` reads `ctx.ai.configured`,
|
|
473
|
+
so the one error this row cannot recover from — no provider connected, whose
|
|
474
|
+
advice line above already says to add a key — draws the button disabled with
|
|
475
|
+
that sentence rather than offering a send that will fail identically. */
|
|
476
|
+
commandButton("assistant.retry", {
|
|
477
|
+
className: "ai-msg-retry",
|
|
478
|
+
content: "Retry",
|
|
479
|
+
})
|
|
480
|
+
}
|
|
254
481
|
</div>
|
|
255
482
|
`
|
|
256
483
|
: nothing
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { html, nothing } from "lit-html";
|
|
18
|
+
import { displayTagName } from "@jxsuite/schema/guards";
|
|
18
19
|
import type { TemplateResult } from "lit-html";
|
|
19
20
|
import { live } from "lit-html/directives/live.js";
|
|
20
21
|
import { ref } from "lit-html/directives/ref.js";
|
|
@@ -22,10 +23,11 @@ import { getNodeAtPath } from "../../state";
|
|
|
22
23
|
import { fetchAvailableModels } from "../../services/ai-models";
|
|
23
24
|
import { getModel, setModel } from "../../services/ai-settings";
|
|
24
25
|
import { activeTab } from "../../workspace/workspace";
|
|
26
|
+
import { primarySelection } from "../../tabs/selection";
|
|
25
27
|
import { buildMessageWithContext } from "./attached-context";
|
|
26
28
|
import type { ContextChip } from "./attached-context";
|
|
27
29
|
import type { AiModel } from "../../services/ai-models";
|
|
28
|
-
import type { JxMutableNode
|
|
30
|
+
import type { JxMutableNode } from "@jxsuite/schema/types";
|
|
29
31
|
|
|
30
32
|
/** Tallest the textarea auto-grows before it scrolls internally. */
|
|
31
33
|
const MAX_INPUT_HEIGHT = 120;
|
|
@@ -46,6 +48,16 @@ export interface Composer {
|
|
|
46
48
|
render: () => TemplateResult;
|
|
47
49
|
focus: () => void;
|
|
48
50
|
clear: () => void;
|
|
51
|
+
/**
|
|
52
|
+
* Attach the canvas selection as a context chip, as the attach menu's second item does.
|
|
53
|
+
*
|
|
54
|
+
* `false` when nothing is selected, so a caller can say why nothing happened. This exists because
|
|
55
|
+
* `assistant.attachSelection` (`panels/ai-panel.ts`) must reach the SAME chip the menu builds —
|
|
56
|
+
* the attach convention is one delimiter and one `ContextChip` shape (`attached-context.ts`), and
|
|
57
|
+
* a command that assembled its own line would be a second way to say "this element", diverging
|
|
58
|
+
* the first time the label changes.
|
|
59
|
+
*/
|
|
60
|
+
attachSelection: () => boolean;
|
|
49
61
|
}
|
|
50
62
|
|
|
51
63
|
/**
|
|
@@ -137,13 +149,17 @@ export function createComposer(opts: ComposerOptions): Composer {
|
|
|
137
149
|
function contextCandidates() {
|
|
138
150
|
const tab = activeTab.value;
|
|
139
151
|
const documentPath = tab?.documentPath || null;
|
|
140
|
-
const selection = (tab?.session.selection
|
|
152
|
+
const selection = primarySelection(tab?.session.selection);
|
|
141
153
|
let selectionChip: ContextChip | null = null;
|
|
142
154
|
if (tab && selection) {
|
|
155
|
+
/* No `tagName?: string` in this cast any more. It overrode the widened type — a tag may be
|
|
156
|
+
a name or a choice between names — so the compiler could not see that this chip would
|
|
157
|
+
render `[object Object]` for a chosen one. A cast that narrows a field back to what it
|
|
158
|
+
used to be is a hole the type system cannot report. */
|
|
143
159
|
const node = getNodeAtPath(tab.doc.document as JxMutableNode, selection) as
|
|
144
|
-
| (JxMutableNode & {
|
|
160
|
+
| (JxMutableNode & { textContent?: string })
|
|
145
161
|
| undefined;
|
|
146
|
-
const tag = node?.tagName || "element";
|
|
162
|
+
const tag = displayTagName(node?.tagName) || "element";
|
|
147
163
|
const text = typeof node?.textContent === "string" ? node.textContent.slice(0, 40) : "";
|
|
148
164
|
selectionChip = {
|
|
149
165
|
detail: `Selected element at ${JSON.stringify(selection)}: <${tag}>${text ? ` "${text}"` : ""}`,
|
|
@@ -170,6 +186,16 @@ export function createComposer(opts: ComposerOptions): Composer {
|
|
|
170
186
|
opts.requestRender();
|
|
171
187
|
}
|
|
172
188
|
|
|
189
|
+
/** {@link Composer.attachSelection} — the attach menu's "Selected element" item, by name. */
|
|
190
|
+
function attachSelection(): boolean {
|
|
191
|
+
const { selectionChip } = contextCandidates();
|
|
192
|
+
if (!selectionChip) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
addChip(selectionChip);
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
|
|
173
199
|
function renderAttachMenu(): TemplateResult {
|
|
174
200
|
const { pageChip, selectionChip } = contextCandidates();
|
|
175
201
|
return html`
|
|
@@ -317,5 +343,5 @@ export function createComposer(opts: ComposerOptions): Composer {
|
|
|
317
343
|
`;
|
|
318
344
|
}
|
|
319
345
|
|
|
320
|
-
return { clear, focus, render };
|
|
346
|
+
return { attachSelection, clear, focus, render };
|
|
321
347
|
}
|
|
@@ -3,13 +3,21 @@
|
|
|
3
3
|
* Sessions-view.js — the full-pane chat history list (VSCode-Copilot style).
|
|
4
4
|
*
|
|
5
5
|
* Renders the session rows (title, relative time, message count) with per-row delete,
|
|
6
|
-
* a header with a New Chat action, and an empty state.
|
|
7
|
-
*
|
|
6
|
+
* a header with a New Chat action, and an empty state. State and storage live in
|
|
7
|
+
* ai-panel / document-assistant; the row callbacks address ONE session each, which is
|
|
8
|
+
* why they stay callbacks.
|
|
9
|
+
*
|
|
10
|
+
* New Chat is the exception, and it is `assistant.newChat` — the same record the chat
|
|
11
|
+
* header runs ({@link commandButton}). The two headers draw the same button, so a
|
|
12
|
+
* second definition site is exactly how they would come to disagree about its name, its
|
|
13
|
+
* chord, or when it is offered.
|
|
8
14
|
*
|
|
9
15
|
* @license MIT
|
|
10
16
|
*/
|
|
11
17
|
|
|
12
18
|
import { html } from "lit-html";
|
|
19
|
+
import { now } from "../../services/clock";
|
|
20
|
+
import { commandButton } from "./chat-view";
|
|
13
21
|
import type { TemplateResult } from "lit-html";
|
|
14
22
|
import type { SessionMeta } from "../../services/ai-session-store";
|
|
15
23
|
|
|
@@ -22,11 +30,11 @@ const DAY = 24 * HOUR;
|
|
|
22
30
|
* date.
|
|
23
31
|
*
|
|
24
32
|
* @param {number} ts
|
|
25
|
-
* @param {number} [now
|
|
33
|
+
* @param {number} [at] Epoch milliseconds to measure against; defaults to the {@link now} seam.
|
|
26
34
|
* @returns {string}
|
|
27
35
|
*/
|
|
28
|
-
export function relativeTime(ts: number,
|
|
29
|
-
const delta = Math.max(0,
|
|
36
|
+
export function relativeTime(ts: number, at: number = now()): string {
|
|
37
|
+
const delta = Math.max(0, at - ts);
|
|
30
38
|
if (delta < MINUTE) {
|
|
31
39
|
return "just now";
|
|
32
40
|
}
|
|
@@ -49,7 +57,6 @@ export interface SessionsListOptions {
|
|
|
49
57
|
sessions: SessionMeta[];
|
|
50
58
|
onOpen: (id: string) => void;
|
|
51
59
|
onDelete: (id: string) => void;
|
|
52
|
-
onNew: () => void;
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
function renderRow(s: SessionMeta, opts: SessionsListOptions): TemplateResult {
|
|
@@ -84,10 +91,10 @@ export function renderSessionsList(opts: SessionsListOptions): TemplateResult {
|
|
|
84
91
|
<div class="ai-chat-header">
|
|
85
92
|
<span class="ai-chat-title">Chats</span>
|
|
86
93
|
<span class="ai-header-spacer"></span>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
94
|
+
${commandButton("assistant.newChat", {
|
|
95
|
+
content: html`<sp-icon-add slot="icon"></sp-icon-add>New Chat`,
|
|
96
|
+
quiet: true,
|
|
97
|
+
})}
|
|
91
98
|
</div>
|
|
92
99
|
<div class="ai-sessions">
|
|
93
100
|
${
|