@schlessera/brain-ui-react 0.35.0 → 0.37.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 +82 -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 +148 -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 +29 -0
- package/dist/components/activity/approval-card.d.ts.map +1 -0
- package/dist/components/activity/approval-card.js +73 -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 +11 -0
- package/dist/components/activity/span-bits.d.ts.map +1 -1
- package/dist/components/activity/span-bits.js +50 -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 +27 -11
- 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 +32 -32
- 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 +45 -14
- 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 +19 -2
- package/dist/components/chat/tool-views.d.ts.map +1 -1
- package/dist/components/chat/tool-views.js +28 -22
- 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 +27 -21
- 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 +4 -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 +28 -0
- package/dist/components/layout/side-rail.d.ts.map +1 -1
- package/dist/components/layout/side-rail.js +72 -27
- package/dist/components/layout/side-rail.js.map +1 -1
- package/dist/components/layout/slide-panel.d.ts +25 -2
- package/dist/components/layout/slide-panel.d.ts.map +1 -1
- package/dist/components/layout/slide-panel.js +13 -4
- 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 +32 -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 +23 -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 +8 -5
- 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 +53 -18
- 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 +51 -10
- package/dist/components/quick-actions/whatsup-modal.js.map +1 -1
- package/dist/components/settings/devices-agents-tab.d.ts +6 -1
- package/dist/components/settings/devices-agents-tab.d.ts.map +1 -1
- package/dist/components/settings/devices-agents-tab.js +55 -20
- package/dist/components/settings/devices-agents-tab.js.map +1 -1
- 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.js +1 -1
- package/dist/components/settings/one-time-agent-credential.js.map +1 -1
- 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 +71 -10
- 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-fine-pointer.d.ts +12 -0
- package/dist/hooks/use-fine-pointer.d.ts.map +1 -0
- package/dist/hooks/use-fine-pointer.js +15 -0
- package/dist/hooks/use-fine-pointer.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 +9 -0
- package/dist/hooks/use-media-query.d.ts.map +1 -0
- package/dist/hooks/use-media-query.js +38 -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.map +1 -1
- package/dist/hooks/use-vpn-status.js +17 -18
- 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 -384
- 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 +28 -6
- 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 +289 -0
- package/dist/lib/api-client.d.ts.map +1 -1
- package/dist/lib/api-client.js +243 -224
- 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/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 +4 -1
- package/dist/lib/push-registration.d.ts.map +1 -1
- package/dist/lib/push-registration.js +20 -2
- package/dist/lib/push-registration.js.map +1 -1
- 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 +233 -0
- package/dist/stores/chat-state.d.ts.map +1 -0
- package/dist/stores/chat-state.js +477 -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 -336
- 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 +4 -15
- package/dist/stores/principal-store.d.ts.map +1 -1
- package/dist/stores/principal-store.js +7 -28
- package/dist/stores/principal-store.js.map +1 -1
- 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 +341 -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 +117 -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 +60 -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 +41 -11
- 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 +41 -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 +75 -26
- 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 +30 -60
- 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 +32 -24
- 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 +5 -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 +77 -150
- package/src/components/layout/slide-panel.tsx +49 -6
- package/src/components/layout/theme.tsx +67 -0
- package/src/components/quick-actions/add-form.tsx +196 -0
- package/src/components/quick-actions/add-modal.tsx +32 -153
- package/src/components/quick-actions/search-modal.tsx +15 -5
- package/src/components/quick-actions/streaming-modal.tsx +57 -72
- package/src/components/quick-actions/streaming-output.tsx +112 -0
- package/src/components/quick-actions/whatsup-modal.tsx +53 -59
- package/src/components/settings/devices-agents-tab.tsx +60 -152
- 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 +1 -1
- 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 +239 -25
- 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-fine-pointer.ts +15 -0
- package/src/hooks/use-hash-routes.ts +4 -2
- package/src/hooks/use-media-query.ts +35 -0
- package/src/hooks/use-share-intake.ts +32 -12
- package/src/hooks/use-vpn-status.ts +18 -17
- package/src/hooks/use-websocket.ts +12 -428
- package/src/hooks/websocket-handlers/activity.ts +4 -5
- package/src/hooks/websocket-handlers/chat.ts +28 -6
- 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 +426 -384
- package/src/lib/backend.ts +20 -10
- package/src/lib/diff.ts +28 -62
- 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 +19 -2
- 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 +822 -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 -390
- 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 +10 -37
- 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,9 +1,9 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
|
-
import { AlertTriangle, Newspaper, X } from "lucide-react";
|
|
3
2
|
|
|
4
|
-
import {
|
|
3
|
+
import type { ActivityDigest } from "../../lib/api-client.js";
|
|
4
|
+
import { useBrainApi } from "../../root-context.js";
|
|
5
5
|
import { useUIStore } from "../../stores/ui-store.js";
|
|
6
|
-
import {
|
|
6
|
+
import { DigestSummary } from "./digest-summary.js";
|
|
7
7
|
import { digestCostClause } from "./span-bits.js";
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -13,17 +13,24 @@ import { digestCostClause } from "./span-bits.js";
|
|
|
13
13
|
* dismissing persists server-side, so a phone and a laptop don't each nag.
|
|
14
14
|
* An empty window stays quiet — no card for "nothing happened". The window
|
|
15
15
|
* is labeled: the card says what period it covers, never implies "now".
|
|
16
|
+
*
|
|
17
|
+
* This is the container (S7): the fetch, the once-per-digest rule and the
|
|
18
|
+
* dismissal live here; `DigestSummary` draws the kit `DigestCard`.
|
|
16
19
|
*/
|
|
17
20
|
export function DigestCard() {
|
|
21
|
+
const api = useBrainApi();
|
|
18
22
|
const [digest, setDigest] = useState<ActivityDigest | null>(null);
|
|
19
23
|
const [visible, setVisible] = useState(false);
|
|
20
24
|
const setActiveView = useUIStore((s) => s.setActiveView);
|
|
21
25
|
|
|
22
26
|
useEffect(() => {
|
|
27
|
+
let active = true;
|
|
28
|
+
setDigest(null);
|
|
29
|
+
setVisible(false);
|
|
23
30
|
void api
|
|
24
31
|
.activityDigest()
|
|
25
32
|
.then(({ digest, dismissedAt }) => {
|
|
26
|
-
if (!digest || digest.runs === 0) return;
|
|
33
|
+
if (!active || !digest || digest.runs === 0) return;
|
|
27
34
|
if (digest.generatedAt <= dismissedAt) return;
|
|
28
35
|
setDigest(digest);
|
|
29
36
|
setVisible(true);
|
|
@@ -31,7 +38,8 @@ export function DigestCard() {
|
|
|
31
38
|
.catch(() => {
|
|
32
39
|
// No digest is a quiet state, never an error surface.
|
|
33
40
|
});
|
|
34
|
-
|
|
41
|
+
return () => { active = false; };
|
|
42
|
+
}, [api]);
|
|
35
43
|
|
|
36
44
|
if (!visible || !digest) return null;
|
|
37
45
|
|
|
@@ -40,63 +48,19 @@ export function DigestCard() {
|
|
|
40
48
|
void api.activityDigestDismiss().catch(() => {});
|
|
41
49
|
}
|
|
42
50
|
|
|
43
|
-
const windowLabel = `${formatDay(digest.windowStart)} – ${formatDay(digest.windowEnd)}`;
|
|
44
|
-
// Effective-only spend clause; a digest persisted before pricing shipped
|
|
45
|
-
// falls back to its old list-cost clause inside the helper.
|
|
46
|
-
const costClause = digestCostClause(digest);
|
|
47
|
-
|
|
48
51
|
return (
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
<button
|
|
62
|
-
type="button"
|
|
63
|
-
onClick={dismiss}
|
|
64
|
-
className="ml-auto rounded p-1 text-muted-foreground transition-colors hover:text-foreground"
|
|
65
|
-
aria-label="Dismiss"
|
|
66
|
-
>
|
|
67
|
-
<X className="h-3.5 w-3.5" />
|
|
68
|
-
</button>
|
|
69
|
-
</div>
|
|
70
|
-
<div className="mt-1.5 text-muted-foreground">
|
|
71
|
-
{digest.runs} run{digest.runs === 1 ? "" : "s"}
|
|
72
|
-
{digest.failures > 0 && (
|
|
73
|
-
<span className="text-destructive"> · {digest.failures} failed</span>
|
|
74
|
-
)}
|
|
75
|
-
{costClause && ` · ${costClause}`}
|
|
76
|
-
</div>
|
|
77
|
-
{digest.notable.length > 0 && (
|
|
78
|
-
<div className="mt-1.5 space-y-0.5">
|
|
79
|
-
{digest.notable.slice(0, 3).map((n) => (
|
|
80
|
-
<div key={n.runId} className="flex items-center gap-1.5 text-[11px]">
|
|
81
|
-
<AlertTriangle className="h-3 w-3 shrink-0 text-destructive" />
|
|
82
|
-
<span className="truncate">
|
|
83
|
-
{n.jobName ?? n.name} — {n.outcome}
|
|
84
|
-
</span>
|
|
85
|
-
</div>
|
|
86
|
-
))}
|
|
87
|
-
</div>
|
|
88
|
-
)}
|
|
89
|
-
<button
|
|
90
|
-
type="button"
|
|
91
|
-
onClick={() => {
|
|
92
|
-
dismiss();
|
|
93
|
-
setActiveView("activity");
|
|
94
|
-
}}
|
|
95
|
-
className="mt-2 text-[11px] font-medium text-primary hover:underline"
|
|
96
|
-
>
|
|
97
|
-
Open Activity
|
|
98
|
-
</button>
|
|
99
|
-
</div>
|
|
52
|
+
<DigestSummary
|
|
53
|
+
digest={digest}
|
|
54
|
+
windowLabel={`${formatDay(digest.windowStart)} – ${formatDay(digest.windowEnd)}`}
|
|
55
|
+
// Effective-only spend clause; a digest persisted before pricing shipped
|
|
56
|
+
// falls back to its old list-cost clause inside the helper.
|
|
57
|
+
costClause={digestCostClause(digest)}
|
|
58
|
+
onDismiss={dismiss}
|
|
59
|
+
onOpen={() => {
|
|
60
|
+
dismiss();
|
|
61
|
+
setActiveView("activity");
|
|
62
|
+
}}
|
|
63
|
+
/>
|
|
100
64
|
);
|
|
101
65
|
}
|
|
102
66
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Button, DigestCard } from "@schlessera/brain-ui-kit";
|
|
2
|
+
import type { DigestGroup } from "@schlessera/brain-ui-kit";
|
|
3
|
+
import type { ActivityDigest } from "../../lib/api-client.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The while-you-were-away card as the design draws it: the kit `DigestCard`
|
|
7
|
+
* — "the briefing as one chat block, ordered settled → needs-you so it can
|
|
8
|
+
* be abandoned halfway" — with the app's two actions under it. Rendered from
|
|
9
|
+
* props (S7); `DigestCard` in `digest-card.tsx` is the container.
|
|
10
|
+
*
|
|
11
|
+
* The kit card does no arithmetic, so the counts arrive as strings; the
|
|
12
|
+
* notable runs (failures, at most three) are the one group that needs you.
|
|
13
|
+
*/
|
|
14
|
+
export interface DigestSummaryProps {
|
|
15
|
+
digest: ActivityDigest;
|
|
16
|
+
windowLabel: string;
|
|
17
|
+
costClause: string | null;
|
|
18
|
+
onDismiss: () => void;
|
|
19
|
+
onOpen: () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function DigestSummary(p: DigestSummaryProps) {
|
|
23
|
+
const d = p.digest;
|
|
24
|
+
const runs = `${d.runs} run${d.runs === 1 ? "" : "s"}`;
|
|
25
|
+
const groups: DigestGroup[] = [
|
|
26
|
+
{ label: "Ran", icon: "agent", tone: "teal", count: String(d.runs), items: [{ text: p.windowLabel, meta: p.costClause ?? undefined }] },
|
|
27
|
+
];
|
|
28
|
+
if (d.failures > 0) {
|
|
29
|
+
groups.push({
|
|
30
|
+
label: "Failed",
|
|
31
|
+
icon: "failed",
|
|
32
|
+
tone: "red",
|
|
33
|
+
count: String(d.failures),
|
|
34
|
+
items: d.notable.slice(0, 3).map((n) => ({ text: n.jobName ?? n.name, meta: n.outcome ?? undefined })),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return (
|
|
38
|
+
<div className="mx-auto mb-3 w-full max-w-2xl">
|
|
39
|
+
<DigestCard
|
|
40
|
+
title="While you were away"
|
|
41
|
+
subtitle={`${p.windowLabel} · ${runs}${d.failures > 0 ? ` · ${d.failures} failed` : ""}`}
|
|
42
|
+
spend={p.costClause ?? ""}
|
|
43
|
+
groups={groups}
|
|
44
|
+
footnote=""
|
|
45
|
+
/>
|
|
46
|
+
<div className="mt-2 flex justify-end gap-2">
|
|
47
|
+
<Button label="Dismiss" tone="quiet" size="sm" block={false} onClick={p.onDismiss} />
|
|
48
|
+
<Button label="Open Actions" icon="resolved" tone="primary" size="sm" block={false} onClick={p.onOpen} />
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Toggle } from "@schlessera/brain-ui-kit";
|
|
2
|
+
import { BellOff } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* What push looks like — nothing about how it is obtained. `PushToggle` is
|
|
6
|
+
* the container that owns the browser permission, the service worker, the
|
|
7
|
+
* server binding and every cancellation guard; this is the S6 split of its
|
|
8
|
+
* presentation into a view that renders from props alone.
|
|
9
|
+
*
|
|
10
|
+
* The permission model is THREE-state, not a bare switch: once the browser
|
|
11
|
+
* prompt is denied, Chrome silently ignores every further in-page request,
|
|
12
|
+
* so `blocked` says where the real switch lives instead of drawing one that
|
|
13
|
+
* does nothing. Where the platform has no push at all (an in-browser iOS
|
|
14
|
+
* tab), `unsupported` explains rather than hides.
|
|
15
|
+
*
|
|
16
|
+
* The switch is the kit's `Toggle`, named "Push notifications" — the name is
|
|
17
|
+
* what it switches, `aria-checked` is its state, and `disabled` is the
|
|
18
|
+
* subscription mid-flight (the design's fourth state, kept as a named switch
|
|
19
|
+
* rather than a vanished one).
|
|
20
|
+
*/
|
|
21
|
+
export type PushState = "unsupported" | "not-asked" | "blocked" | "subscribed" | "unsubscribed";
|
|
22
|
+
|
|
23
|
+
export interface PushSwitchProps {
|
|
24
|
+
state: PushState;
|
|
25
|
+
busy: boolean;
|
|
26
|
+
onToggle: () => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function PushSwitch({ state, busy, onToggle }: PushSwitchProps) {
|
|
30
|
+
if (state === "unsupported") {
|
|
31
|
+
return (
|
|
32
|
+
<div
|
|
33
|
+
className="flex items-center gap-1.5 text-[11px] text-muted-foreground/60"
|
|
34
|
+
title="This browser has no web push. On iOS, install the app to the home screen (iOS 16.4+)."
|
|
35
|
+
>
|
|
36
|
+
<BellOff className="h-3.5 w-3.5" />
|
|
37
|
+
No push here
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
if (state === "blocked") {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
className="flex items-center gap-1.5 text-[11px] text-muted-foreground"
|
|
45
|
+
title="Notifications are blocked at the browser level. Allow them in this site's browser settings, then reload."
|
|
46
|
+
>
|
|
47
|
+
<BellOff className="h-3.5 w-3.5 text-destructive" />
|
|
48
|
+
Blocked in browser settings
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
const on = state === "subscribed";
|
|
53
|
+
return (
|
|
54
|
+
<label
|
|
55
|
+
className="flex items-center gap-2 text-[11px] text-muted-foreground"
|
|
56
|
+
title={on ? "Push notifications are on for this device" : "Get a push notification when background work fails"}
|
|
57
|
+
>
|
|
58
|
+
<span>{on ? "Push on" : "Push"}</span>
|
|
59
|
+
<Toggle on={on} tone="amber" label="Push notifications" disabled={busy} onClick={onToggle} />
|
|
60
|
+
</label>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
@@ -1,38 +1,30 @@
|
|
|
1
|
-
import { useEffect, useState } from "react";
|
|
2
|
-
import { Bell, BellOff } from "lucide-react";
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
2
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { useBrainUiRoot } from "../../root-context.js";
|
|
4
|
+
import { subscriptionMatchesKey } from "../../lib/push-registration.js";
|
|
5
|
+
import { PushSwitch, type PushState } from "./push-switch.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* The push enable/disable
|
|
9
|
-
* alerts it governs land).
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* nothing. Where the platform has no push at all (iOS Safari in-browser,
|
|
14
|
-
* pre-16.4), the control renders disabled-with-explanation, not hidden.
|
|
8
|
+
* The push enable/disable CONTAINER, living on the Activity surface (where
|
|
9
|
+
* the alerts it governs land). It owns the browser permission, the service
|
|
10
|
+
* worker subscription, the server binding, and the lifetime guards that keep
|
|
11
|
+
* a late response from a superseded root or an unmounted panel from acting;
|
|
12
|
+
* `PushSwitch` owns what it looks like (S6). Nothing here renders markup.
|
|
15
13
|
*/
|
|
16
|
-
/** The subscription's bound applicationServerKey, in the base64url form the
|
|
17
|
-
* server hands out — comparable against `pushPublicKey()` directly. */
|
|
18
|
-
function keyToBase64Url(key: ArrayBuffer): string {
|
|
19
|
-
let bin = "";
|
|
20
|
-
for (const b of new Uint8Array(key)) bin += String.fromCharCode(b);
|
|
21
|
-
return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
type PushState =
|
|
25
|
-
| "unsupported"
|
|
26
|
-
| "not-asked"
|
|
27
|
-
| "blocked"
|
|
28
|
-
| "subscribed"
|
|
29
|
-
| "unsubscribed";
|
|
30
14
|
|
|
31
15
|
export function PushToggle() {
|
|
16
|
+
const root = useBrainUiRoot();
|
|
17
|
+
const api = root.api;
|
|
18
|
+
const lifetime = useRef(new AbortController());
|
|
32
19
|
const [state, setState] = useState<PushState>("unsupported");
|
|
33
20
|
const [busy, setBusy] = useState(false);
|
|
34
21
|
|
|
35
22
|
useEffect(() => {
|
|
23
|
+
const controller = new AbortController();
|
|
24
|
+
const signal = controller.signal;
|
|
25
|
+
lifetime.current = controller;
|
|
26
|
+
setState("unsupported");
|
|
27
|
+
setBusy(false);
|
|
36
28
|
void (async () => {
|
|
37
29
|
if (!("Notification" in window) || !("serviceWorker" in navigator) || !("PushManager" in window)) {
|
|
38
30
|
setState("unsupported");
|
|
@@ -47,20 +39,16 @@ export function PushToggle() {
|
|
|
47
39
|
return;
|
|
48
40
|
}
|
|
49
41
|
const registration = await navigator.serviceWorker.ready;
|
|
42
|
+
if (signal.aborted) return;
|
|
50
43
|
const subscription = await registration.pushManager.getSubscription();
|
|
44
|
+
if (signal.aborted) return;
|
|
51
45
|
if (subscription) {
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
// row (a dead-endpoint send, a DB restore) — healed by re-asserting,
|
|
55
|
-
// an idempotent upsert; or the server's VAPID keypair changed, which
|
|
56
|
-
// makes this subscription permanently unsendable — its
|
|
57
|
-
// applicationServerKey no longer matches, so drop it and surface the
|
|
58
|
-
// re-enable button. Offline, trust the browser's own state.
|
|
46
|
+
// Heal a lost server-side binding, but do not delete a browser
|
|
47
|
+
// subscription merely because this UI displays a different server.
|
|
59
48
|
try {
|
|
60
49
|
const { publicKey } = await api.pushPublicKey();
|
|
61
|
-
|
|
62
|
-
if (
|
|
63
|
-
await subscription.unsubscribe().catch(() => {});
|
|
50
|
+
if (signal.aborted) return;
|
|
51
|
+
if (!subscriptionMatchesKey(subscription, publicKey)) {
|
|
64
52
|
setState("unsubscribed");
|
|
65
53
|
return;
|
|
66
54
|
}
|
|
@@ -69,14 +57,17 @@ export function PushToggle() {
|
|
|
69
57
|
// Server unreachable — keep the browser's answer.
|
|
70
58
|
}
|
|
71
59
|
}
|
|
72
|
-
setState(subscription ? "subscribed" : "unsubscribed");
|
|
73
|
-
})();
|
|
74
|
-
|
|
60
|
+
if (!signal.aborted) setState(subscription ? "subscribed" : "unsubscribed");
|
|
61
|
+
})().catch(() => { if (!signal.aborted) setState("unsubscribed"); });
|
|
62
|
+
return () => controller.abort();
|
|
63
|
+
}, [root, api]);
|
|
75
64
|
|
|
76
65
|
async function enable() {
|
|
66
|
+
const signal = lifetime.current.signal;
|
|
77
67
|
setBusy(true);
|
|
78
68
|
try {
|
|
79
69
|
const permission = await Notification.requestPermission();
|
|
70
|
+
if (signal.aborted) return;
|
|
80
71
|
if (permission === "denied") {
|
|
81
72
|
setState("blocked");
|
|
82
73
|
return;
|
|
@@ -86,72 +77,51 @@ export function PushToggle() {
|
|
|
86
77
|
return;
|
|
87
78
|
}
|
|
88
79
|
const { publicKey } = await api.pushPublicKey();
|
|
80
|
+
if (signal.aborted) return;
|
|
89
81
|
const registration = await navigator.serviceWorker.ready;
|
|
82
|
+
if (signal.aborted) return;
|
|
83
|
+
const existing = await registration.pushManager.getSubscription();
|
|
84
|
+
if (signal.aborted) return;
|
|
85
|
+
// Key rotation (or switching servers) is an explicit user action.
|
|
86
|
+
if (existing && !subscriptionMatchesKey(existing, publicKey)) {
|
|
87
|
+
await existing.unsubscribe();
|
|
88
|
+
if (signal.aborted) return;
|
|
89
|
+
}
|
|
90
90
|
const subscription = await registration.pushManager.subscribe({
|
|
91
91
|
userVisibleOnly: true,
|
|
92
92
|
applicationServerKey: publicKey,
|
|
93
93
|
});
|
|
94
|
+
if (signal.aborted) return;
|
|
94
95
|
await api.pushSubscribe(subscription.toJSON(), navigator.userAgent.slice(0, 100));
|
|
95
|
-
setState("subscribed");
|
|
96
|
+
if (!signal.aborted) setState("subscribed");
|
|
96
97
|
} catch {
|
|
97
|
-
setState("unsubscribed");
|
|
98
|
+
if (!signal.aborted) setState("unsubscribed");
|
|
98
99
|
} finally {
|
|
99
|
-
setBusy(false);
|
|
100
|
+
if (!signal.aborted) setBusy(false);
|
|
100
101
|
}
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
async function disable() {
|
|
105
|
+
const signal = lifetime.current.signal;
|
|
104
106
|
setBusy(true);
|
|
105
107
|
try {
|
|
106
108
|
const registration = await navigator.serviceWorker.ready;
|
|
109
|
+
if (signal.aborted) return;
|
|
107
110
|
const subscription = await registration.pushManager.getSubscription();
|
|
111
|
+
if (signal.aborted) return;
|
|
108
112
|
if (subscription) {
|
|
109
113
|
await api.pushUnsubscribe(subscription.endpoint).catch(() => {});
|
|
114
|
+
if (signal.aborted) return;
|
|
110
115
|
await subscription.unsubscribe();
|
|
111
116
|
}
|
|
112
|
-
setState("unsubscribed");
|
|
117
|
+
if (!signal.aborted) setState("unsubscribed");
|
|
118
|
+
} catch {
|
|
119
|
+
// Preserve the current state when the browser rejects an unsubscribe.
|
|
113
120
|
} finally {
|
|
114
|
-
setBusy(false);
|
|
121
|
+
if (!signal.aborted) setBusy(false);
|
|
115
122
|
}
|
|
116
123
|
}
|
|
117
124
|
|
|
118
|
-
if (state === "unsupported") {
|
|
119
|
-
return (
|
|
120
|
-
<div className="flex items-center gap-1.5 text-[11px] text-muted-foreground/60" title="This browser has no web push. On iOS, install the app to the home screen (iOS 16.4+).">
|
|
121
|
-
<BellOff className="h-3.5 w-3.5" />
|
|
122
|
-
No push here
|
|
123
|
-
</div>
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (state === "blocked") {
|
|
128
|
-
return (
|
|
129
|
-
<div
|
|
130
|
-
className="flex items-center gap-1.5 text-[11px] text-muted-foreground"
|
|
131
|
-
title="Notifications are blocked at the browser level. Allow them in this site's browser settings, then reload."
|
|
132
|
-
>
|
|
133
|
-
<BellOff className="h-3.5 w-3.5 text-destructive" />
|
|
134
|
-
Blocked in browser settings
|
|
135
|
-
</div>
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
125
|
const on = state === "subscribed";
|
|
140
|
-
return (
|
|
141
|
-
<button
|
|
142
|
-
type="button"
|
|
143
|
-
disabled={busy}
|
|
144
|
-
onClick={() => void (on ? disable() : enable())}
|
|
145
|
-
className={cn(
|
|
146
|
-
"flex items-center gap-1.5 rounded-md px-2 py-1 text-[11px] transition-colors disabled:opacity-50",
|
|
147
|
-
on
|
|
148
|
-
? "text-primary hover:bg-surface-raised"
|
|
149
|
-
: "text-muted-foreground hover:bg-surface-raised hover:text-foreground"
|
|
150
|
-
)}
|
|
151
|
-
title={on ? "Push notifications are on for this device" : "Get a push notification when background work fails"}
|
|
152
|
-
>
|
|
153
|
-
{on ? <Bell className="h-3.5 w-3.5" /> : <BellOff className="h-3.5 w-3.5" />}
|
|
154
|
-
{on ? "Push on" : "Enable push"}
|
|
155
|
-
</button>
|
|
156
|
-
);
|
|
126
|
+
return <PushSwitch state={state} busy={busy} onToggle={() => void (on ? disable() : enable())} />;
|
|
157
127
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useBrainUiRoot } from "../../root-context.js";
|
|
1
2
|
import { useEffect } from "react";
|
|
2
3
|
import { useShallow } from "zustand/react/shallow";
|
|
3
4
|
import { isFailureOutcome, SPAN_TOOL_NAME_PREFIX } from "@schlessera/brain-ui-sdk/protocol";
|
|
@@ -11,7 +12,6 @@ import type {
|
|
|
11
12
|
import {
|
|
12
13
|
useActivityStore,
|
|
13
14
|
payloadEventsFor,
|
|
14
|
-
loadSpanPayloads,
|
|
15
15
|
} from "../../stores/activity-store.js";
|
|
16
16
|
import { cn } from "../../lib/utils.js";
|
|
17
17
|
import { getToolLabel, formatTokenCount } from "../chat/tool-views.js";
|
|
@@ -42,11 +42,11 @@ export function SpanStatusDot({
|
|
|
42
42
|
className={cn(
|
|
43
43
|
"h-1.5 w-1.5 shrink-0 rounded-full",
|
|
44
44
|
isRunning
|
|
45
|
-
? "animate-pulse bg-primary"
|
|
45
|
+
? "animate-pulse bg-primary-mark"
|
|
46
46
|
: resolved === "success"
|
|
47
|
-
? "bg-accent"
|
|
47
|
+
? "bg-accent-mark"
|
|
48
48
|
: isFailureOutcome(resolved) || resolved === "denied"
|
|
49
|
-
? "bg-destructive"
|
|
49
|
+
? "bg-destructive-mark"
|
|
50
50
|
: "bg-muted-foreground",
|
|
51
51
|
className
|
|
52
52
|
)}
|
|
@@ -80,13 +80,14 @@ export function spanToolLabel(span: ActivitySpan): string {
|
|
|
80
80
|
* the wire `truncated` flag, rendered as a hint line under the block.
|
|
81
81
|
*/
|
|
82
82
|
export function SpanPayload({ spanId }: { spanId: string }) {
|
|
83
|
+
const root = useBrainUiRoot();
|
|
83
84
|
const events = useActivityStore(useShallow((s) => payloadEventsFor(s, spanId)));
|
|
84
85
|
// History fetches skip payload bodies (they exist for duration badges);
|
|
85
86
|
// the first expand of a finished run backfills them over REST. A no-op for
|
|
86
87
|
// live runs (payloads ride the WS deltas) and once per run thereafter.
|
|
87
88
|
useEffect(() => {
|
|
88
|
-
if (events.length === 0) void loadSpanPayloads(spanId);
|
|
89
|
-
}, [spanId, events.length]);
|
|
89
|
+
if (events.length === 0) void root.stores.activity.loadSpanPayloads(spanId);
|
|
90
|
+
}, [spanId, events.length, root]);
|
|
90
91
|
if (events.length === 0) {
|
|
91
92
|
return (
|
|
92
93
|
<p className="px-2 py-1 text-[11px] text-muted-foreground/60">
|
|
@@ -116,12 +117,64 @@ export function eventTypeLabel(eventType: string): string {
|
|
|
116
117
|
return eventType.replace(/_/g, " ");
|
|
117
118
|
}
|
|
118
119
|
|
|
120
|
+
// Maps, not object literals: a stored payload is untrusted, and indexing a
|
|
121
|
+
// literal with "toString" or "__proto__" finds Object.prototype, not a miss.
|
|
122
|
+
const DECISION_TEXT = new Map([
|
|
123
|
+
["allow", "Allowed"],
|
|
124
|
+
["always_allow", "Always allowed"],
|
|
125
|
+
["deny", "Denied"],
|
|
126
|
+
]);
|
|
127
|
+
const CHANNEL_TEXT = new Map([
|
|
128
|
+
["card", "on the card"],
|
|
129
|
+
["voice", "by voice"],
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* An `approval_decision` event as a sentence: what was decided and, when the
|
|
134
|
+
* client said, the channel it was decided on (#113) — "who said yes and how"
|
|
135
|
+
* is the question the record exists to answer. A decision recorded without a
|
|
136
|
+
* channel reads as the decision alone rather than guessing one. Anything
|
|
137
|
+
* this does not recognise returns null and falls back to the raw block.
|
|
138
|
+
*/
|
|
139
|
+
export function readApprovalDecision(
|
|
140
|
+
payload: unknown
|
|
141
|
+
): { text: string; facts: string | null } | null {
|
|
142
|
+
if (!payload || typeof payload !== "object") return null;
|
|
143
|
+
const p = payload as Record<string, unknown>;
|
|
144
|
+
const decision = typeof p.decision === "string" ? DECISION_TEXT.get(p.decision) : undefined;
|
|
145
|
+
if (!decision) return null;
|
|
146
|
+
const channel = typeof p.channel === "string" ? CHANNEL_TEXT.get(p.channel) : undefined;
|
|
147
|
+
if (p.channel !== undefined && !channel) return null;
|
|
148
|
+
const facts = [
|
|
149
|
+
typeof p.principalId === "string" ? `principal ${p.principalId}` : null,
|
|
150
|
+
p.requestKind === "command" ? "command confirmation" : null,
|
|
151
|
+
].filter(Boolean);
|
|
152
|
+
return {
|
|
153
|
+
text: channel ? `${decision} ${channel}` : decision,
|
|
154
|
+
facts: facts.length > 0 ? facts.join(" · ") : null,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
119
158
|
/**
|
|
120
159
|
* ONE labelled block per recorded event — the shared renderer behind the tool
|
|
121
160
|
* payload expander and the run detail's narrative stream, so every event type
|
|
122
161
|
* lands somewhere visible instead of only the two the expander knows.
|
|
123
162
|
*/
|
|
124
163
|
export function SpanEventBlock({ event }: { event: ActivitySpanEvent }) {
|
|
164
|
+
const approval = event.eventType === "approval_decision" ? readApprovalDecision(event.payload) : null;
|
|
165
|
+
if (approval) {
|
|
166
|
+
return (
|
|
167
|
+
<div>
|
|
168
|
+
<div className="mb-0.5 text-[10px] uppercase text-muted-foreground/60">Approval</div>
|
|
169
|
+
<p data-testid="approval-decision" className="text-[11px] text-foreground">
|
|
170
|
+
{approval.text}
|
|
171
|
+
</p>
|
|
172
|
+
{approval.facts && (
|
|
173
|
+
<p className="text-[10px] text-muted-foreground/60">{approval.facts}</p>
|
|
174
|
+
)}
|
|
175
|
+
</div>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
125
178
|
const text =
|
|
126
179
|
typeof event.payload === "string" ? event.payload : JSON.stringify(event.payload, null, 2);
|
|
127
180
|
return (
|
|
@@ -241,7 +294,7 @@ export function CountBadge({ count, className }: { count: number; className?: st
|
|
|
241
294
|
return (
|
|
242
295
|
<span
|
|
243
296
|
className={cn(
|
|
244
|
-
"absolute flex h-4 min-w-4 items-center justify-center rounded-full bg-destructive px-1 text-[9px] font-semibold text-
|
|
297
|
+
"absolute flex h-4 min-w-4 items-center justify-center rounded-full bg-destructive-fill px-1 text-[9px] font-semibold text-primary-foreground",
|
|
245
298
|
className
|
|
246
299
|
)}
|
|
247
300
|
>
|