@schlessera/brain-ui-react 0.34.1 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -4
- package/dist/components/activity/activity-page.d.ts +17 -5
- package/dist/components/activity/activity-page.d.ts.map +1 -1
- package/dist/components/activity/activity-page.js +144 -50
- package/dist/components/activity/activity-page.js.map +1 -1
- package/dist/components/activity/activity-run-detail.d.ts +16 -1
- package/dist/components/activity/activity-run-detail.d.ts.map +1 -1
- package/dist/components/activity/activity-run-detail.js +47 -4
- package/dist/components/activity/activity-run-detail.js.map +1 -1
- package/dist/components/activity/activity-run-list.d.ts +7 -1
- package/dist/components/activity/activity-run-list.d.ts.map +1 -1
- package/dist/components/activity/activity-run-list.js +16 -8
- package/dist/components/activity/activity-run-list.js.map +1 -1
- package/dist/components/activity/activity-views.d.ts +63 -0
- package/dist/components/activity/activity-views.d.ts.map +1 -0
- package/dist/components/activity/activity-views.js +52 -0
- package/dist/components/activity/activity-views.js.map +1 -0
- package/dist/components/activity/approval-card.d.ts +11 -0
- package/dist/components/activity/approval-card.d.ts.map +1 -0
- package/dist/components/activity/approval-card.js +46 -0
- package/dist/components/activity/approval-card.js.map +1 -0
- package/dist/components/activity/digest-card.d.ts +3 -0
- package/dist/components/activity/digest-card.d.ts.map +1 -1
- package/dist/components/activity/digest-card.js +20 -16
- package/dist/components/activity/digest-card.js.map +1 -1
- package/dist/components/activity/digest-summary.d.ts +19 -0
- package/dist/components/activity/digest-summary.d.ts.map +1 -0
- package/dist/components/activity/digest-summary.js +20 -0
- package/dist/components/activity/digest-summary.js.map +1 -0
- package/dist/components/activity/push-switch.d.ts +25 -0
- package/dist/components/activity/push-switch.d.ts.map +1 -0
- package/dist/components/activity/push-switch.js +14 -0
- package/dist/components/activity/push-switch.js.map +1 -0
- package/dist/components/activity/push-toggle.d.ts +7 -0
- package/dist/components/activity/push-toggle.d.ts.map +1 -1
- package/dist/components/activity/push-toggle.js +72 -47
- package/dist/components/activity/push-toggle.js.map +1 -1
- package/dist/components/activity/span-bits.d.ts.map +1 -1
- package/dist/components/activity/span-bits.js +9 -7
- package/dist/components/activity/span-bits.js.map +1 -1
- package/dist/components/chat/ask-user-card.d.ts +76 -3
- package/dist/components/chat/ask-user-card.d.ts.map +1 -1
- package/dist/components/chat/ask-user-card.js +208 -149
- package/dist/components/chat/ask-user-card.js.map +1 -1
- package/dist/components/chat/ask-user-typed.d.ts +42 -0
- package/dist/components/chat/ask-user-typed.d.ts.map +1 -0
- package/dist/components/chat/ask-user-typed.js +60 -0
- package/dist/components/chat/ask-user-typed.js.map +1 -0
- package/dist/components/chat/brain-markdown-links.d.ts +2 -1
- package/dist/components/chat/brain-markdown-links.d.ts.map +1 -1
- package/dist/components/chat/brain-markdown-links.js +3 -4
- package/dist/components/chat/brain-markdown-links.js.map +1 -1
- package/dist/components/chat/brain-markdown.d.ts.map +1 -1
- package/dist/components/chat/brain-markdown.js +4 -2
- package/dist/components/chat/brain-markdown.js.map +1 -1
- package/dist/components/chat/chat-page.d.ts.map +1 -1
- package/dist/components/chat/chat-page.js +24 -9
- package/dist/components/chat/chat-page.js.map +1 -1
- package/dist/components/chat/composer-view.d.ts +75 -0
- package/dist/components/chat/composer-view.d.ts.map +1 -0
- package/dist/components/chat/composer-view.js +31 -0
- package/dist/components/chat/composer-view.js.map +1 -0
- package/dist/components/chat/composer.d.ts +4 -0
- package/dist/components/chat/composer.d.ts.map +1 -1
- package/dist/components/chat/composer.js +76 -59
- package/dist/components/chat/composer.js.map +1 -1
- package/dist/components/chat/markdown-content.d.ts +16 -1
- package/dist/components/chat/markdown-content.d.ts.map +1 -1
- package/dist/components/chat/markdown-content.js +47 -3
- package/dist/components/chat/markdown-content.js.map +1 -1
- package/dist/components/chat/mermaid-block.d.ts +4 -0
- package/dist/components/chat/mermaid-block.d.ts.map +1 -1
- package/dist/components/chat/mermaid-block.js +13 -5
- package/dist/components/chat/mermaid-block.js.map +1 -1
- package/dist/components/chat/mermaid-share.d.ts +2 -1
- package/dist/components/chat/mermaid-share.d.ts.map +1 -1
- package/dist/components/chat/mermaid-share.js +7 -8
- package/dist/components/chat/mermaid-share.js.map +1 -1
- package/dist/components/chat/mermaid-viewer.d.ts.map +1 -1
- package/dist/components/chat/mermaid-viewer.js +3 -1
- package/dist/components/chat/mermaid-viewer.js.map +1 -1
- package/dist/components/chat/message-bubble.d.ts +8 -1
- package/dist/components/chat/message-bubble.d.ts.map +1 -1
- package/dist/components/chat/message-bubble.js +53 -24
- package/dist/components/chat/message-bubble.js.map +1 -1
- package/dist/components/chat/message-share.d.ts +2 -1
- package/dist/components/chat/message-share.d.ts.map +1 -1
- package/dist/components/chat/message-share.js +6 -7
- package/dist/components/chat/message-share.js.map +1 -1
- package/dist/components/chat/renderers/bind.d.ts +39 -0
- package/dist/components/chat/renderers/bind.d.ts.map +1 -0
- package/dist/components/chat/renderers/bind.js +43 -0
- package/dist/components/chat/renderers/bind.js.map +1 -0
- package/dist/components/chat/renderers/brain-ui-tools.d.ts +3 -0
- package/dist/components/chat/renderers/brain-ui-tools.d.ts.map +1 -0
- package/dist/components/chat/renderers/brain-ui-tools.js +41 -0
- package/dist/components/chat/renderers/brain-ui-tools.js.map +1 -0
- package/dist/components/chat/renderers/claude-tools.d.ts.map +1 -1
- package/dist/components/chat/renderers/claude-tools.js +3 -2
- package/dist/components/chat/renderers/claude-tools.js.map +1 -1
- package/dist/components/chat/renderers/index.d.ts +10 -2
- package/dist/components/chat/renderers/index.d.ts.map +1 -1
- package/dist/components/chat/renderers/index.js +15 -10
- package/dist/components/chat/renderers/index.js.map +1 -1
- package/dist/components/chat/session-drawer.d.ts +4 -0
- package/dist/components/chat/session-drawer.d.ts.map +1 -1
- package/dist/components/chat/session-drawer.js +55 -40
- package/dist/components/chat/session-drawer.js.map +1 -1
- package/dist/components/chat/session-list.d.ts +41 -0
- package/dist/components/chat/session-list.d.ts.map +1 -0
- package/dist/components/chat/session-list.js +10 -0
- package/dist/components/chat/session-list.js.map +1 -0
- package/dist/components/chat/share-block.d.ts.map +1 -1
- package/dist/components/chat/share-block.js +12 -11
- package/dist/components/chat/share-block.js.map +1 -1
- package/dist/components/chat/share-card.js +2 -2
- package/dist/components/chat/share-card.js.map +1 -1
- package/dist/components/chat/subagent-view.js +1 -1
- package/dist/components/chat/subagent-view.js.map +1 -1
- package/dist/components/chat/tool-call-timeline.d.ts.map +1 -1
- package/dist/components/chat/tool-call-timeline.js +37 -12
- package/dist/components/chat/tool-call-timeline.js.map +1 -1
- package/dist/components/chat/tool-cards/block-card.d.ts +28 -0
- package/dist/components/chat/tool-cards/block-card.d.ts.map +1 -0
- package/dist/components/chat/tool-cards/block-card.js +103 -0
- package/dist/components/chat/tool-cards/block-card.js.map +1 -0
- package/dist/components/chat/tool-cards/image-mask-card.d.ts +70 -0
- package/dist/components/chat/tool-cards/image-mask-card.d.ts.map +1 -0
- package/dist/components/chat/tool-cards/image-mask-card.js +142 -0
- package/dist/components/chat/tool-cards/image-mask-card.js.map +1 -0
- package/dist/components/chat/tool-cards/location-card.d.ts +45 -0
- package/dist/components/chat/tool-cards/location-card.d.ts.map +1 -0
- package/dist/components/chat/tool-cards/location-card.js +128 -0
- package/dist/components/chat/tool-cards/location-card.js.map +1 -0
- package/dist/components/chat/tool-views.d.ts +15 -4
- package/dist/components/chat/tool-views.d.ts.map +1 -1
- package/dist/components/chat/tool-views.js +22 -38
- package/dist/components/chat/tool-views.js.map +1 -1
- package/dist/components/chat/transcript-turn.d.ts +45 -0
- package/dist/components/chat/transcript-turn.d.ts.map +1 -0
- package/dist/components/chat/transcript-turn.js +25 -0
- package/dist/components/chat/transcript-turn.js.map +1 -0
- package/dist/components/chat/use-chat-commands.d.ts.map +1 -1
- package/dist/components/chat/use-chat-commands.js +13 -16
- package/dist/components/chat/use-chat-commands.js.map +1 -1
- package/dist/components/chat/welcome-state.d.ts +7 -0
- package/dist/components/chat/welcome-state.d.ts.map +1 -1
- package/dist/components/chat/welcome-state.js +13 -5
- package/dist/components/chat/welcome-state.js.map +1 -1
- package/dist/components/connectivity/connection-gate.d.ts.map +1 -1
- package/dist/components/connectivity/connection-gate.js +64 -6
- package/dist/components/connectivity/connection-gate.js.map +1 -1
- package/dist/components/connectivity/login-form.d.ts +31 -0
- package/dist/components/connectivity/login-form.d.ts.map +1 -0
- package/dist/components/connectivity/login-form.js +19 -0
- package/dist/components/connectivity/login-form.js.map +1 -0
- package/dist/components/connectivity/login-screen.d.ts +5 -2
- package/dist/components/connectivity/login-screen.d.ts.map +1 -1
- package/dist/components/connectivity/login-screen.js +41 -31
- package/dist/components/connectivity/login-screen.js.map +1 -1
- package/dist/components/dev/share-harness.js +1 -1
- package/dist/components/dev/share-harness.js.map +1 -1
- package/dist/components/files/file-panel.d.ts +1 -1
- package/dist/components/files/file-panel.d.ts.map +1 -1
- package/dist/components/files/file-panel.js +74 -0
- package/dist/components/files/file-panel.js.map +1 -1
- package/dist/components/files/file-tree-view.d.ts +45 -0
- package/dist/components/files/file-tree-view.d.ts.map +1 -0
- package/dist/components/files/file-tree-view.js +51 -0
- package/dist/components/files/file-tree-view.js.map +1 -0
- package/dist/components/files/file-tree.d.ts +6 -0
- package/dist/components/files/file-tree.d.ts.map +1 -1
- package/dist/components/files/file-tree.js +39 -43
- package/dist/components/files/file-tree.js.map +1 -1
- package/dist/components/files/file-viewer-binary.d.ts.map +1 -1
- package/dist/components/files/file-viewer-binary.js +3 -2
- package/dist/components/files/file-viewer-binary.js.map +1 -1
- package/dist/components/files/file-viewer-frame.d.ts +36 -0
- package/dist/components/files/file-viewer-frame.d.ts.map +1 -0
- package/dist/components/files/file-viewer-frame.js +26 -0
- package/dist/components/files/file-viewer-frame.js.map +1 -0
- package/dist/components/files/file-viewer.d.ts +5 -0
- package/dist/components/files/file-viewer.d.ts.map +1 -1
- package/dist/components/files/file-viewer.js +26 -32
- package/dist/components/files/file-viewer.js.map +1 -1
- package/dist/components/files/frontmatter-chips.d.ts +18 -0
- package/dist/components/files/frontmatter-chips.d.ts.map +1 -0
- package/dist/components/files/frontmatter-chips.js +11 -0
- package/dist/components/files/frontmatter-chips.js.map +1 -0
- package/dist/components/files/frontmatter-panel.d.ts +5 -1
- package/dist/components/files/frontmatter-panel.d.ts.map +1 -1
- package/dist/components/files/frontmatter-panel.js +7 -6
- package/dist/components/files/frontmatter-panel.js.map +1 -1
- package/dist/components/files/staleness.d.ts +18 -0
- package/dist/components/files/staleness.d.ts.map +1 -0
- package/dist/components/files/staleness.js +27 -0
- package/dist/components/files/staleness.js.map +1 -0
- package/dist/components/graph/graph-canvas.d.ts.map +1 -1
- package/dist/components/graph/graph-canvas.js +24 -1
- package/dist/components/graph/graph-canvas.js.map +1 -1
- package/dist/components/graph/graph-controls-column.d.ts +14 -0
- package/dist/components/graph/graph-controls-column.d.ts.map +1 -0
- package/dist/components/graph/graph-controls-column.js +44 -0
- package/dist/components/graph/graph-controls-column.js.map +1 -0
- package/dist/components/graph/graph-controls.d.ts +20 -5
- package/dist/components/graph/graph-controls.d.ts.map +1 -1
- package/dist/components/graph/graph-controls.js +58 -37
- package/dist/components/graph/graph-controls.js.map +1 -1
- package/dist/components/graph/graph-form.d.ts +82 -0
- package/dist/components/graph/graph-form.d.ts.map +1 -0
- package/dist/components/graph/graph-form.js +69 -0
- package/dist/components/graph/graph-form.js.map +1 -0
- package/dist/components/graph/graph-maintenance.d.ts.map +1 -1
- package/dist/components/graph/graph-maintenance.js +6 -10
- package/dist/components/graph/graph-maintenance.js.map +1 -1
- package/dist/components/graph/graph-node-rail.d.ts +13 -0
- package/dist/components/graph/graph-node-rail.d.ts.map +1 -0
- package/dist/components/graph/graph-node-rail.js +92 -0
- package/dist/components/graph/graph-node-rail.js.map +1 -0
- package/dist/components/graph/graph-page.d.ts +7 -0
- package/dist/components/graph/graph-page.d.ts.map +1 -1
- package/dist/components/graph/graph-page.js +102 -12
- package/dist/components/graph/graph-page.js.map +1 -1
- package/dist/components/graph/graph-scene.d.ts.map +1 -1
- package/dist/components/graph/graph-scene.js +100 -24
- package/dist/components/graph/graph-scene.js.map +1 -1
- package/dist/components/graph/lib/graph-helpers.d.ts +42 -12
- package/dist/components/graph/lib/graph-helpers.d.ts.map +1 -1
- package/dist/components/graph/lib/graph-helpers.js +33 -41
- package/dist/components/graph/lib/graph-helpers.js.map +1 -1
- package/dist/components/graph/node-card.d.ts +28 -0
- package/dist/components/graph/node-card.d.ts.map +1 -0
- package/dist/components/graph/node-card.js +7 -0
- package/dist/components/graph/node-card.js.map +1 -0
- package/dist/components/graph/node-popover.d.ts +6 -2
- package/dist/components/graph/node-popover.d.ts.map +1 -1
- package/dist/components/graph/node-popover.js +13 -31
- package/dist/components/graph/node-popover.js.map +1 -1
- package/dist/components/graph/use-graph-theme.d.ts +32 -4
- package/dist/components/graph/use-graph-theme.d.ts.map +1 -1
- package/dist/components/graph/use-graph-theme.js +44 -32
- package/dist/components/graph/use-graph-theme.js.map +1 -1
- package/dist/components/graph/use-node-actions.d.ts +26 -0
- package/dist/components/graph/use-node-actions.d.ts.map +1 -0
- package/dist/components/graph/use-node-actions.js +54 -0
- package/dist/components/graph/use-node-actions.js.map +1 -0
- package/dist/components/images/image-share.d.ts +2 -1
- package/dist/components/images/image-share.d.ts.map +1 -1
- package/dist/components/images/image-share.js +3 -3
- package/dist/components/images/image-share.js.map +1 -1
- package/dist/components/images/image-viewer.d.ts.map +1 -1
- package/dist/components/images/image-viewer.js +3 -1
- package/dist/components/images/image-viewer.js.map +1 -1
- package/dist/components/images/mask-editor.d.ts.map +1 -1
- package/dist/components/images/mask-editor.js +7 -5
- package/dist/components/images/mask-editor.js.map +1 -1
- package/dist/components/layout/app-shell.d.ts.map +1 -1
- package/dist/components/layout/app-shell.js +5 -1
- package/dist/components/layout/app-shell.js.map +1 -1
- package/dist/components/layout/desktop-palette.d.ts +23 -0
- package/dist/components/layout/desktop-palette.d.ts.map +1 -0
- package/dist/components/layout/desktop-palette.js +132 -0
- package/dist/components/layout/desktop-palette.js.map +1 -0
- package/dist/components/layout/key-cap.d.ts +9 -0
- package/dist/components/layout/key-cap.d.ts.map +1 -0
- package/dist/components/layout/key-cap.js +10 -0
- package/dist/components/layout/key-cap.js.map +1 -0
- package/dist/components/layout/mobile-tab-bar.d.ts +13 -0
- package/dist/components/layout/mobile-tab-bar.d.ts.map +1 -1
- package/dist/components/layout/mobile-tab-bar.js +58 -47
- package/dist/components/layout/mobile-tab-bar.js.map +1 -1
- package/dist/components/layout/shortcut-switch.d.ts +13 -0
- package/dist/components/layout/shortcut-switch.d.ts.map +1 -0
- package/dist/components/layout/shortcut-switch.js +22 -0
- package/dist/components/layout/shortcut-switch.js.map +1 -0
- package/dist/components/layout/side-rail.d.ts +24 -0
- package/dist/components/layout/side-rail.d.ts.map +1 -1
- package/dist/components/layout/side-rail.js +65 -27
- package/dist/components/layout/side-rail.js.map +1 -1
- package/dist/components/layout/slide-panel.d.ts +12 -2
- package/dist/components/layout/slide-panel.d.ts.map +1 -1
- package/dist/components/layout/slide-panel.js +11 -2
- package/dist/components/layout/slide-panel.js.map +1 -1
- package/dist/components/layout/theme.d.ts +22 -0
- package/dist/components/layout/theme.d.ts.map +1 -0
- package/dist/components/layout/theme.js +44 -0
- package/dist/components/layout/theme.js.map +1 -0
- package/dist/components/quick-actions/add-form.d.ts +44 -0
- package/dist/components/quick-actions/add-form.d.ts.map +1 -0
- package/dist/components/quick-actions/add-form.js +30 -0
- package/dist/components/quick-actions/add-form.js.map +1 -0
- package/dist/components/quick-actions/add-modal.d.ts +7 -0
- package/dist/components/quick-actions/add-modal.d.ts.map +1 -1
- package/dist/components/quick-actions/add-modal.js +66 -20
- package/dist/components/quick-actions/add-modal.js.map +1 -1
- package/dist/components/quick-actions/search-modal.d.ts.map +1 -1
- package/dist/components/quick-actions/search-modal.js +48 -19
- package/dist/components/quick-actions/search-modal.js.map +1 -1
- package/dist/components/quick-actions/streaming-modal.d.ts +6 -0
- package/dist/components/quick-actions/streaming-modal.d.ts.map +1 -1
- package/dist/components/quick-actions/streaming-modal.js +42 -17
- package/dist/components/quick-actions/streaming-modal.js.map +1 -1
- package/dist/components/quick-actions/streaming-output.d.ts +38 -0
- package/dist/components/quick-actions/streaming-output.d.ts.map +1 -0
- package/dist/components/quick-actions/streaming-output.js +22 -0
- package/dist/components/quick-actions/streaming-output.js.map +1 -0
- package/dist/components/quick-actions/whatsup-modal.d.ts +5 -0
- package/dist/components/quick-actions/whatsup-modal.d.ts.map +1 -1
- package/dist/components/quick-actions/whatsup-modal.js +36 -10
- package/dist/components/quick-actions/whatsup-modal.js.map +1 -1
- package/dist/components/settings/devices-agents-tab.d.ts +10 -0
- package/dist/components/settings/devices-agents-tab.d.ts.map +1 -0
- package/dist/components/settings/devices-agents-tab.js +131 -0
- package/dist/components/settings/devices-agents-tab.js.map +1 -0
- package/dist/components/settings/models-list.d.ts +39 -0
- package/dist/components/settings/models-list.d.ts.map +1 -0
- package/dist/components/settings/models-list.js +72 -0
- package/dist/components/settings/models-list.js.map +1 -0
- package/dist/components/settings/models-tab.d.ts +4 -0
- package/dist/components/settings/models-tab.d.ts.map +1 -1
- package/dist/components/settings/models-tab.js +52 -102
- package/dist/components/settings/models-tab.js.map +1 -1
- package/dist/components/settings/one-time-agent-credential.d.ts +3 -0
- package/dist/components/settings/one-time-agent-credential.d.ts.map +1 -0
- package/dist/components/settings/one-time-agent-credential.js +55 -0
- package/dist/components/settings/one-time-agent-credential.js.map +1 -0
- package/dist/components/settings/passkey-list.d.ts +35 -0
- package/dist/components/settings/passkey-list.d.ts.map +1 -0
- package/dist/components/settings/passkey-list.js +34 -0
- package/dist/components/settings/passkey-list.js.map +1 -0
- package/dist/components/settings/passkey-tab.d.ts +3 -0
- package/dist/components/settings/passkey-tab.d.ts.map +1 -1
- package/dist/components/settings/passkey-tab.js +53 -45
- package/dist/components/settings/passkey-tab.js.map +1 -1
- package/dist/components/settings/pi-accounts-list.d.ts +27 -0
- package/dist/components/settings/pi-accounts-list.d.ts.map +1 -0
- package/dist/components/settings/pi-accounts-list.js +15 -0
- package/dist/components/settings/pi-accounts-list.js.map +1 -0
- package/dist/components/settings/pi-accounts.d.ts +3 -0
- package/dist/components/settings/pi-accounts.d.ts.map +1 -1
- package/dist/components/settings/pi-accounts.js +73 -55
- package/dist/components/settings/pi-accounts.js.map +1 -1
- package/dist/components/settings/principal-list.d.ts +37 -0
- package/dist/components/settings/principal-list.d.ts.map +1 -0
- package/dist/components/settings/principal-list.js +18 -0
- package/dist/components/settings/principal-list.js.map +1 -0
- package/dist/components/settings/settings-panel.d.ts +10 -3
- package/dist/components/settings/settings-panel.d.ts.map +1 -1
- package/dist/components/settings/settings-panel.js +80 -6
- package/dist/components/settings/settings-panel.js.map +1 -1
- package/dist/components/settings/skills-list.d.ts +53 -0
- package/dist/components/settings/skills-list.d.ts.map +1 -0
- package/dist/components/settings/skills-list.js +28 -0
- package/dist/components/settings/skills-list.js.map +1 -0
- package/dist/components/settings/skills-tab.d.ts.map +1 -1
- package/dist/components/settings/skills-tab.js +65 -38
- package/dist/components/settings/skills-tab.js.map +1 -1
- package/dist/components/settings/tool-permissions-list.d.ts +18 -0
- package/dist/components/settings/tool-permissions-list.d.ts.map +1 -0
- package/dist/components/settings/tool-permissions-list.js +6 -0
- package/dist/components/settings/tool-permissions-list.js.map +1 -0
- package/dist/components/settings/tool-permissions.d.ts +2 -1
- package/dist/components/settings/tool-permissions.d.ts.map +1 -1
- package/dist/components/settings/tool-permissions.js +33 -16
- package/dist/components/settings/tool-permissions.js.map +1 -1
- package/dist/components/settings/web-search-chain.d.ts +41 -0
- package/dist/components/settings/web-search-chain.d.ts.map +1 -0
- package/dist/components/settings/web-search-chain.js +47 -0
- package/dist/components/settings/web-search-chain.js.map +1 -0
- package/dist/components/settings/web-search-settings.d.ts +4 -7
- package/dist/components/settings/web-search-settings.d.ts.map +1 -1
- package/dist/components/settings/web-search-settings.js +54 -76
- package/dist/components/settings/web-search-settings.js.map +1 -1
- package/dist/components/share/share-menu.d.ts.map +1 -1
- package/dist/components/share/share-menu.js +24 -4
- package/dist/components/share/share-menu.js.map +1 -1
- package/dist/components/voice/dictation-sheet.js +3 -3
- package/dist/components/voice/dictation-sheet.js.map +1 -1
- package/dist/components/voice/mic-button.js +1 -1
- package/dist/components/voice/mic-button.js.map +1 -1
- package/dist/components/voice/review-card.js +1 -1
- package/dist/components/voice/review-card.js.map +1 -1
- package/dist/config.d.ts +5 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +15 -5
- package/dist/config.js.map +1 -1
- package/dist/connection.d.ts +12 -0
- package/dist/connection.d.ts.map +1 -0
- package/dist/connection.js +421 -0
- package/dist/connection.js.map +1 -0
- package/dist/default-root.d.ts +3 -0
- package/dist/default-root.d.ts.map +1 -0
- package/dist/default-root.js +16 -0
- package/dist/default-root.js.map +1 -0
- package/dist/hooks/use-color-scheme.d.ts +14 -0
- package/dist/hooks/use-color-scheme.d.ts.map +1 -0
- package/dist/hooks/use-color-scheme.js +37 -0
- package/dist/hooks/use-color-scheme.js.map +1 -0
- package/dist/hooks/use-hash-routes.d.ts.map +1 -1
- package/dist/hooks/use-hash-routes.js +4 -2
- package/dist/hooks/use-hash-routes.js.map +1 -1
- package/dist/hooks/use-media-query.d.ts +7 -0
- package/dist/hooks/use-media-query.d.ts.map +1 -0
- package/dist/hooks/use-media-query.js +34 -0
- package/dist/hooks/use-media-query.js.map +1 -0
- package/dist/hooks/use-share-intake.d.ts.map +1 -1
- package/dist/hooks/use-share-intake.js +37 -12
- package/dist/hooks/use-share-intake.js.map +1 -1
- package/dist/hooks/use-vpn-status.d.ts +1 -1
- package/dist/hooks/use-vpn-status.d.ts.map +1 -1
- package/dist/hooks/use-vpn-status.js +20 -16
- package/dist/hooks/use-vpn-status.js.map +1 -1
- package/dist/hooks/use-websocket.d.ts +5 -24
- package/dist/hooks/use-websocket.d.ts.map +1 -1
- package/dist/hooks/use-websocket.js +11 -382
- package/dist/hooks/use-websocket.js.map +1 -1
- package/dist/hooks/websocket-handlers/activity.d.ts +2 -2
- package/dist/hooks/websocket-handlers/activity.d.ts.map +1 -1
- package/dist/hooks/websocket-handlers/activity.js +4 -5
- package/dist/hooks/websocket-handlers/activity.js.map +1 -1
- package/dist/hooks/websocket-handlers/chat.d.ts +1 -0
- package/dist/hooks/websocket-handlers/chat.d.ts.map +1 -1
- package/dist/hooks/websocket-handlers/chat.js +27 -5
- package/dist/hooks/websocket-handlers/chat.js.map +1 -1
- package/dist/hooks/websocket-handlers/connection.d.ts.map +1 -1
- package/dist/hooks/websocket-handlers/connection.js +4 -6
- package/dist/hooks/websocket-handlers/connection.js.map +1 -1
- package/dist/hooks/websocket-handlers/mask.d.ts +1 -1
- package/dist/hooks/websocket-handlers/mask.d.ts.map +1 -1
- package/dist/hooks/websocket-handlers/mask.js +2 -3
- package/dist/hooks/websocket-handlers/mask.js.map +1 -1
- package/dist/hooks/websocket-handlers/provider.d.ts.map +1 -1
- package/dist/hooks/websocket-handlers/provider.js +4 -6
- package/dist/hooks/websocket-handlers/provider.js.map +1 -1
- package/dist/hooks/websocket-handlers/types.d.ts +6 -2
- package/dist/hooks/websocket-handlers/types.d.ts.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/api-client.d.ts +321 -0
- package/dist/lib/api-client.d.ts.map +1 -1
- package/dist/lib/api-client.js +243 -213
- package/dist/lib/api-client.js.map +1 -1
- package/dist/lib/backend.d.ts +19 -2
- package/dist/lib/backend.d.ts.map +1 -1
- package/dist/lib/backend.js +15 -9
- package/dist/lib/backend.js.map +1 -1
- package/dist/lib/diff.d.ts +8 -10
- package/dist/lib/diff.d.ts.map +1 -1
- package/dist/lib/diff.js +26 -53
- package/dist/lib/diff.js.map +1 -1
- package/dist/lib/format-time.d.ts +3 -0
- package/dist/lib/format-time.d.ts.map +1 -0
- package/dist/lib/format-time.js +25 -0
- package/dist/lib/format-time.js.map +1 -0
- package/dist/lib/light-dark.d.ts +37 -0
- package/dist/lib/light-dark.d.ts.map +1 -0
- package/dist/lib/light-dark.js +83 -0
- package/dist/lib/light-dark.js.map +1 -0
- package/dist/lib/mermaid-theme.d.ts +7 -2
- package/dist/lib/mermaid-theme.d.ts.map +1 -1
- package/dist/lib/mermaid-theme.js +125 -203
- package/dist/lib/mermaid-theme.js.map +1 -1
- package/dist/lib/passkeys.d.ts +6 -3
- package/dist/lib/passkeys.d.ts.map +1 -1
- package/dist/lib/passkeys.js +10 -4
- package/dist/lib/passkeys.js.map +1 -1
- package/dist/lib/push-registration.d.ts +10 -0
- package/dist/lib/push-registration.d.ts.map +1 -0
- package/dist/lib/push-registration.js +44 -0
- package/dist/lib/push-registration.js.map +1 -0
- package/dist/lib/share-intake.d.ts +2 -1
- package/dist/lib/share-intake.d.ts.map +1 -1
- package/dist/lib/share-intake.js +3 -3
- package/dist/lib/share-intake.js.map +1 -1
- package/dist/lib/share.d.ts +4 -3
- package/dist/lib/share.d.ts.map +1 -1
- package/dist/lib/share.js +6 -7
- package/dist/lib/share.js.map +1 -1
- package/dist/lib/single-key.d.ts +30 -0
- package/dist/lib/single-key.d.ts.map +1 -0
- package/dist/lib/single-key.js +45 -0
- package/dist/lib/single-key.js.map +1 -0
- package/dist/lib/tool-names.d.ts +8 -6
- package/dist/lib/tool-names.d.ts.map +1 -1
- package/dist/lib/tool-names.js +17 -7
- package/dist/lib/tool-names.js.map +1 -1
- package/dist/root-context.d.ts +229 -0
- package/dist/root-context.d.ts.map +1 -0
- package/dist/root-context.js +33 -0
- package/dist/root-context.js.map +1 -0
- package/dist/root.d.ts +38 -0
- package/dist/root.d.ts.map +1 -0
- package/dist/root.js +47 -0
- package/dist/root.js.map +1 -0
- package/dist/stores/activity-state.d.ts +29 -0
- package/dist/stores/activity-state.d.ts.map +1 -0
- package/dist/stores/activity-state.js +282 -0
- package/dist/stores/activity-state.js.map +1 -0
- package/dist/stores/activity-store.d.ts +10 -41
- package/dist/stores/activity-store.d.ts.map +1 -1
- package/dist/stores/activity-store.js +9 -271
- package/dist/stores/activity-store.js.map +1 -1
- package/dist/stores/chat-state.d.ts +212 -0
- package/dist/stores/chat-state.d.ts.map +1 -0
- package/dist/stores/chat-state.js +466 -0
- package/dist/stores/chat-state.js.map +1 -0
- package/dist/stores/chat-store.d.ts +4 -162
- package/dist/stores/chat-store.d.ts.map +1 -1
- package/dist/stores/chat-store.js +7 -418
- package/dist/stores/chat-store.js.map +1 -1
- package/dist/stores/connection-state.d.ts +40 -0
- package/dist/stores/connection-state.d.ts.map +1 -0
- package/dist/stores/connection-state.js +30 -0
- package/dist/stores/connection-state.js.map +1 -0
- package/dist/stores/connection-store.d.ts +4 -40
- package/dist/stores/connection-store.d.ts.map +1 -1
- package/dist/stores/connection-store.js +7 -27
- package/dist/stores/connection-store.js.map +1 -1
- package/dist/stores/create-stores.d.ts +23 -0
- package/dist/stores/create-stores.d.ts.map +1 -0
- package/dist/stores/create-stores.js +28 -0
- package/dist/stores/create-stores.js.map +1 -0
- package/dist/stores/file-state.d.ts +53 -0
- package/dist/stores/file-state.d.ts.map +1 -0
- package/dist/stores/file-state.js +341 -0
- package/dist/stores/file-state.js.map +1 -0
- package/dist/stores/file-store.d.ts +4 -52
- package/dist/stores/file-store.d.ts.map +1 -1
- package/dist/stores/file-store.js +7 -300
- package/dist/stores/file-store.js.map +1 -1
- package/dist/stores/graph-state.d.ts +95 -0
- package/dist/stores/graph-state.d.ts.map +1 -0
- package/dist/stores/graph-state.js +252 -0
- package/dist/stores/graph-state.js.map +1 -0
- package/dist/stores/graph-store.d.ts +7 -83
- package/dist/stores/graph-store.d.ts.map +1 -1
- package/dist/stores/graph-store.js +8 -249
- package/dist/stores/graph-store.js.map +1 -1
- package/dist/stores/mask-state.d.ts +21 -0
- package/dist/stores/mask-state.d.ts.map +1 -0
- package/dist/stores/mask-state.js +9 -0
- package/dist/stores/mask-state.js.map +1 -0
- package/dist/stores/mask-store.d.ts +4 -21
- package/dist/stores/mask-store.d.ts.map +1 -1
- package/dist/stores/mask-store.js +7 -6
- package/dist/stores/mask-store.js.map +1 -1
- package/dist/stores/principal-state.d.ts +16 -0
- package/dist/stores/principal-state.d.ts.map +1 -0
- package/dist/stores/principal-state.js +31 -0
- package/dist/stores/principal-state.js.map +1 -0
- package/dist/stores/principal-store.d.ts +5 -0
- package/dist/stores/principal-store.d.ts.map +1 -0
- package/dist/stores/principal-store.js +8 -0
- package/dist/stores/principal-store.js.map +1 -0
- package/dist/stores/provider-state.d.ts +24 -0
- package/dist/stores/provider-state.d.ts.map +1 -0
- package/dist/stores/provider-state.js +68 -0
- package/dist/stores/provider-state.js.map +1 -0
- package/dist/stores/provider-store.d.ts +4 -23
- package/dist/stores/provider-store.d.ts.map +1 -1
- package/dist/stores/provider-store.js +7 -64
- package/dist/stores/provider-store.js.map +1 -1
- package/dist/stores/share-state.d.ts +29 -0
- package/dist/stores/share-state.d.ts.map +1 -0
- package/dist/stores/share-state.js +21 -0
- package/dist/stores/share-state.js.map +1 -0
- package/dist/stores/share-store.d.ts +4 -28
- package/dist/stores/share-store.d.ts.map +1 -1
- package/dist/stores/share-store.js +7 -18
- package/dist/stores/share-store.js.map +1 -1
- package/dist/stores/store-environment.d.ts +10 -0
- package/dist/stores/store-environment.d.ts.map +1 -0
- package/dist/stores/store-environment.js +2 -0
- package/dist/stores/store-environment.js.map +1 -0
- package/dist/stores/ui-state.d.ts +71 -0
- package/dist/stores/ui-state.d.ts.map +1 -0
- package/dist/stores/ui-state.js +58 -0
- package/dist/stores/ui-state.js.map +1 -0
- package/dist/stores/ui-store.d.ts +4 -45
- package/dist/stores/ui-store.d.ts.map +1 -1
- package/dist/stores/ui-store.js +7 -36
- package/dist/stores/ui-store.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/theme.css +150 -97
- package/dist/voice/asr-clients.d.ts +2 -1
- package/dist/voice/asr-clients.d.ts.map +1 -1
- package/dist/voice/asr-clients.js +16 -17
- package/dist/voice/asr-clients.js.map +1 -1
- package/dist/voice/use-dictation.d.ts.map +1 -1
- package/dist/voice/use-dictation.js +12 -8
- package/dist/voice/use-dictation.js.map +1 -1
- package/dist/voice/voice-state.d.ts +25 -0
- package/dist/voice/voice-state.d.ts.map +1 -0
- package/dist/voice/voice-state.js +29 -0
- package/dist/voice/voice-state.js.map +1 -0
- package/dist/voice/voice-store.d.ts +4 -25
- package/dist/voice/voice-store.d.ts.map +1 -1
- package/dist/voice/voice-store.js +7 -26
- package/dist/voice/voice-store.js.map +1 -1
- package/package.json +3 -2
- package/src/components/activity/activity-page.tsx +334 -160
- package/src/components/activity/activity-run-detail.tsx +81 -47
- package/src/components/activity/activity-run-list.tsx +27 -59
- package/src/components/activity/activity-views.tsx +155 -0
- package/src/components/activity/approval-card.tsx +80 -0
- package/src/components/activity/digest-card.tsx +25 -61
- package/src/components/activity/digest-summary.tsx +52 -0
- package/src/components/activity/push-switch.tsx +62 -0
- package/src/components/activity/push-toggle.tsx +51 -81
- package/src/components/activity/span-bits.tsx +8 -7
- package/src/components/chat/ask-user-card.tsx +292 -356
- package/src/components/chat/ask-user-typed.ts +77 -0
- package/src/components/chat/brain-markdown-links.tsx +4 -4
- package/src/components/chat/brain-markdown.tsx +4 -2
- package/src/components/chat/chat-page.tsx +38 -9
- package/src/components/chat/composer-view.tsx +194 -0
- package/src/components/chat/composer.tsx +117 -296
- package/src/components/chat/markdown-content.tsx +53 -2
- package/src/components/chat/mermaid-block.tsx +13 -5
- package/src/components/chat/mermaid-share.ts +8 -7
- package/src/components/chat/mermaid-viewer.tsx +3 -1
- package/src/components/chat/message-bubble.tsx +78 -94
- package/src/components/chat/message-share.ts +7 -7
- package/src/components/chat/renderers/bind.tsx +94 -0
- package/src/components/chat/renderers/brain-ui-tools.tsx +56 -0
- package/src/components/chat/renderers/claude-tools.tsx +3 -2
- package/src/components/chat/renderers/index.ts +15 -10
- package/src/components/chat/session-drawer.tsx +60 -138
- package/src/components/chat/session-list.tsx +113 -0
- package/src/components/chat/share-block.tsx +16 -12
- package/src/components/chat/share-card.tsx +2 -2
- package/src/components/chat/subagent-view.tsx +4 -4
- package/src/components/chat/tool-call-timeline.tsx +59 -22
- package/src/components/chat/tool-cards/block-card.tsx +145 -0
- package/src/components/chat/tool-cards/image-mask-card.tsx +214 -0
- package/src/components/chat/tool-cards/location-card.tsx +159 -0
- package/src/components/chat/tool-views.tsx +23 -73
- package/src/components/chat/transcript-turn.tsx +108 -0
- package/src/components/chat/use-chat-commands.ts +14 -16
- package/src/components/chat/welcome-state.tsx +36 -91
- package/src/components/connectivity/connection-gate.tsx +80 -9
- package/src/components/connectivity/login-form.tsx +122 -0
- package/src/components/connectivity/login-screen.tsx +45 -100
- package/src/components/dev/share-harness.tsx +2 -2
- package/src/components/files/file-panel.tsx +168 -0
- package/src/components/files/file-tree-view.tsx +127 -0
- package/src/components/files/file-tree.tsx +55 -109
- package/src/components/files/file-viewer-binary.tsx +3 -2
- package/src/components/files/file-viewer-frame.tsx +113 -0
- package/src/components/files/file-viewer.tsx +40 -95
- package/src/components/files/frontmatter-chips.tsx +42 -0
- package/src/components/files/frontmatter-panel.tsx +6 -71
- package/src/components/files/staleness.ts +29 -0
- package/src/components/graph/graph-canvas.tsx +24 -1
- package/src/components/graph/graph-controls-column.tsx +92 -0
- package/src/components/graph/graph-controls.tsx +83 -127
- package/src/components/graph/graph-form.tsx +183 -0
- package/src/components/graph/graph-maintenance.tsx +9 -14
- package/src/components/graph/graph-node-rail.tsx +147 -0
- package/src/components/graph/graph-page.tsx +189 -49
- package/src/components/graph/graph-scene.tsx +200 -30
- package/src/components/graph/lib/graph-helpers.ts +65 -43
- package/src/components/graph/node-card.tsx +64 -0
- package/src/components/graph/node-popover.tsx +28 -117
- package/src/components/graph/use-graph-theme.ts +69 -32
- package/src/components/graph/use-node-actions.ts +56 -0
- package/src/components/images/image-share.ts +4 -2
- package/src/components/images/image-viewer.tsx +3 -1
- package/src/components/images/mask-editor.tsx +7 -4
- package/src/components/layout/app-shell.tsx +7 -1
- package/src/components/layout/desktop-palette.tsx +151 -0
- package/src/components/layout/key-cap.tsx +15 -0
- package/src/components/layout/mobile-tab-bar.tsx +80 -157
- package/src/components/layout/shortcut-switch.tsx +32 -0
- package/src/components/layout/side-rail.tsx +70 -150
- package/src/components/layout/slide-panel.tsx +29 -2
- package/src/components/layout/theme.tsx +67 -0
- package/src/components/quick-actions/add-form.tsx +188 -0
- package/src/components/quick-actions/add-modal.tsx +68 -144
- package/src/components/quick-actions/search-modal.tsx +49 -19
- package/src/components/quick-actions/streaming-modal.tsx +44 -71
- package/src/components/quick-actions/streaming-output.tsx +112 -0
- package/src/components/quick-actions/whatsup-modal.tsx +38 -60
- package/src/components/settings/devices-agents-tab.tsx +139 -0
- package/src/components/settings/models-list.tsx +299 -0
- package/src/components/settings/models-tab.tsx +63 -337
- package/src/components/settings/one-time-agent-credential.tsx +131 -0
- package/src/components/settings/passkey-list.tsx +201 -0
- package/src/components/settings/passkey-tab.tsx +53 -197
- package/src/components/settings/pi-accounts-list.tsx +128 -0
- package/src/components/settings/pi-accounts.tsx +71 -170
- package/src/components/settings/principal-list.tsx +172 -0
- package/src/components/settings/settings-panel.tsx +245 -19
- package/src/components/settings/skills-list.tsx +276 -0
- package/src/components/settings/skills-tab.tsx +82 -269
- package/src/components/settings/tool-permissions-list.tsx +54 -0
- package/src/components/settings/tool-permissions.tsx +27 -46
- package/src/components/settings/web-search-chain.tsx +300 -0
- package/src/components/settings/web-search-settings.tsx +58 -328
- package/src/components/share/share-menu.tsx +19 -4
- package/src/components/voice/dictation-sheet.tsx +5 -5
- package/src/components/voice/mic-button.tsx +1 -1
- package/src/components/voice/review-card.tsx +1 -1
- package/src/config.ts +21 -7
- package/src/connection.ts +443 -0
- package/src/default-root.ts +16 -0
- package/src/hooks/use-color-scheme.ts +36 -0
- package/src/hooks/use-hash-routes.ts +4 -2
- package/src/hooks/use-media-query.ts +32 -0
- package/src/hooks/use-share-intake.ts +32 -12
- package/src/hooks/use-vpn-status.ts +23 -15
- package/src/hooks/use-websocket.ts +12 -426
- package/src/hooks/websocket-handlers/activity.ts +4 -5
- package/src/hooks/websocket-handlers/chat.ts +26 -5
- package/src/hooks/websocket-handlers/connection.ts +4 -6
- package/src/hooks/websocket-handlers/mask.ts +2 -3
- package/src/hooks/websocket-handlers/provider.ts +4 -6
- package/src/hooks/websocket-handlers/types.ts +6 -2
- package/src/index.ts +7 -3
- package/src/lib/api-client.ts +446 -365
- package/src/lib/backend.ts +20 -10
- package/src/lib/diff.ts +28 -62
- package/src/lib/format-time.ts +20 -0
- package/src/lib/light-dark.ts +83 -0
- package/src/lib/mermaid-theme.ts +183 -214
- package/src/lib/passkeys.ts +12 -4
- package/src/lib/push-registration.ts +46 -0
- package/src/lib/share-intake.ts +6 -3
- package/src/lib/share.ts +7 -4
- package/src/lib/single-key.ts +47 -0
- package/src/lib/tool-names.ts +31 -8
- package/src/root-context.tsx +40 -0
- package/src/root.ts +83 -0
- package/src/stores/activity-state.ts +295 -0
- package/src/stores/activity-store.ts +11 -285
- package/src/stores/chat-state.ts +795 -0
- package/src/stores/chat-store.ts +11 -705
- package/src/stores/connection-state.ts +78 -0
- package/src/stores/connection-store.ts +11 -76
- package/src/stores/create-stores.ts +31 -0
- package/src/stores/file-state.ts +399 -0
- package/src/stores/file-store.ts +9 -360
- package/src/stores/graph-state.ts +368 -0
- package/src/stores/graph-store.ts +10 -355
- package/src/stores/mask-state.ts +30 -0
- package/src/stores/mask-store.ts +10 -27
- package/src/stores/principal-state.ts +42 -0
- package/src/stores/principal-store.ts +11 -0
- package/src/stores/provider-state.ts +103 -0
- package/src/stores/provider-store.ts +10 -95
- package/src/stores/share-state.ts +56 -0
- package/src/stores/share-store.ts +11 -54
- package/src/stores/store-environment.ts +10 -0
- package/src/stores/ui-state.ts +143 -0
- package/src/stores/ui-store.ts +11 -93
- package/src/styles.css +4 -1
- package/src/theme.css +150 -97
- package/src/voice/asr-clients.ts +17 -17
- package/src/voice/use-dictation.ts +11 -8
- package/src/voice/voice-state.ts +57 -0
- package/src/voice/voice-store.ts +11 -55
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useBrainUiRoot } from "../../root-context.js";
|
|
2
|
+
import { useState, useEffect, useRef, type KeyboardEvent } from "react";
|
|
2
3
|
import {
|
|
3
4
|
Check,
|
|
4
5
|
X,
|
|
@@ -9,7 +10,7 @@ import {
|
|
|
9
10
|
AlertTriangle,
|
|
10
11
|
FileText,
|
|
11
12
|
} from "lucide-react";
|
|
12
|
-
import {
|
|
13
|
+
import { type ToolSemantics } from "@schlessera/brain-ui-sdk/client";
|
|
13
14
|
import { useChatStore, type ToolCall } from "../../stores/chat-store.js";
|
|
14
15
|
import { cn } from "../../lib/utils.js";
|
|
15
16
|
import { motion, AnimatePresence } from "framer-motion";
|
|
@@ -17,6 +18,8 @@ import { getToolLabel, getTouchedFile, formatDuration, formatTokenCount } from "
|
|
|
17
18
|
import { registerBuiltinRenderers, GENERIC_RENDERER } from "./renderers/index.js";
|
|
18
19
|
import { riskHints } from "./risk-hints.js";
|
|
19
20
|
import { useShallow } from "zustand/react/shallow";
|
|
21
|
+
import { focusAfterDecision, singleKey } from "../../lib/single-key.js";
|
|
22
|
+
import { KeyCap } from "../layout/key-cap.js";
|
|
20
23
|
import { useActivityStore, spanForTool, childSpans } from "../../stores/activity-store.js";
|
|
21
24
|
import { useUIStore } from "../../stores/ui-store.js";
|
|
22
25
|
import { useNow } from "../../hooks/use-now.js";
|
|
@@ -46,7 +49,8 @@ export function ToolCallTimeline({
|
|
|
46
49
|
live?: boolean;
|
|
47
50
|
}) {
|
|
48
51
|
// Resolution happens below during this render, before effects can run.
|
|
49
|
-
|
|
52
|
+
const root = useBrainUiRoot();
|
|
53
|
+
registerBuiltinRenderers(root.renderers);
|
|
50
54
|
|
|
51
55
|
// Collapse the whole run to a summary row once the turn is over. History
|
|
52
56
|
// messages mount collapsed; a live timeline collapses when streaming ends.
|
|
@@ -108,12 +112,13 @@ function TimelineSummaryRow({
|
|
|
108
112
|
backendId: string;
|
|
109
113
|
onExpand: () => void;
|
|
110
114
|
}) {
|
|
115
|
+
const root = useBrainUiRoot();
|
|
111
116
|
const steps = toolCalls.length;
|
|
112
117
|
const files = new Set(
|
|
113
118
|
toolCalls
|
|
114
119
|
.map(
|
|
115
120
|
(t) =>
|
|
116
|
-
|
|
121
|
+
root.renderers.resolve(t, backendId)?.touchedFile?.(t) ?? getTouchedFile(t)
|
|
117
122
|
)
|
|
118
123
|
.filter(Boolean)
|
|
119
124
|
).size;
|
|
@@ -156,6 +161,7 @@ function ToolCallEntry({
|
|
|
156
161
|
backendId: string;
|
|
157
162
|
onApproval: (toolUseId: string, approved: boolean, always?: boolean) => void;
|
|
158
163
|
}) {
|
|
164
|
+
const root = useBrainUiRoot();
|
|
159
165
|
const [expanded, setExpanded] = useState(
|
|
160
166
|
toolCall.status === "pending_approval"
|
|
161
167
|
);
|
|
@@ -175,13 +181,30 @@ function ToolCallEntry({
|
|
|
175
181
|
: toolCall;
|
|
176
182
|
// Resolve the renderer for this tool (backend-scoped exact -> global exact ->
|
|
177
183
|
// shape-sniffing predicate). Falls back to the generic renderer.
|
|
178
|
-
const renderer =
|
|
184
|
+
const renderer = root.renderers.resolve(toolCall, backendId) ?? GENERIC_RENDERER;
|
|
179
185
|
const Icon = renderer.icon ?? FileText;
|
|
180
186
|
const label =
|
|
181
187
|
typeof renderer.label === "function"
|
|
182
188
|
? renderer.label(toolCall)
|
|
183
189
|
: renderer.label ?? getToolLabel(toolCall.name);
|
|
184
190
|
const isPending = toolCall.status === "pending_approval";
|
|
191
|
+
const keys = useUIStore((s) => s.singleKeyShortcuts);
|
|
192
|
+
/**
|
|
193
|
+
* A decision hands focus on before the card goes (D36): the next pending
|
|
194
|
+
* approval in the transcript, else the composer — the thing the reader
|
|
195
|
+
* continues with, since a chat has no empty-state heading to land on.
|
|
196
|
+
*/
|
|
197
|
+
function decide(card: HTMLElement | null, approved: boolean, always?: boolean) {
|
|
198
|
+
if (card) focusAfterDecision(card, "[data-approval-card]", "textarea[data-composer]");
|
|
199
|
+
onApproval(toolCall.id, approved, always);
|
|
200
|
+
}
|
|
201
|
+
function onCardKeyDown(event: KeyboardEvent<HTMLDivElement>) {
|
|
202
|
+
if (!keys) return;
|
|
203
|
+
const key = singleKey(event);
|
|
204
|
+
if (key !== "a" && key !== "d") return;
|
|
205
|
+
event.preventDefault();
|
|
206
|
+
decide(event.currentTarget, key === "a");
|
|
207
|
+
}
|
|
185
208
|
const summary = renderer.summary?.(timed) ?? null;
|
|
186
209
|
const meta = renderer.meta?.(timed) ?? null;
|
|
187
210
|
const Input = renderer.Input;
|
|
@@ -204,17 +227,18 @@ function ToolCallEntry({
|
|
|
204
227
|
|
|
205
228
|
return (
|
|
206
229
|
<div className="relative">
|
|
207
|
-
{/* Timeline dot
|
|
230
|
+
{/* Timeline dot: a bare mark with no content, so it takes the MARK
|
|
231
|
+
weight — a fill sits at 1.3-1.8:1 on paper at any diameter. */}
|
|
208
232
|
<div
|
|
209
233
|
className={cn(
|
|
210
234
|
"absolute -left-[21px] top-2 h-2.5 w-2.5 rounded-full border-2 border-background",
|
|
211
|
-
toolCall.status === "streaming" && "bg-primary animate-pulse",
|
|
235
|
+
toolCall.status === "streaming" && "bg-primary-mark animate-pulse",
|
|
212
236
|
toolCall.status === "pending_approval" &&
|
|
213
|
-
"bg-primary",
|
|
214
|
-
toolCall.status === "approved" && "bg-accent",
|
|
215
|
-
toolCall.status === "denied" && "bg-destructive",
|
|
237
|
+
"bg-primary-mark",
|
|
238
|
+
toolCall.status === "approved" && "bg-accent-mark",
|
|
239
|
+
toolCall.status === "denied" && "bg-destructive-mark",
|
|
216
240
|
toolCall.status === "complete" &&
|
|
217
|
-
(toolCall.isError ? "bg-destructive" : "bg-accent"),
|
|
241
|
+
(toolCall.isError ? "bg-destructive-mark" : "bg-accent-mark"),
|
|
218
242
|
!["streaming", "pending_approval", "approved", "denied", "complete"].includes(toolCall.status) && "bg-muted-foreground"
|
|
219
243
|
)}
|
|
220
244
|
style={
|
|
@@ -275,7 +299,7 @@ function ToolCallEntry({
|
|
|
275
299
|
className={cn(
|
|
276
300
|
"mt-1 rounded-lg p-3 space-y-2",
|
|
277
301
|
isPending
|
|
278
|
-
? "border-2 border-primary/40 bg-primary/5"
|
|
302
|
+
? "border-2 border-primary/40 bg-primary-fill/5"
|
|
279
303
|
: "border border-border-subtle bg-surface"
|
|
280
304
|
)}
|
|
281
305
|
>
|
|
@@ -291,30 +315,42 @@ function ToolCallEntry({
|
|
|
291
315
|
requests — a destructive-command confirmation (kind
|
|
292
316
|
"command") stays per-use. */}
|
|
293
317
|
{isPending && (
|
|
294
|
-
|
|
318
|
+
// The card is the focus scope for `a` / `d` (D36): the keys
|
|
319
|
+
// act only while it, or a button inside it, holds focus, and
|
|
320
|
+
// they are printed on the buttons they belong to.
|
|
321
|
+
<div
|
|
322
|
+
data-approval-card=""
|
|
323
|
+
role="group"
|
|
324
|
+
aria-label={`Approval: ${label}`}
|
|
325
|
+
tabIndex={0}
|
|
326
|
+
onKeyDown={onCardKeyDown}
|
|
327
|
+
className="flex flex-wrap gap-2 rounded-md outline-none focus-visible:ring-2 focus-visible:ring-primary/50"
|
|
328
|
+
>
|
|
295
329
|
<button
|
|
296
|
-
onClick={() =>
|
|
297
|
-
className="flex items-center gap-1.5 rounded-lg bg-primary px-4 py-1.5 text-xs font-medium text-primary-foreground transition-colors hover:brightness-110"
|
|
330
|
+
onClick={(e) => decide(e.currentTarget.closest("[data-approval-card]"), true)}
|
|
331
|
+
className="flex items-center gap-1.5 rounded-lg bg-primary-fill px-4 py-1.5 text-xs font-medium text-primary-foreground transition-colors hover:brightness-110"
|
|
298
332
|
>
|
|
299
333
|
<Check className="h-3 w-3" />
|
|
300
334
|
Allow
|
|
335
|
+
{keys && <KeyCap>a</KeyCap>}
|
|
301
336
|
</button>
|
|
302
337
|
{toolCall.approvalKind !== "command" && (
|
|
303
338
|
<button
|
|
304
|
-
onClick={() =>
|
|
339
|
+
onClick={(e) => decide(e.currentTarget.closest("[data-approval-card]"), true, true)}
|
|
305
340
|
title={`Allow ${toolCall.name} without asking from now on (revocable in Settings → Models)`}
|
|
306
|
-
className="flex items-center gap-1.5 rounded-lg border border-primary/40 px-4 py-1.5 text-xs font-medium text-primary transition-colors hover:bg-primary/10"
|
|
341
|
+
className="flex items-center gap-1.5 rounded-lg border border-primary/40 px-4 py-1.5 text-xs font-medium text-primary transition-colors hover:bg-primary-fill/10"
|
|
307
342
|
>
|
|
308
343
|
<Check className="h-3 w-3" />
|
|
309
344
|
Always allow
|
|
310
345
|
</button>
|
|
311
346
|
)}
|
|
312
347
|
<button
|
|
313
|
-
onClick={() =>
|
|
314
|
-
className="flex items-center gap-1.5 rounded-lg border border-destructive/30 px-4 py-1.5 text-xs font-medium text-destructive transition-colors hover:bg-destructive/10"
|
|
348
|
+
onClick={(e) => decide(e.currentTarget.closest("[data-approval-card]"), false)}
|
|
349
|
+
className="flex items-center gap-1.5 rounded-lg border border-destructive/30 px-4 py-1.5 text-xs font-medium text-destructive transition-colors hover:bg-destructive-fill/10"
|
|
315
350
|
>
|
|
316
351
|
<X className="h-3 w-3" />
|
|
317
352
|
Deny
|
|
353
|
+
{keys && <KeyCap>d</KeyCap>}
|
|
318
354
|
</button>
|
|
319
355
|
</div>
|
|
320
356
|
)}
|
|
@@ -389,7 +425,7 @@ function RiskHints({
|
|
|
389
425
|
const hints = riskHints(toolCall, semantics);
|
|
390
426
|
if (hints.length === 0) return null;
|
|
391
427
|
return (
|
|
392
|
-
<div className="space-y-0.5 text-[11px] text-
|
|
428
|
+
<div className="space-y-0.5 text-[11px] text-primary">
|
|
393
429
|
{hints.map((hint) => (
|
|
394
430
|
<div key={hint} className="flex items-center gap-1.5">
|
|
395
431
|
<AlertTriangle className="h-3 w-3 shrink-0" />
|
|
@@ -410,11 +446,11 @@ function StatusIndicator({
|
|
|
410
446
|
switch (status) {
|
|
411
447
|
case "streaming":
|
|
412
448
|
return (
|
|
413
|
-
<span className="inline-block h-1.5 w-1.5 animate-pulse rounded-full bg-primary" />
|
|
449
|
+
<span className="inline-block h-1.5 w-1.5 animate-pulse rounded-full bg-primary-mark" />
|
|
414
450
|
);
|
|
415
451
|
case "pending_approval":
|
|
416
452
|
return (
|
|
417
|
-
<span className="rounded bg-primary/20 px-1.5 py-0.5 text-[10px] font-medium text-primary">
|
|
453
|
+
<span className="rounded bg-primary-fill/20 px-1.5 py-0.5 text-[10px] font-medium text-primary">
|
|
418
454
|
Approval needed
|
|
419
455
|
</span>
|
|
420
456
|
);
|
|
@@ -430,3 +466,4 @@ function StatusIndicator({
|
|
|
430
466
|
);
|
|
431
467
|
}
|
|
432
468
|
}
|
|
469
|
+
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `show_block` result: one of the kit's answer blocks, drawn inline (D41).
|
|
3
|
+
*
|
|
4
|
+
* A switch typed by the contract's payload, handing each variant to its kit
|
|
5
|
+
* component. That typing is the drift check the contract promised: a schema
|
|
6
|
+
* field the kit does not accept fails here, and the kit's own tone unions are
|
|
7
|
+
* asserted equal to the schema's lists in `tests/block-contract.test-d.ts`.
|
|
8
|
+
*
|
|
9
|
+
* Icons come from the model as strings; the kit's `Icon` renders an empty
|
|
10
|
+
* box for a key it does not know, so unknown keys are dropped before the
|
|
11
|
+
* prop is handed on. Optional TEXT props are the other translation: the kit
|
|
12
|
+
* ports the design's demo defaults, so a `QuoteCard` with no `source` names
|
|
13
|
+
* a forecast from the Odysseus fixture world and a `ContactCard` with no
|
|
14
|
+
* `label` is Penelope, and omitted `facts` or `ticks` draw a demo list. Each
|
|
15
|
+
* of those components honours an empty string or an empty array as
|
|
16
|
+
* "cleared", so an omitted field is handed on as `""` or `[]` rather than
|
|
17
|
+
* `undefined`. Everything else is passed through untouched: the schema
|
|
18
|
+
* already rejected what the kit cannot draw.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
BarList,
|
|
23
|
+
ComparisonTable,
|
|
24
|
+
ContactCard,
|
|
25
|
+
DataTable,
|
|
26
|
+
ICONS,
|
|
27
|
+
QuoteCard,
|
|
28
|
+
Receipt,
|
|
29
|
+
ScheduleList,
|
|
30
|
+
StatTiles,
|
|
31
|
+
StepList,
|
|
32
|
+
TimelineList,
|
|
33
|
+
TrendChart,
|
|
34
|
+
type IconName,
|
|
35
|
+
} from "@schlessera/brain-ui-kit";
|
|
36
|
+
import type { Block, ShowBlockPayload } from "@schlessera/brain-ui-sdk/client";
|
|
37
|
+
|
|
38
|
+
/** A kit icon key, or nothing when the model named one the kit lacks. */
|
|
39
|
+
export function kitIcon(name: string | undefined): IconName | undefined {
|
|
40
|
+
// An own-property check: `"constructor" in ICONS` is true through the
|
|
41
|
+
// prototype, and the kit would then try to render a function that is not
|
|
42
|
+
// a component.
|
|
43
|
+
return name !== undefined && Object.hasOwn(ICONS, name) ? (name as IconName) : undefined;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** An omitted optional text prop, cleared rather than left to the kit's demo default. */
|
|
47
|
+
const text = (value: string | undefined): string => value ?? "";
|
|
48
|
+
|
|
49
|
+
/** The collapsed one-liner for the trace: `comparison · 3 columns · 4 rows`. */
|
|
50
|
+
export function blockSummary({ block }: ShowBlockPayload): string {
|
|
51
|
+
const count = (n: number, noun: string) => `${n} ${noun}${n === 1 ? "" : "s"}`;
|
|
52
|
+
switch (block.kind) {
|
|
53
|
+
case "comparison":
|
|
54
|
+
return `comparison · ${count(block.columns.length, "column")} · ${count(block.rows.length, "row")}`;
|
|
55
|
+
case "stats":
|
|
56
|
+
return `stats · ${count(block.tiles.length, "tile")}`;
|
|
57
|
+
case "trend":
|
|
58
|
+
return `trend · ${block.label ?? block.value ?? count(block.values.length, "point")}`;
|
|
59
|
+
case "table":
|
|
60
|
+
return `table · ${count(block.columns.length, "column")} · ${count(block.rows.length, "row")}`;
|
|
61
|
+
case "bars":
|
|
62
|
+
return `bars · ${count(block.rows.length, "row")}`;
|
|
63
|
+
case "receipt":
|
|
64
|
+
return `receipt · ${block.title ?? count(block.rows.length, "row")}`;
|
|
65
|
+
case "steps":
|
|
66
|
+
return `steps · ${count(block.steps.length, "step")}`;
|
|
67
|
+
case "timeline":
|
|
68
|
+
return `timeline · ${count(block.items.length, "event")}`;
|
|
69
|
+
case "schedule":
|
|
70
|
+
return `schedule · ${count(block.groups.length, "day")}`;
|
|
71
|
+
case "quote":
|
|
72
|
+
return `quote · ${block.source ?? "unattributed"}`;
|
|
73
|
+
case "contact":
|
|
74
|
+
return `contact · ${block.label}`;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function BlockView({ block }: { block: Block }) {
|
|
79
|
+
switch (block.kind) {
|
|
80
|
+
case "comparison": {
|
|
81
|
+
const { kind: _kind, footnote, ...props } = block;
|
|
82
|
+
return <ComparisonTable {...props} footnote={text(footnote)} />;
|
|
83
|
+
}
|
|
84
|
+
case "stats":
|
|
85
|
+
return (
|
|
86
|
+
<StatTiles
|
|
87
|
+
tiles={block.tiles.map((tile) => ({ ...tile, icon: kitIcon(tile.icon) }))}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
case "trend": {
|
|
91
|
+
const { kind: _kind, label, value, ticks, ...props } = block;
|
|
92
|
+
return <TrendChart {...props} label={text(label)} value={text(value)} ticks={ticks ?? []} />;
|
|
93
|
+
}
|
|
94
|
+
case "table": {
|
|
95
|
+
const { kind: _kind, ...props } = block;
|
|
96
|
+
return <DataTable {...props} />;
|
|
97
|
+
}
|
|
98
|
+
case "bars":
|
|
99
|
+
return <BarList rows={block.rows} />;
|
|
100
|
+
case "receipt": {
|
|
101
|
+
const { kind: _kind, title, titleIcon, footnote, ...props } = block;
|
|
102
|
+
return (
|
|
103
|
+
<Receipt
|
|
104
|
+
{...props}
|
|
105
|
+
title={text(title)}
|
|
106
|
+
titleIcon={kitIcon(titleIcon)}
|
|
107
|
+
footnote={text(footnote)}
|
|
108
|
+
/>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
case "steps": {
|
|
112
|
+
const { kind: _kind, ...props } = block;
|
|
113
|
+
return <StepList {...props} />;
|
|
114
|
+
}
|
|
115
|
+
case "timeline":
|
|
116
|
+
return <TimelineList items={block.items} />;
|
|
117
|
+
case "schedule":
|
|
118
|
+
return <ScheduleList groups={block.groups} />;
|
|
119
|
+
case "quote": {
|
|
120
|
+
const { kind: _kind, icon, source, locator, note, ...props } = block;
|
|
121
|
+
return (
|
|
122
|
+
<QuoteCard
|
|
123
|
+
{...props}
|
|
124
|
+
source={text(source)}
|
|
125
|
+
locator={text(locator)}
|
|
126
|
+
note={text(note)}
|
|
127
|
+
icon={kitIcon(icon)}
|
|
128
|
+
/>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
case "contact": {
|
|
132
|
+
const { kind: _kind, contactKind, role, facts, ...props } = block;
|
|
133
|
+
return <ContactCard {...props} kind={contactKind} role={text(role)} facts={facts ?? []} />;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Bound to `SHOW_BLOCK_CONTRACT`; receives the parsed payload as props. */
|
|
139
|
+
export function BlockCard({ block }: ShowBlockPayload) {
|
|
140
|
+
return (
|
|
141
|
+
<div data-block={block.kind}>
|
|
142
|
+
<BlockView block={block} />
|
|
143
|
+
</div>
|
|
144
|
+
);
|
|
145
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `request_image_mask` result: a receipt, not a path (D38 §2).
|
|
3
|
+
*
|
|
4
|
+
* The source thumb — hatched, as everywhere: no remote image loads inline for
|
|
5
|
+
* the source — stacked ABOVE a kit `Receipt` (the truncation rule: a receipt
|
|
6
|
+
* value column under ~160px means change the layout, not the break rule).
|
|
7
|
+
*
|
|
8
|
+
* Typed `ImageMaskPayload`, so the rows are the fields the handler actually
|
|
9
|
+
* sends: `imagePath`, `maskPath`, `bytes`. The design also draws a region and
|
|
10
|
+
* a coverage row; the payload carries neither. The seventh drop's ruling 8
|
|
11
|
+
* settles what happens then: **state the absence**. The receipt's `region`
|
|
12
|
+
* row reads "region not recorded", in gold, rather than disappearing — a
|
|
13
|
+
* load-bearing fact that vanishes cannot be told apart from a whole-image
|
|
14
|
+
* mask, and a later answer citing that receipt would be citing a gap. A
|
|
15
|
+
* caller that does supply a region (the view test) gets the figures.
|
|
16
|
+
*
|
|
17
|
+
* And the mask itself is DRAWN over the thumb whenever its bytes exist: the
|
|
18
|
+
* PNG the handler wrote is fetched from the files API and laid over the
|
|
19
|
+
* hatch, with the teal region fill beneath it so the transparent (editable)
|
|
20
|
+
* pixels show as the user's answer. When the bytes do not exist the thumb
|
|
21
|
+
* shows the source alone with a mono line saying the mask was not rendered.
|
|
22
|
+
*
|
|
23
|
+
* Failure is a fact about the evidence, not a dialog: a declined or failed
|
|
24
|
+
* mask comes back as a tool error with a message, and `ImageMaskFallback`
|
|
25
|
+
* states it in a red boxed mono `Callout` from the result's own words.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { useState, type CSSProperties } from "react";
|
|
29
|
+
import { Callout, Receipt, Surface, color, font, type ReceiptRow } from "@schlessera/brain-ui-kit";
|
|
30
|
+
import type { ImageMaskPayload, ToolCallView } from "@schlessera/brain-ui-sdk/client";
|
|
31
|
+
import { useBrainUiRoot } from "../../../root-context.js";
|
|
32
|
+
import { ClampedPre } from "../tool-views.js";
|
|
33
|
+
|
|
34
|
+
/** A normalised rectangle over the source image: every value in 0..1. */
|
|
35
|
+
export interface MaskRegion {
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
w: number;
|
|
39
|
+
h: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const THUMB_W = 160;
|
|
43
|
+
const THUMB_H = 100;
|
|
44
|
+
|
|
45
|
+
export const REGION_NOT_RECORDED = "region not recorded";
|
|
46
|
+
export const MASK_NOT_RENDERED = "mask not rendered";
|
|
47
|
+
|
|
48
|
+
/** The kit's image placeholder: raised stripes on the surface, no pixels. */
|
|
49
|
+
const HATCH = `repeating-linear-gradient(135deg,${color.raised} 0 6px,var(--bk-hatch-stripe) 6px 12px)`;
|
|
50
|
+
|
|
51
|
+
function bytesLabel(bytes: number): string {
|
|
52
|
+
if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
53
|
+
if (bytes >= 1024) return `${Math.round(bytes / 1024)} KB`;
|
|
54
|
+
return `${bytes} B`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** The mask file exists with content: the handler reports the PNG's byte length. */
|
|
58
|
+
export function hasMaskBytes(payload: Pick<ImageMaskPayload, "bytes">): boolean {
|
|
59
|
+
return typeof payload.bytes === "number" && payload.bytes > 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The thumb: the hatched source, the drawn region when a caller has one, and
|
|
64
|
+
* the mask image over both when `maskUrl` is given. Exported for the view
|
|
65
|
+
* test; the bound card computes `maskUrl` from the payload.
|
|
66
|
+
*/
|
|
67
|
+
export function MaskThumb({
|
|
68
|
+
region,
|
|
69
|
+
label,
|
|
70
|
+
maskUrl,
|
|
71
|
+
maskShown,
|
|
72
|
+
onMaskLoad,
|
|
73
|
+
onMaskError,
|
|
74
|
+
}: {
|
|
75
|
+
region?: MaskRegion;
|
|
76
|
+
label: string;
|
|
77
|
+
maskUrl?: string;
|
|
78
|
+
/** The teal fill sits under the mask only once the PNG has loaded: until
|
|
79
|
+
* then, or after a failure, a full teal frame would read as a whole-image
|
|
80
|
+
* mask that was never drawn. */
|
|
81
|
+
maskShown?: boolean;
|
|
82
|
+
onMaskLoad?: () => void;
|
|
83
|
+
onMaskError?: () => void;
|
|
84
|
+
}) {
|
|
85
|
+
const frame: CSSProperties = {
|
|
86
|
+
position: "relative",
|
|
87
|
+
width: "100%",
|
|
88
|
+
maxWidth: THUMB_W * 2,
|
|
89
|
+
aspectRatio: `${THUMB_W} / ${THUMB_H}`,
|
|
90
|
+
borderRadius: 9,
|
|
91
|
+
border: `1px solid ${color.edge}`,
|
|
92
|
+
background: HATCH,
|
|
93
|
+
overflow: "hidden",
|
|
94
|
+
};
|
|
95
|
+
const drawn: CSSProperties | undefined = region
|
|
96
|
+
? {
|
|
97
|
+
position: "absolute",
|
|
98
|
+
left: `${region.x * 100}%`,
|
|
99
|
+
top: `${region.y * 100}%`,
|
|
100
|
+
width: `${region.w * 100}%`,
|
|
101
|
+
height: `${region.h * 100}%`,
|
|
102
|
+
border: "1.5px dashed var(--bk-teal-ink)",
|
|
103
|
+
background: "var(--bk-mask-region-fill)",
|
|
104
|
+
borderRadius: 3,
|
|
105
|
+
boxSizing: "border-box",
|
|
106
|
+
}
|
|
107
|
+
: undefined;
|
|
108
|
+
// The teal fill sits under the mask: where the PNG is transparent — the
|
|
109
|
+
// editable region, the user's own answer — the teal shows through.
|
|
110
|
+
const fill: CSSProperties = { position: "absolute", inset: 0, background: "var(--bk-mask-region-fill)" };
|
|
111
|
+
const overlay: CSSProperties = {
|
|
112
|
+
position: "absolute",
|
|
113
|
+
inset: 0,
|
|
114
|
+
width: "100%",
|
|
115
|
+
height: "100%",
|
|
116
|
+
objectFit: "contain",
|
|
117
|
+
};
|
|
118
|
+
return (
|
|
119
|
+
<div role="img" aria-label={label} style={frame} data-mask-thumb>
|
|
120
|
+
{drawn ? <div style={drawn} data-mask-region /> : null}
|
|
121
|
+
{maskUrl ? (
|
|
122
|
+
<>
|
|
123
|
+
{maskShown ? <div style={fill} aria-hidden="true" /> : null}
|
|
124
|
+
<img
|
|
125
|
+
src={maskUrl}
|
|
126
|
+
alt=""
|
|
127
|
+
style={{ ...overlay, visibility: maskShown ? "visible" : "hidden" }}
|
|
128
|
+
data-mask-overlay
|
|
129
|
+
data-mask-shown={maskShown ? "" : undefined}
|
|
130
|
+
onLoad={onMaskLoad}
|
|
131
|
+
onError={onMaskError}
|
|
132
|
+
/>
|
|
133
|
+
</>
|
|
134
|
+
) : null}
|
|
135
|
+
</div>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** The rows the receipt prints. The region row is always there: figures when
|
|
140
|
+
* a caller has them, the stated absence when the payload carries none. */
|
|
141
|
+
export function maskReceiptRows(payload: ImageMaskPayload, region?: MaskRegion): ReceiptRow[] {
|
|
142
|
+
const rows: ReceiptRow[] = [];
|
|
143
|
+
if (region) {
|
|
144
|
+
rows.push({
|
|
145
|
+
k: "region",
|
|
146
|
+
v: `${pct(region.x)},${pct(region.y)} → ${pct(region.x + region.w)},${pct(region.y + region.h)}`,
|
|
147
|
+
tone: "teal",
|
|
148
|
+
});
|
|
149
|
+
rows.push({ k: "covers", v: `${pct(region.w * region.h)} of the image`, tone: "teal" });
|
|
150
|
+
} else {
|
|
151
|
+
rows.push({ k: "region", v: REGION_NOT_RECORDED, tone: "gold" });
|
|
152
|
+
}
|
|
153
|
+
rows.push({ k: "source", v: payload.imagePath });
|
|
154
|
+
rows.push({ k: "mask", v: `${payload.maskPath} · ${bytesLabel(payload.bytes)}` });
|
|
155
|
+
return rows;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function pct(fraction: number): string {
|
|
159
|
+
return `${Math.round(fraction * 100)}%`;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function ImageMaskResultCard(payload: ImageMaskPayload & { region?: MaskRegion }) {
|
|
163
|
+
const root = useBrainUiRoot();
|
|
164
|
+
const region = payload.region;
|
|
165
|
+
const hasBytes = hasMaskBytes(payload);
|
|
166
|
+
const maskUrl = hasBytes
|
|
167
|
+
? `${root.apiBase()}/files/content?path=${encodeURIComponent(payload.maskPath)}&raw=1`
|
|
168
|
+
: undefined;
|
|
169
|
+
// The bytes say a mask was written; only the browser can say it loaded.
|
|
170
|
+
// A file gone since, or a path the raw route refuses, must not leave a
|
|
171
|
+
// full teal frame standing in for a mask nobody can see.
|
|
172
|
+
const [maskState, setMaskState] = useState<"loading" | "shown" | "failed">("loading");
|
|
173
|
+
const rendered = hasBytes && maskState === "shown";
|
|
174
|
+
const note: CSSProperties = { font: `400 10.5px/1.5 ${font.mono}`, color: color.inkMute };
|
|
175
|
+
return (
|
|
176
|
+
<Surface tone="teal" label="Mask drawn" labelIcon="confirm" meta="by you" pad={12}>
|
|
177
|
+
<div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
|
|
178
|
+
<MaskThumb
|
|
179
|
+
region={region}
|
|
180
|
+
maskUrl={maskUrl}
|
|
181
|
+
maskShown={rendered}
|
|
182
|
+
onMaskLoad={() => setMaskState("shown")}
|
|
183
|
+
onMaskError={() => setMaskState("failed")}
|
|
184
|
+
label={
|
|
185
|
+
rendered
|
|
186
|
+
? `Mask ${payload.maskPath} over the source ${payload.imagePath}`
|
|
187
|
+
: `Source ${payload.imagePath}; the mask is in ${payload.maskPath}`
|
|
188
|
+
}
|
|
189
|
+
/>
|
|
190
|
+
{!hasBytes || maskState === "failed" ? <div style={note}>{MASK_NOT_RENDERED}</div> : null}
|
|
191
|
+
<Receipt keyWidth={58} rows={maskReceiptRows(payload, region)} />
|
|
192
|
+
</div>
|
|
193
|
+
</Surface>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* No payload: the user declined, the editor failed, or an older server
|
|
199
|
+
* answered with a sentence. An error is stated as a fact in red; anything
|
|
200
|
+
* else is shown as the text it is.
|
|
201
|
+
*/
|
|
202
|
+
export function ImageMaskFallback({ tool }: { tool: ToolCallView }) {
|
|
203
|
+
if (!tool.output) return null;
|
|
204
|
+
if (!tool.isError) return <ClampedPre text={tool.output} />;
|
|
205
|
+
const source = typeof tool.input.imagePath === "string" ? tool.input.imagePath : null;
|
|
206
|
+
return (
|
|
207
|
+
<Callout
|
|
208
|
+
tone="red"
|
|
209
|
+
variant="boxed"
|
|
210
|
+
mono
|
|
211
|
+
text={`no mask drawn${source ? ` on ${source}` : ""} · ${tool.output.trim()}`}
|
|
212
|
+
/>
|
|
213
|
+
);
|
|
214
|
+
}
|