gloomberb 0.16.5 → 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/package.json +2 -1
- 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 +49 -1
- package/src/api-client/europe-energy.ts +106 -0
- package/src/api-client/index.ts +9 -0
- package/src/api-client/market-discovery.ts +3 -0
- package/src/api-client/normalizers.ts +32 -0
- package/src/api-client/perps.ts +8 -0
- package/src/api-client/request.ts +9 -2
- package/src/api-client/socket.ts +29 -0
- package/src/api-client/themes.ts +22 -1
- package/src/api-client/types.ts +61 -1
- package/src/app/global-shortcuts.ts +35 -1
- 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 +9 -3
- 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 +4 -13
- 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/capabilities/chart-series.ts +8 -1
- 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 +28 -2
- package/src/cli/commands/fred-series.ts +89 -4
- package/src/cli/commands/market.ts +101 -18
- package/src/cli/commands/overview.ts +47 -14
- package/src/cli/commands/search.ts +254 -23
- package/src/cli/commands/ticker.ts +73 -13
- package/src/cli/desktop-pane-shot.ts +23 -6
- 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/glossary.ts +62 -8
- package/src/cli/help.ts +10 -0
- package/src/cli/helpers.ts +2 -5
- package/src/cli/history-rows.ts +70 -0
- package/src/cli/index.ts +9 -3
- package/src/cli/known-gaps.ts +65 -8
- package/src/cli/listing-arg.ts +182 -89
- package/src/cli/not-a-ticker.ts +12 -4
- package/src/cli/pane-functions/access-gate.ts +8 -2
- package/src/cli/pane-functions/capabilities.ts +1 -1
- package/src/cli/pane-functions/catalog.ts +183 -39
- package/src/cli/pane-functions/data.ts +30 -0
- package/src/cli/pane-functions/dom.ts +17 -2
- package/src/cli/pane-functions/freshness.ts +48 -24
- package/src/cli/pane-functions/function-help.ts +19 -10
- package/src/cli/pane-functions/headless.ts +55 -15
- package/src/cli/pane-functions/index.ts +45 -16
- package/src/cli/pane-functions/options.ts +8 -0
- package/src/cli/pane-functions/resolver.ts +25 -7
- package/src/cli/pane-functions/screenshot.ts +145 -9
- package/src/cli/perpetual-contract.ts +60 -0
- package/src/cli/registry.ts +3 -1
- package/src/cli/report-tables.ts +23 -7
- package/src/cli/result.ts +41 -10
- package/src/cli/series-search.ts +111 -0
- package/src/cli/staged-tickers.ts +1 -1
- package/src/cli/symbol-args.ts +18 -0
- package/src/cli/symbol-list.ts +1 -19
- package/src/cli/symbol-rows.ts +154 -0
- package/src/cli/ticker-resolution.ts +99 -8
- package/src/components/chart/composite/axis-overlays.tsx +8 -1
- package/src/components/chart/composite/composite-chart.tsx +41 -15
- 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 +52 -32
- 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 +6 -8
- 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/routes/root/plugin-install.ts +4 -4
- package/src/components/command-bar/routing/actions.ts +1 -1
- package/src/components/command-bar/workflow/tickers.ts +35 -29
- package/src/components/layout/detached-pane-shell.tsx +59 -39
- package/src/components/layout/floating-pane.tsx +7 -1
- package/src/components/layout/header.tsx +5 -0
- 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/footer/keyboard.ts +3 -0
- package/src/components/layout/pane/footer/model.ts +7 -1
- package/src/components/layout/pane/header.tsx +26 -0
- package/src/components/layout/pane/index.tsx +9 -1
- package/src/components/layout/pane/sidebar.tsx +10 -11
- package/src/components/layout/shell/cursor-occlusion.ts +2 -1
- package/src/components/layout/shell/index.tsx +61 -60
- package/src/components/layout/shell/menu.ts +9 -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 +26 -5
- package/src/components/layout/shell/pane/management-shortcuts.ts +46 -1
- package/src/components/layout/shell/shortcuts.ts +21 -4
- package/src/components/metric-treemap/heat-surface.tsx +1 -3
- package/src/components/reader/article-reader.tsx +642 -0
- package/src/components/reader/article-text.ts +527 -0
- package/src/components/ticker/list-table-view.tsx +19 -1
- package/src/components/ui/data-table/index.tsx +1 -0
- package/src/components/ui/icon.tsx +4 -1
- package/src/components/ui/query-bar.tsx +10 -1
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/portfolio-as-of-column.ts +57 -0
- package/src/docs/snapshot.json +162 -23
- package/src/i18n/es.ts +4 -1
- package/src/i18n/ja.ts +4 -1
- package/src/i18n/ko.ts +4 -1
- package/src/i18n/zh-cn.ts +4 -1
- package/src/i18n/zh-tw.ts +4 -1
- package/src/layout-marketplace/gallery.tsx +1 -1
- package/src/market-data/market/freshness.ts +3 -2
- package/src/market-data/market/session-close-note.ts +3 -2
- package/src/market-data/quotes/contributions.ts +2 -0
- package/src/market-data/quotes/metadata.ts +12 -0
- package/src/market-data/quotes/resolution.ts +3 -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/alerts/catalysts.ts +1 -1
- package/src/plugins/builtin/alerts/focus.ts +27 -0
- package/src/plugins/builtin/alerts/index.tsx +6 -2
- package/src/plugins/builtin/alerts/pane.tsx +19 -1
- package/src/plugins/builtin/analytics/index.tsx +4 -1
- package/src/plugins/builtin/analytics/risk-headless.ts +30 -15
- package/src/plugins/builtin/attention/headless.ts +1 -1
- package/src/plugins/builtin/awards/headless.ts +88 -18
- package/src/plugins/builtin/awards/model.ts +41 -1
- package/src/plugins/builtin/awards/pane.tsx +19 -12
- package/src/plugins/builtin/backtest/headless.ts +2 -2
- package/src/plugins/builtin/broker-manager/index.tsx +1 -0
- package/src/plugins/builtin/catalysts/headless.ts +1 -1
- package/src/plugins/builtin/cds/client.ts +11 -31
- package/src/plugins/builtin/cds/headless.ts +5 -2
- package/src/plugins/builtin/cds/model.ts +21 -1
- package/src/plugins/builtin/cds/pane.tsx +6 -4
- 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 +1 -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 +19 -25
- package/src/plugins/builtin/chart-composer/catalog-inventory.ts +1 -0
- package/src/plugins/builtin/chart-composer/headless-schema.ts +1 -1
- package/src/plugins/builtin/chart-composer/headless.ts +65 -5
- package/src/plugins/builtin/chart-composer/index.tsx +6 -1
- package/src/plugins/builtin/chart-composer/pane.tsx +81 -38
- 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-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 +121 -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/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/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/thesis/module.tsx +1 -0
- package/src/plugins/builtin/company-attention/headless.ts +2 -2
- 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 +13 -14
- package/src/plugins/builtin/connections/index.ts +1 -0
- package/src/plugins/builtin/cot/headless.ts +1 -1
- 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/model.ts +11 -1
- 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 +16 -9
- package/src/plugins/builtin/credit-conditions/model.ts +19 -11
- package/src/plugins/builtin/credit-conditions/series.ts +8 -18
- package/src/plugins/builtin/credit-documents/headless.ts +2 -2
- package/src/plugins/builtin/debt-maturities/headless.ts +17 -11
- package/src/plugins/builtin/dividend-yield/client.ts +3 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +5 -2
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/types.ts +2 -0
- package/src/plugins/builtin/doe/headless.ts +12 -8
- 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 +9 -0
- package/src/plugins/builtin/equity-screener/headless.ts +3 -3
- 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/index.tsx +1 -0
- package/src/plugins/builtin/exposure/model.ts +23 -3
- package/src/plugins/builtin/exposure/pane.tsx +11 -11
- package/src/plugins/builtin/fear-greed/index.tsx +14 -10
- package/src/plugins/builtin/futures-curve/headless.ts +1 -1
- package/src/plugins/builtin/futures-curve/index.tsx +1 -1
- 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 +3 -3
- package/src/plugins/builtin/gpu/headless.ts +4 -4
- package/src/plugins/builtin/help/function-index.ts +2 -0
- package/src/plugins/builtin/help/index.tsx +14 -1
- package/src/plugins/builtin/ipo-calendar/headless.ts +1 -1
- package/src/plugins/builtin/iv-history/client.ts +6 -2
- package/src/plugins/builtin/iv-history/format.ts +9 -0
- package/src/plugins/builtin/iv-history/headless.ts +50 -18
- package/src/plugins/builtin/iv-history/model.ts +35 -4
- package/src/plugins/builtin/jobs/headless.ts +6 -8
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/market-heatmap/headless.ts +20 -5
- package/src/plugins/builtin/market-heatmap/index.tsx +6 -0
- package/src/plugins/builtin/members/headless.ts +1 -1
- package/src/plugins/builtin/members/pane.tsx +3 -2
- package/src/plugins/builtin/mna/distress/headless.ts +4 -4
- package/src/plugins/builtin/mna/headless.ts +3 -3
- package/src/plugins/builtin/money-markets/headless.ts +5 -4
- 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/index.tsx +1 -0
- package/src/plugins/builtin/options/index.tsx +3 -0
- package/src/plugins/builtin/options-positioning/headless.ts +3 -3
- package/src/plugins/builtin/perps/client.ts +50 -10
- package/src/plugins/builtin/perps/equity-row.tsx +29 -16
- package/src/plugins/builtin/perps/headless.ts +2 -2
- package/src/plugins/builtin/perps/index.tsx +5 -3
- package/src/plugins/builtin/perps/list-perpetuals.ts +118 -0
- package/src/plugins/builtin/perps/open-market.ts +15 -0
- package/src/plugins/builtin/plugin-marketplace/index.tsx +1 -1
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +6 -6
- 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 +23 -135
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +59 -15
- package/src/plugins/builtin/portfolio-list/cli/render.ts +248 -51
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +5 -12
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +3 -2
- package/src/plugins/builtin/portfolio-list/column-values.ts +103 -25
- package/src/plugins/builtin/portfolio-list/headless.ts +51 -15
- package/src/plugins/builtin/portfolio-list/index.tsx +5 -1
- 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 +46 -8
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +16 -10
- 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 +8 -3
- package/src/plugins/builtin/portfolio-list/table.tsx +30 -6
- package/src/plugins/builtin/power/evidence.ts +57 -8
- package/src/plugins/builtin/power/headless.ts +6 -2
- package/src/plugins/builtin/power/index.tsx +24 -2
- package/src/plugins/builtin/power/model.ts +2 -2
- package/src/plugins/builtin/power/pane.tsx +5 -0
- 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 +38 -18
- package/src/plugins/builtin/relative-rotation/headless.ts +3 -3
- 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/sec/headless.ts +25 -3
- package/src/plugins/builtin/sec/index.tsx +2 -1
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/cloud-denied.ts +15 -0
- package/src/plugins/builtin/shared/free-preview.ts +47 -0
- package/src/plugins/builtin/shared/report-freshness.ts +3 -1
- package/src/plugins/builtin/shared/volatility/options.ts +4 -1
- package/src/plugins/builtin/short-interest/watch-headless.ts +2 -2
- package/src/plugins/builtin/short-volume/headless.ts +1 -1
- package/src/plugins/builtin/social-mentions/headless.ts +1 -1
- 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 +5 -5
- 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/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 +23 -11
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +1 -1
- package/src/plugins/builtin/time-sales/headless.ts +1 -1
- package/src/plugins/builtin/time-sales/index.tsx +2 -1
- package/src/plugins/builtin/vol-surface/evidence.ts +7 -1
- package/src/plugins/builtin/vol-surface/headless.ts +50 -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/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-svg.tsx +6 -6
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +16 -9
- 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/index.tsx +1 -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/portfolio/collection-name.ts +31 -0
- package/src/portfolio/valuation-basis.ts +79 -0
- package/src/public/time-series.ts +1 -1
- package/src/react/input.ts +33 -1
- package/src/react/key-repeat.ts +86 -0
- package/src/remote/controller.ts +21 -1
- package/src/remote/schema.ts +3 -2
- package/src/renderers/browser/main.tsx +1 -1
- package/src/renderers/browser/research-entry.ts +4 -2
- package/src/renderers/dom/data-table/row.tsx +3 -0
- package/src/renderers/dom/desktop/icons.tsx +9 -0
- package/src/renderers/dom/host/block-glyph-canvas.tsx +6 -3
- package/src/renderers/dom/host/box.tsx +7 -2
- package/src/renderers/dom/host/chart-surface.tsx +27 -0
- package/src/renderers/dom/host/scroll-box.tsx +32 -0
- package/src/renderers/dom/host/size-observer.ts +24 -9
- 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 +13 -6
- package/src/renderers/dom/host/surface-fit.ts +406 -0
- package/src/renderers/dom/input-host.tsx +1 -0
- package/src/renderers/dom/styles.css +48 -12
- 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 +12 -0
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +59 -24
- package/src/renderers/electrobun/view/main.tsx +3 -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/resolve.ts +3 -2
- package/src/series/types.ts +8 -0
- package/src/series/validate.ts +1 -1
- 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 +102 -3
- package/src/sources/gloomberb-cloud/normalizers.ts +2 -0
- package/src/sources/gloomberb-cloud/perpetuals.ts +249 -0
- package/src/sources/history-retention.ts +11 -0
- package/src/sources/listing-target.ts +4 -0
- package/src/sources/provider-router/index.ts +14 -0
- package/src/state/hooks/inline-tickers.ts +49 -11
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/theme-context.tsx +15 -1
- package/src/tickers/instrument-kind.ts +9 -1
- package/src/tickers/listing-name.ts +34 -0
- package/src/tickers/listing-venues.ts +132 -0
- package/src/tickers/open-target.ts +11 -3
- package/src/tickers/perpetual-listing.ts +151 -0
- package/src/tickers/prediction-listing.ts +26 -0
- package/src/tickers/search/index.ts +27 -4
- package/src/tickers/search/ranking.ts +66 -4
- package/src/tickers/ticker-changes.ts +213 -0
- package/src/time-series/economic.ts +2 -6
- package/src/time-series/ice-credit.ts +39 -0
- package/src/time-series/resolve.ts +116 -13
- package/src/time-series/studies.ts +1 -0
- package/src/time-series/types.ts +8 -0
- package/src/types/config.ts +4 -2
- package/src/types/data-provider.ts +6 -0
- package/src/types/financials.ts +10 -0
- package/src/types/headless.ts +52 -0
- package/src/types/instrument.ts +4 -0
- package/src/types/plugin.ts +33 -2
- package/src/types/ticker-changes.ts +26 -0
- package/src/ui/context-menu.tsx +13 -1
- package/src/ui/host.tsx +43 -7
- package/src/ui/live-resize.ts +10 -0
- package/src/ui/live-stretch.ts +51 -19
- package/src/ui/sticky-scroll.ts +7 -0
- package/src/utils/central-banks.ts +76 -0
- package/src/utils/cli-output.ts +126 -16
- package/src/utils/currency-units.ts +11 -0
- package/src/utils/datetime-format.ts +27 -6
- package/src/utils/dom-screenshot.ts +3 -1
- package/src/utils/double-escape-close.ts +15 -1
- package/src/utils/exchanges.ts +36 -0
- package/src/utils/format.ts +19 -2
- package/src/utils/forward-dividend.ts +14 -0
- 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/utc-time.ts +12 -0
- package/src/ui/pane-fill.ts +0 -11
- /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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useRef, type Dispatch } from "react";
|
|
1
|
+
import { useEffect, useRef, useState, type Dispatch } from "react";
|
|
2
2
|
import { useShortcut } from "../react/input";
|
|
3
3
|
import { useNativeRenderer, useRendererHost, useUiHost } from "../ui";
|
|
4
4
|
import { useDialogState } from "../ui/dialog";
|
|
@@ -13,6 +13,7 @@ import { getVisiblePaneCycleOrder } from "../components/layout/pane/cycle-order"
|
|
|
13
13
|
import { requestFunctionHelp, useFunctionHelpHost } from "../plugins/builtin/help/function-card";
|
|
14
14
|
import { buildRegistryHelpIndex, helpFunctionForPane } from "../plugins/builtin/help/function-index";
|
|
15
15
|
import { recordFunctionOpen } from "../telemetry/usage-counts";
|
|
16
|
+
import { createOneShots } from "../utils/one-shot";
|
|
16
17
|
import { DOCS_PANE_TEMPLATE_ID } from "../docs/content";
|
|
17
18
|
import { registerPaneDocsHandler } from "../docs/requests";
|
|
18
19
|
import { isMoveDownShortcut, isMoveUpShortcut } from "../components/command-bar/keyboard-handlers";
|
|
@@ -117,6 +118,10 @@ export function useAppGlobalShortcuts({
|
|
|
117
118
|
const uiKind = useUiHost().kind;
|
|
118
119
|
const toastHost = useToastHost();
|
|
119
120
|
useKeybindingIssueNotice(keybindings, pluginRegistry, state.initialized);
|
|
121
|
+
// Every action here runs once per press: a held key, or a terminal that does
|
|
122
|
+
// not say it is a repeat, must not run it again. Only moving focus between
|
|
123
|
+
// panes (Tab) and switching layouts by number (idempotent) are left to repeat.
|
|
124
|
+
const [shots] = useState(createOneShots);
|
|
120
125
|
useFunctionHelpHost({
|
|
121
126
|
closeCommandBar: () => {
|
|
122
127
|
if (state.commandBarOpen) dispatch({ type: "SET_COMMAND_BAR", open: false });
|
|
@@ -149,6 +154,23 @@ export function useAppGlobalShortcuts({
|
|
|
149
154
|
|
|
150
155
|
const match = matchKeybinding(keybindings, event);
|
|
151
156
|
const action = match?.kind === "action" ? match.id : null;
|
|
157
|
+
/**
|
|
158
|
+
* Whether the action already ran for this press or hold. An action that
|
|
159
|
+
* takes the key (`claims`) swallows the refused ones as well; one that
|
|
160
|
+
* leaves it to the pane (R) does not, so a pane's own key keeps working.
|
|
161
|
+
*/
|
|
162
|
+
const ranAlready = (id: string, claims = true): boolean => {
|
|
163
|
+
const shot = shots.get(id);
|
|
164
|
+
if (shot.refuses(event)) {
|
|
165
|
+
if (claims) {
|
|
166
|
+
event.preventDefault();
|
|
167
|
+
event.stopPropagation();
|
|
168
|
+
}
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
shot.end();
|
|
172
|
+
return false;
|
|
173
|
+
};
|
|
152
174
|
|
|
153
175
|
// Terminals send Ctrl; the browser and the desktop webview send Cmd on
|
|
154
176
|
// macOS, which the OpenTUI host also reports as `super` under the kitty
|
|
@@ -172,6 +194,7 @@ export function useAppGlobalShortcuts({
|
|
|
172
194
|
// The status bar's star line answers the same keys once no toast does,
|
|
173
195
|
// but only over the workspace itself.
|
|
174
196
|
if (action === "notification-action" || action === "notification-dismiss") {
|
|
197
|
+
if (ranAlready(action)) return;
|
|
175
198
|
const toastHandled = action === "notification-action"
|
|
176
199
|
? toastHost.activateNewest?.() === true
|
|
177
200
|
: toastHost.dismissNewest?.() === true;
|
|
@@ -195,12 +218,14 @@ export function useAppGlobalShortcuts({
|
|
|
195
218
|
// Ctrl+P and Ctrl+N move the open bar's selection, so a bar chord that
|
|
196
219
|
// is one of them only opens it; Esc and the bar's other chords close it.
|
|
197
220
|
if (state.commandBarOpen && (isMoveUpShortcut(event) || isMoveDownShortcut(event))) return;
|
|
221
|
+
if (ranAlready(action)) return;
|
|
198
222
|
event.preventDefault();
|
|
199
223
|
event.stopPropagation();
|
|
200
224
|
dispatch({ type: "TOGGLE_COMMAND_BAR" });
|
|
201
225
|
return;
|
|
202
226
|
}
|
|
203
227
|
if (!isDetachedWindow && action === "ticker-search" && !state.commandBarOpen) {
|
|
228
|
+
if (ranAlready(action)) return;
|
|
204
229
|
event.preventDefault();
|
|
205
230
|
event.stopPropagation();
|
|
206
231
|
dispatch({
|
|
@@ -233,6 +258,7 @@ export function useAppGlobalShortcuts({
|
|
|
233
258
|
// Command and function keys are never text, so they still fire.
|
|
234
259
|
const editing = state.inputCaptured || event.targetEditable === true;
|
|
235
260
|
if (editing && event.ctrl && !(event.meta || event.super)) return;
|
|
261
|
+
if (ranAlready(`command:${match.command.query}`)) return;
|
|
236
262
|
event.preventDefault();
|
|
237
263
|
event.stopPropagation();
|
|
238
264
|
dispatch({
|
|
@@ -246,6 +272,7 @@ export function useAppGlobalShortcuts({
|
|
|
246
272
|
|
|
247
273
|
// A function key is never text, so the card opens from a focused field too.
|
|
248
274
|
if (action === "function-help") {
|
|
275
|
+
if (ranAlready(action)) return;
|
|
249
276
|
event.preventDefault();
|
|
250
277
|
event.stopPropagation();
|
|
251
278
|
recordFunctionOpen({ shortcut: "HELP", externalPluginId: null });
|
|
@@ -259,6 +286,7 @@ export function useAppGlobalShortcuts({
|
|
|
259
286
|
if (state.inputCaptured) return;
|
|
260
287
|
|
|
261
288
|
if (!isDetachedWindow && action === "help") {
|
|
289
|
+
if (ranAlready(action)) return;
|
|
262
290
|
event.preventDefault();
|
|
263
291
|
event.stopPropagation();
|
|
264
292
|
pluginRegistry.showPane("help");
|
|
@@ -266,13 +294,16 @@ export function useAppGlobalShortcuts({
|
|
|
266
294
|
}
|
|
267
295
|
|
|
268
296
|
if (!isDetachedWindow && action === "quit") {
|
|
297
|
+
if (ranAlready(action, false)) return;
|
|
269
298
|
if (uiKind === "opentui") rendererHost.requestExit();
|
|
270
299
|
} else if (action === "refresh-ticker") {
|
|
300
|
+
if (ranAlready(action, false)) return;
|
|
271
301
|
if (focusedTickerSymbol) {
|
|
272
302
|
const ticker = state.tickers.get(focusedTickerSymbol);
|
|
273
303
|
if (ticker) refreshTicker(ticker.metadata.ticker, ticker.metadata.exchange, ticker, 0);
|
|
274
304
|
}
|
|
275
305
|
} else if (action === "refresh-all") {
|
|
306
|
+
if (ranAlready(action, false)) return;
|
|
276
307
|
for (const ticker of state.tickers.values()) {
|
|
277
308
|
refreshTicker(ticker.metadata.ticker, ticker.metadata.exchange, ticker, 1);
|
|
278
309
|
}
|
|
@@ -280,10 +311,12 @@ export function useAppGlobalShortcuts({
|
|
|
280
311
|
// A release that can install itself downloads on its own, so the key is
|
|
281
312
|
// for the one that waits for a restart and for the one that failed.
|
|
282
313
|
if (!isDetachedWindow && canRestartToApply(state.updateProgress)) {
|
|
314
|
+
if (ranAlready(action)) return;
|
|
283
315
|
event.preventDefault();
|
|
284
316
|
event.stopPropagation();
|
|
285
317
|
restartToApplyUpdate();
|
|
286
318
|
} else if (canRetryUpdate(state)) {
|
|
319
|
+
if (ranAlready(action)) return;
|
|
287
320
|
event.preventDefault();
|
|
288
321
|
event.stopPropagation();
|
|
289
322
|
startUpdate(state.updateAvailable!);
|
|
@@ -296,6 +329,7 @@ export function useAppGlobalShortcuts({
|
|
|
296
329
|
if (ownerId && disabledPlugins.has(ownerId)) continue;
|
|
297
330
|
const chords = resolvePluginShortcutChords(keybindingsConfig, shortcut);
|
|
298
331
|
if (chords.some((chord) => matchesKeyChord(chord, event))) {
|
|
332
|
+
if (ranAlready(`plugin:${shortcut.id}`, false)) return;
|
|
299
333
|
shortcut.execute();
|
|
300
334
|
break;
|
|
301
335
|
}
|
|
@@ -28,6 +28,7 @@ export type CoreKeybindingActionId =
|
|
|
28
28
|
| "pane-screenshot"
|
|
29
29
|
| "pane-export-csv"
|
|
30
30
|
| "pane-share"
|
|
31
|
+
| "pane-ask"
|
|
31
32
|
| "layout-gallery"
|
|
32
33
|
| "tidy-windows"
|
|
33
34
|
| "window-move-mode"
|
|
@@ -59,6 +60,7 @@ export const PANE_ACTION_IDS = new Set<CoreKeybindingActionId>([
|
|
|
59
60
|
"pane-screenshot",
|
|
60
61
|
"pane-export-csv",
|
|
61
62
|
"pane-share",
|
|
63
|
+
"pane-ask",
|
|
62
64
|
"layout-gallery",
|
|
63
65
|
"tidy-windows",
|
|
64
66
|
"window-move-mode",
|
|
@@ -225,9 +227,18 @@ export const KEYBINDING_ACTIONS: readonly KeybindingActionDef[] = [
|
|
|
225
227
|
{
|
|
226
228
|
id: "pane-share",
|
|
227
229
|
category: "Pane Management",
|
|
228
|
-
description: "Share the focused pane.",
|
|
230
|
+
description: "Share the focused pane: post a picture to chat or copy its link.",
|
|
229
231
|
defaults: ["CmdOrCtrl+Shift+S"],
|
|
230
232
|
},
|
|
233
|
+
{
|
|
234
|
+
id: "pane-ask",
|
|
235
|
+
category: "Pane Management",
|
|
236
|
+
description: "Ask Gloom about the focused pane, in a new conversation with the pane attached.",
|
|
237
|
+
// A for ask. Alt+A first, because it reaches most terminals, where
|
|
238
|
+
// Ctrl+Shift+A is often the terminal's own select all; the desktop app
|
|
239
|
+
// advertises the chord on its platform modifier.
|
|
240
|
+
defaults: ["Alt+A", "CmdOrCtrl+Shift+A"],
|
|
241
|
+
},
|
|
231
242
|
{
|
|
232
243
|
id: "layout-gallery",
|
|
233
244
|
category: "Pane Management",
|
|
@@ -16,8 +16,8 @@ import {
|
|
|
16
16
|
} from "../../components/layout/shell/visible-layout";
|
|
17
17
|
import { applyPluginToggles } from "../../plugins/ownership";
|
|
18
18
|
import { setLayoutManagerDispatch } from "../../plugins/builtin/layout-manager";
|
|
19
|
-
import { setMarketplaceHost } from "../../plugins/
|
|
20
|
-
import type { InstalledPlugin } from "../../plugins/
|
|
19
|
+
import { setMarketplaceHost } from "../../plugins/marketplace/store";
|
|
20
|
+
import type { InstalledPlugin } from "../../plugins/marketplace/model";
|
|
21
21
|
import {
|
|
22
22
|
listExternalPlugins,
|
|
23
23
|
removeExternalPlugin,
|
|
@@ -111,11 +111,11 @@ export function useAppTickerOpenRuntime({
|
|
|
111
111
|
return true;
|
|
112
112
|
}, [pluginRegistry, stateRef]);
|
|
113
113
|
|
|
114
|
-
const placePinnedTickerTarget = useCallback((target: TickerOpenTarget, options?: PinTickerOptions) => {
|
|
114
|
+
const placePinnedTickerTarget = useCallback((target: TickerOpenTarget, options?: PinTickerOptions, typed?: string) => {
|
|
115
115
|
const paneType = normalizePaneId(options?.paneType ?? TICKER_RESEARCH_PANE_ID);
|
|
116
116
|
const paneDef = pluginRegistry.panes.get(paneType);
|
|
117
117
|
if (!paneDef) return;
|
|
118
|
-
if (refuseWhileOwnerOff(target.symbol, options, () => placePinnedTickerTarget(target, options))) return;
|
|
118
|
+
if (refuseWhileOwnerOff(target.symbol, options, () => placePinnedTickerTarget(target, options, typed))) return;
|
|
119
119
|
|
|
120
120
|
publishTickerOpenTarget(target);
|
|
121
121
|
const symbol = target.symbol;
|
|
@@ -128,6 +128,12 @@ export function useAppTickerOpenRuntime({
|
|
|
128
128
|
let existing = options?.forceNewPane
|
|
129
129
|
? null
|
|
130
130
|
: findFixedTickerPaneForSymbol(currentLayout, paneType, symbol, instrument);
|
|
131
|
+
// A pane bound to the key as typed (the web terminal's first pane for ?ticker=7203:TSE) is the one the
|
|
132
|
+
// resolved listing (7203:JPX) settles.
|
|
133
|
+
const typedKey = typed?.trim().toUpperCase();
|
|
134
|
+
if (!options?.forceNewPane && !existing && typedKey && typedKey !== symbol) {
|
|
135
|
+
existing = findFixedTickerPaneForSymbol(currentLayout, paneType, typedKey, instrument);
|
|
136
|
+
}
|
|
131
137
|
// Without a broker route, the public listing and an unnamed route are the same security: a link that names
|
|
132
138
|
// neither still finds the DES the command bar opened on the public listing, and leaves its binding as it is.
|
|
133
139
|
let keepBinding = false;
|
|
@@ -213,7 +219,7 @@ export function useAppTickerOpenRuntime({
|
|
|
213
219
|
? { symbol: selectedTicker.metadata.ticker, ticker: selectedTicker, created: false, instrument: options?.instrument, listing: options?.listing }
|
|
214
220
|
: await resolveOpenTickerTarget(rawSymbol, options?.instrument === null);
|
|
215
221
|
if (!target) return;
|
|
216
|
-
placePinnedTickerTarget(target, options);
|
|
222
|
+
placePinnedTickerTarget(target, options, rawSymbol);
|
|
217
223
|
const action = attentionActionForPane(options?.paneType ?? TICKER_RESEARCH_PANE_ID);
|
|
218
224
|
if (action && pluginRegistry.panes.has(options?.paneType ?? TICKER_RESEARCH_PANE_ID)) {
|
|
219
225
|
recordAttention(publicTickerKey(target.symbol, target.listing?.exchange ?? target.ticker.metadata.exchange), action);
|
|
@@ -17,6 +17,7 @@ import { getShare } from "../../shares/api";
|
|
|
17
17
|
import { openPaneShare } from "../../shares/pane";
|
|
18
18
|
import { PluginOffError, notifyPluginOff } from "../../plugins/plugin-off";
|
|
19
19
|
import { materializeMarketplaceLayout } from "../../shares/portable-layout";
|
|
20
|
+
import { settleTypedListingKey } from "../../tickers/listing-venues";
|
|
20
21
|
|
|
21
22
|
type CloudDeepLinkRoute = {
|
|
22
23
|
kind: "cloud-alerts" | "cloud-emails" | "cloud-roundup" | "cloud-success" | "cloud-teams";
|
|
@@ -475,11 +476,15 @@ function handleOpenNews(
|
|
|
475
476
|
notifyError(pluginRegistry, "Ticker news is unavailable.");
|
|
476
477
|
return;
|
|
477
478
|
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
479
|
+
// A link's 7203:TSE is the venue its symbol trades on; ticker and alert links settle it where they open.
|
|
480
|
+
void settleTypedListingKey(action.symbol, { store: pluginRegistry.tickerRepository, dataProvider: pluginRegistry.marketData })
|
|
481
|
+
.then((symbol) => pluginRegistry.createPaneFromTemplateAsync("ticker-news-pane", { symbol: symbol.toUpperCase() }))
|
|
482
|
+
.then(() => {
|
|
483
|
+
notifySuccess(pluginRegistry, action.message);
|
|
484
|
+
})
|
|
485
|
+
.catch((error) => {
|
|
486
|
+
notifyError(pluginRegistry, error instanceof Error ? error.message : "Failed to open ticker news.");
|
|
487
|
+
});
|
|
483
488
|
return;
|
|
484
489
|
}
|
|
485
490
|
|
|
@@ -6,7 +6,7 @@ import type { MarketDataCoordinator } from "../../market-data/coordinator";
|
|
|
6
6
|
import { instrumentFromTicker, type InstrumentRef } from "../../market-data/request-types";
|
|
7
7
|
import { useSavedLayoutWarmup } from "./layout-warmup";
|
|
8
8
|
import { chatController } from "../../plugins/builtin/chat/controller";
|
|
9
|
-
import { PLUGIN_MARKETPLACE_PANE_ID } from "../../plugins/
|
|
9
|
+
import { PLUGIN_MARKETPLACE_PANE_ID } from "../../plugins/marketplace/ids";
|
|
10
10
|
import type { LoadedExternalPlugin } from "../../plugins/loader";
|
|
11
11
|
import type { PluginRegistry } from "../../plugins/registry";
|
|
12
12
|
import type {
|
package/src/app.tsx
CHANGED
|
@@ -38,6 +38,7 @@ import type { LayoutBounds } from "./layout/pane-manager";
|
|
|
38
38
|
import type { AppSessionSnapshot } from "./core/state/session-persistence";
|
|
39
39
|
import type { MarketDataCoordinator } from "./market-data/coordinator";
|
|
40
40
|
import { createAppNotifier } from "./notifications/app-notifier";
|
|
41
|
+
import { attachNotificationLog } from "./notifications/notification-log";
|
|
41
42
|
import { useBrokerImportRuntime } from "./app/runtime/broker-import";
|
|
42
43
|
import { useDesktopDeepLinkRuntime } from "./app/runtime/desktop-deeplink";
|
|
43
44
|
import { useDesktopApplicationMenuRuntime } from "./app/runtime/desktop-menu";
|
|
@@ -374,6 +375,11 @@ function AppInner({
|
|
|
374
375
|
|
|
375
376
|
// Wire up app-level notifications.
|
|
376
377
|
pluginRegistry.bindHost({ notify: appNotifier.notify });
|
|
378
|
+
// Missed alerts live in this device's state store. A detached window keeps
|
|
379
|
+
// its own in memory rather than overwrite the main window's.
|
|
380
|
+
useEffect(() => (
|
|
381
|
+
isDetachedWindow ? undefined : attachNotificationLog(pluginRegistry.persistence.pluginState)
|
|
382
|
+
), [isDetachedWindow, pluginRegistry]);
|
|
377
383
|
|
|
378
384
|
// Persist layout changes (switching, saving, deleting, renaming layouts).
|
|
379
385
|
// The saved layouts also mirror live pane state and focus, so they change on
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"src/api-client/askg.ts": ["cloud"],
|
|
3
3
|
"src/app.tsx": ["cloud"],
|
|
4
4
|
"src/app/global-shortcuts.ts": ["help"],
|
|
5
|
-
"src/app/pane-runtime/plugin-bindings.ts": ["broker-manager","layout-manager"
|
|
5
|
+
"src/app/pane-runtime/plugin-bindings.ts": ["broker-manager","layout-manager"],
|
|
6
6
|
"src/app/runtime/broker-import.ts": ["portfolio-list"],
|
|
7
7
|
"src/app/runtime/desktop-deeplink.ts": ["account-management","chat","cloud"],
|
|
8
|
-
"src/app/runtime/startup.ts": ["chat"
|
|
8
|
+
"src/app/runtime/startup.ts": ["chat"],
|
|
9
9
|
"src/cli/commands/market.ts": ["holders","insider","research","sec"],
|
|
10
10
|
"src/cli/commands/options-chain.ts": ["options","options-calculator"],
|
|
11
11
|
"src/cli/commands/options-leaps.ts": ["options","vol-surface"],
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
"src/components/command-bar/commands/direct/index.ts": ["broker-manager","portfolio-list"],
|
|
24
24
|
"src/components/command-bar/routes/root/command-items.ts": ["portfolio-list"],
|
|
25
25
|
"src/components/command-bar/routes/root/help-items.ts": ["help"],
|
|
26
|
-
"src/components/command-bar/routes/root/plugin-install.ts": ["plugin-marketplace"],
|
|
27
26
|
"src/components/command-bar/routes/root/shortcut-items.ts": ["portfolio-list"],
|
|
28
27
|
"src/components/command-bar/workflow/builtin.ts": ["cloud","portfolio-list"],
|
|
29
28
|
"src/components/command-bar/workflow/collection-actions.ts": ["cloud","portfolio-list"],
|
|
@@ -32,30 +31,22 @@
|
|
|
32
31
|
"src/components/feedback-dialog.tsx": ["cloud"],
|
|
33
32
|
"src/components/form-modal/routes.ts": ["portfolio-list"],
|
|
34
33
|
"src/components/index.ts": ["portfolio-list"],
|
|
35
|
-
"src/components/layout/missing-pane.tsx": ["plugin-marketplace"],
|
|
36
34
|
"src/components/layout/shell/index.tsx": ["cloud"],
|
|
37
35
|
"src/components/layout/status-bar-groups.ts": ["cloud"],
|
|
38
36
|
"src/components/layout/status-bar.tsx": ["cloud"],
|
|
39
37
|
"src/components/onboarding/use-onboarding-upgrade.ts": ["chat"],
|
|
40
38
|
"src/components/onboarding/wizard-model.ts": ["portfolio-list"],
|
|
41
39
|
"src/components/onboarding/wizard-positions.ts": ["portfolio-list"],
|
|
42
|
-
"src/layout-marketplace/gallery.tsx": ["cloud"
|
|
40
|
+
"src/layout-marketplace/gallery.tsx": ["cloud"],
|
|
43
41
|
"src/layout-marketplace/linked-sync.ts": ["cloud"],
|
|
44
42
|
"src/layout/desks.ts": ["chart-composer"],
|
|
45
|
-
"src/plugins/auto-update-node.ts": ["plugin-marketplace"],
|
|
46
|
-
"src/plugins/auto-update.ts": ["plugin-marketplace"],
|
|
47
43
|
"src/plugins/catalog-browser.ts": ["alerts","analytics","attention","awards","backtest","bond-calculator","catalysts","cds","central-bank-rates","changelog","chart-composer","clinical-trials","cloud","comment-letters","company-attention","company-kpis","connections","correlation","cot","cpi","credit-boards","credit-conditions","credit-documents","crypto-board","debt-maturities","dividend-yield","docs","doe","earnings-calls","earnings-ripple","econ","econ-statistics","equity-screener","estimate-revisions","executives","exposure","fear-greed","filing-events","futures","futures-curve","fx-matrix","gpu","help","insider","ipo-calendar","iv-history","jobs","kelly-sizer","layout-manager","macro-day","market-halts","market-heatmap","market-valuation","members","mna","money-markets","news","openfda","options","options-calculator","options-positioning","options-scenario","pe-band","perps","portfolio-list","power","rate-path","realized-vol","relative-rotation","research","research-search","revenue-breakdown","reverse-dcf","risk-factors","scanner","seasonality","sec","sectors","short-interest","short-volume","social-mentions","supply-chain","ticker-detail","time-sales","treasury-auctions","vol-surface","volatility","world-indices","world-venue-map","yield-curve"],
|
|
48
44
|
"src/plugins/catalog-ui.ts": ["alerts","clinical-trials","cloud","comment-letters","custom-view","fear-greed","ipo-calendar","market-halts","market-heatmap","members","news","notes","openfda","research-search"],
|
|
49
45
|
"src/plugins/catalog.ts": ["debug"],
|
|
50
|
-
"src/plugins/installer.ts": ["plugin-marketplace"],
|
|
51
|
-
"src/plugins/manager-node.ts": ["plugin-marketplace"],
|
|
52
46
|
"src/remote/controller.ts": ["custom-view"],
|
|
53
|
-
"src/renderers/browser/main.tsx": ["plugin-marketplace"],
|
|
54
47
|
"src/renderers/electrobun/bun/core-capabilities.ts": ["notes"],
|
|
55
|
-
"src/renderers/electrobun/shared/protocol.ts": ["plugin-marketplace"],
|
|
56
48
|
"src/renderers/electrobun/view/cli-pane-shot-entry.tsx": ["econ-statistics","market-valuation","time-sales"],
|
|
57
|
-
"src/renderers/electrobun/view/main.tsx": ["notes"
|
|
49
|
+
"src/renderers/electrobun/view/main.tsx": ["notes"],
|
|
58
50
|
"src/renderers/electrobun/view/remote/connection-health.ts": ["connections"],
|
|
59
|
-
"src/renderers/opentui/start.tsx": ["plugin-marketplace"],
|
|
60
51
|
"src/sync/core-contributors.ts": ["analytics","portfolio-list"]
|
|
61
52
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { PluginRegistry } from "../plugins/registry";
|
|
2
|
+
import { paneShowsPersonalData } from "../shares/personal-pane";
|
|
3
|
+
import type { AppConfig, PaneInstanceConfig } from "../types/config";
|
|
4
|
+
import type { PaneSharePrivateFields } from "../types/plugin";
|
|
5
|
+
import type { TickerRecord } from "../types/ticker";
|
|
6
|
+
import type { AskGloomPaneAttachment } from "./pane-request";
|
|
7
|
+
|
|
8
|
+
/** A handful of the pane's own settings is enough to say how it is set up. */
|
|
9
|
+
const MAX_ARGS = 8;
|
|
10
|
+
const MAX_ARG_KEY_LENGTH = 32;
|
|
11
|
+
const MAX_ARG_VALUE_LENGTH = 48;
|
|
12
|
+
/** Layout and view bookkeeping, not what the pane shows. */
|
|
13
|
+
const BOOKKEEPING_KEYS = [
|
|
14
|
+
/scroll|width|height|offset|index|expanded|collapsed|focus|hover|sidebar|column|sort|order|version|draft/i,
|
|
15
|
+
// The cursor's position, but not the symbol it is on.
|
|
16
|
+
/^cursor(?!Symbol)/,
|
|
17
|
+
// Timestamps such as `updatedAt`.
|
|
18
|
+
/[a-z]At$/,
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
type ArgSource = Readonly<Record<string, unknown>> | undefined;
|
|
22
|
+
|
|
23
|
+
function isPrivate(fields: PaneSharePrivateFields | undefined, key: string): boolean {
|
|
24
|
+
return fields === true || (Array.isArray(fields) && fields.includes(key));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function scalarArgs(source: ArgSource, privateFields: PaneSharePrivateFields | undefined): Array<[string, string]> {
|
|
28
|
+
if (!source || privateFields === true) return [];
|
|
29
|
+
return Object.entries(source).flatMap(([key, value]): Array<[string, string]> => {
|
|
30
|
+
if (key.length > MAX_ARG_KEY_LENGTH || BOOKKEEPING_KEYS.some((pattern) => pattern.test(key)) || isPrivate(privateFields, key)) return [];
|
|
31
|
+
if (typeof value === "number" && Number.isFinite(value)) return [[key, String(value)]];
|
|
32
|
+
if (typeof value !== "string") return [];
|
|
33
|
+
const trimmed = value.trim();
|
|
34
|
+
return trimmed && trimmed.length <= MAX_ARG_VALUE_LENGTH ? [[key, trimmed]] : [];
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The function code a pane is opened by: the one its title starts with when
|
|
40
|
+
* that opens this pane (a chart opened with `GP` stays `GP`), else the first
|
|
41
|
+
* template that opens it.
|
|
42
|
+
*/
|
|
43
|
+
function functionCode(registry: Pick<PluginRegistry, "paneTemplates">, paneType: string, title: string): string | null {
|
|
44
|
+
const prefixes = [...registry.paneTemplates.values()]
|
|
45
|
+
.filter((template) => template.paneId === paneType && template.shortcut?.prefix)
|
|
46
|
+
.map((template) => template.shortcut!.prefix.toUpperCase());
|
|
47
|
+
const token = title.trim().split(/\s+/)[0]?.toUpperCase() ?? "";
|
|
48
|
+
if (token && prefixes.includes(token)) return token;
|
|
49
|
+
return prefixes[0] ?? null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface PaneAttachmentSource {
|
|
53
|
+
registry: Pick<PluginRegistry, "panes" | "paneTemplates" | "brokers" | "getPanePluginId" | "getBrokerPluginId">;
|
|
54
|
+
instance: PaneInstanceConfig;
|
|
55
|
+
/** What the header calls it. */
|
|
56
|
+
title: string;
|
|
57
|
+
symbol: string | null;
|
|
58
|
+
paneState?: Readonly<Record<string, unknown>>;
|
|
59
|
+
config: Pick<AppConfig, "portfolios" | "brokerInstances">;
|
|
60
|
+
tickers?: ReadonlyMap<string, TickerRecord>;
|
|
61
|
+
/** The tab each of its tab strips has open, outermost first. */
|
|
62
|
+
activeTabs?: readonly string[];
|
|
63
|
+
visibleText: string | null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* What Ask Gloom is told about a pane: its function and arguments as the
|
|
68
|
+
* user set them, and its text as drawn. Fields the pane keeps to itself when
|
|
69
|
+
* shared (`portableShare.private`) stay out of its arguments.
|
|
70
|
+
*/
|
|
71
|
+
export function buildAskGloomPaneAttachment({
|
|
72
|
+
registry,
|
|
73
|
+
instance,
|
|
74
|
+
title,
|
|
75
|
+
symbol,
|
|
76
|
+
paneState,
|
|
77
|
+
config,
|
|
78
|
+
tickers,
|
|
79
|
+
activeTabs = [],
|
|
80
|
+
visibleText,
|
|
81
|
+
}: PaneAttachmentSource): AskGloomPaneAttachment {
|
|
82
|
+
const privateFields = registry.panes.get(instance.paneId)?.portableShare?.private;
|
|
83
|
+
const args: Record<string, string> = {};
|
|
84
|
+
const tabs = activeTabs.map((tab) => tab.trim()).filter(Boolean);
|
|
85
|
+
if (tabs.length > 0) args.tab = tabs.join(" > ").slice(0, MAX_ARG_VALUE_LENGTH);
|
|
86
|
+
for (const [key, value] of [
|
|
87
|
+
...scalarArgs(instance.params, privateFields?.params),
|
|
88
|
+
...scalarArgs(instance.settings, privateFields?.settings),
|
|
89
|
+
...scalarArgs(paneState, privateFields?.state),
|
|
90
|
+
]) {
|
|
91
|
+
if (Object.keys(args).length >= MAX_ARGS) break;
|
|
92
|
+
if (key in args || value === symbol) continue;
|
|
93
|
+
args[key] = value;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
paneId: instance.instanceId,
|
|
97
|
+
paneType: instance.paneId,
|
|
98
|
+
title,
|
|
99
|
+
code: functionCode(registry, instance.paneId, title),
|
|
100
|
+
symbol,
|
|
101
|
+
args,
|
|
102
|
+
visibleText,
|
|
103
|
+
personal: showsPersonalData({ registry, instance, paneState, symbol, config, tickers }),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** A pane that cannot be read for it counts as personal: its contents then wait for a yes. */
|
|
108
|
+
function showsPersonalData(source: Parameters<typeof paneShowsPersonalData>[0]): boolean {
|
|
109
|
+
try {
|
|
110
|
+
return paneShowsPersonalData(source);
|
|
111
|
+
} catch {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asking Ask Gloom about a pane. Every pane offers it the same way, with no
|
|
3
|
+
* code of its own: the button beside the `?` in a desktop pane header, Ask
|
|
4
|
+
* Gloom in the pane menu, and the pane-ask key. The shell describes the pane
|
|
5
|
+
* here, and Ask Gloom, while its plugin is on, opens a new conversation with
|
|
6
|
+
* the pane attached.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** A pane as Ask Gloom receives it: what it is and what it showed when asked. */
|
|
10
|
+
export interface AskGloomPaneAttachment {
|
|
11
|
+
/** The pane instance. */
|
|
12
|
+
paneId: string;
|
|
13
|
+
/** Its pane type. */
|
|
14
|
+
paneType: string;
|
|
15
|
+
/** What its header calls it, such as `DES AAPL`. */
|
|
16
|
+
title: string;
|
|
17
|
+
/** The function code that opens it, such as `DES`, when one does. */
|
|
18
|
+
code: string | null;
|
|
19
|
+
/** The ticker it shows, when it shows one. */
|
|
20
|
+
symbol: string | null;
|
|
21
|
+
/** How it is set up as the user sees it: its tab, range or view. Short values only. */
|
|
22
|
+
args: Readonly<Record<string, string>>;
|
|
23
|
+
/** Its text as drawn when asked, bounded; null when none could be read. */
|
|
24
|
+
visibleText: string | null;
|
|
25
|
+
/**
|
|
26
|
+
* It shows holdings, balances or account data, so Ask Gloom asks before
|
|
27
|
+
* anything it shows leaves the device.
|
|
28
|
+
*/
|
|
29
|
+
personal: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type AskGloomPaneHandler = (attachment: AskGloomPaneAttachment) => void;
|
|
33
|
+
|
|
34
|
+
const handlers = new Set<AskGloomPaneHandler>();
|
|
35
|
+
const listeners = new Set<() => void>();
|
|
36
|
+
|
|
37
|
+
function changed(): void {
|
|
38
|
+
for (const listener of [...listeners]) listener();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Ask Gloom takes pane questions while it is registered. The shell offers the
|
|
43
|
+
* button, the menu entry and the key only then, so a profile with the cloud
|
|
44
|
+
* plugin off shows none of them.
|
|
45
|
+
*/
|
|
46
|
+
export function registerAskGloomPaneHandler(handler: AskGloomPaneHandler): () => void {
|
|
47
|
+
handlers.add(handler);
|
|
48
|
+
changed();
|
|
49
|
+
return () => {
|
|
50
|
+
if (handlers.delete(handler)) changed();
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function canAskGloomAboutPanes(): boolean {
|
|
55
|
+
return handlers.size > 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function subscribeAskGloomAboutPanes(listener: () => void): () => void {
|
|
59
|
+
listeners.add(listener);
|
|
60
|
+
return () => {
|
|
61
|
+
listeners.delete(listener);
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Hands the pane to Ask Gloom. False when nothing takes it. */
|
|
66
|
+
export function askGloomAboutPane(attachment: AskGloomPaneAttachment): boolean {
|
|
67
|
+
if (handlers.size === 0) return false;
|
|
68
|
+
for (const handler of [...handlers]) handler(attachment);
|
|
69
|
+
return true;
|
|
70
|
+
}
|