gloomberb 0.16.3 → 0.16.4
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/package.json +4 -1
- package/src/api-client/askg.ts +43 -0
- package/src/api-client/auth.ts +15 -0
- package/src/api-client/beneficial-owners.ts +4 -0
- package/src/api-client/chat.ts +19 -0
- package/src/api-client/company-kpis.ts +14 -2
- package/src/api-client/data.ts +34 -16
- package/src/api-client/index.ts +12 -0
- package/src/api-client/normalizers.ts +27 -0
- package/src/api-client/paths.ts +88 -23
- package/src/api-client/request.ts +2 -1
- package/src/api-client/research-activity.ts +31 -0
- package/src/api-client/socket.ts +39 -8
- package/src/api-client/types.ts +57 -1
- package/src/api-client/upgrade-experiment.ts +90 -0
- package/src/app/global-shortcuts.ts +11 -1
- package/src/app/keybindings/actions.ts +10 -0
- package/src/app/pane-runtime/index.tsx +8 -0
- package/src/app/pane-runtime/pane-template-runtime.ts +5 -0
- package/src/app/pane-runtime/plugin-bindings.ts +65 -25
- package/src/app/pane-runtime/ticker-inspector-runtime.ts +12 -0
- package/src/app/pane-runtime/ticker-open-runtime.ts +18 -1
- package/src/app/runtime/desktop-deeplink.ts +5 -0
- package/src/app/star-prompt/model.ts +98 -0
- package/src/app/star-prompt/runtime.ts +41 -0
- package/src/app/star-prompt/status-line.tsx +190 -0
- package/src/app.tsx +13 -7
- package/src/architecture/core-builtin-allowlist.json +70 -0
- package/src/brokers/signed-in/adapter.ts +33 -2
- package/src/brokers/signed-in/client.ts +10 -0
- package/src/brokers/signed-in/sign-in-dialog.tsx +23 -9
- package/src/brokers/signed-in/sign-in.ts +62 -5
- package/src/capabilities/registry.ts +8 -1
- package/src/capabilities/types.ts +2 -0
- package/src/cli/commands/crypto-hints.ts +12 -4
- package/src/cli/commands/market.ts +359 -99
- package/src/cli/commands/options-chain.ts +172 -0
- package/src/cli/commands/options-leaps.ts +422 -0
- package/src/cli/commands/overview.ts +164 -26
- package/src/cli/commands/search.ts +29 -8
- package/src/cli/commands/system.ts +99 -19
- package/src/cli/commands/themes.ts +64 -0
- package/src/cli/commands/ticker.ts +62 -30
- package/src/cli/desktop-pane-shot.ts +97 -16
- package/src/cli/errors.ts +25 -2
- package/src/cli/freshness.ts +7 -4
- package/src/cli/fx-pair.ts +57 -0
- package/src/cli/help.ts +14 -1
- package/src/cli/index-roots.ts +51 -0
- package/src/cli/index.ts +9 -6
- package/src/cli/listing-arg.ts +211 -3
- package/src/cli/not-a-ticker.ts +37 -0
- package/src/cli/options.ts +50 -6
- package/src/cli/pane-functions/capabilities.ts +8 -2
- package/src/cli/pane-functions/catalog.ts +13 -2
- package/src/cli/pane-functions/data.ts +36 -5
- package/src/cli/pane-functions/dom.ts +21 -13
- package/src/cli/pane-functions/freshness.ts +205 -26
- package/src/cli/pane-functions/function-help.ts +67 -22
- package/src/cli/pane-functions/headless.ts +5 -4
- package/src/cli/pane-functions/index.ts +3 -0
- package/src/cli/pane-functions/market-session.ts +133 -0
- package/src/cli/pane-functions/options.ts +15 -4
- package/src/cli/pane-functions/report-notices.ts +63 -0
- package/src/cli/pane-functions/report.ts +4 -0
- package/src/cli/pane-functions/resolver.ts +4 -6
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +105 -23
- package/src/cli/registry.ts +2 -1
- package/src/cli/result.ts +50 -13
- package/src/cli/row-window.ts +76 -0
- package/src/cli/scroll-truncation.ts +34 -0
- package/src/components/chart/composite/composite-chart.tsx +43 -4
- package/src/components/chart/composite/legend.tsx +39 -6
- package/src/components/chart/composite/rasterizer.ts +64 -4
- package/src/components/chart/composite/series-cues.ts +71 -0
- package/src/components/chart/composite/text-renderer.ts +16 -8
- package/src/components/chart/composite/types.ts +3 -0
- package/src/components/command-bar/commands/direct/index.ts +9 -1
- package/src/components/command-bar/commands/plugin/items.ts +3 -1
- package/src/components/command-bar/commands/registry.ts +7 -0
- package/src/components/command-bar/layout-items/focused-pane.ts +38 -0
- package/src/components/command-bar/pane-templates/workflow.ts +5 -0
- package/src/components/command-bar/routes/root/command-items.ts +2 -0
- package/src/components/command-bar/routes/root/plugin-turn-on.ts +92 -0
- package/src/components/command-bar/routes/root/results.ts +40 -10
- package/src/components/command-bar/routes/root/runtime.ts +8 -0
- package/src/components/command-bar/routes/root/search-providers.ts +97 -14
- package/src/components/command-bar/surface/index.tsx +18 -4
- package/src/components/command-bar/theme-picker.tsx +48 -13
- package/src/components/command-bar/workflow/ops.ts +5 -3
- package/src/components/data-table/view.tsx +28 -9
- package/src/components/layout/floating-pane.tsx +6 -2
- package/src/components/layout/market-summary.ts +23 -9
- package/src/components/layout/pane/content.tsx +46 -29
- package/src/components/layout/pane/cycle-order.ts +2 -11
- package/src/components/layout/pane/header.tsx +2 -1
- package/src/components/layout/pane/title.ts +1 -1
- package/src/components/layout/presentation.ts +22 -0
- package/src/components/layout/shell/active-drag.ts +1 -1
- package/src/components/layout/shell/drag/index.ts +4 -0
- package/src/components/layout/shell/drag/live.ts +76 -5
- package/src/components/layout/shell/drag/runtime.ts +8 -8
- package/src/components/layout/shell/index.tsx +47 -6
- package/src/components/layout/shell/layout-state.ts +5 -11
- package/src/components/layout/shell/menu.ts +28 -1
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +51 -10
- package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
- package/src/components/layout/shell/pane/new-layout.ts +116 -0
- package/src/components/layout/shell/shortcuts.ts +5 -2
- package/src/components/layout/shell/visible-layout.ts +44 -1
- package/src/components/layout/status-bar.tsx +4 -1
- package/src/components/markdown-text.tsx +9 -5
- package/src/components/metric-treemap/heat-surface.tsx +27 -8
- package/src/components/metric-treemap/heat-tiles.ts +48 -17
- package/src/components/onboarding/onboarding-frame.tsx +33 -10
- package/src/components/onboarding/onboarding-wizard.tsx +49 -40
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +5 -2
- package/src/components/onboarding/pro-step-layout.ts +86 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +6 -2
- package/src/components/ui/button.tsx +10 -0
- package/src/components/ui/data-table/index.tsx +38 -0
- package/src/components/ui/data-table/types.ts +8 -1
- package/src/components/ui/data-table/visible-range.ts +2 -0
- package/src/components/ui/icon.tsx +11 -2
- package/src/components/ui/index.ts +1 -1
- package/src/core/connection-health.ts +1 -1
- package/src/core/state/app/layout-reducer.ts +89 -3
- package/src/core/state/app/state.ts +8 -5
- package/src/core/state/app/types.ts +13 -2
- package/src/data/config/layout.ts +55 -21
- package/src/data/config/store/fold-panes.ts +149 -0
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/node.ts +27 -6
- package/src/data/config/store/normalize.ts +37 -3
- package/src/i18n/es.ts +14 -1
- package/src/i18n/ja.ts +14 -1
- package/src/i18n/ko.ts +14 -1
- package/src/i18n/zh-cn.ts +14 -1
- package/src/i18n/zh-tw.ts +14 -1
- package/src/layout/desks.ts +1 -2
- package/src/layout/pane-layout-move.ts +264 -0
- package/src/layout/pane-manager/hidden-panes.ts +160 -0
- package/src/layout/pane-manager/index.ts +1 -0
- package/src/market-data/coordinator/entries.ts +7 -1
- package/src/market-data/coordinator/quotes.ts +2 -2
- package/src/market-data/market/freshness.ts +118 -18
- package/src/market-data/market/status.ts +40 -0
- package/src/market-data/options-alternatives.ts +69 -0
- package/src/market-data/quotes/contributions.ts +19 -2
- package/src/market-data/quotes/metadata.ts +16 -0
- package/src/market-data/quotes/screener-live-quotes.ts +56 -5
- package/src/plugins/builtin/account-management/keyboard.ts +3 -0
- package/src/plugins/builtin/account-management/model.ts +1 -0
- package/src/plugins/builtin/account-management/navigation.ts +1 -1
- package/src/plugins/builtin/account-management/pane.tsx +31 -4
- package/src/plugins/builtin/alerts/quotes.ts +3 -0
- package/src/plugins/builtin/analytics/risk-headless.ts +3 -1
- package/src/plugins/builtin/analytics/risk-model.ts +37 -8
- package/src/plugins/builtin/analytics/risk-pane.tsx +8 -4
- package/src/plugins/builtin/backtest/pane.tsx +1 -1
- package/src/plugins/builtin/broker-manager/detail.tsx +4 -0
- package/src/plugins/builtin/broker-manager/index.tsx +7 -3
- package/src/plugins/builtin/broker-manager/model.ts +8 -0
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -2
- package/src/plugins/builtin/broker-manager/sign-in-end.ts +82 -0
- package/src/plugins/builtin/broker-manager/table.ts +5 -0
- package/src/plugins/builtin/builtin-plugin-meta.ts +121 -11
- package/src/plugins/builtin/chart-composer/pane.tsx +1 -1
- package/src/plugins/builtin/chat/channels.ts +34 -36
- package/src/plugins/builtin/chat/command-bar.ts +138 -0
- package/src/plugins/builtin/chat/composer-commands.ts +21 -1
- package/src/plugins/builtin/chat/content/composer-runtime.ts +11 -1
- package/src/plugins/builtin/chat/content/footer.tsx +5 -3
- package/src/plugins/builtin/chat/content/index.tsx +21 -1
- package/src/plugins/builtin/chat/content/mentions.ts +2 -1
- package/src/plugins/builtin/chat/content/user-map.ts +3 -1
- package/src/plugins/builtin/chat/controller/index.ts +48 -0
- package/src/plugins/builtin/chat/conversations.ts +256 -0
- package/src/plugins/builtin/chat/discord-command.ts +91 -0
- package/src/plugins/builtin/chat/edit-window.ts +12 -6
- package/src/plugins/builtin/chat/ghost-user.ts +14 -0
- package/src/plugins/builtin/chat/index.tsx +40 -2
- package/src/plugins/builtin/chat/layout.ts +2 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +2 -1
- package/src/plugins/builtin/chat/message/header.tsx +24 -15
- package/src/plugins/builtin/chat/message/profile-popover.tsx +2 -1
- package/src/plugins/builtin/chat/message/render-state.ts +3 -0
- package/src/plugins/builtin/chat/pane-requests.ts +60 -0
- package/src/plugins/builtin/chat/pane-state.ts +32 -2
- package/src/plugins/builtin/chat/pane.tsx +8 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +112 -4
- package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
- package/src/plugins/builtin/cloud/askg/manifest.ts +1 -0
- package/src/plugins/builtin/cloud/askg/model.ts +129 -70
- package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
- package/src/plugins/builtin/cloud/askg/protocol.ts +40 -2
- package/src/plugins/builtin/cloud/askg/tool-display.ts +437 -0
- package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -0
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -9
- package/src/plugins/builtin/cloud/mcp-connect/command.ts +24 -0
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +360 -0
- package/src/plugins/builtin/cloud/mcp-connect/model.ts +135 -0
- package/src/plugins/builtin/cloud/mcp-connect/sections.ts +62 -0
- package/src/plugins/builtin/cloud/plugin.tsx +36 -1
- package/src/plugins/builtin/cloud/starter-symbols.ts +8 -0
- package/src/plugins/builtin/cloud/terminal-relay/acm-tab.tsx +89 -0
- package/src/plugins/builtin/cloud/terminal-relay/client.ts +97 -0
- package/src/plugins/builtin/cloud/terminal-relay/connect-section.tsx +57 -0
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +666 -0
- package/src/plugins/builtin/cloud/terminal-relay/grants.ts +137 -0
- package/src/plugins/builtin/cloud/terminal-relay/host.tsx +81 -0
- package/src/plugins/builtin/cloud/terminal-relay/indicator.tsx +82 -0
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +234 -0
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +153 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +168 -0
- package/src/plugins/builtin/cloud/terminal-relay/redact.ts +73 -0
- package/src/plugins/builtin/cloud/terminal-relay/summary.ts +62 -0
- package/src/plugins/builtin/cloud/upgrade-dialog.tsx +26 -2
- package/src/plugins/builtin/cloud/upgrade-personalization.ts +57 -0
- package/src/plugins/builtin/cloud/upgrade-tickers.ts +124 -0
- package/src/plugins/builtin/comment-letters/client.ts +1 -3
- package/src/plugins/builtin/company-kpis/client.ts +23 -8
- package/src/plugins/builtin/company-kpis/headless.ts +3 -1
- package/src/plugins/builtin/company-kpis/pane.tsx +15 -7
- package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
- package/src/plugins/builtin/composite-plugins.ts +107 -64
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +4 -4
- package/src/plugins/builtin/credit-boards/index.tsx +21 -21
- package/src/plugins/builtin/credit-boards/model.ts +0 -1
- package/src/plugins/builtin/credit-boards/pane.tsx +30 -0
- package/src/plugins/builtin/credit-boards/sovr-pane.tsx +4 -4
- package/src/plugins/builtin/debt-maturities/client.ts +37 -9
- package/src/plugins/builtin/debt-maturities/headless.ts +3 -1
- package/src/plugins/builtin/debt-maturities/pane.tsx +5 -4
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
- package/src/plugins/builtin/earnings-calls/data.ts +28 -7
- package/src/plugins/builtin/earnings-calls/headless.ts +3 -2
- package/src/plugins/builtin/earnings-calls/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +42 -17
- package/src/plugins/builtin/econ/detail-view.tsx +2 -2
- package/src/plugins/builtin/econ/index.tsx +68 -22
- package/src/plugins/builtin/econ-statistics/headless.ts +12 -2
- package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
- package/src/plugins/builtin/econ-statistics/view.ts +17 -0
- package/src/plugins/builtin/executives/data.ts +17 -6
- package/src/plugins/builtin/executives/pane.tsx +16 -7
- package/src/plugins/builtin/filing-events/pane.tsx +22 -5
- package/src/plugins/builtin/fx-matrix/freshness.ts +65 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +22 -1
- package/src/plugins/builtin/fx-matrix/pairs.ts +1 -1
- package/src/plugins/builtin/fx-matrix/settings.ts +42 -2
- package/src/plugins/builtin/gpu/headless.ts +9 -3
- package/src/plugins/builtin/gpu/model.ts +14 -5
- package/src/plugins/builtin/help/index.tsx +1 -0
- package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/headless.ts +6 -1
- package/src/plugins/builtin/holders/pane.tsx +3 -0
- package/src/plugins/builtin/insider/index.tsx +4 -4
- package/src/plugins/builtin/iv-history/charts.tsx +21 -7
- package/src/plugins/builtin/iv-history/client.ts +12 -2
- package/src/plugins/builtin/iv-history/format.ts +33 -2
- package/src/plugins/builtin/iv-history/headless.ts +22 -10
- package/src/plugins/builtin/iv-history/index.tsx +3 -3
- package/src/plugins/builtin/iv-history/model.ts +61 -13
- package/src/plugins/builtin/iv-history/pane.tsx +11 -3
- package/src/plugins/builtin/iv-history/screen-pane.tsx +42 -18
- package/src/plugins/builtin/jobs/pane.tsx +1 -1
- package/src/plugins/builtin/kelly-sizer/headless.ts +149 -0
- package/src/plugins/builtin/kelly-sizer/history.ts +80 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +109 -39
- package/src/plugins/builtin/kelly-sizer/sections.tsx +14 -0
- package/src/plugins/builtin/kelly-sizer/types.ts +9 -1
- package/src/plugins/builtin/layout-manager/index.tsx +9 -1
- package/src/plugins/builtin/macro-day/client.ts +24 -0
- package/src/plugins/builtin/macro-day/headless.ts +11 -8
- package/src/plugins/builtin/macro-day/index.tsx +3 -0
- package/src/plugins/builtin/macro-day/model.ts +11 -6
- package/src/plugins/builtin/macro-day/pane.tsx +12 -8
- package/src/plugins/builtin/macro-day/release-table.ts +40 -0
- package/src/plugins/builtin/macro-day/releases.ts +62 -44
- package/src/plugins/builtin/market-heatmap/data.ts +25 -5
- package/src/plugins/builtin/market-heatmap/evidence.ts +90 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +144 -63
- package/src/plugins/builtin/market-heatmap/model.ts +94 -3
- package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
- package/src/plugins/builtin/market-movers/headless.ts +31 -4
- package/src/plugins/builtin/market-movers/index.tsx +8 -1
- package/src/plugins/builtin/market-movers/model.ts +71 -17
- package/src/plugins/builtin/market-movers/table.ts +50 -23
- package/src/plugins/builtin/news/headless.ts +9 -2
- package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
- package/src/plugins/builtin/openfda/client.ts +1 -1
- package/src/plugins/builtin/options/carry.ts +95 -0
- package/src/plugins/builtin/options/index.tsx +58 -5
- package/src/plugins/builtin/options/strike-window.ts +183 -0
- package/src/plugins/builtin/options/table.ts +55 -3
- package/src/plugins/builtin/options/types.ts +8 -1
- package/src/plugins/builtin/options/view.tsx +161 -12
- package/src/plugins/builtin/options-positioning/headless.ts +4 -2
- package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +73 -17
- package/src/plugins/builtin/options-scenario/headless.ts +71 -24
- package/src/plugins/builtin/options-scenario/hedge.ts +284 -0
- package/src/plugins/builtin/options-scenario/index.tsx +9 -2
- package/src/plugins/builtin/options-scenario/model.ts +33 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +40 -16
- package/src/plugins/builtin/pe-band/model.ts +2 -2
- package/src/plugins/builtin/pe-band/report-dates.ts +11 -7
- package/src/plugins/builtin/perps/equity-row.tsx +8 -5
- package/src/plugins/builtin/perps/model.ts +16 -5
- package/src/plugins/builtin/plugin-marketplace/model.ts +64 -21
- package/src/plugins/builtin/plugin-marketplace/packs.ts +118 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +344 -32
- package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
- package/src/plugins/builtin/plugin-module.ts +87 -4
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +71 -36
- package/src/plugins/builtin/portfolio-list/cli/render.ts +87 -18
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +2 -16
- package/src/plugins/builtin/portfolio-list/headless.ts +38 -7
- package/src/plugins/builtin/realized-vol/headless.ts +3 -0
- package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +2 -2
- package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -1
- package/src/plugins/builtin/revenue-breakdown/client.ts +13 -6
- package/src/plugins/builtin/revenue-breakdown/headless.ts +4 -1
- package/src/plugins/builtin/revenue-breakdown/pane.tsx +7 -4
- package/src/plugins/builtin/reverse-dcf/headless.ts +5 -1
- package/src/plugins/builtin/reverse-dcf/pane.tsx +1 -1
- package/src/plugins/builtin/risk-factors/data.ts +23 -9
- package/src/plugins/builtin/risk-factors/headless.ts +5 -2
- package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
- package/src/plugins/builtin/seasonality/pane.tsx +1 -1
- package/src/plugins/builtin/sec/index.tsx +5 -5
- package/src/plugins/builtin/sectors/client.ts +10 -2
- package/src/plugins/builtin/sectors/headless.ts +35 -6
- package/src/plugins/builtin/sectors/index.tsx +18 -1
- package/src/plugins/builtin/sectors/sector-model.ts +150 -41
- package/src/plugins/builtin/shared/command-tab.ts +51 -0
- package/src/plugins/builtin/shared/headless-market-data.ts +33 -1
- package/src/plugins/builtin/shared/members-menu.tsx +4 -4
- package/src/plugins/builtin/shared/report-freshness.ts +50 -2
- package/src/plugins/builtin/shared/ticker-request.ts +25 -1
- package/src/plugins/builtin/shared/use-quote-board.ts +25 -5
- package/src/plugins/builtin/shared/volatility/options.ts +1 -46
- package/src/plugins/builtin/short-interest/index.tsx +19 -4
- package/src/plugins/builtin/short-interest/surface.tsx +4 -4
- package/src/plugins/builtin/short-volume/index.tsx +1 -10
- package/src/plugins/builtin/supply-chain/model.ts +1 -1
- package/src/plugins/builtin/ticker-detail/headless.ts +43 -21
- package/src/plugins/builtin/ticker-detail/pane.tsx +4 -5
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +94 -6
- package/src/plugins/builtin/treasury-auctions/cache.ts +5 -2
- package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
- package/src/plugins/builtin/treasury-auctions/headless.ts +40 -4
- package/src/plugins/builtin/treasury-auctions/index.tsx +11 -9
- package/src/plugins/builtin/treasury-auctions/model.ts +197 -30
- package/src/plugins/builtin/treasury-auctions/pane.tsx +35 -11
- package/src/plugins/builtin/treasury-auctions/types.ts +11 -1
- package/src/plugins/builtin/vol-surface/charts.tsx +1 -3
- package/src/plugins/builtin/vol-surface/client.ts +6 -2
- package/src/plugins/builtin/vol-surface/evidence.ts +11 -6
- package/src/plugins/builtin/vol-surface/headless.ts +124 -20
- package/src/plugins/builtin/vol-surface/model.ts +23 -11
- package/src/plugins/builtin/vol-surface/pane.tsx +38 -27
- package/src/plugins/builtin/vol-surface/tables.ts +124 -0
- package/src/plugins/builtin/world-indices/client.ts +22 -4
- package/src/plugins/builtin/world-indices/headless.ts +54 -27
- package/src/plugins/builtin/world-indices/model.ts +4 -2
- package/src/plugins/builtin/world-indices/table.tsx +13 -2
- package/src/plugins/builtin/world-venue-map/geo-series.ts +1 -1
- package/src/plugins/builtin/world-venue-map/index.ts +1 -1
- package/src/plugins/builtin/yield-curve/index.tsx +1 -1
- package/src/plugins/builtin-editorial.ts +126 -0
- package/src/plugins/catalog-backend.ts +16 -9
- package/src/plugins/catalog-browser.ts +127 -63
- package/src/plugins/catalog-manifest.ts +73 -40
- package/src/plugins/catalog-ui.ts +26 -6
- package/src/plugins/extracted-plugins.ts +7 -1
- package/src/plugins/ownership.ts +150 -7
- package/src/plugins/plugin-functions.ts +54 -0
- package/src/plugins/plugin-off.ts +36 -0
- package/src/plugins/registry/host-actions.ts +16 -0
- package/src/plugins/registry/index.ts +84 -24
- package/src/plugins/registry/plugin-state.ts +25 -1
- package/src/plugins/runtime/context.tsx +29 -0
- package/src/react/input.ts +48 -1
- package/src/remote/app-host.tsx +5 -0
- package/src/remote/controller.ts +3 -53
- package/src/remote/matching.ts +69 -0
- package/src/remote/schema.ts +1 -1
- package/src/remote/semantic-tree.tsx +14 -0
- package/src/remote/types.ts +2 -0
- package/src/renderers/dom/desktop/icons.tsx +14 -0
- package/src/renderers/dom/desktop/query-bar.tsx +59 -32
- package/src/renderers/dom/host/box.tsx +1 -1
- package/src/renderers/dom/host/drag-shield.ts +17 -6
- package/src/renderers/dom/host/live-frame.ts +10 -2
- package/src/renderers/dom/input-host.tsx +6 -1
- package/src/renderers/dom/styles.css +13 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +5 -1
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +12 -1
- package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -1
- package/src/renderers/electrobun/shared/protocol.ts +2 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +101 -5
- package/src/renderers/electrobun/view/main.tsx +4 -1
- package/src/renderers/opentui/input-host.tsx +6 -1
- package/src/renderers/opentui/start.tsx +9 -0
- package/src/shares/portable-layout.ts +16 -6
- package/src/sources/gloomberb-cloud/index.ts +19 -10
- package/src/sources/gloomberb-cloud/normalizers.ts +4 -1
- package/src/sources/listing-symbols.ts +11 -5
- package/src/sources/provider-errors.ts +88 -3
- package/src/sources/provider-router/cached-routes.ts +8 -4
- package/src/sources/provider-router/financial-routes.ts +11 -5
- package/src/sources/provider-router/financials.ts +42 -15
- package/src/sources/provider-router/history.ts +27 -11
- package/src/sources/provider-router/index.ts +1 -1
- package/src/sources/provider-router/primary.ts +23 -5
- package/src/sources/sec-edgar.ts +68 -8
- package/src/sync/core-contributors.ts +4 -3
- package/src/test-support/cli-context.ts +2 -1
- package/src/test-support/data-provider.ts +34 -0
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/series-colors.ts +46 -0
- package/src/theme/themes.ts +149 -0
- package/src/tickers/search/index.ts +22 -2
- package/src/tickers/search/ranking.ts +45 -1
- package/src/tickers/search/types.ts +3 -1
- package/src/time-series/resolve.ts +1 -14
- package/src/types/config.ts +61 -1
- package/src/types/headless.ts +11 -0
- package/src/types/instrument.ts +8 -0
- package/src/types/plugin.ts +49 -3
- package/src/ui/host.tsx +8 -4
- package/src/ui/index.tsx +2 -0
- package/src/utils/cli-output.ts +14 -1
- package/src/utils/exchanges.ts +13 -0
- package/src/utils/format.ts +2 -1
- package/src/utils/fx-market-hours.ts +34 -0
- package/src/utils/option-expiry.ts +126 -0
- package/src/utils/price-history.ts +39 -6
- package/src/utils/rpc-timeout-error.ts +6 -2
- package/src/utils/sec-eps-basis.ts +159 -30
- package/src/utils/sec.ts +38 -34
- package/src/utils/throttled-fetch.ts +51 -22
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import type { FunctionAccess } from "../cli/pane-functions/function-help";
|
|
2
|
+
import type { GloomPlugin, PluginTarget } from "../types/plugin";
|
|
1
3
|
import { ABSORBED_PLUGINS } from "./absorbed";
|
|
4
|
+
import { highlightedCodes, pluginFunctions } from "./plugin-functions";
|
|
5
|
+
import { BUILTIN_EDITORIAL } from "./builtin-editorial";
|
|
2
6
|
import { getPluginCatalog } from "./catalog";
|
|
7
|
+
import { browserBuiltinPlugins } from "./catalog-browser";
|
|
3
8
|
|
|
4
9
|
/**
|
|
5
10
|
* The public description of the plugins that ship inside Gloomberb.
|
|
@@ -8,71 +13,80 @@ import { getPluginCatalog } from "./catalog";
|
|
|
8
13
|
* built-in has no repository to read metadata from. Hand-maintaining that half
|
|
9
14
|
* elsewhere meant it silently drifted every time a built-in changed its panes
|
|
10
15
|
* or description, so it is derived from the live catalog here instead and
|
|
11
|
-
* checked against a committed snapshot in CI.
|
|
16
|
+
* checked against a committed snapshot in CI. Editorial copy the catalog does
|
|
17
|
+
* not carry lives in `builtin-editorial.ts`.
|
|
18
|
+
*
|
|
19
|
+
* Fields added since the first version are optional for the directory, which
|
|
20
|
+
* keeps reading a manifest without them.
|
|
12
21
|
*/
|
|
13
22
|
|
|
23
|
+
/** A function the plugin adds, as the directory lists it. */
|
|
24
|
+
interface BuiltinShortcutManifestEntry {
|
|
25
|
+
code: string;
|
|
26
|
+
name: string;
|
|
27
|
+
description: string;
|
|
28
|
+
/** Free gets only the upgrade (`pro`) or a preview (`preview`); absent when Free gets it all. */
|
|
29
|
+
access?: FunctionAccess;
|
|
30
|
+
/** Where it runs, when that is narrower than the plugin: a code the web app lacks. */
|
|
31
|
+
targets?: PluginTarget[];
|
|
32
|
+
}
|
|
33
|
+
|
|
14
34
|
interface BuiltinPluginManifestEntry {
|
|
15
35
|
id: string;
|
|
16
36
|
name: string;
|
|
17
37
|
description: string;
|
|
38
|
+
/** Ten words at most, for a card. */
|
|
39
|
+
tagline?: string;
|
|
18
40
|
/** Curated, since the catalog has no notion of categories. */
|
|
19
41
|
categories: string[];
|
|
20
42
|
toggleable: boolean;
|
|
21
43
|
featured?: true;
|
|
22
44
|
/** Path to artwork in this repo, resolved by the directory against HEAD. */
|
|
23
45
|
icon?: string;
|
|
46
|
+
/** Everywhere the app runs, and the web when the browser catalog carries it. */
|
|
47
|
+
targets: PluginTarget[];
|
|
24
48
|
contributes: {
|
|
25
49
|
panes: string[];
|
|
26
50
|
capabilities: string[];
|
|
27
51
|
broker: boolean;
|
|
52
|
+
shortcuts?: BuiltinShortcutManifestEntry[];
|
|
28
53
|
};
|
|
54
|
+
/** The codes a card shows. */
|
|
55
|
+
highlights?: string[];
|
|
56
|
+
/** Codes whose reviewed capture the directory shows, best first. */
|
|
57
|
+
screenshots?: string[];
|
|
29
58
|
}
|
|
30
59
|
|
|
31
|
-
/**
|
|
32
|
-
* Editorial metadata the runtime catalog does not carry. Anything missing here
|
|
33
|
-
* is reported by `generate-plugin-manifest.ts` rather than silently defaulted,
|
|
34
|
-
* so a new built-in cannot slip into the directory uncategorised.
|
|
35
|
-
*/
|
|
36
|
-
const EDITORIAL: Record<
|
|
37
|
-
string,
|
|
38
|
-
{ categories: string[]; featured?: true; icon?: string }
|
|
39
|
-
> = {
|
|
40
|
-
"gloomberb-cloud": {
|
|
41
|
-
categories: ["data", "cloud"],
|
|
42
|
-
featured: true,
|
|
43
|
-
icon: "plugin-icons/gloomberb-cloud.webp",
|
|
44
|
-
},
|
|
45
|
-
alerts: { categories: ["alerts"] },
|
|
46
|
-
application: { categories: ["core"] },
|
|
47
|
-
broker: { categories: ["broker"] },
|
|
48
|
-
"clinical-trials": { categories: ["research"] },
|
|
49
|
-
"comment-letters": { categories: ["research"] },
|
|
50
|
-
"custom-view": { categories: ["data", "productivity"] },
|
|
51
|
-
debug: { categories: ["developer"] },
|
|
52
|
-
"fear-greed": { categories: ["markets", "sentiment"], icon: "plugin-icons/fear-greed.webp" },
|
|
53
|
-
members: { categories: ["markets", "research"] },
|
|
54
|
-
"ipo-calendar": { categories: ["macro", "markets"], icon: "plugin-icons/ipo-calendar.webp" },
|
|
55
|
-
macro: { categories: ["macro"] },
|
|
56
|
-
"market-halts": { categories: ["markets"], icon: "plugin-icons/market-halts.webp" },
|
|
57
|
-
"market-heatmap": { categories: ["markets"], icon: "plugin-icons/market-heatmap.webp" },
|
|
58
|
-
"market-overview": { categories: ["markets"] },
|
|
59
|
-
news: { categories: ["news"] },
|
|
60
|
-
notes: { categories: ["productivity"] },
|
|
61
|
-
openfda: { categories: ["research"] },
|
|
62
|
-
portfolio: { categories: ["portfolio"] },
|
|
63
|
-
"research-search": { categories: ["research", "news"] },
|
|
64
|
-
"ticker-research": { categories: ["research"] },
|
|
65
|
-
};
|
|
66
|
-
|
|
67
60
|
export interface BuiltinManifest {
|
|
68
61
|
version: 1;
|
|
69
62
|
plugins: BuiltinPluginManifestEntry[];
|
|
70
63
|
/** Built-in ids with no editorial entry; a non-empty list fails generation. */
|
|
71
64
|
uncategorised: string[];
|
|
65
|
+
/** Editorial highlights or screenshots naming a code the plugin lacks, as `id:CODE`; these fail generation too. */
|
|
66
|
+
unknownCodes: string[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const NATIVE_TARGETS: PluginTarget[] = ["cli", "tui", "desktop"];
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The codes a plugin's pane templates answer to. Commands a plugin registers
|
|
73
|
+
* while it sets up (ALRT, NOTE) are not known until it runs, so they are not
|
|
74
|
+
* listed; the Plugins pane reads them from the running app.
|
|
75
|
+
*/
|
|
76
|
+
function functionsOf(plugin: GloomPlugin) {
|
|
77
|
+
return pluginFunctions({
|
|
78
|
+
templates: (plugin.paneTemplates ?? []).map((template) => ({
|
|
79
|
+
label: template.label,
|
|
80
|
+
prefix: template.shortcut?.prefix,
|
|
81
|
+
description: template.description,
|
|
82
|
+
})),
|
|
83
|
+
});
|
|
72
84
|
}
|
|
73
85
|
|
|
74
86
|
export function buildBuiltinManifest(): BuiltinManifest {
|
|
75
87
|
const uncategorised: string[] = [];
|
|
88
|
+
const unknownCodes: string[] = [];
|
|
89
|
+
const web = new Map(browserBuiltinPlugins.map((plugin) => [plugin.id, plugin]));
|
|
76
90
|
|
|
77
91
|
const plugins = getPluginCatalog()
|
|
78
92
|
// Built in again, but released apps from before that still install these
|
|
@@ -80,18 +94,34 @@ export function buildBuiltinManifest(): BuiltinManifest {
|
|
|
80
94
|
// id a built-in claims. This build shows that row as its built-in, so they
|
|
81
95
|
// join the manifest once those releases have updated.
|
|
82
96
|
.filter(({ plugin }) => !ABSORBED_PLUGINS.some((absorbed) => absorbed.id === plugin.id))
|
|
83
|
-
.map(({ plugin }) => {
|
|
84
|
-
const editorial =
|
|
97
|
+
.map(({ plugin }): BuiltinPluginManifestEntry => {
|
|
98
|
+
const editorial = BUILTIN_EDITORIAL[plugin.id];
|
|
85
99
|
if (!editorial) uncategorised.push(plugin.id);
|
|
86
100
|
|
|
101
|
+
// Some built-ins carry fewer functions in the web app.
|
|
102
|
+
const webPlugin = web.get(plugin.id);
|
|
103
|
+
const webCodes = new Set(webPlugin ? functionsOf(webPlugin).map((fn) => fn.code) : []);
|
|
104
|
+
const functions = functionsOf(plugin);
|
|
105
|
+
const shortcuts = functions.map((fn): BuiltinShortcutManifestEntry => ({
|
|
106
|
+
...fn,
|
|
107
|
+
...(webPlugin && !webCodes.has(fn.code) ? { targets: [...NATIVE_TARGETS] } : {}),
|
|
108
|
+
}));
|
|
109
|
+
const codes = new Set(functions.map((fn) => fn.code));
|
|
110
|
+
for (const code of [...editorial?.highlights ?? [], ...editorial?.screenshots ?? []]) {
|
|
111
|
+
if (!codes.has(code)) unknownCodes.push(`${plugin.id}:${code}`);
|
|
112
|
+
}
|
|
113
|
+
const screenshots = (editorial?.screenshots ?? []).filter((code) => codes.has(code));
|
|
114
|
+
|
|
87
115
|
return {
|
|
88
116
|
id: plugin.id,
|
|
89
117
|
name: plugin.name,
|
|
90
118
|
description: plugin.description ?? "",
|
|
119
|
+
...(editorial?.tagline ? { tagline: editorial.tagline } : {}),
|
|
91
120
|
categories: editorial?.categories ?? [],
|
|
92
121
|
toggleable: plugin.toggleable === true,
|
|
93
122
|
...(editorial?.featured ? { featured: true as const } : {}),
|
|
94
123
|
...(editorial?.icon ? { icon: editorial.icon } : {}),
|
|
124
|
+
targets: webPlugin ? [...NATIVE_TARGETS, "web"] : [...NATIVE_TARGETS],
|
|
95
125
|
contributes: {
|
|
96
126
|
panes: (plugin.panes ?? []).map((pane) => pane.id).sort(),
|
|
97
127
|
capabilities: (plugin.capabilities ?? [])
|
|
@@ -101,10 +131,13 @@ export function buildBuiltinManifest(): BuiltinManifest {
|
|
|
101
131
|
})
|
|
102
132
|
.sort(),
|
|
103
133
|
broker: !!plugin.broker,
|
|
134
|
+
...(shortcuts.length > 0 ? { shortcuts } : {}),
|
|
104
135
|
},
|
|
136
|
+
...(functions.length > 0 ? { highlights: highlightedCodes(plugin.id, functions) } : {}),
|
|
137
|
+
...(screenshots.length > 0 ? { screenshots } : {}),
|
|
105
138
|
};
|
|
106
139
|
})
|
|
107
140
|
.sort((left, right) => left.id.localeCompare(right.id));
|
|
108
141
|
|
|
109
|
-
return { version: 1, plugins, uncategorised: uncategorised.sort() };
|
|
142
|
+
return { version: 1, plugins, uncategorised: uncategorised.sort(), unknownCodes };
|
|
110
143
|
}
|
|
@@ -15,24 +15,42 @@ import { clinicalTrialsPlugin } from "./builtin/clinical-trials";
|
|
|
15
15
|
import { commentLettersPlugin } from "./builtin/comment-letters";
|
|
16
16
|
import { openFdaPlugin } from "./builtin/openfda";
|
|
17
17
|
import {
|
|
18
|
+
altDataPlugin,
|
|
18
19
|
applicationPlugin,
|
|
19
20
|
brokerPlugin,
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
creditPlugin,
|
|
22
|
+
cryptoPlugin,
|
|
23
|
+
earningsPlugin,
|
|
24
|
+
filingsPlugin,
|
|
25
|
+
futuresCommoditiesPlugin,
|
|
26
|
+
globalMarketsPlugin,
|
|
27
|
+
optionsVolatilityPlugin,
|
|
28
|
+
ownershipPlugin,
|
|
22
29
|
portfolioPlugin,
|
|
23
|
-
|
|
30
|
+
quantPlugin,
|
|
31
|
+
ratesMacroPlugin,
|
|
32
|
+
screenersPlugin,
|
|
33
|
+
tickerCorePlugin,
|
|
24
34
|
} from "./builtin/composite-plugins";
|
|
25
35
|
|
|
26
36
|
export const uiBuiltinPlugins: GloomPlugin[] = [
|
|
27
37
|
gloomberbCloudPlugin,
|
|
28
38
|
portfolioPlugin,
|
|
29
|
-
|
|
39
|
+
tickerCorePlugin,
|
|
40
|
+
optionsVolatilityPlugin,
|
|
41
|
+
ownershipPlugin,
|
|
42
|
+
filingsPlugin,
|
|
30
43
|
brokerPlugin,
|
|
31
44
|
applicationPlugin,
|
|
32
45
|
newsPlugin,
|
|
33
46
|
notesPlugin,
|
|
34
47
|
customViewPlugin,
|
|
35
|
-
|
|
48
|
+
globalMarketsPlugin,
|
|
49
|
+
screenersPlugin,
|
|
50
|
+
futuresCommoditiesPlugin,
|
|
51
|
+
cryptoPlugin,
|
|
52
|
+
altDataPlugin,
|
|
53
|
+
quantPlugin,
|
|
36
54
|
marketHeatmapPlugin,
|
|
37
55
|
marketHaltsPlugin,
|
|
38
56
|
fearGreedPlugin,
|
|
@@ -41,7 +59,9 @@ export const uiBuiltinPlugins: GloomPlugin[] = [
|
|
|
41
59
|
clinicalTrialsPlugin,
|
|
42
60
|
commentLettersPlugin,
|
|
43
61
|
openFdaPlugin,
|
|
44
|
-
|
|
62
|
+
ratesMacroPlugin,
|
|
63
|
+
creditPlugin,
|
|
64
|
+
earningsPlugin,
|
|
45
65
|
alertsPlugin,
|
|
46
66
|
researchSearchPlugin,
|
|
47
67
|
];
|
|
@@ -4,6 +4,7 @@ import { join } from "path";
|
|
|
4
4
|
import type { AppConfig } from "../types/config";
|
|
5
5
|
import { debugLog } from "../utils/debug-log";
|
|
6
6
|
import { getPluginsDir } from "./loader";
|
|
7
|
+
import { encodeBuiltinDisabledPluginIds } from "./ownership";
|
|
7
8
|
import { pluginDirectoryNames } from "./plugin-names";
|
|
8
9
|
|
|
9
10
|
const log = debugLog.createLogger("plugin-seed");
|
|
@@ -63,7 +64,12 @@ export async function seedExtractedPlugins(
|
|
|
63
64
|
pluginsDir: string = getPluginsDir(),
|
|
64
65
|
): Promise<SeedResult> {
|
|
65
66
|
const alreadySeeded = new Set(config.seededPlugins ?? []);
|
|
66
|
-
|
|
67
|
+
// A previous owner that is now a group of built-ins counts as off only while
|
|
68
|
+
// all of them are, which is when its id is saved.
|
|
69
|
+
const disabled = new Set([
|
|
70
|
+
...config.disabledPlugins ?? [],
|
|
71
|
+
...encodeBuiltinDisabledPluginIds(config.disabledPlugins ?? []),
|
|
72
|
+
]);
|
|
67
73
|
|
|
68
74
|
const result: SeedResult = { installed: [], failed: [], seeded: [...alreadySeeded] };
|
|
69
75
|
|
package/src/plugins/ownership.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Built-in module ids and the
|
|
3
|
-
* does two jobs: config, sync and session state saved under it is
|
|
4
|
-
*
|
|
5
|
-
* have its state merged
|
|
6
|
-
* to an external plugin leaves this map so that plugin can claim its id.
|
|
2
|
+
* Built-in module ids and the state namespace each one's state lives in now.
|
|
3
|
+
* Every key does two jobs: config, sync and session state saved under it is
|
|
4
|
+
* rewritten to that namespace, and it is reserved, because an external plugin
|
|
5
|
+
* using it would have its state merged in the same way. A module that moves
|
|
6
|
+
* out to an external plugin leaves this map so that plugin can claim its id.
|
|
7
|
+
*
|
|
8
|
+
* A switched-off module id in `disabledPlugins` follows this map too, unless
|
|
9
|
+
* BUILTIN_DISABLED_PLUGIN_ALIASES sends it somewhere else.
|
|
7
10
|
*/
|
|
8
11
|
const BUILTIN_PLUGIN_OWNER_ALIASES: Record<string, string> = {
|
|
9
12
|
analytics: "portfolio",
|
|
@@ -42,6 +45,90 @@ const BUILTIN_PLUGIN_OWNER_ALIASES: Record<string, string> = {
|
|
|
42
45
|
"world-indices": "market-overview",
|
|
43
46
|
};
|
|
44
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Retired ids in `disabledPlugins` whose plugin is not the namespace their
|
|
50
|
+
* state moved to: once a plugin is split, a module's state stays where it was
|
|
51
|
+
* while its switch belongs to the successor that holds the module now.
|
|
52
|
+
*/
|
|
53
|
+
const BUILTIN_DISABLED_PLUGIN_ALIASES: Record<string, string> = {
|
|
54
|
+
"chart-composer": "ticker-core",
|
|
55
|
+
"company-research": "ticker-core",
|
|
56
|
+
"comparison-chart": "ticker-core",
|
|
57
|
+
correlation: "quant",
|
|
58
|
+
"crypto-board": "crypto",
|
|
59
|
+
"dividend-yield": "ticker-core",
|
|
60
|
+
"earnings-calendar": "earnings",
|
|
61
|
+
"earnings-calls": "earnings",
|
|
62
|
+
executives: "ticker-core",
|
|
63
|
+
"filing-events": "filings",
|
|
64
|
+
"fx-matrix": "global-markets",
|
|
65
|
+
holders: "ownership",
|
|
66
|
+
insider: "ownership",
|
|
67
|
+
jobs: "alt-data",
|
|
68
|
+
"market-movers": "screeners",
|
|
69
|
+
options: "options-volatility",
|
|
70
|
+
research: "ticker-core",
|
|
71
|
+
"risk-factors": "filings",
|
|
72
|
+
sec: "filings",
|
|
73
|
+
sectors: "global-markets",
|
|
74
|
+
"short-interest": "ownership",
|
|
75
|
+
"short-volume": "ownership",
|
|
76
|
+
"social-mentions": "alt-data",
|
|
77
|
+
thirteenf: "ownership",
|
|
78
|
+
"ticker-detail": "ticker-core",
|
|
79
|
+
"world-indices": "global-markets",
|
|
80
|
+
// `macro-tv` keeps meaning all of Macro: TV left for its own repository, so
|
|
81
|
+
// no successor holds it, and turning it off was turning Macro off.
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Retired built-in plugin ids that now stand for a group of built-ins in
|
|
86
|
+
* `disabledPlugins`, reserved for good. Turning the old plugin off, here or in
|
|
87
|
+
* an older app through sync, turns off every successor holding one of its
|
|
88
|
+
* modules; the old id is written back only while all of them are off, so an
|
|
89
|
+
* older app shows it off exactly then, and turning it back on there brings
|
|
90
|
+
* them all back.
|
|
91
|
+
*/
|
|
92
|
+
const BUILTIN_PLUGIN_GROUPS: Readonly<Record<string, readonly string[]>> = {
|
|
93
|
+
macro: ["rates-macro", "credit", "earnings"],
|
|
94
|
+
"market-overview": ["global-markets", "screeners", "futures-commodities", "crypto", "alt-data", "quant"],
|
|
95
|
+
// Shares Credit & Bonds and Earnings with Macro, and Alt Data and Quant with
|
|
96
|
+
// Market Overview: each holds modules from both.
|
|
97
|
+
"ticker-research": ["ticker-core", "options-volatility", "ownership", "filings", "alt-data", "quant", "credit", "earnings"],
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/** Every built-in that came out of a retired group: the plugins starter packs switch. */
|
|
101
|
+
export function regroupedBuiltinPluginIds(): string[] {
|
|
102
|
+
return [...new Set(Object.values(BUILTIN_PLUGIN_GROUPS).flat())];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** The built-ins a retired group id stands for, or null when the id is not a group. */
|
|
106
|
+
export function builtinPluginGroupMembers(pluginId: string): readonly string[] | null {
|
|
107
|
+
return Object.prototype.hasOwnProperty.call(BUILTIN_PLUGIN_GROUPS, pluginId) ? BUILTIN_PLUGIN_GROUPS[pluginId]! : null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* `disabledPlugins` after switching plugins on or off in one go, or null when
|
|
112
|
+
* nothing changes. A retired group id switches every member, the way
|
|
113
|
+
* `gloomberb plugin enable|disable` does. Changes apply in order, so a later
|
|
114
|
+
* one wins for a plugin two groups share.
|
|
115
|
+
*/
|
|
116
|
+
export function applyPluginToggles(
|
|
117
|
+
disabledPlugins: readonly string[],
|
|
118
|
+
changes: Readonly<Record<string, boolean>>,
|
|
119
|
+
): string[] | null {
|
|
120
|
+
let next = [...disabledPlugins];
|
|
121
|
+
for (const [pluginId, enabled] of Object.entries(changes)) {
|
|
122
|
+
for (const memberId of builtinPluginGroupMembers(pluginId) ?? [pluginId]) {
|
|
123
|
+
if (enabled) next = next.filter((entry) => entry !== memberId);
|
|
124
|
+
else if (!next.includes(memberId)) next.push(memberId);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const unchanged = next.length === disabledPlugins.length
|
|
128
|
+
&& next.every((pluginId, index) => pluginId === disabledPlugins[index]);
|
|
129
|
+
return unchanged ? null : next;
|
|
130
|
+
}
|
|
131
|
+
|
|
45
132
|
/** The one built-in that cannot be disabled; its legacy module ids normalize to it. */
|
|
46
133
|
const NON_TOGGLEABLE_BUILTIN_PLUGIN_ID = "application";
|
|
47
134
|
|
|
@@ -54,18 +141,74 @@ function normalizeBuiltinPluginOwnerId(pluginId: string): string {
|
|
|
54
141
|
return BUILTIN_PLUGIN_OWNER_ALIASES[pluginId] ?? pluginId;
|
|
55
142
|
}
|
|
56
143
|
|
|
144
|
+
/** Every retired built-in module id, for checks that each still lands on the right plugin. */
|
|
145
|
+
export function retiredBuiltinModuleIds(): string[] {
|
|
146
|
+
return Object.keys(BUILTIN_PLUGIN_OWNER_ALIASES);
|
|
147
|
+
}
|
|
148
|
+
|
|
57
149
|
export function isReservedBuiltinPluginId(pluginId: string): boolean {
|
|
58
|
-
return Object.prototype.hasOwnProperty.call(BUILTIN_PLUGIN_OWNER_ALIASES, pluginId)
|
|
150
|
+
return Object.prototype.hasOwnProperty.call(BUILTIN_PLUGIN_OWNER_ALIASES, pluginId)
|
|
151
|
+
|| builtinPluginGroupMembers(pluginId) !== null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function normalizeBuiltinDisabledPluginId(pluginId: string): string {
|
|
155
|
+
return BUILTIN_DISABLED_PLUGIN_ALIASES[pluginId] ?? normalizeBuiltinPluginOwnerId(pluginId);
|
|
59
156
|
}
|
|
60
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Rewrites retired module ids to the plugin that holds the module now. Group
|
|
160
|
+
* ids are left as they are: the configuration migrations after this one read
|
|
161
|
+
* them before `expandBuiltinPluginGroups` runs.
|
|
162
|
+
*/
|
|
61
163
|
export function normalizeBuiltinDisabledPluginIds(pluginIds: readonly string[]): string[] {
|
|
62
164
|
return [...new Set(
|
|
63
165
|
pluginIds
|
|
64
|
-
.map(
|
|
166
|
+
.map(normalizeBuiltinDisabledPluginId)
|
|
65
167
|
.filter((pluginId) => pluginId !== NON_TOGGLEABLE_BUILTIN_PLUGIN_ID),
|
|
66
168
|
)];
|
|
67
169
|
}
|
|
68
170
|
|
|
171
|
+
/**
|
|
172
|
+
* `disabledPlugins` as saved, in the ids the registry knows: a retired group
|
|
173
|
+
* id becomes every member. Applied on every load, after the migrations; it
|
|
174
|
+
* only ever adds switched-off plugins, and running it twice changes nothing.
|
|
175
|
+
*/
|
|
176
|
+
export function expandBuiltinPluginGroups(pluginIds: readonly string[]): string[] {
|
|
177
|
+
return [...new Set(pluginIds.flatMap((pluginId) => builtinPluginGroupMembers(pluginId) ?? [pluginId]))];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* `disabledPlugins` as pulled. Another device may run an app from before
|
|
182
|
+
* modules were merged or plugins split, so retired module ids are rewritten
|
|
183
|
+
* as the migrations would, then groups expanded.
|
|
184
|
+
*/
|
|
185
|
+
export function decodeBuiltinDisabledPluginIds(pluginIds: readonly string[]): string[] {
|
|
186
|
+
return expandBuiltinPluginGroups(normalizeBuiltinDisabledPluginIds(pluginIds));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* `disabledPlugins` as written to disk and pushed: a group whose members are
|
|
191
|
+
* all off is written as its retired id alone, where its first member stood,
|
|
192
|
+
* and a group partly off as the members that are. Expanding the result gives
|
|
193
|
+
* the list back.
|
|
194
|
+
*/
|
|
195
|
+
export function encodeBuiltinDisabledPluginIds(pluginIds: readonly string[]): string[] {
|
|
196
|
+
const disabled = new Set(pluginIds);
|
|
197
|
+
const fullyOff = Object.entries(BUILTIN_PLUGIN_GROUPS)
|
|
198
|
+
.filter(([, members]) => members.length > 0 && members.every((member) => disabled.has(member)));
|
|
199
|
+
if (fullyOff.length === 0) return [...disabled];
|
|
200
|
+
const groupAt = new Map<string, string[]>();
|
|
201
|
+
for (const [groupId, members] of fullyOff) {
|
|
202
|
+
const first = pluginIds.find((pluginId) => members.includes(pluginId))!;
|
|
203
|
+
groupAt.set(first, [...(groupAt.get(first) ?? []), groupId]);
|
|
204
|
+
}
|
|
205
|
+
const covered = new Set(fullyOff.flatMap(([, members]) => members));
|
|
206
|
+
return [...new Set(pluginIds.flatMap((pluginId) => [
|
|
207
|
+
...(groupAt.get(pluginId) ?? []),
|
|
208
|
+
...(covered.has(pluginId) ? [] : [pluginId]),
|
|
209
|
+
]))];
|
|
210
|
+
}
|
|
211
|
+
|
|
69
212
|
export function normalizeBuiltinPluginStateMap(
|
|
70
213
|
value: Record<string, Record<string, unknown>>,
|
|
71
214
|
): Record<string, Record<string, unknown>> {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { FUNCTION_HELP, type FunctionAccess } from "../cli/pane-functions/function-help";
|
|
2
|
+
import { commands as coreCommands, getCommandPrefixes } from "../components/command-bar/commands/registry";
|
|
3
|
+
import { BUILTIN_EDITORIAL } from "./builtin-editorial";
|
|
4
|
+
|
|
5
|
+
/** A command-bar function a plugin adds, as the Plugins pane and gloom.sh list it. */
|
|
6
|
+
export interface PluginFunction {
|
|
7
|
+
code: string;
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
access?: FunctionAccess;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface FunctionSources {
|
|
14
|
+
templates: ReadonlyArray<{ label: string; prefix?: string; description?: string }>;
|
|
15
|
+
commands?: ReadonlyArray<{ label: string; shortcut?: string; description?: string }>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** The core command an alias belongs to: the research pane's T is DES. */
|
|
19
|
+
const CORE_PRIMARY = new Map(coreCommands.flatMap((command) => {
|
|
20
|
+
const [primary, ...aliases] = getCommandPrefixes(command);
|
|
21
|
+
return primary ? aliases.map((alias) => [alias, primary] as const) : [];
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The functions a plugin answers to, once each, in the order it registered
|
|
26
|
+
* them: its pane templates, then its commands. A code that is an alias of a
|
|
27
|
+
* core command is listed under the code people type.
|
|
28
|
+
*/
|
|
29
|
+
export function pluginFunctions({ templates, commands = [] }: FunctionSources): PluginFunction[] {
|
|
30
|
+
const byCode = new Map<string, PluginFunction>();
|
|
31
|
+
const add = (rawCode: string | undefined, name: string, description = "") => {
|
|
32
|
+
const typed = rawCode?.trim().toUpperCase();
|
|
33
|
+
if (!typed) return;
|
|
34
|
+
const code = CORE_PRIMARY.get(typed) ?? typed;
|
|
35
|
+
if (byCode.has(code)) return;
|
|
36
|
+
const access = FUNCTION_HELP[code]?.access;
|
|
37
|
+
byCode.set(code, { code, name, description, ...(access ? { access } : {}) });
|
|
38
|
+
};
|
|
39
|
+
for (const template of templates) add(template.prefix, template.label, template.description);
|
|
40
|
+
for (const command of commands) add(command.shortcut, command.label, command.description);
|
|
41
|
+
return [...byCode.values()];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Functions Free cannot fully open: Pro only, or a preview on Free. */
|
|
45
|
+
export function proFunctionCount(functions: readonly PluginFunction[]): number {
|
|
46
|
+
return functions.filter((fn) => fn.access).length;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The codes a row shows: the editorial pick when it names real codes, else the first three. */
|
|
50
|
+
export function highlightedCodes(pluginId: string, functions: readonly PluginFunction[]): string[] {
|
|
51
|
+
const codes = functions.map((fn) => fn.code);
|
|
52
|
+
const picked = (BUILTIN_EDITORIAL[pluginId]?.highlights ?? []).filter((code) => codes.includes(code));
|
|
53
|
+
return (picked.length > 0 ? picked : codes).slice(0, 3);
|
|
54
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { AppNotificationRequest } from "../types/plugin";
|
|
2
|
+
import type { DisabledPluginOwner } from "./registry";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Opening something whose plugin is switched off. A pane added for it would
|
|
6
|
+
* stay hidden, so the open is refused and the user is offered the switch.
|
|
7
|
+
*/
|
|
8
|
+
export class PluginOffError extends Error {
|
|
9
|
+
constructor(readonly plugin: DisabledPluginOwner, what: string) {
|
|
10
|
+
super(`Turn on ${plugin.name} to open ${what}.`);
|
|
11
|
+
this.name = "PluginOffError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface PluginOffNotifier {
|
|
16
|
+
notify(notification: AppNotificationRequest): unknown;
|
|
17
|
+
setPluginEnabled(pluginId: string, enabled: boolean): void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Says which plugin to turn on, with a button that turns it on and, when
|
|
22
|
+
* given, opens what was asked for.
|
|
23
|
+
*/
|
|
24
|
+
export function notifyPluginOff(host: PluginOffNotifier, error: PluginOffError, reopen?: () => void): void {
|
|
25
|
+
host.notify({
|
|
26
|
+
body: error.message,
|
|
27
|
+
type: "info",
|
|
28
|
+
action: {
|
|
29
|
+
label: "Turn on",
|
|
30
|
+
onClick: () => {
|
|
31
|
+
host.setPluginEnabled(error.plugin.id, true);
|
|
32
|
+
reopen?.();
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -45,6 +45,10 @@ export interface PluginHostActions {
|
|
|
45
45
|
openWindowMode(paneId?: string, mode?: WindowEditMode): void;
|
|
46
46
|
/** The shell's fullscreen toggle for a pane; false when there is nothing to fill the window with. */
|
|
47
47
|
togglePaneFullscreen(paneId: string): boolean;
|
|
48
|
+
/** The shell's Move to New Layout for a pane; false when it did nothing. Not on the plugin API. */
|
|
49
|
+
movePaneToNewLayout(paneId: string): boolean;
|
|
50
|
+
/** Returns a pane Move to New Layout moved to where it came from; false when it did nothing. Not on the plugin API. */
|
|
51
|
+
movePaneBack(paneId: string): boolean;
|
|
48
52
|
showPane(paneId: string): void;
|
|
49
53
|
createPaneFromTemplate(templateId: string, options?: PaneTemplateCreateOptions): void;
|
|
50
54
|
createPaneFromTemplateAsync(templateId: string, options?: PaneTemplateCreateOptions): Promise<void>;
|
|
@@ -62,6 +66,14 @@ export interface PluginHostActions {
|
|
|
62
66
|
watchNewsQuery(query: NewsQuery, listener: (state: NewsQueryState) => void): () => void;
|
|
63
67
|
|
|
64
68
|
notify(notification: AppNotificationRequest): AppNotificationDelivery | void;
|
|
69
|
+
/** Switches a plugin on or off the way the Plugins pane does. Not on the plugin API. */
|
|
70
|
+
setPluginEnabled(pluginId: string, enabled: boolean): void;
|
|
71
|
+
/**
|
|
72
|
+
* Switches several plugins on or off as one change: one config write and
|
|
73
|
+
* one save. A switched-off plugin's panes are hidden, never removed, so
|
|
74
|
+
* switching it back on shows them where they were. Not on the plugin API.
|
|
75
|
+
*/
|
|
76
|
+
setPluginsEnabled(changes: Readonly<Record<string, boolean>>): void;
|
|
65
77
|
getPaneRuntimeState(paneId: string): PaneRuntimeState | null;
|
|
66
78
|
updatePaneRuntimeState(paneId: string, patch: Partial<PaneRuntimeState>): void;
|
|
67
79
|
applyPaneSettingValue(paneId: string, field: PaneSettingField, value: unknown): Promise<void>;
|
|
@@ -95,6 +107,8 @@ export function createDefaultHostActions(current?: () => Pick<PluginHostActions,
|
|
|
95
107
|
sharePane: () => {},
|
|
96
108
|
openWindowMode: () => {},
|
|
97
109
|
togglePaneFullscreen: () => false,
|
|
110
|
+
movePaneToNewLayout: () => false,
|
|
111
|
+
movePaneBack: () => false,
|
|
98
112
|
showPane: () => {},
|
|
99
113
|
createPaneFromTemplate: () => {},
|
|
100
114
|
createPaneFromTemplateAsync: async () => {},
|
|
@@ -109,6 +123,8 @@ export function createDefaultHostActions(current?: () => Pick<PluginHostActions,
|
|
|
109
123
|
registerNewsCapability: () => () => {},
|
|
110
124
|
watchNewsQuery: () => () => {},
|
|
111
125
|
notify: () => {},
|
|
126
|
+
setPluginEnabled: () => {},
|
|
127
|
+
setPluginsEnabled: () => {},
|
|
112
128
|
getPaneRuntimeState: () => null,
|
|
113
129
|
updatePaneRuntimeState: () => {},
|
|
114
130
|
applyPaneSettingValue: async () => {},
|