@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
package/src/panels/ai-panel.ts
CHANGED
|
@@ -3,9 +3,16 @@
|
|
|
3
3
|
* Ai-panel.ts — AI assistant tab for the right panel (Stack B document assistant).
|
|
4
4
|
*
|
|
5
5
|
* Native lit-html chat UI (VSCode-Copilot style) over the reactive document-assistant
|
|
6
|
-
* session: a view-state machine (
|
|
6
|
+
* session: a view-state machine (sessions list ↔ chat), a message list with
|
|
7
7
|
* stick-to-bottom scrolling, and the sticky composer.
|
|
8
8
|
*
|
|
9
|
+
* Credentials are NOT a state of this panel. A provider key is a roaming APPLICATION setting
|
|
10
|
+
* configured once, so it lives in Preferences › Assistant (⌘,) — not in a dialog reachable only
|
|
11
|
+
* from the panel that is broken for want of one. The panel with no key configured still opens on an
|
|
12
|
+
* invitation to talk, with the way to fix it offered beneath. It repaints when a credential is
|
|
13
|
+
* saved or revoked by subscribing to `settings/preferences-accounts.ts`, which is a LEAF both
|
|
14
|
+
* modules depend on rather than an import back into the sheet.
|
|
15
|
+
*
|
|
9
16
|
* Rendering: this panel owns a private rAF-coalesced render loop into the assistant
|
|
10
17
|
* `.panel-body` container (bound once via {@link bindAiPanelHost}). It deliberately
|
|
11
18
|
* bypasses the right-panel scheduler's focus guard — streaming must repaint while the
|
|
@@ -13,49 +20,39 @@
|
|
|
13
20
|
* textarea is uncontrolled). The right panel renders the same template into the same
|
|
14
21
|
* container on tab switches; lit reconciles both paths through one part cache.
|
|
15
22
|
*
|
|
23
|
+
* @docs studio/ai/chat
|
|
16
24
|
* @license MIT
|
|
17
25
|
*/
|
|
18
26
|
|
|
19
27
|
import { html, render as litRender, nothing } from "lit-html";
|
|
20
28
|
import type { TemplateResult } from "lit-html";
|
|
21
|
-
import { getPlatform } from "../platform";
|
|
22
29
|
import { effect, effectScope } from "../reactivity";
|
|
23
30
|
import { createDocumentAssistant } from "../services/document-assistant";
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
31
|
+
import { writesForTurn } from "../services/ai-writes";
|
|
32
|
+
import { notify } from "../services/notify";
|
|
33
|
+
import { undo } from "../tabs/transact";
|
|
34
|
+
import { activeTab } from "../workspace/workspace";
|
|
35
|
+
import { setOpenAiKey } from "../services/ai-settings";
|
|
36
|
+
import { hasAiCredentials } from "../services/ai-models";
|
|
37
|
+
import { openPreferences } from "../settings/preferences-dialog";
|
|
38
|
+
import { onCredentialsChanged } from "../settings/preferences-accounts";
|
|
39
|
+
import { setDockCollapsed } from "../shell";
|
|
40
|
+
import { hasSelection } from "../commands/context";
|
|
27
41
|
import { clearMarkdownCache } from "./ai-chat/chat-markdown";
|
|
28
42
|
import { renderChatHeader, renderMessageList } from "./ai-chat/chat-view";
|
|
29
43
|
import { createComposer } from "./ai-chat/composer";
|
|
30
44
|
import { renderSessionsList } from "./ai-chat/sessions-view";
|
|
45
|
+
import { setInspectorTab } from "./right-panel";
|
|
31
46
|
|
|
47
|
+
import type { AnyCommand } from "../commands/registry";
|
|
48
|
+
import type { CommandContext } from "../commands/context";
|
|
32
49
|
import type { EffectScope } from "@vue/reactivity";
|
|
33
50
|
|
|
34
51
|
// ─── State (module-level, persists across tab switches) ─────────────────────
|
|
35
52
|
|
|
36
53
|
let mounted = false;
|
|
37
54
|
|
|
38
|
-
/**
|
|
39
|
-
let keyEditing = false;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* One-time proxy probe: managed platforms (cloud Workers AI) and env-keyed dev servers report
|
|
43
|
-
* `configured` from /models, unlocking the assistant without a locally stored key. Fired lazily on
|
|
44
|
-
* the first gated render.
|
|
45
|
-
*/
|
|
46
|
-
let proxyProbe: Promise<void> | null = null;
|
|
47
|
-
|
|
48
|
-
function ensureProxyProbe() {
|
|
49
|
-
proxyProbe ??= fetchAvailableModels({ force: true })
|
|
50
|
-
.catch(() => {
|
|
51
|
-
// Unreachable proxy — the key gate stays up.
|
|
52
|
-
})
|
|
53
|
-
.then(() => {
|
|
54
|
-
scheduleAiRender();
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/** Which pane the panel shows once the key gate is passed. */
|
|
55
|
+
/** Which pane the panel shows. */
|
|
59
56
|
let view: "chat" | "sessions" = "chat";
|
|
60
57
|
|
|
61
58
|
/** Document AST assistant session — created lazily, persists across tab switches. */
|
|
@@ -124,6 +121,9 @@ export function mountAiPanel() {
|
|
|
124
121
|
return;
|
|
125
122
|
}
|
|
126
123
|
mounted = true;
|
|
124
|
+
// A key saved (or revoked) in Preferences changes what this panel shows — the setup notice, and
|
|
125
|
+
// Whether the composer can send. One subscription, and no import back into the sheet.
|
|
126
|
+
onCredentialsChanged(scheduleAiRender);
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
// ─── Auto-scroll (stick to bottom unless the user scrolled up) ──────────────
|
|
@@ -150,88 +150,29 @@ function maintainScroll() {
|
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
// ───
|
|
154
|
-
|
|
155
|
-
/** The panel's shared credentials form (draft/model state lives inside the form's closure). */
|
|
156
|
-
const credsForm = createAiCredentialsForm({
|
|
157
|
-
onCancel: () => {
|
|
158
|
-
keyEditing = false;
|
|
159
|
-
},
|
|
160
|
-
onSaved: () => {
|
|
161
|
-
keyEditing = false;
|
|
162
|
-
},
|
|
163
|
-
requestRender: scheduleAiRender,
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
/** Open the key form, pre-filled with the current settings. */
|
|
167
|
-
function startEditApiKey() {
|
|
168
|
-
keyEditing = true;
|
|
169
|
-
credsForm.startEdit();
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// ─── Managed Cloudflare connect (Workers AI) ─────────────────────────────────
|
|
173
|
-
|
|
174
|
-
let cfConnectBusy = false;
|
|
175
|
-
let cfConnectError = "";
|
|
153
|
+
// ─── The credentials gate's in-panel residue ─────────────────────────────────
|
|
176
154
|
|
|
177
155
|
/**
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
156
|
+
* One line and the action that fixes it, under a chat that still invites a conversation.
|
|
157
|
+
*
|
|
158
|
+
* The action is `Preferences › Assistant`, not a dialog of this panel's own: a provider key is an
|
|
159
|
+
* application setting, and the surface that owns application settings is the one that can also list
|
|
160
|
+
* and revoke it. The probe fires here for the same reason the old gate fired it — a managed
|
|
161
|
+
* platform or an env-keyed dev server may already be configured, and only `/models` knows.
|
|
181
162
|
*/
|
|
182
|
-
function
|
|
183
|
-
return isManagedProxy() && !isProxyConfigured() && Boolean(getPlatform().cfConnect);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
async function connectCloudflareForAi() {
|
|
187
|
-
if (cfConnectBusy) {
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
cfConnectBusy = true;
|
|
191
|
-
cfConnectError = "";
|
|
192
|
-
scheduleAiRender();
|
|
193
|
-
try {
|
|
194
|
-
const connection = await getPlatform().cfConnect?.();
|
|
195
|
-
if (connection) {
|
|
196
|
-
// Re-probe: /models flips to configured once the connection lands, opening the gate.
|
|
197
|
-
await fetchAvailableModels({ force: true });
|
|
198
|
-
} else {
|
|
199
|
-
cfConnectError = "Cloudflare connection was not completed.";
|
|
200
|
-
}
|
|
201
|
-
} catch (error) {
|
|
202
|
-
cfConnectError = error instanceof Error ? error.message : String(error);
|
|
203
|
-
}
|
|
204
|
-
cfConnectBusy = false;
|
|
205
|
-
scheduleAiRender();
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function renderManagedConnect() {
|
|
163
|
+
function renderSetupNotice(): TemplateResult {
|
|
209
164
|
return html`
|
|
210
|
-
<div class="ai-
|
|
211
|
-
<
|
|
212
|
-
<sp-button
|
|
213
|
-
|
|
165
|
+
<div class="ai-setup-notice">
|
|
166
|
+
<span>No AI provider is connected yet.</span>
|
|
167
|
+
<sp-button
|
|
168
|
+
size="s"
|
|
169
|
+
variant="secondary"
|
|
170
|
+
@click=${() => {
|
|
171
|
+
void openPreferences("assistant");
|
|
172
|
+
}}
|
|
173
|
+
>
|
|
174
|
+
Open Preferences…
|
|
214
175
|
</sp-button>
|
|
215
|
-
${
|
|
216
|
-
cfConnectError
|
|
217
|
-
? html`<div class="ai-managed-connect-error">${cfConnectError}</div>`
|
|
218
|
-
: nothing
|
|
219
|
-
}
|
|
220
|
-
<div class="ai-managed-connect-divider">— or bring your own key —</div>
|
|
221
|
-
</div>
|
|
222
|
-
`;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* The credentials gate: on managed platforms a keyless "Connect Cloudflare" (Workers AI) option
|
|
227
|
-
* sits above the OpenAI-compatible key form — both are real, working paths.
|
|
228
|
-
*/
|
|
229
|
-
function renderKeyGate() {
|
|
230
|
-
return html`
|
|
231
|
-
<div class="ai-tab-body">
|
|
232
|
-
<div class="ai-status-center">
|
|
233
|
-
${canOfferManagedConnect() ? renderManagedConnect() : nothing} ${credsForm.render()}
|
|
234
|
-
</div>
|
|
235
176
|
</div>
|
|
236
177
|
`;
|
|
237
178
|
}
|
|
@@ -255,6 +196,64 @@ async function handleAssistantSend(text: string) {
|
|
|
255
196
|
}
|
|
256
197
|
}
|
|
257
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Re-send the last user message — §7.4's Retry.
|
|
201
|
+
*
|
|
202
|
+
* `chatState.retryLast()` pops the failed assistant turn AND the user message that caused it, on
|
|
203
|
+
* the contract that the caller re-sends. It has been exported with zero callers since it was
|
|
204
|
+
* written, so a failed turn's only recovery was retyping the prompt. Read the text before popping;
|
|
205
|
+
* there is nowhere else it survives.
|
|
206
|
+
*/
|
|
207
|
+
async function handleRetry(): Promise<void> {
|
|
208
|
+
const cs = assistant.chatState;
|
|
209
|
+
const lastUser = cs.messages.toReversed().find((m) => m.role === "user");
|
|
210
|
+
if (!lastUser) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const { content } = lastUser;
|
|
214
|
+
cs.retryLast();
|
|
215
|
+
scheduleAiRender();
|
|
216
|
+
await handleAssistantSend(content);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Undo everything one assistant turn changed — §7.4's "Restore to here".
|
|
221
|
+
*
|
|
222
|
+
* The loop opens one batch per turn per document, so undoing the turn is undoing that batch. The
|
|
223
|
+
* button is offered by the renderer only when every recorded change was transactional; this guard
|
|
224
|
+
* is the second half of the same promise, because a ledger can be trimmed (MAX_TURNS) between the
|
|
225
|
+
* render and the click and a Restore that silently restored SOME of a turn would be worse than one
|
|
226
|
+
* that refused.
|
|
227
|
+
*
|
|
228
|
+
* @param {string} messageId
|
|
229
|
+
*/
|
|
230
|
+
/* Exported so the guard can be exercised directly: the button is not RENDERED for a turn that
|
|
231
|
+
touched disk, which would otherwise make the refusal path unreachable from the panel. */
|
|
232
|
+
export function handleRestore(messageId: string): void {
|
|
233
|
+
const writes = writesForTurn(messageId);
|
|
234
|
+
if (writes.length === 0) {
|
|
235
|
+
notify.warn("There is no longer a record of what that turn changed.", { source: "Assistant" });
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const disk = writes.filter((w) => w.disk).map((w) => w.path);
|
|
239
|
+
if (disk.length > 0) {
|
|
240
|
+
notify.warn(
|
|
241
|
+
`Cannot restore: ${disk.join(", ")} ${disk.length === 1 ? "was" : "were"} written straight ` +
|
|
242
|
+
"to disk, which undo cannot reach.",
|
|
243
|
+
{ source: "Assistant" },
|
|
244
|
+
);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const tab = activeTab.value;
|
|
248
|
+
if (!tab) {
|
|
249
|
+
notify.warn("Open the document that turn edited to restore it.", { source: "Assistant" });
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
undo(tab);
|
|
253
|
+
notify.success("Restored to before that turn.", { action: "edit.redo", source: "Assistant" });
|
|
254
|
+
scheduleAiRender();
|
|
255
|
+
}
|
|
256
|
+
|
|
258
257
|
/**
|
|
259
258
|
* Seed the assistant with a prompt programmatically (e.g. the New Project flow handing off a
|
|
260
259
|
* project brief). Delegates to the same send path as the composer. Safe to call right after the
|
|
@@ -292,7 +291,6 @@ let seededCount = 0;
|
|
|
292
291
|
*/
|
|
293
292
|
export function seedAssistantMessages(messages: SeededAssistantMessage[]): void {
|
|
294
293
|
setOpenAiKey("sk-demo");
|
|
295
|
-
keyEditing = false;
|
|
296
294
|
view = "chat";
|
|
297
295
|
stickToBottom = true;
|
|
298
296
|
for (const msg of messages) {
|
|
@@ -319,6 +317,35 @@ export function seedAssistantMessages(messages: SeededAssistantMessage[]): void
|
|
|
319
317
|
|
|
320
318
|
// ─── Controls ─────────────────────────────────────────────────────────────────
|
|
321
319
|
|
|
320
|
+
/**
|
|
321
|
+
* Show the assistant: open the Inspector, then select its fourth tab.
|
|
322
|
+
*
|
|
323
|
+
* The two lines `view.setAssistant { open: true }` runs, in the module that owns the surface, so
|
|
324
|
+
* the three callers that need them — that record, `chat-panel.ts`'s pending-prompt handoff, and
|
|
325
|
+
* every `Assistant:` command below — do not each keep their own copy. `chat-panel.ts` had one
|
|
326
|
+
* inline, and a reveal that opens the dock but forgets the tab (or the reverse) is a silent
|
|
327
|
+
* half-success.
|
|
328
|
+
*/
|
|
329
|
+
export function revealAssistant(): void {
|
|
330
|
+
setDockCollapsed("right", false);
|
|
331
|
+
setInspectorTab("assistant");
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Whether a turn is in flight — the probe `commands/live-context.ts` declares as `aiStreaming` and
|
|
336
|
+
* projects onto `ctx.ai.streaming`.
|
|
337
|
+
*
|
|
338
|
+
* That source was declared optional with the note "there is nothing to read yet; the caller passes
|
|
339
|
+
* a probe when one exists", and no caller ever did — so `ctx.ai.streaming` read `false` forever and
|
|
340
|
+
* `assistant.stop` would have been permanently refused. Reading the reactive chat state here is
|
|
341
|
+
* what makes the fact LIVE: `createLiveContext` builds a fresh record per predicate evaluation, so
|
|
342
|
+
* a surface repainting from an effect tracks this status and re-renders when the stream starts or
|
|
343
|
+
* ends.
|
|
344
|
+
*/
|
|
345
|
+
export function isAssistantStreaming(): boolean {
|
|
346
|
+
return assistant.chatState.status === "streaming";
|
|
347
|
+
}
|
|
348
|
+
|
|
322
349
|
function stop() {
|
|
323
350
|
assistant.stop();
|
|
324
351
|
}
|
|
@@ -361,8 +388,10 @@ function activeSessionTitle(): string | null {
|
|
|
361
388
|
// ─── Composer ───────────────────────────────────────────────────────────────
|
|
362
389
|
|
|
363
390
|
const composer = createComposer({
|
|
364
|
-
isStreaming:
|
|
365
|
-
onOpenSettings:
|
|
391
|
+
isStreaming: isAssistantStreaming,
|
|
392
|
+
onOpenSettings: () => {
|
|
393
|
+
void openPreferences("assistant");
|
|
394
|
+
},
|
|
366
395
|
onSend: (text) => {
|
|
367
396
|
void handleAssistantSend(text);
|
|
368
397
|
},
|
|
@@ -370,26 +399,155 @@ const composer = createComposer({
|
|
|
370
399
|
requestRender: scheduleAiRender,
|
|
371
400
|
});
|
|
372
401
|
|
|
402
|
+
/**
|
|
403
|
+
* Reveal the assistant, put it on the chat view, and place the caret in the composer.
|
|
404
|
+
*
|
|
405
|
+
* The focus rides a frame because {@link scheduleAiRender} is rAF-coalesced: revealing from the
|
|
406
|
+
* sessions list means the textarea does not exist yet, and focusing a node that is about to be
|
|
407
|
+
* replaced would leave the caret nowhere. Ordering holds because this frame is queued after the
|
|
408
|
+
* render's.
|
|
409
|
+
*/
|
|
410
|
+
function focusComposer(): void {
|
|
411
|
+
revealAssistant();
|
|
412
|
+
if (view !== "chat") {
|
|
413
|
+
view = "chat";
|
|
414
|
+
scheduleAiRender();
|
|
415
|
+
}
|
|
416
|
+
requestAnimationFrame(() => {
|
|
417
|
+
composer.focus();
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// ─── The `Assistant:` command family (§11.1) ────────────────────────────────
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Six records, beside the chat session they write.
|
|
425
|
+
*
|
|
426
|
+
* §11.1 pays for the chat column's demotion into an Inspector tab with a command family, and the
|
|
427
|
+
* `Assistant` category — declared in `commands/levels.ts` since the taxonomy landed — held ZERO
|
|
428
|
+
* records. Every capability below already existed and every one of them existed ONLY as a button in
|
|
429
|
+
* this panel: not in the palette, not bindable, not reachable by `__jxAutomation` or by name, and
|
|
430
|
+
* absent from the generated commands and shortcuts sheets. A capability that one surface can reach
|
|
431
|
+
* and the registry cannot is the second definition site inverted.
|
|
432
|
+
*
|
|
433
|
+
* **All six are `level: "application"`, by principle 3 — a record is filed by the level of the
|
|
434
|
+
* state it WRITES, not the state it reads.** The chat session is application state: it outlives the
|
|
435
|
+
* open document, survives project close, and `assistant.attachSelection` is the case that proves
|
|
436
|
+
* the rule — it READS the canvas selection and writes a chip into the composer, so it is
|
|
437
|
+
* application, not selection, however selection-ish it looks. That is also why it may declare
|
|
438
|
+
* `menus: ["palette"]` at all: `blockbar` and `context/element` admit selection-level records
|
|
439
|
+
* only.
|
|
440
|
+
*
|
|
441
|
+
* **No `aiTool` on any of them.** The assistant projecting "start a new chat" into its own tool
|
|
442
|
+
* list would let a turn end its own conversation; the tier tables in `services/ai-tools.ts` gate
|
|
443
|
+
* what the agent may do TO A PROJECT, not to the chat it is running inside.
|
|
444
|
+
*/
|
|
445
|
+
export function assistantCommands(): AnyCommand[] {
|
|
446
|
+
return [
|
|
447
|
+
{
|
|
448
|
+
category: "Assistant",
|
|
449
|
+
id: "assistant.focus",
|
|
450
|
+
level: "application",
|
|
451
|
+
/* A sixth record, and it earns its place: `inspector.focus.assistant` (⌘⇧4) is DOCUMENT-level
|
|
452
|
+
and refuses when nothing is open — which is exactly the state the assistant is most wanted
|
|
453
|
+
in, because the panel deliberately renders with no project and no document. `view.setAssistant`
|
|
454
|
+
is `menus: ["never"]`. Neither puts the caret anywhere, so neither answers "let me type".
|
|
455
|
+
The title is distinct on purpose: two palette rows printing one sentence is the defect
|
|
456
|
+
`tests/app-commands-composition.test.ts` refuses, and "Show Assistant" is already taken. */
|
|
457
|
+
title: "Focus Composer",
|
|
458
|
+
keybinding: "mod+shift+a",
|
|
459
|
+
menus: ["palette"],
|
|
460
|
+
group: "1_chat",
|
|
461
|
+
run: focusComposer,
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
category: "Assistant",
|
|
465
|
+
id: "assistant.newChat",
|
|
466
|
+
level: "application",
|
|
467
|
+
title: "New Chat",
|
|
468
|
+
menus: ["palette"],
|
|
469
|
+
group: "1_chat",
|
|
470
|
+
// No `enablement` on the stream: `newChat()` calls `stop()` first (see
|
|
471
|
+
// `services/document-assistant.ts`), so starting one mid-turn is already the handled case.
|
|
472
|
+
run: () => {
|
|
473
|
+
revealAssistant();
|
|
474
|
+
newChat();
|
|
475
|
+
},
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
category: "Assistant",
|
|
479
|
+
id: "assistant.history",
|
|
480
|
+
level: "application",
|
|
481
|
+
title: "Chat History",
|
|
482
|
+
menus: ["palette"],
|
|
483
|
+
group: "1_chat",
|
|
484
|
+
run: () => {
|
|
485
|
+
revealAssistant();
|
|
486
|
+
showSessions();
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
category: "Assistant",
|
|
491
|
+
id: "assistant.attachSelection",
|
|
492
|
+
level: "application",
|
|
493
|
+
title: "Attach Selection",
|
|
494
|
+
menus: ["palette"],
|
|
495
|
+
group: "2_turn",
|
|
496
|
+
requires: "an element selected on the canvas",
|
|
497
|
+
// `hasSelection` is `commands/context.ts`'s shared predicate — the same one the element menu
|
|
498
|
+
// And the structural verbs are gated on, so "a selection" means one thing in three menus.
|
|
499
|
+
when: (ctx: CommandContext) => hasSelection(ctx),
|
|
500
|
+
run: () => {
|
|
501
|
+
if (!composer.attachSelection()) {
|
|
502
|
+
// Reachable despite `when`: a script or the palette can race the selection away between
|
|
503
|
+
// The predicate and the run, and a silent no-op would look like the chip had landed.
|
|
504
|
+
notify.warn("Nothing is selected to attach.", { source: "Assistant" });
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
focusComposer();
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
category: "Assistant",
|
|
512
|
+
id: "assistant.retry",
|
|
513
|
+
level: "application",
|
|
514
|
+
title: "Retry Last Message",
|
|
515
|
+
menus: ["palette"],
|
|
516
|
+
group: "2_turn",
|
|
517
|
+
requires: "a connected AI provider, and no turn already in flight",
|
|
518
|
+
/* `ctx.ai.configured` and `ctx.ai.streaming` have been declared in `commands/context.ts` with
|
|
519
|
+
zero readers; this record and `assistant.stop` are the first. Re-sending with no provider
|
|
520
|
+
connected reproduces the same failure the error row is already explaining, and re-sending
|
|
521
|
+
mid-stream would interleave two turns. */
|
|
522
|
+
enablement: (ctx: CommandContext) => ctx.ai.configured && !ctx.ai.streaming,
|
|
523
|
+
run: () => {
|
|
524
|
+
revealAssistant();
|
|
525
|
+
void handleRetry();
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
{
|
|
529
|
+
category: "Assistant",
|
|
530
|
+
id: "assistant.stop",
|
|
531
|
+
level: "application",
|
|
532
|
+
title: "Stop Responding",
|
|
533
|
+
menus: ["palette"],
|
|
534
|
+
group: "2_turn",
|
|
535
|
+
requires: "a turn in flight",
|
|
536
|
+
enablement: (ctx: CommandContext) => ctx.ai.streaming,
|
|
537
|
+
run: stop,
|
|
538
|
+
},
|
|
539
|
+
];
|
|
540
|
+
}
|
|
541
|
+
|
|
373
542
|
// ─── Template ───────────────────────────────────────────────────────────────
|
|
374
543
|
|
|
375
544
|
/** @returns {TemplateResult} */
|
|
376
545
|
export function renderAiPanelTemplate(): TemplateResult {
|
|
377
|
-
/* The document assistant authenticates via the AI proxy. Gate the chat
|
|
378
|
-
behind the key form until a key is stored locally OR the proxy reports
|
|
379
|
-
itself configured (managed platforms, env-keyed dev servers). */
|
|
380
|
-
if ((!hasOpenAiKey() && !isProxyConfigured()) || keyEditing) {
|
|
381
|
-
if (!keyEditing) {
|
|
382
|
-
ensureProxyProbe();
|
|
383
|
-
}
|
|
384
|
-
return renderKeyGate();
|
|
385
|
-
}
|
|
386
|
-
|
|
387
546
|
if (view === "sessions") {
|
|
388
547
|
return html`
|
|
389
548
|
<div class="ai-tab-body">
|
|
390
549
|
${renderSessionsList({
|
|
391
550
|
onDelete: deleteSession,
|
|
392
|
-
onNew: newChat,
|
|
393
551
|
onOpen: openSession,
|
|
394
552
|
sessions: assistant.listSessions(),
|
|
395
553
|
})}
|
|
@@ -401,19 +559,20 @@ export function renderAiPanelTemplate(): TemplateResult {
|
|
|
401
559
|
return html`
|
|
402
560
|
<div class="ai-tab-body">
|
|
403
561
|
${renderChatHeader({
|
|
404
|
-
|
|
405
|
-
onShowSessions: showSessions,
|
|
562
|
+
overBudget: cs.contextWarning,
|
|
406
563
|
streaming: cs.status === "streaming",
|
|
407
564
|
title: activeSessionTitle(),
|
|
565
|
+
tokens: cs.tokenCount,
|
|
408
566
|
})}
|
|
409
567
|
${renderMessageList({
|
|
410
568
|
error: cs.error,
|
|
411
569
|
listRef: onMessagesListRef,
|
|
412
570
|
messages: cs.messages,
|
|
571
|
+
onRestore: handleRestore,
|
|
413
572
|
onScroll: onMessagesScroll,
|
|
414
573
|
status: cs.status,
|
|
415
574
|
})}
|
|
416
|
-
${composer.render()}
|
|
575
|
+
${hasAiCredentials() ? nothing : renderSetupNotice()} ${composer.render()}
|
|
417
576
|
</div>
|
|
418
577
|
`;
|
|
419
578
|
}
|