gloomberb 0.16.4 → 0.16.6
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 +14 -91
- package/package.json +5 -1
- package/src/{plugins/builtin/cloud → account}/auth-form.tsx +9 -9
- package/src/{plugins/builtin/cloud → account}/auth-model.ts +4 -4
- package/src/account/billing.ts +57 -0
- package/src/{plugins/builtin/cloud → account}/device-signin-dialog.tsx +18 -12
- package/src/{plugins/builtin/cloud → account}/device-signin.ts +2 -2
- package/src/{plugins/builtin/cloud → account}/email-auth-attempt.ts +2 -2
- package/src/account/session.ts +16 -0
- package/src/{plugins/builtin/cloud → account}/upgrade-dialog.tsx +16 -15
- package/src/{plugins/builtin/cloud → account}/upgrade-personalization.ts +7 -7
- package/src/{plugins/builtin/cloud → account}/upgrade-tickers.ts +6 -6
- package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
- package/src/api-client/central-bank-rates.ts +6 -1
- package/src/api-client/chat.ts +26 -0
- package/src/api-client/credit-boards.ts +2 -0
- package/src/api-client/data.ts +73 -3
- package/src/api-client/earnings.ts +6 -0
- package/src/api-client/europe-energy.ts +106 -0
- package/src/api-client/futures-curve.ts +56 -0
- package/src/api-client/index.ts +13 -1
- package/src/api-client/market-discovery.ts +13 -1
- package/src/api-client/normalizers.ts +32 -0
- package/src/api-client/paths.ts +7 -0
- package/src/api-client/perps.ts +8 -0
- package/src/api-client/request.ts +9 -2
- package/src/api-client/research-activity.ts +15 -10
- package/src/api-client/socket.ts +29 -0
- package/src/api-client/themes.ts +22 -1
- package/src/api-client/types.ts +78 -2
- package/src/api-client/yield-curves.ts +8 -0
- package/src/app/global-shortcuts.ts +50 -2
- package/src/app/keybindings/actions.ts +12 -1
- package/src/app/pane-runtime/plugin-bindings.ts +2 -2
- package/src/app/pane-runtime/ticker-open-runtime.ts +16 -6
- package/src/app/runtime/desktop-deeplink.ts +10 -5
- package/src/app/runtime/startup.ts +1 -1
- package/src/app.tsx +6 -0
- package/src/architecture/core-builtin-allowlist.json +8 -26
- package/src/ask-gloom/pane-context.ts +114 -0
- package/src/ask-gloom/pane-request.ts +70 -0
- package/src/ask-gloom/pane-text.ts +201 -0
- package/src/brokers/signed-in/sign-in-dialog.tsx +11 -5
- package/src/capabilities/chart-series.ts +19 -2
- package/src/capabilities/factories.ts +1 -0
- package/src/cli/central-bank-events.ts +23 -0
- package/src/cli/command-options.ts +17 -5
- package/src/cli/commands/crypto-hints.ts +35 -2
- package/src/cli/commands/fred-series.ts +146 -0
- package/src/cli/commands/market.ts +501 -115
- package/src/cli/commands/news-hints.ts +62 -0
- package/src/cli/commands/news-search.ts +53 -0
- package/src/cli/commands/options-leaps.ts +5 -2
- package/src/cli/commands/overview.ts +132 -26
- package/src/cli/commands/remote.ts +2 -1
- package/src/cli/commands/search.ts +317 -13
- package/src/cli/commands/system.ts +55 -8
- package/src/cli/commands/ticker.ts +155 -18
- package/src/cli/context.ts +45 -14
- package/src/cli/desktop-pane-shot.ts +76 -7
- package/src/cli/earnings-calendar.ts +71 -0
- package/src/cli/errors.ts +7 -5
- package/src/cli/exit-codes.ts +8 -0
- package/src/cli/export-source.ts +58 -0
- package/src/cli/freshness.ts +18 -7
- package/src/cli/glossary.ts +483 -0
- package/src/cli/help.ts +10 -0
- package/src/cli/helpers.ts +2 -5
- package/src/cli/history-rows.ts +118 -7
- package/src/cli/index-roots.ts +7 -0
- package/src/cli/index.ts +29 -9
- package/src/cli/known-gaps.ts +84 -0
- package/src/cli/listing-arg.ts +551 -97
- package/src/cli/not-a-ticker.ts +24 -9
- package/src/cli/pane-functions/access-gate.ts +13 -2
- package/src/cli/pane-functions/capabilities.ts +4 -3
- package/src/cli/pane-functions/catalog.ts +214 -40
- package/src/cli/pane-functions/data.ts +42 -8
- package/src/cli/pane-functions/discovery.ts +1 -0
- package/src/cli/pane-functions/dom.ts +37 -8
- package/src/cli/pane-functions/freshness.ts +393 -49
- package/src/cli/pane-functions/function-help.ts +31 -15
- package/src/cli/pane-functions/headless.ts +98 -30
- package/src/cli/pane-functions/index.ts +101 -19
- package/src/cli/pane-functions/market-session.ts +22 -8
- package/src/cli/pane-functions/options.ts +71 -22
- package/src/cli/pane-functions/report-notices.ts +25 -7
- package/src/cli/pane-functions/report.ts +15 -8
- package/src/cli/pane-functions/resolver.ts +74 -19
- package/src/cli/pane-functions/screenshot.ts +250 -27
- package/src/cli/perpetual-contract.ts +60 -0
- package/src/cli/registry.ts +3 -1
- package/src/cli/report-tables.ts +26 -7
- package/src/cli/result.ts +45 -11
- package/src/cli/series-search.ts +111 -0
- package/src/cli/staged-tickers.ts +52 -0
- package/src/cli/symbol-args.ts +27 -0
- package/src/cli/symbol-list.ts +154 -0
- package/src/cli/symbol-rows.ts +154 -0
- package/src/cli/ticker-resolution.ts +311 -27
- package/src/cli/types.ts +5 -0
- package/src/components/chart/composite/axis-overlays.tsx +14 -3
- package/src/components/chart/composite/composite-chart.tsx +71 -11
- package/src/components/chart/composite/crosshair-readout.tsx +150 -0
- package/src/components/chart/composite/downsample.ts +1 -1
- package/src/components/chart/composite/format.ts +29 -0
- package/src/components/chart/composite/interactions.ts +9 -2
- package/src/components/chart/composite/legend.tsx +100 -33
- package/src/components/chart/composite/panel-bitmap.ts +70 -35
- package/src/components/chart/composite/panel-labels.ts +18 -17
- package/src/components/chart/composite/panel-series.ts +1 -0
- package/src/components/chart/composite/panel-surface.tsx +46 -21
- package/src/components/chart/composite/price-axis-labels.tsx +3 -1
- package/src/components/chart/composite/rasterizer.ts +50 -8
- package/src/components/chart/composite/scene.ts +2 -1
- package/src/components/chart/composite/time-scale.ts +26 -9
- package/src/components/chart/composite/types.ts +18 -0
- package/src/components/chart/composite/use-composite-viewport.ts +30 -2
- package/src/components/chart/native/raster/crosshair.ts +8 -3
- package/src/components/chart/native/raster/primitives.ts +85 -21
- package/src/components/chart/native/surface/manager.ts +33 -8
- package/src/components/chart/surface3d/chart.tsx +1 -1
- package/src/components/command-bar/action-runtime.ts +1 -1
- package/src/components/command-bar/commands/collection-list.ts +210 -0
- package/src/components/command-bar/commands/collection.ts +40 -1
- package/src/components/command-bar/commands/direct/index.ts +4 -0
- package/src/components/command-bar/commands/registry.ts +8 -0
- package/src/components/command-bar/panel/index.tsx +11 -3
- package/src/components/command-bar/panel/runtime.ts +3 -0
- package/src/components/command-bar/panel/types.ts +2 -0
- package/src/components/command-bar/routes/root/plugin-install.ts +4 -4
- package/src/components/command-bar/routes/root/provider-search.ts +4 -3
- package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
- package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
- package/src/components/command-bar/routing/actions.ts +1 -1
- package/src/components/command-bar/workflow/tickers.ts +42 -17
- package/src/components/layout/detached-pane-shell.tsx +68 -39
- package/src/components/layout/floating-pane.tsx +10 -1
- package/src/components/layout/header.tsx +25 -5
- package/src/components/layout/missing-pane.tsx +3 -3
- package/src/components/layout/pane/capture-stamp.ts +41 -0
- package/src/components/layout/pane/capture-status.ts +12 -0
- package/src/components/layout/pane/content.tsx +7 -13
- package/src/components/layout/pane/footer/index.tsx +6 -2
- package/src/components/layout/pane/footer/keyboard.ts +3 -0
- package/src/components/layout/pane/footer/model.ts +41 -1
- package/src/components/layout/pane/header.tsx +50 -1
- package/src/components/layout/pane/index.tsx +21 -3
- package/src/components/layout/pane/sidebar.tsx +88 -21
- package/src/components/layout/shell/active-drag.ts +21 -5
- package/src/components/layout/shell/cursor-occlusion.ts +2 -1
- package/src/components/layout/shell/drag/index.ts +39 -9
- package/src/components/layout/shell/drag/live.ts +61 -51
- package/src/components/layout/shell/drag/runtime.ts +54 -12
- package/src/components/layout/shell/index.tsx +84 -65
- package/src/components/layout/shell/menu.ts +14 -1
- package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
- package/src/components/layout/shell/pane/actions.ts +32 -10
- package/src/components/layout/shell/pane/ask.ts +131 -0
- package/src/components/layout/shell/pane/capture.ts +162 -0
- package/src/components/layout/shell/pane/layers.tsx +218 -50
- package/src/components/layout/shell/pane/management-shortcuts.ts +46 -1
- package/src/components/layout/shell/shortcuts.ts +21 -4
- package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
- package/src/components/markdown-text.tsx +62 -20
- package/src/components/metric-treemap/heat-surface.tsx +8 -1
- package/src/components/onboarding/account-step/form-panel.tsx +1 -1
- package/src/components/onboarding/account-step/index.tsx +1 -1
- package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
- package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
- package/src/components/onboarding/onboarding-keyboard.ts +1 -1
- package/src/components/onboarding/onboarding-wizard.tsx +2 -2
- package/src/components/onboarding/use-onboarding-upgrade.ts +3 -3
- package/src/components/onboarding/wizard-account.ts +2 -2
- package/src/components/pane-template-wizard.tsx +9 -1
- package/src/components/price-selector-dialog.tsx +11 -2
- package/src/components/reader/article-reader.tsx +642 -0
- package/src/components/reader/article-text.ts +527 -0
- package/src/components/sign-in-gate.tsx +3 -3
- package/src/components/ticker/list-table-view.tsx +43 -2
- package/src/components/ui/action-row.tsx +2 -1
- package/src/components/ui/button.tsx +7 -1
- package/src/components/ui/choice-dialog.tsx +6 -4
- package/src/components/ui/confirm-dialog.tsx +28 -18
- package/src/components/ui/data-table/index.tsx +18 -6
- package/src/components/ui/data-table/opentui/index.tsx +37 -6
- package/src/components/ui/data-table/types.ts +12 -0
- package/src/components/ui/dialog-actions.tsx +64 -0
- package/src/components/ui/display.tsx +17 -3
- package/src/components/ui/frame.tsx +35 -2
- package/src/components/ui/icon.tsx +6 -1
- package/src/components/ui/query-bar.tsx +10 -1
- package/src/components/ui/text-prompt-dialog.tsx +11 -9
- package/src/data/cached-query.ts +2 -0
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/normalize.ts +7 -2
- package/src/data/config/store/portfolio-as-of-column.ts +57 -0
- package/src/data/ticker-repository.ts +5 -0
- package/src/data/ticker-store.ts +15 -0
- package/src/docs/content.ts +215 -0
- package/src/docs/load.ts +139 -0
- package/src/docs/requests.ts +39 -0
- package/src/docs/snapshot.chunk.ts +8 -0
- package/src/docs/snapshot.json +7555 -0
- package/src/docs/topics.ts +216 -0
- package/src/i18n/es.ts +65 -5
- package/src/i18n/ja.ts +65 -5
- package/src/i18n/ko.ts +65 -5
- package/src/i18n/zh-cn.ts +65 -5
- package/src/i18n/zh-tw.ts +65 -5
- package/src/layout/desks.ts +1 -1
- package/src/layout/pane-manager/dock-tree.ts +18 -0
- package/src/layout/pane-manager/index.ts +1 -0
- package/src/layout-marketplace/gallery.tsx +1 -1
- package/src/market-data/coordinator/chart.ts +10 -4
- package/src/market-data/coordinator/index.ts +6 -3
- package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
- package/src/market-data/futures-contract.ts +151 -0
- package/src/market-data/hooks.tsx +10 -2
- package/src/market-data/market/format.ts +39 -21
- package/src/market-data/market/freshness.ts +84 -20
- package/src/market-data/market/session-close-note.ts +3 -2
- package/src/market-data/market/status.ts +19 -23
- package/src/market-data/published-apac-sessions.ts +23 -1
- package/src/market-data/quotes/contributions.ts +5 -0
- package/src/market-data/quotes/metadata.ts +19 -24
- package/src/market-data/quotes/resolution.ts +5 -0
- package/src/market-data/quotes/screener-live-quotes.ts +5 -4
- package/src/market-data/result-types.ts +2 -0
- package/src/notifications/app-notifier.ts +17 -1
- package/src/notifications/notification-log.ts +180 -0
- package/src/plugins/auto-update-node.ts +2 -2
- package/src/plugins/auto-update.ts +2 -2
- package/src/plugins/builtin/account-management/index.tsx +1 -0
- package/src/plugins/builtin/account-management/model.ts +1 -56
- package/src/plugins/builtin/account-management/pane.tsx +6 -4
- package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
- package/src/plugins/builtin/alerts/catalysts.ts +1 -1
- package/src/plugins/builtin/alerts/cli.ts +313 -47
- package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
- package/src/plugins/builtin/alerts/events.ts +23 -2
- package/src/plugins/builtin/alerts/focus.ts +27 -0
- package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
- package/src/plugins/builtin/alerts/history.ts +2 -0
- package/src/plugins/builtin/alerts/index.tsx +47 -11
- package/src/plugins/builtin/alerts/pane.tsx +27 -1
- package/src/plugins/builtin/alerts/research-builder.ts +8 -3
- package/src/plugins/builtin/alerts/research-rules.ts +18 -2
- package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
- package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
- package/src/plugins/builtin/alerts/scheduled.ts +254 -0
- package/src/plugins/builtin/alerts/targets.ts +92 -0
- package/src/plugins/builtin/analytics/index.tsx +8 -3
- package/src/plugins/builtin/analytics/risk-headless.ts +60 -27
- package/src/plugins/builtin/analytics/risk-math.ts +91 -27
- package/src/plugins/builtin/analytics/risk-model.ts +35 -5
- package/src/plugins/builtin/analytics/risk-pane.tsx +15 -8
- package/src/plugins/builtin/attention/headless.ts +1 -1
- package/src/plugins/builtin/attention/index.tsx +2 -0
- package/src/plugins/builtin/attention/pane.tsx +3 -1
- package/src/plugins/builtin/attention/series.ts +26 -0
- package/src/plugins/builtin/awards/headless.ts +88 -18
- package/src/plugins/builtin/awards/index.tsx +2 -0
- package/src/plugins/builtin/awards/model.ts +41 -1
- package/src/plugins/builtin/awards/pane.tsx +22 -13
- package/src/plugins/builtin/awards/series.ts +29 -0
- package/src/plugins/builtin/backtest/headless.ts +2 -2
- package/src/plugins/builtin/bond-calculator/model.ts +2 -1
- package/src/plugins/builtin/broker-manager/index.tsx +1 -0
- package/src/plugins/builtin/catalysts/headless.ts +1 -1
- package/src/plugins/builtin/catalysts/pane.tsx +3 -1
- package/src/plugins/builtin/cds/client.ts +49 -12
- package/src/plugins/builtin/cds/headless.ts +119 -19
- package/src/plugins/builtin/cds/index.tsx +3 -1
- package/src/plugins/builtin/cds/model.ts +214 -32
- package/src/plugins/builtin/cds/pane.tsx +58 -14
- package/src/plugins/builtin/cds/series.ts +19 -0
- package/src/plugins/builtin/central-bank-rates/client.ts +4 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +46 -16
- package/src/plugins/builtin/central-bank-rates/index.tsx +3 -1
- package/src/plugins/builtin/central-bank-rates/model.ts +99 -0
- package/src/plugins/builtin/central-bank-rates/pane.tsx +1 -1
- package/src/plugins/builtin/central-bank-rates/series.ts +36 -0
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +193 -255
- package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
- package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
- package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
- package/src/plugins/builtin/chart-composer/headless-schema.ts +1 -1
- package/src/plugins/builtin/chart-composer/headless.ts +70 -5
- package/src/plugins/builtin/chart-composer/index.tsx +15 -3
- package/src/plugins/builtin/chart-composer/pane.tsx +81 -38
- package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
- package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
- package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
- package/src/plugins/builtin/chat/content/composer-runtime.ts +6 -1
- package/src/plugins/builtin/chat/content/composer.tsx +5 -1
- package/src/plugins/builtin/chat/content/footer.tsx +12 -0
- package/src/plugins/builtin/chat/content/index.tsx +89 -5
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
- package/src/plugins/builtin/chat/content/new-messages.tsx +89 -0
- package/src/plugins/builtin/chat/content/row-activity.ts +132 -0
- package/src/plugins/builtin/chat/content/scroll.ts +127 -27
- package/src/plugins/builtin/chat/content/shortcuts.ts +2 -2
- package/src/plugins/builtin/chat/content/transcript.tsx +145 -78
- package/src/plugins/builtin/chat/content/types.ts +1 -0
- package/src/plugins/builtin/chat/controller/fetch.ts +8 -2
- package/src/plugins/builtin/chat/controller/index.ts +123 -1
- package/src/plugins/builtin/chat/controller/message-loading.ts +3 -0
- package/src/plugins/builtin/chat/controller/messages.ts +7 -2
- package/src/plugins/builtin/chat/controller/realtime.ts +10 -1
- package/src/plugins/builtin/chat/controller/send.ts +61 -1
- package/src/plugins/builtin/chat/controller/state.ts +8 -0
- package/src/plugins/builtin/chat/ghost-user.ts +20 -0
- package/src/plugins/builtin/chat/index.tsx +23 -5
- package/src/plugins/builtin/chat/layout.ts +78 -5
- package/src/plugins/builtin/chat/message/ai-badge.tsx +18 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +55 -6
- package/src/plugins/builtin/chat/message/header.tsx +16 -4
- package/src/plugins/builtin/chat/message/profile-popover.tsx +5 -1
- package/src/plugins/builtin/chat/message/reactions.tsx +210 -0
- package/src/plugins/builtin/chat/message/render-state.ts +18 -2
- package/src/plugins/builtin/chat/message/terminal.tsx +43 -4
- package/src/plugins/builtin/chat/message/types.ts +12 -0
- package/src/plugins/builtin/chat/reactions.ts +197 -0
- package/src/plugins/builtin/chat/share/flow.tsx +87 -0
- package/src/plugins/builtin/chat/share/targets.ts +27 -0
- package/src/plugins/builtin/chat/status-widget.tsx +6 -3
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +148 -27
- package/src/plugins/builtin/chat/unread-inbox.ts +22 -0
- package/src/plugins/builtin/cloud/askg/attached-pane.tsx +69 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +111 -19
- package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
- package/src/plugins/builtin/cloud/askg/manifest.ts +32 -7
- package/src/plugins/builtin/cloud/askg/model.ts +27 -8
- package/src/plugins/builtin/cloud/askg/pane-attachment.ts +94 -0
- package/src/plugins/builtin/cloud/askg/pane.tsx +141 -12
- package/src/plugins/builtin/cloud/askg/pending-question.ts +11 -0
- package/src/plugins/builtin/cloud/askg/protocol.ts +10 -1
- package/src/plugins/builtin/cloud/askg/tool-display.ts +3 -0
- package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
- package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
- package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
- package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -1
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +3 -0
- package/src/plugins/builtin/cloud/plugin.tsx +19 -2
- package/src/plugins/builtin/cloud/team/model.ts +5 -0
- package/src/plugins/builtin/cloud/team/module.tsx +1 -0
- package/src/plugins/builtin/cloud/team/store.ts +8 -3
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +77 -9
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +6 -1
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +9 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +35 -11
- package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
- package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
- package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
- package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
- package/src/plugins/builtin/company-attention/headless.ts +21 -7
- package/src/plugins/builtin/company-attention/index.tsx +2 -0
- package/src/plugins/builtin/company-attention/model.ts +26 -7
- package/src/plugins/builtin/company-attention/pane.tsx +12 -9
- package/src/plugins/builtin/company-attention/series.ts +52 -0
- package/src/plugins/builtin/company-kpis/headless.ts +97 -10
- package/src/plugins/builtin/company-kpis/model.ts +24 -2
- package/src/plugins/builtin/company-kpis/pane.tsx +17 -16
- package/src/plugins/builtin/composite-plugins.ts +19 -13
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/cot/headless.ts +1 -1
- package/src/plugins/builtin/cot/index.tsx +3 -1
- package/src/plugins/builtin/cot/model.ts +40 -11
- package/src/plugins/builtin/cot/series.ts +27 -0
- package/src/plugins/builtin/cpi/headless.ts +3 -3
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +10 -1
- package/src/plugins/builtin/credit-boards/client.ts +6 -2
- package/src/plugins/builtin/credit-boards/headless.ts +108 -31
- package/src/plugins/builtin/credit-boards/index.tsx +2 -0
- package/src/plugins/builtin/credit-boards/model.ts +11 -1
- package/src/plugins/builtin/credit-boards/series.ts +66 -0
- package/src/plugins/builtin/credit-conditions/client.ts +12 -9
- package/src/plugins/builtin/credit-conditions/headless.ts +13 -2
- package/src/plugins/builtin/credit-conditions/index.tsx +18 -9
- package/src/plugins/builtin/credit-conditions/model.ts +19 -11
- package/src/plugins/builtin/credit-conditions/series.ts +16 -0
- package/src/plugins/builtin/credit-documents/headless.ts +33 -3
- package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
- package/src/plugins/builtin/crypto-board/headless.ts +2 -3
- package/src/plugins/builtin/crypto-board/index.tsx +2 -0
- package/src/plugins/builtin/crypto-board/model.ts +12 -0
- package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
- package/src/plugins/builtin/crypto-board/series.ts +48 -0
- package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
- package/src/plugins/builtin/debt-maturities/headless.ts +17 -11
- package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
- package/src/plugins/builtin/debt-maturities/series.ts +45 -0
- package/src/plugins/builtin/dividend-yield/client.ts +3 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +7 -4
- package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/series.ts +20 -0
- package/src/plugins/builtin/dividend-yield/types.ts +2 -0
- package/src/plugins/builtin/docs/blocks.tsx +181 -0
- package/src/plugins/builtin/docs/index.tsx +68 -0
- package/src/plugins/builtin/docs/pane.tsx +426 -0
- package/src/plugins/builtin/docs/targets.ts +72 -0
- package/src/plugins/builtin/docs/use-docs.ts +60 -0
- package/src/plugins/builtin/doe/headless.ts +12 -8
- package/src/plugins/builtin/doe/index.tsx +2 -0
- package/src/plugins/builtin/doe/series.ts +62 -0
- package/src/plugins/builtin/earnings/client.ts +3 -2
- package/src/plugins/builtin/earnings/format.ts +1 -5
- package/src/plugins/builtin/earnings/headless.ts +58 -6
- package/src/plugins/builtin/earnings/history-model.ts +15 -1
- package/src/plugins/builtin/earnings/history-table.ts +13 -2
- package/src/plugins/builtin/earnings/history.tsx +7 -3
- package/src/plugins/builtin/earnings/index.tsx +9 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +28 -2
- package/src/plugins/builtin/earnings-calls/index.tsx +1 -1
- package/src/plugins/builtin/earnings-ripple/index.tsx +2 -0
- package/src/plugins/builtin/econ/fred-catalog.ts +198 -0
- package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
- package/src/plugins/builtin/econ/index.tsx +2 -0
- package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +19 -4
- package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
- package/src/plugins/builtin/equity-screener/headless.ts +3 -3
- package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
- package/src/plugins/builtin/estimate-revisions/headless.ts +3 -3
- package/src/plugins/builtin/exposure/drivers.ts +13 -0
- package/src/plugins/builtin/exposure/headless.ts +205 -13
- package/src/plugins/builtin/exposure/holdings.ts +1 -1
- package/src/plugins/builtin/exposure/index.tsx +1 -0
- package/src/plugins/builtin/exposure/model.ts +23 -3
- package/src/plugins/builtin/exposure/pane.tsx +14 -12
- package/src/plugins/builtin/fear-greed/index.tsx +18 -10
- package/src/plugins/builtin/fear-greed/series.ts +52 -0
- package/src/plugins/builtin/futures/index.tsx +43 -3
- package/src/plugins/builtin/futures/model.ts +1 -1
- package/src/plugins/builtin/futures/returns.ts +1 -1
- package/src/plugins/builtin/futures/series.ts +13 -0
- package/src/plugins/builtin/futures/table.tsx +1 -1
- package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +71 -10
- package/src/plugins/builtin/futures-curve/index.tsx +1 -1
- package/src/plugins/builtin/futures-curve/model.ts +66 -11
- package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
- package/src/plugins/builtin/fx-matrix/client.ts +63 -0
- package/src/plugins/builtin/fx-matrix/export.ts +2 -1
- package/src/plugins/builtin/fx-matrix/headless.ts +154 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +4 -4
- package/src/plugins/builtin/gpu/board.tsx +13 -10
- package/src/plugins/builtin/gpu/changes.tsx +4 -4
- package/src/plugins/builtin/gpu/client.ts +19 -1
- package/src/plugins/builtin/gpu/equities.tsx +14 -10
- package/src/plugins/builtin/gpu/headless.ts +58 -27
- package/src/plugins/builtin/gpu/history.tsx +3 -3
- package/src/plugins/builtin/gpu/index.tsx +2 -0
- package/src/plugins/builtin/gpu/model.ts +101 -16
- package/src/plugins/builtin/gpu/pane.tsx +28 -12
- package/src/plugins/builtin/gpu/series.ts +38 -0
- package/src/plugins/builtin/help/function-card.tsx +25 -6
- package/src/plugins/builtin/help/function-index.ts +2 -0
- package/src/plugins/builtin/help/index.tsx +31 -9
- package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
- package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
- package/src/plugins/builtin/holders/beneficial-view.tsx +55 -11
- package/src/plugins/builtin/holders/client.ts +22 -3
- package/src/plugins/builtin/holders/format.ts +18 -3
- package/src/plugins/builtin/holders/headless.ts +36 -133
- package/src/plugins/builtin/holders/pane.tsx +11 -4
- package/src/plugins/builtin/holders/report-header.ts +40 -5
- package/src/plugins/builtin/holders/report-rows.ts +240 -0
- package/src/plugins/builtin/insider/client.ts +35 -20
- package/src/plugins/builtin/insider/headless.ts +41 -11
- package/src/plugins/builtin/insider/index.tsx +26 -9
- package/src/plugins/builtin/insider/insider-data.ts +10 -0
- package/src/plugins/builtin/insider/issuer.ts +49 -0
- package/src/plugins/builtin/insider/model.ts +3 -0
- package/src/plugins/builtin/ipo-calendar/headless.ts +1 -1
- package/src/plugins/builtin/iv-history/client.ts +20 -6
- package/src/plugins/builtin/iv-history/format.ts +9 -0
- package/src/plugins/builtin/iv-history/headless.ts +56 -21
- package/src/plugins/builtin/iv-history/index.tsx +2 -0
- package/src/plugins/builtin/iv-history/model.ts +143 -8
- package/src/plugins/builtin/iv-history/screen-pane.tsx +5 -9
- package/src/plugins/builtin/iv-history/series.ts +29 -0
- package/src/plugins/builtin/jobs/headless.ts +26 -3
- package/src/plugins/builtin/jobs/index.tsx +3 -1
- package/src/plugins/builtin/jobs/series.ts +19 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +2 -1
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
- package/src/plugins/builtin/macro-day/client.ts +44 -3
- package/src/plugins/builtin/macro-day/headless.ts +13 -10
- package/src/plugins/builtin/macro-day/model.ts +56 -10
- package/src/plugins/builtin/macro-day/pane.tsx +30 -20
- package/src/plugins/builtin/market-heatmap/headless.ts +20 -5
- package/src/plugins/builtin/market-heatmap/index.tsx +6 -0
- package/src/plugins/builtin/market-heatmap/model.ts +19 -11
- package/src/plugins/builtin/market-heatmap/portfolio.ts +2 -2
- package/src/plugins/builtin/market-movers/client.ts +7 -5
- package/src/plugins/builtin/market-movers/index.tsx +3 -2
- package/src/plugins/builtin/market-movers/model.ts +30 -0
- package/src/plugins/builtin/market-movers/screener.ts +31 -0
- package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
- package/src/plugins/builtin/market-valuation/index.tsx +3 -3
- package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
- package/src/plugins/builtin/members/headless.ts +8 -3
- package/src/plugins/builtin/members/model.ts +31 -3
- package/src/plugins/builtin/members/pane.tsx +6 -8
- package/src/plugins/builtin/mna/distress/headless.ts +4 -4
- package/src/plugins/builtin/mna/headless.ts +18 -6
- package/src/plugins/builtin/money-markets/headless.ts +5 -4
- package/src/plugins/builtin/money-markets/index.tsx +2 -0
- package/src/plugins/builtin/money-markets/series.ts +41 -0
- package/src/plugins/builtin/news/index.tsx +0 -2
- package/src/plugins/builtin/news/wire/news/detail-view.tsx +53 -104
- package/src/plugins/builtin/news/wire/news/footer.ts +2 -25
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +0 -2
- package/src/plugins/builtin/notes/cli.ts +12 -7
- package/src/plugins/builtin/notes/index.tsx +1 -0
- package/src/plugins/builtin/options/index.tsx +3 -0
- package/src/plugins/builtin/options/view.tsx +1 -1
- package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
- package/src/plugins/builtin/options-positioning/client.ts +7 -3
- package/src/plugins/builtin/options-positioning/headless.ts +4 -3
- package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +2 -1
- package/src/plugins/builtin/options-scenario/headless.ts +1 -0
- package/src/plugins/builtin/options-scenario/hedge.ts +2 -1
- package/src/plugins/builtin/perps/client.ts +90 -16
- package/src/plugins/builtin/perps/equity-row.tsx +52 -17
- package/src/plugins/builtin/perps/freshness.ts +66 -0
- package/src/plugins/builtin/perps/headless.ts +47 -32
- package/src/plugins/builtin/perps/index.tsx +23 -4
- package/src/plugins/builtin/perps/list-perpetuals.ts +118 -0
- package/src/plugins/builtin/perps/model.ts +20 -5
- package/src/plugins/builtin/perps/open-market.ts +15 -0
- package/src/plugins/builtin/perps/pane.tsx +76 -20
- package/src/plugins/builtin/perps/series.ts +76 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +1 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +73 -67
- package/src/plugins/builtin/plugin-module.ts +3 -0
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
- package/src/plugins/builtin/portfolio-list/allocation.ts +5 -4
- package/src/plugins/builtin/portfolio-list/cell-version.ts +8 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +161 -0
- package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +384 -74
- package/src/plugins/builtin/portfolio-list/cli/render.ts +437 -71
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +21 -4
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +121 -47
- package/src/plugins/builtin/portfolio-list/column-values.ts +104 -26
- package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
- package/src/plugins/builtin/portfolio-list/headless.ts +84 -18
- package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
- package/src/plugins/builtin/portfolio-list/index.tsx +5 -1
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
- package/src/plugins/builtin/portfolio-list/mutations.ts +2 -9
- package/src/plugins/builtin/portfolio-list/pane/data.ts +5 -1
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +52 -9
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +33 -11
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +21 -1
- package/src/plugins/builtin/portfolio-list/settings.ts +17 -0
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +12 -0
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +9 -4
- package/src/plugins/builtin/portfolio-list/table.tsx +37 -7
- package/src/plugins/builtin/power/client.ts +16 -0
- package/src/plugins/builtin/power/evidence.ts +63 -10
- package/src/plugins/builtin/power/headless.ts +77 -9
- package/src/plugins/builtin/power/index.tsx +28 -3
- package/src/plugins/builtin/power/model.ts +73 -2
- package/src/plugins/builtin/power/pane.tsx +37 -9
- package/src/plugins/builtin/power/prices-client.ts +139 -0
- package/src/plugins/builtin/power/prices-headless.ts +137 -0
- package/src/plugins/builtin/power/prices-model.ts +103 -0
- package/src/plugins/builtin/power/prices.tsx +179 -0
- package/src/plugins/builtin/rate-path/headless.ts +46 -18
- package/src/plugins/builtin/realized-vol/headless.ts +5 -0
- package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +5 -2
- package/src/plugins/builtin/research/event-model.ts +68 -24
- package/src/plugins/builtin/research/events-headless.ts +2 -1
- package/src/plugins/builtin/research/headless.ts +2 -1
- package/src/plugins/builtin/research/index.tsx +2 -0
- package/src/plugins/builtin/research-search/article.ts +65 -0
- package/src/plugins/builtin/research-search/document-view.tsx +33 -215
- package/src/plugins/builtin/research-search/model.ts +0 -9
- package/src/plugins/builtin/research-search/pane.tsx +41 -30
- package/src/plugins/builtin/research-search/snippet.ts +0 -29
- package/src/plugins/builtin/revenue-breakdown/headless.ts +18 -6
- package/src/plugins/builtin/seasonality/client.ts +15 -7
- package/src/plugins/builtin/seasonality/headless.ts +36 -12
- package/src/plugins/builtin/seasonality/index.tsx +2 -2
- package/src/plugins/builtin/seasonality/model.ts +119 -0
- package/src/plugins/builtin/seasonality/pane.tsx +108 -37
- package/src/plugins/builtin/sec/headless.ts +25 -3
- package/src/plugins/builtin/sec/index.tsx +2 -1
- package/src/plugins/builtin/series-inventory.ts +93 -0
- package/src/plugins/builtin/shared/cloud-denied.ts +15 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
- package/src/plugins/builtin/shared/command-tab.ts +30 -12
- package/src/plugins/builtin/shared/earnings-report.ts +55 -0
- package/src/plugins/builtin/shared/fred-points.ts +20 -0
- package/src/plugins/builtin/shared/free-preview.ts +47 -0
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
- package/src/plugins/builtin/shared/open-description.ts +29 -0
- package/src/plugins/builtin/shared/report-freshness.ts +12 -1
- package/src/plugins/builtin/shared/series-warning.ts +5 -0
- package/src/plugins/builtin/shared/volatility/options.ts +4 -1
- package/src/plugins/builtin/short-interest/headless.ts +1 -0
- package/src/plugins/builtin/short-interest/index.tsx +2 -0
- package/src/plugins/builtin/short-interest/series.ts +36 -0
- package/src/plugins/builtin/short-interest/watch-headless.ts +3 -2
- package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
- package/src/plugins/builtin/short-volume/headless.ts +2 -1
- package/src/plugins/builtin/short-volume/index.tsx +2 -0
- package/src/plugins/builtin/short-volume/series.ts +23 -0
- package/src/plugins/builtin/social-mentions/headless.ts +1 -1
- package/src/plugins/builtin/social-mentions/index.tsx +2 -0
- package/src/plugins/builtin/social-mentions/series.ts +23 -0
- package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
- package/src/plugins/builtin/supply-chain/headless.ts +43 -11
- package/src/plugins/builtin/supply-chain/model.ts +13 -0
- package/src/plugins/builtin/supply-chain/pane.tsx +8 -6
- package/src/plugins/builtin/themes/headless.ts +74 -10
- package/src/plugins/builtin/themes/model.ts +71 -4
- package/src/plugins/builtin/themes/pane.tsx +22 -5
- package/src/plugins/builtin/thirteenf/api.ts +1 -0
- package/src/plugins/builtin/thirteenf/data.ts +6 -4
- package/src/plugins/builtin/thirteenf/headless.ts +217 -36
- package/src/plugins/builtin/thirteenf/model.ts +39 -1
- package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
- package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
- package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
- package/src/plugins/builtin/thirteenf/types.ts +2 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +114 -0
- package/src/plugins/builtin/ticker-detail/data-panes/returns-model.ts +57 -2
- package/src/plugins/builtin/ticker-detail/data-panes/returns-pane.tsx +19 -55
- package/src/plugins/builtin/ticker-detail/headless-schema.ts +30 -0
- package/src/plugins/builtin/ticker-detail/headless.ts +86 -0
- package/src/plugins/builtin/ticker-detail/index.tsx +26 -11
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/overview/futures-contract.ts +31 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +3 -3
- package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +49 -5
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
- package/src/plugins/builtin/time-sales/headless.ts +2 -1
- package/src/plugins/builtin/time-sales/index.tsx +2 -1
- package/src/plugins/builtin/treasury-auctions/headless.ts +16 -2
- package/src/plugins/builtin/treasury-auctions/index.tsx +1 -0
- package/src/plugins/builtin/treasury-auctions/model.ts +8 -0
- package/src/plugins/builtin/vol-surface/evidence.ts +7 -1
- package/src/plugins/builtin/vol-surface/headless.ts +51 -17
- package/src/plugins/builtin/vol-surface/heat-grid.tsx +113 -0
- package/src/plugins/builtin/vol-surface/model.ts +39 -6
- package/src/plugins/builtin/vol-surface/pane.tsx +14 -13
- package/src/plugins/builtin/vol-surface/stored.ts +63 -3
- package/src/plugins/builtin/vol-surface/surface.tsx +30 -2
- package/src/plugins/builtin/volatility/index.tsx +2 -0
- package/src/plugins/builtin/volatility/series.ts +84 -0
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +6 -5
- package/src/plugins/builtin/world-venue-map/basemap.ts +6 -3
- package/src/plugins/builtin/world-venue-map/geo-draw.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/geo-series.ts +26 -1
- package/src/plugins/builtin/world-venue-map/geo-svg.tsx +6 -6
- package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
- package/src/plugins/builtin/world-venue-map/index.ts +2 -1
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +24 -13
- package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +144 -13
- package/src/plugins/builtin/world-venue-map/model.ts +56 -19
- package/src/plugins/builtin/world-venue-map/pane.tsx +5 -2
- package/src/plugins/builtin/yield-curve/chart.ts +2 -2
- package/src/plugins/builtin/yield-curve/curves.ts +21 -8
- package/src/plugins/builtin/yield-curve/headless.ts +71 -18
- package/src/plugins/builtin/yield-curve/index.tsx +4 -2
- package/src/plugins/builtin/yield-curve/series.ts +86 -0
- package/src/plugins/catalog-browser.ts +2 -1
- package/src/plugins/installer.ts +2 -2
- package/src/plugins/loader.ts +15 -0
- package/src/plugins/manager-node.ts +1 -1
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/feed.ts +2 -2
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/model.ts +6 -6
- package/src/plugins/{builtin/plugin-marketplace → marketplace}/store.ts +1 -1
- package/src/plugins/registry/host-actions.ts +11 -0
- package/src/plugins/registry/index.ts +89 -4
- package/src/portfolio/collection-name.ts +31 -0
- package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
- package/src/portfolio/position-value.ts +40 -0
- package/src/portfolio/valuation-basis.ts +79 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
- package/src/public/time-series.ts +17 -0
- package/src/react/auto-refresh.ts +13 -3
- package/src/react/input.ts +33 -1
- package/src/react/key-repeat.ts +86 -0
- package/src/remote/app-host.tsx +20 -4
- package/src/remote/confirm-change.tsx +85 -0
- package/src/remote/controller-utils.ts +8 -1
- package/src/remote/controller.ts +144 -7
- package/src/remote/pane-screenshot.ts +47 -0
- package/src/remote/schema.ts +65 -2
- package/src/remote/types.ts +30 -0
- package/src/remote/watchlist.ts +306 -0
- package/src/renderers/browser/main.tsx +4 -3
- package/src/renderers/browser/research-entry.ts +4 -2
- package/src/renderers/cloudflare/worker.ts +1 -1
- package/src/renderers/dom/data-table/frozen-column.ts +3 -1
- package/src/renderers/dom/data-table/index.tsx +33 -6
- package/src/renderers/dom/data-table/row.tsx +30 -1
- package/src/renderers/dom/desktop/control-styles.ts +63 -1
- package/src/renderers/dom/desktop/controls.tsx +30 -23
- package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
- package/src/renderers/dom/desktop/icons.tsx +16 -0
- package/src/renderers/dom/dom-ui-host.tsx +3 -0
- package/src/renderers/dom/host/block-glyph-canvas.tsx +6 -3
- package/src/renderers/dom/host/box.tsx +8 -0
- package/src/renderers/dom/host/chart-surface.tsx +33 -2
- package/src/renderers/dom/host/live-frame.ts +6 -2
- package/src/renderers/dom/host/overflow-fade.ts +14 -1
- package/src/renderers/dom/host/scroll-box.tsx +32 -0
- package/src/renderers/dom/host/size-observer.ts +41 -0
- package/src/renderers/dom/host/sticky-scroll.ts +128 -0
- package/src/renderers/dom/host/style.ts +1 -1
- package/src/renderers/dom/host/surface-3d.tsx +19 -7
- package/src/renderers/dom/host/surface-fit.ts +406 -0
- package/src/renderers/dom/host/text.tsx +1 -1
- package/src/renderers/dom/input-host.tsx +1 -0
- package/src/renderers/dom/styles.css +102 -5
- package/src/renderers/electrobun/bun/application-menu/click.ts +18 -0
- package/src/renderers/electrobun/bun/index.ts +3 -2
- package/src/renderers/electrobun/shared/protocol.ts +1 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +29 -2
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +63 -20
- package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
- package/src/renderers/electrobun/view/main.tsx +5 -3
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +2 -0
- package/src/renderers/opentui/chart-surface.tsx +1 -0
- package/src/renderers/opentui/frame-capture.ts +33 -0
- package/src/renderers/opentui/host.tsx +10 -13
- package/src/renderers/opentui/pane-image/glyphs-license.txt +107 -0
- package/src/renderers/opentui/pane-image/glyphs.json +1 -0
- package/src/renderers/opentui/pane-image/index.ts +107 -0
- package/src/renderers/opentui/pane-image/raster.ts +428 -0
- package/src/renderers/opentui/start.tsx +3 -3
- package/src/renderers/opentui/test-utils.tsx +3 -0
- package/src/renderers/opentui/ui-host.tsx +29 -1
- package/src/series/capability.ts +75 -0
- package/src/series/csv.ts +160 -0
- package/src/series/files.ts +107 -0
- package/src/series/registry.ts +198 -0
- package/src/series/resolve.ts +108 -0
- package/src/series/standalone.ts +48 -0
- package/src/series/types.ts +153 -0
- package/src/series/validate.ts +171 -0
- package/src/shares/chat.ts +34 -0
- package/src/shares/dialog.tsx +295 -0
- package/src/shares/flow.tsx +56 -0
- package/src/shares/live.ts +14 -22
- package/src/shares/pane-image.ts +152 -0
- package/src/shares/personal-pane.ts +64 -0
- package/src/shares/portable-layout.ts +4 -2
- package/src/shares/prepare.ts +20 -0
- package/src/sources/gloomberb-cloud/index.ts +109 -10
- package/src/sources/gloomberb-cloud/normalizers.ts +3 -0
- package/src/sources/gloomberb-cloud/perpetuals.ts +249 -0
- package/src/sources/history-result.ts +1 -0
- package/src/sources/history-retention.ts +11 -0
- package/src/sources/listing-symbols.ts +4 -1
- package/src/sources/listing-target.ts +4 -0
- package/src/sources/provider-router/batches.ts +4 -1
- package/src/sources/provider-router/cache.ts +4 -2
- package/src/sources/provider-router/cached-routes.ts +1 -1
- package/src/sources/provider-router/financial-routes.ts +1 -0
- package/src/sources/provider-router/financials.ts +13 -0
- package/src/sources/provider-router/history.ts +43 -25
- package/src/sources/provider-router/index.ts +14 -0
- package/src/sources/provider-router/search.ts +1 -0
- package/src/state/hooks/inline-tickers.ts +49 -11
- package/src/sync/core-contributors.ts +1 -0
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/theme-context.tsx +15 -1
- package/src/tickers/company-name.ts +75 -0
- package/src/tickers/instrument-kind.ts +34 -1
- package/src/tickers/listing-name.ts +34 -0
- package/src/tickers/listing-venues.ts +132 -0
- package/src/tickers/open-target.ts +13 -4
- package/src/tickers/perpetual-listing.ts +151 -0
- package/src/tickers/prediction-listing.ts +26 -0
- package/src/tickers/search/index.ts +72 -11
- package/src/tickers/search/ranking.ts +98 -20
- package/src/tickers/search/types.ts +7 -1
- package/src/tickers/ticker-changes.ts +213 -0
- package/src/tickers/us-listing.ts +34 -0
- package/src/time-series/economic.ts +2 -6
- package/src/time-series/hooks.ts +9 -0
- package/src/time-series/ice-credit.ts +39 -0
- package/src/time-series/resolve.ts +211 -29
- package/src/time-series/studies.ts +1 -0
- package/src/time-series/types.ts +12 -2
- package/src/time-series/use-chart-resolution.ts +32 -0
- package/src/types/config.ts +10 -2
- package/src/types/data-provider.ts +11 -0
- package/src/types/financials.ts +62 -1
- package/src/types/headless.ts +113 -0
- package/src/types/instrument.ts +4 -0
- package/src/types/plugin.ts +52 -2
- package/src/types/price-history.ts +7 -0
- package/src/types/ticker-changes.ts +26 -0
- package/src/types/ticker.ts +14 -0
- package/src/ui/context-menu.tsx +13 -1
- package/src/ui/host.tsx +57 -3
- package/src/ui/live-resize.ts +91 -0
- package/src/ui/live-stretch.ts +153 -0
- package/src/ui/measured-cells.ts +58 -0
- package/src/ui/sticky-scroll.ts +7 -0
- package/src/utils/basis-points.ts +17 -0
- package/src/utils/central-banks.ts +76 -0
- package/src/utils/cli-output.ts +131 -15
- package/src/utils/concurrency.ts +25 -0
- package/src/utils/crypto-pair.ts +20 -0
- package/src/utils/currency-pair.ts +19 -0
- package/src/utils/currency-units.ts +11 -0
- package/src/utils/datetime-format.ts +27 -6
- package/src/utils/decimal-comma.ts +19 -0
- package/src/utils/dom-screenshot-css.ts +265 -0
- package/src/utils/dom-screenshot-rasters.ts +276 -0
- package/src/utils/dom-screenshot.ts +439 -52
- package/src/utils/double-escape-close.ts +15 -1
- package/src/utils/exchange-rate-snapshot.ts +6 -2
- package/src/utils/exchanges.ts +143 -1
- package/src/utils/format.ts +35 -5
- package/src/utils/forward-dividend.ts +14 -0
- package/src/utils/fundamentals.ts +66 -0
- package/src/utils/futures-generic.ts +6 -12
- package/src/utils/fx-market-hours.ts +15 -5
- package/src/utils/fx-status.ts +6 -1
- package/src/utils/inline-content-tokenizer.ts +22 -3
- package/src/utils/market-capitalization.ts +8 -0
- package/src/utils/one-shot.ts +73 -0
- package/src/utils/options.ts +37 -8
- package/src/utils/price-history.ts +99 -42
- package/src/utils/sec-eps-basis.ts +24 -11
- package/src/utils/sec.ts +61 -7
- package/src/utils/utc-time.ts +63 -4
- package/src/plugins/builtin/fx-matrix/freshness.ts +0 -65
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/activation.ts +0 -0
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/ids.ts +0 -0
- /package/src/plugins/{builtin/plugin-marketplace → marketplace}/packs.ts +0 -0
- /package/src/{plugins/builtin/cloud → tickers}/starter-symbols.ts +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { registerAccountSession } from "../../../../account/session";
|
|
1
2
|
import type {
|
|
2
3
|
AppNotificationDelivery,
|
|
3
4
|
AppNotificationRequest,
|
|
@@ -10,8 +11,11 @@ import {
|
|
|
10
11
|
type ChatChannel,
|
|
11
12
|
type ChatChannelState,
|
|
12
13
|
type ChatMessage,
|
|
14
|
+
type ChatReaction,
|
|
15
|
+
type ChatReactionsUpdate,
|
|
13
16
|
type PersistedAuthUser,
|
|
14
17
|
} from "../../../../api-client";
|
|
18
|
+
import { withOwnReaction } from "../reactions";
|
|
15
19
|
import { normalizeSessionUser } from "./persistence";
|
|
16
20
|
import { debugLog } from "../../../../utils/debug-log";
|
|
17
21
|
import {
|
|
@@ -32,7 +36,8 @@ import {
|
|
|
32
36
|
updateChatChannelDraft,
|
|
33
37
|
updateChatChannelNotifications,
|
|
34
38
|
} from "./channel-actions";
|
|
35
|
-
import { retryChatMessageInChannel, sendChatMessageToChannel } from "./send";
|
|
39
|
+
import { postImageMessageToChannel, retryChatMessageInChannel, sendChatMessageToChannel } from "./send";
|
|
40
|
+
import { describeChatImageError } from "../attachments/model";
|
|
36
41
|
import {
|
|
37
42
|
addDraftAttachments,
|
|
38
43
|
discardDraftAttachments,
|
|
@@ -143,6 +148,7 @@ export class ChatController {
|
|
|
143
148
|
emit: (channelId) => this.emit(channelId),
|
|
144
149
|
mergeMessages: (channelId, messages, options) => this.mergeMessages(channelId, messages, options),
|
|
145
150
|
persistChannelState: (channelId) => this.storage.persistChannelState(channelId),
|
|
151
|
+
getReaderId: () => this.session.user?.id ?? null,
|
|
146
152
|
});
|
|
147
153
|
private readonly realtime = new ChatControllerRealtime({
|
|
148
154
|
getAppActive: () => this.appActive,
|
|
@@ -150,6 +156,7 @@ export class ChatController {
|
|
|
150
156
|
getUser: () => this.session.user,
|
|
151
157
|
refreshSession: () => this.refreshSession(),
|
|
152
158
|
handleNotification: (notification) => this.handleChatNotification(notification),
|
|
159
|
+
handleReactions: (update) => this.applyReactionsUpdate(update),
|
|
153
160
|
setOnlineCount: (onlineCount) => {
|
|
154
161
|
this.channelCatalog.setOnlineCount(onlineCount);
|
|
155
162
|
},
|
|
@@ -171,6 +178,30 @@ export class ChatController {
|
|
|
171
178
|
this.openMessageFn = openMessage;
|
|
172
179
|
}
|
|
173
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Mark all read in the Unread list: each unread channel is read through its
|
|
183
|
+
* newest message the way opening it in Chat reads it, and a channel with
|
|
184
|
+
* nothing on this device yet once its latest messages load. A failed load
|
|
185
|
+
* leaves that channel unread.
|
|
186
|
+
*/
|
|
187
|
+
markAllChannelsRead(): void {
|
|
188
|
+
let changed = false;
|
|
189
|
+
for (const [channelId, channel] of this.storage.channelStates) {
|
|
190
|
+
if (channel.unreadCount <= 0) continue;
|
|
191
|
+
if (channel.messages.length > 0) {
|
|
192
|
+
changed = this.markViewedThroughLatestMessage(channelId) || changed;
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
void this.refreshChannelMessages(channelId)
|
|
196
|
+
.then(() => {
|
|
197
|
+
if (this.ensureChannelState(channelId).messages.length === 0) return;
|
|
198
|
+
if (this.markViewedThroughLatestMessage(channelId)) this.emit(channelId);
|
|
199
|
+
})
|
|
200
|
+
.catch(() => {});
|
|
201
|
+
}
|
|
202
|
+
if (changed) this.emit();
|
|
203
|
+
}
|
|
204
|
+
|
|
174
205
|
hydrate(): void {
|
|
175
206
|
hydrateChatControllerSession({
|
|
176
207
|
session: this.session,
|
|
@@ -569,6 +600,47 @@ export class ChatController {
|
|
|
569
600
|
};
|
|
570
601
|
}
|
|
571
602
|
|
|
603
|
+
/**
|
|
604
|
+
* Posts one picture with an optional caption as the user's own message, as
|
|
605
|
+
* Share to Chat does: uploads it, then sends it, leaving the channel's
|
|
606
|
+
* draft alone. Rejects with a sentence that says what went wrong.
|
|
607
|
+
*/
|
|
608
|
+
async postImage(
|
|
609
|
+
channelId: string,
|
|
610
|
+
upload: ChatAttachmentUpload & { previewUrl?: string | null },
|
|
611
|
+
caption: string,
|
|
612
|
+
options: { signal?: AbortSignal; onProgress?: (fraction: number) => void } = {},
|
|
613
|
+
): Promise<ChatMessage> {
|
|
614
|
+
const normalizedChannelId = normalizeChannelId(channelId);
|
|
615
|
+
const user = this.session.user;
|
|
616
|
+
if (!user?.emailVerified) throw new Error("Verify your email to post in chat.");
|
|
617
|
+
let attachment;
|
|
618
|
+
try {
|
|
619
|
+
attachment = await this.uploadAttachment(normalizedChannelId, upload, {
|
|
620
|
+
signal: options.signal ?? new AbortController().signal,
|
|
621
|
+
onProgress: options.onProgress ?? (() => {}),
|
|
622
|
+
});
|
|
623
|
+
} catch (error) {
|
|
624
|
+
throw new Error(describeChatImageError(error));
|
|
625
|
+
}
|
|
626
|
+
const channel = this.ensureChannelState(normalizedChannelId);
|
|
627
|
+
return postImageMessageToChannel({
|
|
628
|
+
channelId: normalizedChannelId,
|
|
629
|
+
channel,
|
|
630
|
+
content: caption,
|
|
631
|
+
attachment,
|
|
632
|
+
previewUrl: upload.previewUrl ?? null,
|
|
633
|
+
user,
|
|
634
|
+
getVisibleMessages: () => this.getVisibleMessages(normalizedChannelId),
|
|
635
|
+
nextPendingMessageId: () => `local:${Date.now()}:${this.pendingMessageSeq += 1}`,
|
|
636
|
+
emit: () => this.emit(normalizedChannelId),
|
|
637
|
+
mergeMessages: (messages) => this.mergeMessages(normalizedChannelId, messages),
|
|
638
|
+
send: (content, clientMessageId, attachmentIds) => (
|
|
639
|
+
apiClient.sendMessage(normalizedChannelId, content, undefined, clientMessageId, attachmentIds)
|
|
640
|
+
),
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
|
|
572
644
|
/** Sends a failed message again with the same images and idempotency key. */
|
|
573
645
|
retryChannelMessage(channelId: string, messageId: string): boolean {
|
|
574
646
|
const normalizedChannelId = normalizeChannelId(channelId);
|
|
@@ -625,6 +697,55 @@ export class ChatController {
|
|
|
625
697
|
}
|
|
626
698
|
}
|
|
627
699
|
|
|
700
|
+
/**
|
|
701
|
+
* Adds or takes back your reaction with one emoji. The chip moves at once;
|
|
702
|
+
* the server's answer settles it, and a refusal puts it back and says why.
|
|
703
|
+
*/
|
|
704
|
+
async toggleChannelReaction(channelId: string, messageId: string, emoji: string): Promise<boolean> {
|
|
705
|
+
const normalizedChannelId = normalizeChannelId(channelId);
|
|
706
|
+
const channel = this.ensureChannelState(normalizedChannelId);
|
|
707
|
+
const user = this.session.user;
|
|
708
|
+
if (!user?.emailVerified) return false;
|
|
709
|
+
const message = channel.messages.find((entry) => entry.id === messageId);
|
|
710
|
+
if (!message) return false;
|
|
711
|
+
const reacted = !(message.reactions ?? []).some((reaction) => reaction.emoji === emoji && reaction.me);
|
|
712
|
+
const self = { id: user.id, username: user.username, displayName: user.username };
|
|
713
|
+
this.replaceMessageReactions(normalizedChannelId, messageId, (current) => withOwnReaction(current, emoji, reacted, self));
|
|
714
|
+
try {
|
|
715
|
+
const update = await apiClient.setChatReaction(normalizedChannelId, messageId, emoji, reacted);
|
|
716
|
+
this.replaceMessageReactions(normalizedChannelId, messageId, () => update.reactions);
|
|
717
|
+
return true;
|
|
718
|
+
} catch (error) {
|
|
719
|
+
// Only this change is undone; what others did meanwhile stays.
|
|
720
|
+
this.replaceMessageReactions(normalizedChannelId, messageId, (current) => withOwnReaction(current, emoji, !reacted, self));
|
|
721
|
+
const body = error instanceof Error && error.message ? error.message : "Failed to react.";
|
|
722
|
+
this.notifyFn({ body, type: "error" });
|
|
723
|
+
return false;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/** A message's reactions as everyone reading the channel just got them. */
|
|
728
|
+
applyReactionsUpdate(update: ChatReactionsUpdate): void {
|
|
729
|
+
this.replaceMessageReactions(normalizeChannelId(update.channelId), update.messageId, () => update.reactions);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
private replaceMessageReactions(
|
|
733
|
+
channelId: string,
|
|
734
|
+
messageId: string,
|
|
735
|
+
next: (current: ChatReaction[]) => ChatReaction[],
|
|
736
|
+
): void {
|
|
737
|
+
const channel = this.storage.channelStates.get(channelId);
|
|
738
|
+
if (!channel) return;
|
|
739
|
+
const index = channel.messages.findIndex((entry) => entry.id === messageId);
|
|
740
|
+
if (index < 0) return;
|
|
741
|
+
const message = channel.messages[index]!;
|
|
742
|
+
channel.messages = channel.messages.map((entry, entryIndex) => (
|
|
743
|
+
entryIndex === index ? { ...message, reactions: next(message.reactions ?? []) } : entry
|
|
744
|
+
));
|
|
745
|
+
this.storage.persistTranscript(channelId);
|
|
746
|
+
this.emit(channelId);
|
|
747
|
+
}
|
|
748
|
+
|
|
628
749
|
ensureConnection(channelId = DEFAULT_CHAT_CHANNEL_ID): void {
|
|
629
750
|
const normalizedChannelId = normalizeChannelId(channelId);
|
|
630
751
|
const channel = this.ensureChannelState(normalizedChannelId);
|
|
@@ -757,3 +878,4 @@ export class ChatController {
|
|
|
757
878
|
}
|
|
758
879
|
|
|
759
880
|
export const chatController = new ChatController();
|
|
881
|
+
registerAccountSession(chatController);
|
|
@@ -15,6 +15,8 @@ interface ChatControllerMessageLoadingOptions {
|
|
|
15
15
|
emit: (channelId?: string) => void;
|
|
16
16
|
mergeMessages: (channelId: string, messages: ChatMessage[], options?: MergeMessagesOptions) => void;
|
|
17
17
|
persistChannelState: (channelId: string) => void;
|
|
18
|
+
/** The signed-in account's id, or null. */
|
|
19
|
+
getReaderId?: () => string | null;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
export class ChatControllerMessageLoading {
|
|
@@ -45,6 +47,7 @@ export class ChatControllerMessageLoading {
|
|
|
45
47
|
persistChannelState: (nextChannelId) => {
|
|
46
48
|
this.options.persistChannelState(nextChannelId);
|
|
47
49
|
},
|
|
50
|
+
readerId: () => this.options.getReaderId?.() ?? null,
|
|
48
51
|
})
|
|
49
52
|
.catch((error: unknown) => {
|
|
50
53
|
channel.messagesError = error instanceof Error && error.message.trim()
|
|
@@ -49,10 +49,15 @@ function mergeStoredMessages(channel: ChannelRuntimeState, messages: ChatMessage
|
|
|
49
49
|
const incoming = new Map<string, ChatMessage>();
|
|
50
50
|
for (const message of channel.messages) merged.set(message.id, message);
|
|
51
51
|
for (const message of messages) {
|
|
52
|
-
|
|
52
|
+
const current = merged.get(message.id);
|
|
53
|
+
if (!current) {
|
|
53
54
|
incoming.set(message.id, message);
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
+
// A live copy (an edit) leaves reactions out; the ones held stay.
|
|
57
|
+
merged.set(
|
|
58
|
+
message.id,
|
|
59
|
+
current?.reactions && message.reactions === undefined ? { ...message, reactions: current.reactions } : message,
|
|
60
|
+
);
|
|
56
61
|
}
|
|
57
62
|
for (const message of messages) {
|
|
58
63
|
for (const [id, current] of merged) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { apiClient, type ChatNotification } from "../../../../api-client";
|
|
1
|
+
import { apiClient, type ChatNotification, type ChatReactionsUpdate } from "../../../../api-client";
|
|
2
2
|
import {
|
|
3
3
|
SAFETY_REFRESH_MS,
|
|
4
4
|
SESSION_RETRY_MS,
|
|
@@ -11,6 +11,7 @@ interface ChatControllerRealtimeOptions {
|
|
|
11
11
|
getUser: () => { emailVerified?: boolean } | null;
|
|
12
12
|
refreshSession: () => Promise<void>;
|
|
13
13
|
handleNotification: (notification: ChatNotification) => void;
|
|
14
|
+
handleReactions: (update: ChatReactionsUpdate) => void;
|
|
14
15
|
setOnlineCount: (onlineCount: number) => void;
|
|
15
16
|
emit: () => void;
|
|
16
17
|
getSafetyRefreshChannelIds: () => string[];
|
|
@@ -23,6 +24,7 @@ export class ChatControllerRealtime {
|
|
|
23
24
|
private safetyRefreshTimer: ReturnType<typeof setInterval> | null = null;
|
|
24
25
|
private chatNotificationUnsubscribe: (() => void) | null = null;
|
|
25
26
|
private chatPresenceUnsubscribe: (() => void) | null = null;
|
|
27
|
+
private chatReactionsUnsubscribe: (() => void) | null = null;
|
|
26
28
|
|
|
27
29
|
constructor(private readonly options: ChatControllerRealtimeOptions) {}
|
|
28
30
|
|
|
@@ -65,6 +67,11 @@ export class ChatControllerRealtime {
|
|
|
65
67
|
this.options.handleNotification(notification);
|
|
66
68
|
});
|
|
67
69
|
}
|
|
70
|
+
if (!this.chatReactionsUnsubscribe) {
|
|
71
|
+
this.chatReactionsUnsubscribe = apiClient.subscribeChatReactions((update) => {
|
|
72
|
+
this.options.handleReactions(update);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
68
75
|
if (!this.chatPresenceUnsubscribe) {
|
|
69
76
|
this.chatPresenceUnsubscribe = apiClient.subscribeChatPresence((onlineCount) => {
|
|
70
77
|
this.options.setOnlineCount(onlineCount);
|
|
@@ -78,6 +85,8 @@ export class ChatControllerRealtime {
|
|
|
78
85
|
this.chatNotificationUnsubscribe = null;
|
|
79
86
|
this.chatPresenceUnsubscribe?.();
|
|
80
87
|
this.chatPresenceUnsubscribe = null;
|
|
88
|
+
this.chatReactionsUnsubscribe?.();
|
|
89
|
+
this.chatReactionsUnsubscribe = null;
|
|
81
90
|
}
|
|
82
91
|
|
|
83
92
|
stopVerificationPolling(): void {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AppNotificationRequest } from "../../../../types/plugin";
|
|
2
|
-
import type { ChatMessage } from "../../../../api-client";
|
|
2
|
+
import type { ChatAttachment, ChatMessage } from "../../../../api-client";
|
|
3
3
|
import { describeChatSendError } from "../attachments/model";
|
|
4
4
|
import { readyDraftAttachments } from "./attachments";
|
|
5
5
|
import {
|
|
@@ -147,6 +147,66 @@ export function sendChatMessageToChannel({
|
|
|
147
147
|
return true;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
/**
|
|
151
|
+
* Posts a message that carries an image uploaded for it (a pane shared to
|
|
152
|
+
* chat), without touching the channel's draft. It shows as sending at once,
|
|
153
|
+
* like a typed message; a failed send stays in the channel to retry, and the
|
|
154
|
+
* returned promise rejects with the reason.
|
|
155
|
+
*/
|
|
156
|
+
export async function postImageMessageToChannel({
|
|
157
|
+
channelId,
|
|
158
|
+
channel,
|
|
159
|
+
content,
|
|
160
|
+
attachment,
|
|
161
|
+
previewUrl,
|
|
162
|
+
user,
|
|
163
|
+
getVisibleMessages,
|
|
164
|
+
nextPendingMessageId,
|
|
165
|
+
emit,
|
|
166
|
+
mergeMessages,
|
|
167
|
+
send,
|
|
168
|
+
}: {
|
|
169
|
+
channelId: string;
|
|
170
|
+
channel: ChannelRuntimeState;
|
|
171
|
+
content: string;
|
|
172
|
+
attachment: ChatAttachment;
|
|
173
|
+
/** The local copy to show until the server's answer arrives. */
|
|
174
|
+
previewUrl: string | null;
|
|
175
|
+
user: ChatSessionUser;
|
|
176
|
+
getVisibleMessages: () => ChatMessage[];
|
|
177
|
+
nextPendingMessageId: () => string;
|
|
178
|
+
emit: () => void;
|
|
179
|
+
mergeMessages: (messages: ChatMessage[]) => void;
|
|
180
|
+
send: (content: string, clientMessageId: string, attachmentIds: string[]) => Promise<ChatMessage>;
|
|
181
|
+
}): Promise<ChatMessage> {
|
|
182
|
+
const pendingMessage = createPendingMessage({
|
|
183
|
+
channelId,
|
|
184
|
+
content: content.trim(),
|
|
185
|
+
pendingId: nextPendingMessageId(),
|
|
186
|
+
user,
|
|
187
|
+
visibleMessages: getVisibleMessages(),
|
|
188
|
+
attachments: [{ ...attachment, url: previewUrl ?? attachment.url }],
|
|
189
|
+
clientMessageId: createClientMessageId(),
|
|
190
|
+
});
|
|
191
|
+
channel.pendingMessages = [...channel.pendingMessages, pendingMessage];
|
|
192
|
+
emit();
|
|
193
|
+
try {
|
|
194
|
+
const message = await send(pendingMessage.content, pendingMessage.clientMessageId!, [attachment.id]);
|
|
195
|
+
channel.pendingMessages = channel.pendingMessages.filter((entry) => entry.id !== pendingMessage.id);
|
|
196
|
+
mergeMessages([message]);
|
|
197
|
+
return message;
|
|
198
|
+
} catch (error) {
|
|
199
|
+
const errorMessage = describeChatSendError(error);
|
|
200
|
+
channel.pendingMessages = channel.pendingMessages.map((entry) => (
|
|
201
|
+
entry.id === pendingMessage.id
|
|
202
|
+
? { ...entry, clientStatus: "failed", clientError: errorMessage }
|
|
203
|
+
: entry
|
|
204
|
+
));
|
|
205
|
+
emit();
|
|
206
|
+
throw new Error(errorMessage);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
150
210
|
/**
|
|
151
211
|
* Sends a failed message again: same text, same images (not uploaded again)
|
|
152
212
|
* and the same idempotency key, so a send that did reach the server is not
|
|
@@ -92,6 +92,13 @@ export interface ChannelRuntimeState {
|
|
|
92
92
|
* never be requested again; one uncursored fetch per session repairs it.
|
|
93
93
|
*/
|
|
94
94
|
backfilled: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* The account that backfill read the channel as (null signed out). Each
|
|
97
|
+
* message comes back with that reader's own reactions, so a different
|
|
98
|
+
* reader (a pane that mounted before the session was restored, a sign-in)
|
|
99
|
+
* reads the latest page again.
|
|
100
|
+
*/
|
|
101
|
+
backfilledAs: string | null;
|
|
95
102
|
messages: ChatMessage[];
|
|
96
103
|
pendingMessages: ChatMessage[];
|
|
97
104
|
draft: string;
|
|
@@ -129,6 +136,7 @@ export function createEmptyChannelState(): ChannelRuntimeState {
|
|
|
129
136
|
loadOlderMessagesPromise: null,
|
|
130
137
|
reachedOldestMessage: false,
|
|
131
138
|
backfilled: false,
|
|
139
|
+
backfilledAs: null,
|
|
132
140
|
messages: [],
|
|
133
141
|
pendingMessages: [],
|
|
134
142
|
draft: "",
|
|
@@ -8,6 +8,26 @@ export function isDiscordGhost(user: Pick<ChatUserSummary, "accountType"> | null
|
|
|
8
8
|
return user?.accountType === "discord";
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* A managed assistant (Gloombot, Gloom Wire, the AI desk personas): an account
|
|
13
|
+
* Gloom runs, not a person. Wherever it signs a message it carries an AI badge.
|
|
14
|
+
*/
|
|
15
|
+
export function isManagedBot(user: Pick<ChatUserSummary, "accountType"> | null | undefined): boolean {
|
|
16
|
+
return user?.accountType === "managed_llm";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A reply quotes its author by name only, so whether that author is a managed
|
|
21
|
+
* assistant comes from the users the pane has seen.
|
|
22
|
+
*/
|
|
23
|
+
export function isQuotedAuthorManagedBot(
|
|
24
|
+
quoted: { user: { username?: string | null } },
|
|
25
|
+
userByUsername: ReadonlyMap<string, ChatUserSummary>,
|
|
26
|
+
): boolean {
|
|
27
|
+
const username = quoted.user.username?.toLowerCase();
|
|
28
|
+
return !!username && isManagedBot(userByUsername.get(username));
|
|
29
|
+
}
|
|
30
|
+
|
|
11
31
|
/** The name a message is signed with: the username, or for a ghost that has none the Discord name it carries. */
|
|
12
32
|
export function chatAuthorName(user: Pick<ChatUserSummary, "username" | "displayName" | "accountType">): string {
|
|
13
33
|
return user.username ?? ((isDiscordGhost(user) && user.displayName?.trim()) || "anon");
|
|
@@ -3,6 +3,7 @@ import { teamChannelId } from "../cloud/team/model";
|
|
|
3
3
|
import { teamStore } from "../cloud/team/store";
|
|
4
4
|
import { formatChatPaneTitle } from "./channel-labels";
|
|
5
5
|
import {
|
|
6
|
+
DEFAULT_CHAT_CHANNEL_ID,
|
|
6
7
|
buildDmCommandResults,
|
|
7
8
|
getPreferredChatOpenChannelId,
|
|
8
9
|
hasOnlyDmUsernameArgs,
|
|
@@ -18,6 +19,7 @@ import { ChatPane } from "./pane";
|
|
|
18
19
|
import { chatSidebarStore } from "./sidebar-store";
|
|
19
20
|
import { ChatStatusWidget } from "./status-widget";
|
|
20
21
|
import { UnreadInboxPane } from "./unread-inbox-pane";
|
|
22
|
+
import { installPaneChatSharing } from "./share/flow";
|
|
21
23
|
import { UNREAD_INBOX_PANE_ID, UNREAD_INBOX_TEMPLATE_ID } from "./unread-inbox";
|
|
22
24
|
|
|
23
25
|
/**
|
|
@@ -37,6 +39,15 @@ async function resolveTypedChannelId(rawArg: string): Promise<string> {
|
|
|
37
39
|
}
|
|
38
40
|
}
|
|
39
41
|
|
|
42
|
+
/** A DM, a group or a team channel: what only its members read. */
|
|
43
|
+
function isPrivateConversation(channelId: unknown): boolean {
|
|
44
|
+
const id = typeof channelId === "string" && channelId.trim() ? channelId.trim() : DEFAULT_CHAT_CHANNEL_ID;
|
|
45
|
+
const kind = chatController.getChannels().find((channel) => channel.id === id)?.kind;
|
|
46
|
+
return kind ? kind !== "public" : /^(dm|grp|group|team):/.test(id);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let disposePaneChatSharing: (() => void) | undefined;
|
|
50
|
+
|
|
40
51
|
export const chatModule: PluginModule = {
|
|
41
52
|
panes: [{
|
|
42
53
|
id: "chat",
|
|
@@ -46,18 +57,21 @@ export const chatModule: PluginModule = {
|
|
|
46
57
|
defaultPosition: "right",
|
|
47
58
|
defaultMode: "floating",
|
|
48
59
|
defaultFloatingSize: { width: 80, height: 30 },
|
|
60
|
+
personalData: (context) => (isPrivateConversation(context.settings.channelId) ? "messages" : null),
|
|
49
61
|
portableShare: {
|
|
50
62
|
private: { title: true, params: true, settings: true, state: true },
|
|
51
63
|
},
|
|
52
64
|
}, {
|
|
53
65
|
id: UNREAD_INBOX_PANE_ID,
|
|
54
|
-
reportFreshness: { status: "not-a-feed", basis: "chat messages" },
|
|
66
|
+
reportFreshness: { status: "not-a-feed", basis: "chat messages and missed alerts" },
|
|
55
67
|
name: "Unread",
|
|
68
|
+
// Mentions and replies from every conversation, DMs included.
|
|
69
|
+
personalData: "messages",
|
|
56
70
|
icon: "U",
|
|
57
71
|
component: UnreadInboxPane,
|
|
58
72
|
defaultPosition: "right",
|
|
59
73
|
defaultMode: "floating",
|
|
60
|
-
defaultFloatingSize: { width:
|
|
74
|
+
defaultFloatingSize: { width: 88, height: 16 },
|
|
61
75
|
}],
|
|
62
76
|
paneTemplates: [{
|
|
63
77
|
id: "new-chat-pane",
|
|
@@ -117,9 +131,9 @@ export const chatModule: PluginModule = {
|
|
|
117
131
|
}, {
|
|
118
132
|
id: UNREAD_INBOX_TEMPLATE_ID,
|
|
119
133
|
paneId: UNREAD_INBOX_PANE_ID,
|
|
120
|
-
label: "Unread
|
|
121
|
-
description: "
|
|
122
|
-
keywords: ["unread", "chat", "inbox", "mentions"],
|
|
134
|
+
label: "Unread",
|
|
135
|
+
description: "Unread chat, then price alerts, catalysts and team notices you missed",
|
|
136
|
+
keywords: ["unread", "chat", "inbox", "mentions", "missed", "notifications", "alerts"],
|
|
123
137
|
createInstance: () => ({
|
|
124
138
|
placement: "floating",
|
|
125
139
|
instanceId: "unread-inbox",
|
|
@@ -131,6 +145,8 @@ export const chatModule: PluginModule = {
|
|
|
131
145
|
},
|
|
132
146
|
setup(ctx) {
|
|
133
147
|
ctx.registerCommandBarSearchProvider(createChatSearchProvider(ctx));
|
|
148
|
+
disposePaneChatSharing?.();
|
|
149
|
+
disposePaneChatSharing = installPaneChatSharing(ctx);
|
|
134
150
|
chatController.attachPersistence(ctx.persistence, ctx.resume);
|
|
135
151
|
chatSidebarStore.attach(ctx.persistence);
|
|
136
152
|
chatController.setNotifier(ctx.notify, (channelId, messageId) => {
|
|
@@ -160,6 +176,8 @@ export const chatModule: PluginModule = {
|
|
|
160
176
|
});
|
|
161
177
|
},
|
|
162
178
|
dispose() {
|
|
179
|
+
disposePaneChatSharing?.();
|
|
180
|
+
disposePaneChatSharing = undefined;
|
|
163
181
|
chatController.dispose();
|
|
164
182
|
},
|
|
165
183
|
};
|
|
@@ -9,10 +9,11 @@ import {
|
|
|
9
9
|
type TickerBadgeStatus,
|
|
10
10
|
} from "../../../components/ticker/badge/format";
|
|
11
11
|
import type { InlineTickerCatalogEntry } from "../../../state/hooks/inline-tickers";
|
|
12
|
+
import { STICKY_BOTTOM_THRESHOLD_PX } from "../../../ui/sticky-scroll";
|
|
13
|
+
import { terminalReactionRows } from "./reactions";
|
|
12
14
|
|
|
13
15
|
const MESSAGE_GROUP_THRESHOLD_MS = 5 * 60 * 1000;
|
|
14
16
|
const MESSAGE_SELECTION_BOTTOM_INSET = 1;
|
|
15
|
-
const SCROLL_BOTTOM_THRESHOLD_PX = 2;
|
|
16
17
|
|
|
17
18
|
export const CHAT_COMPOSER_MAX_ROWS = 5;
|
|
18
19
|
export const MESSAGE_ACTION_WIDTH = 9;
|
|
@@ -277,7 +278,8 @@ export function estimateMessageHeight(
|
|
|
277
278
|
? getMessageBodyTokenLines(message.content, contentLineWidth, catalog).length
|
|
278
279
|
: getMessageBodyLines(message, width, catalog).length;
|
|
279
280
|
const reviewNoteHeight = message.attachmentReview ? 1 : 0;
|
|
280
|
-
|
|
281
|
+
const reactionRows = message.reactions?.length ? terminalReactionRows(message.reactions, contentLineWidth).length : 0;
|
|
282
|
+
return headerHeight + (message.replyTo ? 1 : 0) + bodyLineCount + imageCount + reviewNoteHeight + reactionRows;
|
|
281
283
|
}
|
|
282
284
|
|
|
283
285
|
export function estimateComposerHeight(text: string, width: number) {
|
|
@@ -336,7 +338,7 @@ export function isScrolledToBottom(scrollBox: ScrollBoxRenderable | null, prefer
|
|
|
336
338
|
const exactPixels = preferPixels && hasPixelScrollMetrics(scrollBox);
|
|
337
339
|
const scrollTop = getScrollTop(scrollBox, exactPixels);
|
|
338
340
|
const maxScrollTop = Math.max(0, getScrollHeight(scrollBox, exactPixels) - getViewportHeight(scrollBox, exactPixels));
|
|
339
|
-
const threshold = exactPixels ?
|
|
341
|
+
const threshold = exactPixels ? STICKY_BOTTOM_THRESHOLD_PX : 0;
|
|
340
342
|
return maxScrollTop - scrollTop <= threshold;
|
|
341
343
|
}
|
|
342
344
|
|
|
@@ -354,21 +356,31 @@ function getScrollTopForElementIntoView({
|
|
|
354
356
|
elementTop,
|
|
355
357
|
elementHeight,
|
|
356
358
|
bottomInset = 0,
|
|
359
|
+
center = false,
|
|
357
360
|
}: {
|
|
358
361
|
scrollTop: number;
|
|
359
362
|
viewportHeight: number;
|
|
360
363
|
elementTop: number;
|
|
361
364
|
elementHeight: number;
|
|
362
365
|
bottomInset?: number;
|
|
366
|
+
/** An element out of view is brought to the middle of it, not to the nearest edge. */
|
|
367
|
+
center?: boolean;
|
|
363
368
|
}) {
|
|
364
369
|
const visibleHeight = Math.max(viewportHeight - bottomInset, 1);
|
|
365
370
|
const elementBottom = elementTop + elementHeight;
|
|
366
|
-
if (
|
|
371
|
+
if (elementHeight >= visibleHeight) return elementTop;
|
|
372
|
+
const outOfView = elementTop < scrollTop || elementBottom > scrollTop + visibleHeight;
|
|
373
|
+
if (center && outOfView) return Math.max(0, elementTop - (visibleHeight - elementHeight) / 2);
|
|
374
|
+
if (elementTop < scrollTop) return elementTop;
|
|
367
375
|
if (elementBottom > scrollTop + visibleHeight) return elementBottom - visibleHeight;
|
|
368
376
|
return scrollTop;
|
|
369
377
|
}
|
|
370
378
|
|
|
371
|
-
export function scrollElementIntoScrollBoxView(
|
|
379
|
+
export function scrollElementIntoScrollBoxView(
|
|
380
|
+
scrollBox: ScrollBoxRenderable | null,
|
|
381
|
+
node: unknown,
|
|
382
|
+
options: { center?: boolean } = {},
|
|
383
|
+
) {
|
|
372
384
|
const nodeRect = (node as { getBoundingClientRect?: () => { x?: number; y?: number; top?: number; width?: number; height?: number } } | null)
|
|
373
385
|
?.getBoundingClientRect?.();
|
|
374
386
|
const scrollRect = scrollBox?.getBoundingClientRect?.() as { x?: number; y?: number; top?: number; width?: number; height?: number } | undefined;
|
|
@@ -388,6 +400,7 @@ export function scrollElementIntoScrollBoxView(scrollBox: ScrollBoxRenderable |
|
|
|
388
400
|
viewportHeight: scrollBox.viewportPx.height,
|
|
389
401
|
elementTop,
|
|
390
402
|
elementHeight: Math.max(nodeRect.height ?? 0, 1),
|
|
403
|
+
center: options.center,
|
|
391
404
|
});
|
|
392
405
|
if (nextScrollTop !== scrollBox.scrollTopPx) {
|
|
393
406
|
scrollBox.scrollToPixels(nextScrollTop);
|
|
@@ -401,6 +414,66 @@ export function scrollElementIntoScrollBoxView(scrollBox: ScrollBoxRenderable |
|
|
|
401
414
|
return true;
|
|
402
415
|
}
|
|
403
416
|
|
|
417
|
+
/** Where a reader is in the list: at the bottom, or which message is at the top of the view and how far down. */
|
|
418
|
+
export interface ScrollPlace {
|
|
419
|
+
atBottom: boolean;
|
|
420
|
+
anchorId: string | null;
|
|
421
|
+
/** In px from the top of the view to the top of the anchor message. */
|
|
422
|
+
anchorOffsetPx: number;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function messageRect(node: unknown): { y: number; height: number } | null {
|
|
426
|
+
const rect = (node as { getBoundingClientRect?: () => { y?: number; top?: number; height?: number } } | null)
|
|
427
|
+
?.getBoundingClientRect?.();
|
|
428
|
+
if (!rect) return null;
|
|
429
|
+
return { y: rect.y ?? rect.top ?? 0, height: rect.height ?? 0 };
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* The reader's place in a pixel-scrolled list, to put them back after the list is
|
|
434
|
+
* rebuilt. Null where the list has no pixel layout.
|
|
435
|
+
*/
|
|
436
|
+
export function readScrollPlace(
|
|
437
|
+
scrollBox: ScrollBoxRenderable | null,
|
|
438
|
+
messages: ChatMessage[],
|
|
439
|
+
elements: Map<string, unknown>,
|
|
440
|
+
): ScrollPlace | null {
|
|
441
|
+
const view = scrollBox?.getBoundingClientRect?.();
|
|
442
|
+
if (!scrollBox || !view || !hasPixelScrollMetrics(scrollBox)) return null;
|
|
443
|
+
if (isScrolledToBottom(scrollBox, true)) return { atBottom: true, anchorId: null, anchorOffsetPx: 0 };
|
|
444
|
+
// Rows run down the page in order, so the first with any part in view is found by halving.
|
|
445
|
+
let low = 0;
|
|
446
|
+
let high = messages.length - 1;
|
|
447
|
+
let found: { id: string; y: number } | null = null;
|
|
448
|
+
while (low <= high) {
|
|
449
|
+
const middle = (low + high) >> 1;
|
|
450
|
+
const message = messages[middle]!;
|
|
451
|
+
const rect = messageRect(elements.get(message.id));
|
|
452
|
+
if (!rect) return null;
|
|
453
|
+
if (rect.y + rect.height > view.y + 1) {
|
|
454
|
+
found = { id: message.id, y: rect.y };
|
|
455
|
+
high = middle - 1;
|
|
456
|
+
} else {
|
|
457
|
+
low = middle + 1;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return found ? { atBottom: false, anchorId: found.id, anchorOffsetPx: found.y - view.y } : null;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
export function restoreScrollPlace(
|
|
464
|
+
scrollBox: ScrollBoxRenderable | null,
|
|
465
|
+
place: ScrollPlace,
|
|
466
|
+
elements: Map<string, unknown>,
|
|
467
|
+
) {
|
|
468
|
+
const view = scrollBox?.getBoundingClientRect?.();
|
|
469
|
+
const rect = place.anchorId ? messageRect(elements.get(place.anchorId)) : null;
|
|
470
|
+
if (!scrollBox || !view || place.atBottom || !rect || typeof scrollBox.scrollTopPx !== "number") {
|
|
471
|
+
scrollToBottom(scrollBox, true);
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
scrollToPosition(scrollBox, scrollBox.scrollTopPx + (rect.y - view.y) - place.anchorOffsetPx, true);
|
|
475
|
+
}
|
|
476
|
+
|
|
404
477
|
export function getSelectedMessageScrollTop({
|
|
405
478
|
scrollTop,
|
|
406
479
|
viewportHeight,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Badge } from "../../../../components/ui";
|
|
2
|
+
import { Box } from "../../../../ui";
|
|
3
|
+
|
|
4
|
+
/** What the badge takes of a terminal line: the cell before it, then "AI" with a cell of padding either side. */
|
|
5
|
+
export const CHAT_AI_BADGE_WIDTH = 5;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* "AI" and a cell of space before it, beside the name of a managed assistant.
|
|
9
|
+
* The neutral badge is the quietest the kit has; a selected row passes its own
|
|
10
|
+
* text color so the chip stays legible on the selection.
|
|
11
|
+
*/
|
|
12
|
+
export function ChatAiBadge({ selectedColor }: { selectedColor?: string }) {
|
|
13
|
+
return (
|
|
14
|
+
<Box flexShrink={0} paddingLeft={1} data-gloom-role="chat-ai-badge">
|
|
15
|
+
<Badge label="AI" color={selectedColor} />
|
|
16
|
+
</Box>
|
|
17
|
+
);
|
|
18
|
+
}
|