gloomberb 0.16.1 → 0.16.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/package.json +2 -1
- package/src/api-client/beneficial-owners.ts +92 -0
- package/src/api-client/data.ts +26 -8
- package/src/api-client/errors.ts +12 -0
- package/src/api-client/geo.ts +363 -0
- package/src/api-client/index.ts +2 -0
- package/src/api-client/market-discovery.ts +10 -0
- package/src/api-client/paths.ts +30 -1
- package/src/api-client/perps.ts +37 -0
- package/src/api-client/request.ts +5 -2
- package/src/api-client/types.ts +2 -0
- package/src/brokers/account-cache.ts +69 -0
- package/src/cli/command-options.ts +74 -0
- package/src/cli/commands/command-utils.ts +37 -0
- package/src/cli/commands/crypto-hints.ts +75 -0
- package/src/cli/commands/market.ts +560 -136
- package/src/cli/commands/overview.ts +136 -48
- package/src/cli/commands/ticker.ts +220 -67
- package/src/cli/desktop-pane-shot.ts +37 -4
- package/src/cli/freshness.ts +61 -0
- package/src/cli/help.ts +27 -6
- package/src/cli/helpers.ts +4 -8
- package/src/cli/history-rows.ts +187 -15
- package/src/cli/index.ts +23 -8
- package/src/cli/listing-arg.ts +321 -0
- package/src/cli/options.ts +5 -1
- package/src/cli/pane-functions/access-gate.ts +42 -0
- package/src/cli/pane-functions/capabilities.ts +5 -0
- package/src/cli/pane-functions/catalog.ts +28 -1
- package/src/cli/pane-functions/data.ts +3 -1
- package/src/cli/pane-functions/dom.ts +87 -16
- package/src/cli/pane-functions/freshness.ts +400 -0
- package/src/cli/pane-functions/function-help.ts +31 -22
- package/src/cli/pane-functions/headless.ts +201 -41
- package/src/cli/pane-functions/index.ts +24 -6
- package/src/cli/pane-functions/options.ts +3 -0
- package/src/cli/pane-functions/report.ts +12 -1
- package/src/cli/pane-functions/resolver.ts +63 -9
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +11 -3
- package/src/cli/registry.ts +6 -3
- package/src/cli/report-tables.ts +460 -0
- package/src/cli/result.ts +53 -29
- package/src/cli/ticker-resolution.ts +7 -5
- package/src/components/chart/composite/composite-chart.tsx +88 -2536
- package/src/components/chart/composite/drawing-store.ts +59 -0
- package/src/components/chart/composite/legend.tsx +319 -0
- package/src/components/chart/composite/panel-bitmap.ts +139 -0
- package/src/components/chart/composite/panel-gestures.ts +59 -0
- package/src/components/chart/composite/panel-labels.ts +107 -0
- package/src/components/chart/composite/panel-surface.tsx +876 -0
- package/src/components/chart/composite/tool-catalog.ts +98 -0
- package/src/components/chart/composite/toolbar.tsx +186 -0
- package/src/components/chart/composite/tools.ts +8 -0
- package/src/components/chart/composite/use-composite-chart-keyboard.ts +703 -0
- package/src/components/chart/composite/use-composite-viewport.ts +143 -0
- package/src/components/command-bar/list/model.ts +5 -0
- package/src/components/command-bar/list/view.tsx +16 -3
- package/src/components/command-bar/pane-templates/workflow.ts +1 -0
- package/src/components/command-bar/routes/ticker-search/actions.ts +5 -0
- package/src/components/command-bar/workflow/ops.ts +1 -1
- package/src/components/command-bar/workflow/tickers.ts +6 -0
- package/src/components/data-table/export.ts +6 -51
- package/src/components/data-table/view.tsx +32 -11
- package/src/components/feedback-dialog.tsx +2 -1
- package/src/components/form-modal/field-row.tsx +2 -2
- package/src/components/layout/detached-pane-shell.tsx +6 -3
- package/src/components/layout/pane/content.tsx +23 -10
- package/src/components/layout/pane/error-boundary.tsx +103 -0
- package/src/components/layout/pane/footer/registration.tsx +68 -23
- package/src/components/layout/pane/header.tsx +11 -11
- package/src/components/layout/shell/active-drag.ts +67 -35
- package/src/components/layout/shell/cursor-occlusion.ts +6 -5
- package/src/components/layout/shell/drag/index.ts +12 -7
- package/src/components/layout/shell/drag/live.ts +122 -0
- package/src/components/layout/shell/drag/overlays.tsx +179 -35
- package/src/components/layout/shell/drag/runtime.ts +62 -50
- package/src/components/layout/shell/drag/slide.ts +10 -0
- package/src/components/layout/shell/index.tsx +37 -51
- package/src/components/layout/shell/menu.ts +2 -1
- package/src/components/layout/shell/native/pointer-runtime.ts +13 -13
- package/src/components/layout/shell/native/surfaces.ts +30 -14
- package/src/components/layout/shell/pane/actions.ts +2 -1
- package/src/components/layout/shell/pane/layers.tsx +419 -168
- package/src/components/layout/shell/terminal-pointer-runtime.ts +18 -18
- package/src/components/layout/shell/window-mode/overlays.tsx +12 -4
- package/src/components/metric-treemap/heat-surface.tsx +43 -16
- package/src/components/metric-treemap/heat-tiles.ts +18 -0
- package/src/components/metric-treemap/layout.ts +2 -0
- package/src/components/onboarding/onboarding-keyboard.ts +311 -0
- package/src/components/onboarding/onboarding-wizard.tsx +101 -788
- package/src/components/onboarding/use-onboarding-broker-form.ts +263 -0
- package/src/components/onboarding/use-onboarding-progress.ts +298 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +83 -0
- package/src/components/ticker/list-table-view.tsx +13 -1
- package/src/components/ui/fields.tsx +8 -0
- package/src/components/ui/range-track.tsx +10 -3
- package/src/components/ui/status.tsx +8 -2
- package/src/components/ui/tabs.tsx +7 -4
- package/src/components/ui/text-prompt-dialog.tsx +4 -2
- package/src/data/config/store/normalize.ts +17 -1
- package/src/data/json-persistence.ts +17 -3
- package/src/data/json-storage.ts +2 -0
- package/src/data/memory-resource-store.ts +46 -0
- package/src/i18n/es.ts +19 -1
- package/src/i18n/ja.ts +19 -1
- package/src/i18n/ko.ts +19 -1
- package/src/i18n/zh-cn.ts +19 -1
- package/src/i18n/zh-tw.ts +19 -1
- package/src/market-data/coordinator/chart.ts +1 -1
- package/src/market-data/coordinator/quotes.ts +23 -4
- package/src/market-data/fx-closes.ts +72 -0
- package/src/market-data/market/freshness.ts +123 -6
- package/src/market-data/market/session-close-note.ts +57 -0
- package/src/market-data/market/status.ts +151 -0
- package/src/market-data/published-apac-sessions.ts +66 -0
- package/src/market-data/quotes/contributions.ts +2 -0
- package/src/market-data/quotes/freshness.ts +5 -0
- package/src/market-data/quotes/resolution.ts +2 -0
- package/src/market-data/quotes/screener-live-quotes.ts +49 -4
- package/src/plugins/builtin/account-management/pane.tsx +4 -0
- package/src/plugins/builtin/alerts/cli.ts +10 -5
- package/src/plugins/builtin/alerts/index.tsx +1 -0
- package/src/plugins/builtin/analytics/metrics.ts +8 -3
- package/src/plugins/builtin/analytics/pane-model.ts +10 -6
- package/src/plugins/builtin/analytics/risk-client.ts +191 -66
- package/src/plugins/builtin/analytics/risk-fx.ts +102 -0
- package/src/plugins/builtin/analytics/risk-headless.ts +19 -13
- package/src/plugins/builtin/analytics/risk-model.ts +45 -17
- package/src/plugins/builtin/analytics/risk-pane.tsx +1 -0
- package/src/plugins/builtin/analytics/risk-test-data.ts +25 -1
- package/src/plugins/builtin/attention/headless.ts +6 -4
- package/src/plugins/builtin/attention/index.tsx +1 -1
- package/src/plugins/builtin/attention/pane.tsx +2 -2
- package/src/plugins/builtin/awards/headless.ts +1 -0
- package/src/plugins/builtin/awards/pane.tsx +1 -1
- package/src/plugins/builtin/backtest/headless.ts +1 -0
- package/src/plugins/builtin/bond-calculator/headless.ts +1 -0
- package/src/plugins/builtin/buildout/index.tsx +1 -0
- package/src/plugins/builtin/catalysts/detail.tsx +1 -1
- package/src/plugins/builtin/catalysts/headless.ts +3 -1
- package/src/plugins/builtin/cds/headless.ts +2 -0
- package/src/plugins/builtin/central-bank-rates/headless.ts +1 -0
- package/src/plugins/builtin/chart-composer/headless.ts +38 -3
- package/src/plugins/builtin/chart-composer/index.tsx +3 -1
- package/src/plugins/builtin/chart-composer/series-expression.ts +18 -2
- package/src/plugins/builtin/chat/channels.ts +19 -3
- package/src/plugins/builtin/chat/content/composer-runtime.ts +28 -13
- package/src/plugins/builtin/chat/content/footer.tsx +15 -6
- package/src/plugins/builtin/chat/content/index.tsx +120 -21
- package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +261 -113
- package/src/plugins/builtin/chat/content/transcript.tsx +20 -2
- package/src/plugins/builtin/chat/direct-messages.ts +200 -0
- package/src/plugins/builtin/chat/index.tsx +1 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +3 -0
- package/src/plugins/builtin/chat/message/header.tsx +16 -6
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +72 -32
- package/src/plugins/builtin/chat/message/profile-popover.tsx +96 -12
- package/src/plugins/builtin/chat/message/terminal.tsx +3 -0
- package/src/plugins/builtin/chat/message/types.ts +14 -2
- package/src/plugins/builtin/chat/profile-popover.ts +18 -13
- package/src/plugins/builtin/clinical-trials/index.tsx +1 -0
- package/src/plugins/builtin/cloud/askg/executor.ts +2 -1
- package/src/plugins/builtin/cloud/plugin.tsx +1 -0
- package/src/plugins/builtin/cloud/team/module.tsx +1 -0
- package/src/plugins/builtin/cloud/thesis/module.tsx +1 -0
- package/src/plugins/builtin/cloud-tweets/registration.ts +1 -0
- package/src/plugins/builtin/comment-letters/index.tsx +1 -0
- package/src/plugins/builtin/company-attention/headless.ts +5 -1
- package/src/plugins/builtin/company-attention/pane.tsx +2 -2
- package/src/plugins/builtin/company-kpis/headless.ts +1 -0
- package/src/plugins/builtin/congress-trades/headless.ts +1 -0
- package/src/plugins/builtin/correlation/compute.ts +59 -16
- package/src/plugins/builtin/correlation/geo.ts +34 -0
- package/src/plugins/builtin/correlation/headless-schema.ts +4 -1
- package/src/plugins/builtin/correlation/headless.ts +42 -8
- package/src/plugins/builtin/correlation/history.ts +2 -0
- package/src/plugins/builtin/correlation/index.tsx +68 -14
- package/src/plugins/builtin/correlation/matrix/model.ts +17 -2
- package/src/plugins/builtin/correlation/matrix/selection.ts +5 -3
- package/src/plugins/builtin/correlation/relationship/model.ts +1 -1
- package/src/plugins/builtin/correlation/relationship/pane.tsx +4 -2
- package/src/plugins/builtin/correlation/relationship/view-model.ts +16 -1
- package/src/plugins/builtin/correlation/settings.ts +1 -1
- package/src/plugins/builtin/cot/headless.ts +6 -3
- package/src/plugins/builtin/cot/index.tsx +3 -3
- package/src/plugins/builtin/cot/model.ts +36 -3
- package/src/plugins/builtin/cpi/headless.ts +4 -0
- package/src/plugins/builtin/credit-boards/headless.ts +2 -0
- package/src/plugins/builtin/credit-conditions/headless.ts +1 -0
- package/src/plugins/builtin/credit-documents/gauge.tsx +5 -8
- package/src/plugins/builtin/credit-documents/headless.ts +2 -0
- package/src/plugins/builtin/crypto-board/headless.ts +3 -0
- package/src/plugins/builtin/custom-view/loader.ts +1 -1
- package/src/plugins/builtin/debt-maturities/headless.ts +4 -0
- package/src/plugins/builtin/dividend-yield/headless.ts +1 -0
- package/src/plugins/builtin/doe/headless.ts +7 -0
- package/src/plugins/builtin/doe/range-bar.tsx +7 -37
- package/src/plugins/builtin/earnings/headless.ts +5 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +1 -0
- package/src/plugins/builtin/earnings-ripple/client.ts +91 -18
- package/src/plugins/builtin/earnings-ripple/headless.ts +28 -8
- package/src/plugins/builtin/earnings-ripple/index.tsx +2 -2
- package/src/plugins/builtin/earnings-ripple/model.ts +97 -7
- package/src/plugins/builtin/earnings-ripple/pane.tsx +148 -23
- package/src/plugins/builtin/econ/index.tsx +1 -0
- package/src/plugins/builtin/econ-statistics/headless.ts +2 -0
- package/src/plugins/builtin/equity-screener/headless.ts +2 -0
- package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
- package/src/plugins/builtin/executives/index.tsx +1 -0
- package/src/plugins/builtin/exposure/headless.ts +3 -1
- package/src/plugins/builtin/fear-greed/headless.ts +2 -0
- package/src/plugins/builtin/filing-events/index.tsx +1 -0
- package/src/plugins/builtin/futures-curve/client.ts +12 -3
- package/src/plugins/builtin/futures-curve/headless.ts +39 -10
- package/src/plugins/builtin/futures-curve/index.tsx +3 -3
- package/src/plugins/builtin/futures-curve/model.ts +188 -4
- package/src/plugins/builtin/futures-curve/pane.tsx +51 -9
- package/src/plugins/builtin/gpu/headless.ts +7 -3
- package/src/plugins/builtin/gpu/ladder.tsx +26 -30
- package/src/plugins/builtin/gpu/model.ts +27 -1
- package/src/plugins/builtin/holders/beneficial-client.ts +209 -0
- package/src/plugins/builtin/holders/beneficial-model.ts +279 -0
- package/src/plugins/builtin/holders/beneficial-report.ts +126 -0
- package/src/plugins/builtin/holders/beneficial-view.tsx +241 -0
- package/src/plugins/builtin/holders/client.ts +3 -6
- package/src/plugins/builtin/holders/format.ts +31 -1
- package/src/plugins/builtin/holders/headless.ts +161 -6
- package/src/plugins/builtin/holders/index.tsx +10 -3
- package/src/plugins/builtin/holders/pane.tsx +42 -16
- package/src/plugins/builtin/holders/report-header.ts +136 -0
- package/src/plugins/builtin/holders/table-model.ts +20 -5
- package/src/plugins/builtin/holders/thirteenf-match.ts +29 -1
- package/src/plugins/builtin/holders/types.ts +2 -1
- package/src/plugins/builtin/insider/headless.ts +2 -0
- package/src/plugins/builtin/ipo-calendar/headless.ts +1 -0
- package/src/plugins/builtin/iv-history/headless.ts +4 -1
- package/src/plugins/builtin/jobs/headless.ts +1 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +1 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +12 -6
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +25 -0
- package/src/plugins/builtin/macro-day/headless.ts +2 -0
- package/src/plugins/builtin/market-halts/index.tsx +1 -0
- package/src/plugins/builtin/market-heatmap/data.ts +2 -0
- package/src/plugins/builtin/market-heatmap/headless.ts +135 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +39 -46
- package/src/plugins/builtin/market-heatmap/model.ts +146 -0
- package/src/plugins/builtin/market-heatmap/portfolio.ts +23 -4
- package/src/plugins/builtin/market-movers/headless.ts +2 -0
- package/src/plugins/builtin/market-valuation/headless.ts +2 -0
- package/src/plugins/builtin/members/client.ts +20 -3
- package/src/plugins/builtin/members/headless.ts +5 -3
- package/src/plugins/builtin/members/model.ts +10 -2
- package/src/plugins/builtin/members/pane.tsx +23 -6
- package/src/plugins/builtin/mna/distress/headless.ts +1 -0
- package/src/plugins/builtin/mna/headless.ts +1 -0
- package/src/plugins/builtin/money-markets/headless.ts +1 -0
- package/src/plugins/builtin/news/headless.ts +2 -0
- package/src/plugins/builtin/news/wire/index.tsx +8 -1
- package/src/plugins/builtin/notes/cli.ts +14 -6
- package/src/plugins/builtin/notes/index.tsx +1 -0
- package/src/plugins/builtin/openfda/index.tsx +1 -0
- package/src/plugins/builtin/options-calculator/headless.ts +2 -0
- package/src/plugins/builtin/options-positioning/headless.ts +3 -0
- package/src/plugins/builtin/options-scenario/headless.ts +5 -0
- package/src/plugins/builtin/pe-band/client.ts +48 -3
- package/src/plugins/builtin/pe-band/headless.ts +25 -7
- package/src/plugins/builtin/pe-band/model.ts +92 -16
- package/src/plugins/builtin/pe-band/pane.tsx +33 -16
- package/src/plugins/builtin/perps/client.ts +50 -3
- package/src/plugins/builtin/perps/headless.ts +144 -16
- package/src/plugins/builtin/perps/index.tsx +6 -6
- package/src/plugins/builtin/perps/model.ts +189 -12
- package/src/plugins/builtin/perps/pane.tsx +249 -48
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +16 -1
- package/src/plugins/builtin/portfolio-list/allocation.ts +248 -0
- package/src/plugins/builtin/portfolio-list/cached-account.ts +42 -0
- package/src/plugins/builtin/portfolio-list/cell-version.ts +19 -1
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +328 -29
- package/src/plugins/builtin/portfolio-list/cli/render.ts +232 -39
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +67 -2
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +35 -31
- package/src/plugins/builtin/portfolio-list/column-values.ts +124 -47
- package/src/plugins/builtin/portfolio-list/headless.ts +100 -16
- package/src/plugins/builtin/portfolio-list/index.tsx +14 -3
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +7 -5
- package/src/plugins/builtin/portfolio-list/mutations.ts +55 -1
- package/src/plugins/builtin/portfolio-list/pane/data.ts +6 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +53 -16
- package/src/plugins/builtin/portfolio-list/settings.ts +33 -2
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +46 -5
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +11 -1
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +26 -7
- package/src/plugins/builtin/power/headless.ts +3 -1
- package/src/plugins/builtin/rate-path/headless.ts +2 -0
- package/src/plugins/builtin/realized-vol/headless.ts +2 -0
- package/src/plugins/builtin/relative-rotation/headless.ts +2 -0
- package/src/plugins/builtin/research/analyst-headless.ts +3 -0
- package/src/plugins/builtin/research/events-headless.ts +2 -0
- package/src/plugins/builtin/research/headless.ts +2 -0
- package/src/plugins/builtin/research/index.tsx +1 -0
- package/src/plugins/builtin/research/relative-valuation-headless.ts +10 -5
- package/src/plugins/builtin/research/relative-valuation-model.ts +18 -6
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +3 -3
- package/src/plugins/builtin/research-search/index.tsx +1 -0
- package/src/plugins/builtin/revenue-breakdown/headless.ts +2 -0
- package/src/plugins/builtin/reverse-dcf/headless.ts +2 -0
- package/src/plugins/builtin/reverse-dcf/model.ts +2 -1
- package/src/plugins/builtin/risk-factors/headless.ts +2 -0
- package/src/plugins/builtin/scanner/flow-history.ts +2 -13
- package/src/plugins/builtin/scanner/headless.ts +14 -0
- package/src/plugins/builtin/seasonality/headless.ts +2 -0
- package/src/plugins/builtin/sec/command-bar-search.ts +14 -4
- package/src/plugins/builtin/sec/filing-content.ts +42 -17
- package/src/plugins/builtin/sec/forms.ts +12 -0
- package/src/plugins/builtin/sec/headless.ts +2 -0
- package/src/plugins/builtin/sectors/client.ts +1 -0
- package/src/plugins/builtin/sectors/headless.ts +9 -1
- package/src/plugins/builtin/sectors/sector-model.ts +2 -0
- package/src/plugins/builtin/shared/crypto-pair.ts +14 -0
- package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
- package/src/plugins/builtin/shared/members-menu.tsx +260 -0
- package/src/plugins/builtin/shared/report-freshness.ts +57 -0
- package/src/plugins/builtin/shared/research-cells.tsx +4 -9
- package/src/plugins/builtin/short-interest/headless.ts +2 -0
- package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
- package/src/plugins/builtin/short-volume/headless.ts +1 -0
- package/src/plugins/builtin/short-volume/pane.tsx +1 -1
- package/src/plugins/builtin/social-mentions/headless.ts +1 -0
- package/src/plugins/builtin/social-mentions/pane.tsx +1 -1
- package/src/plugins/builtin/supply-chain/headless.ts +7 -1
- package/src/plugins/builtin/supply-chain/index.tsx +10 -1
- package/src/plugins/builtin/supply-chain/model.ts +27 -2
- package/src/plugins/builtin/supply-chain/pane.tsx +71 -32
- package/src/plugins/builtin/themes/headless.ts +3 -0
- package/src/plugins/builtin/themes/pane.tsx +3 -0
- package/src/plugins/builtin/thirteenf/headless.ts +110 -25
- package/src/plugins/builtin/thirteenf/report-notes.ts +149 -0
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +4 -0
- package/src/plugins/builtin/ticker-detail/financials/model.ts +25 -2
- package/src/plugins/builtin/ticker-detail/headless.ts +27 -5
- package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
- package/src/plugins/builtin/ticker-detail/overview/model.ts +17 -5
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +27 -26
- package/src/plugins/builtin/time-sales/headless.ts +5 -1
- package/src/plugins/builtin/treasury-auctions/headless.ts +1 -0
- package/src/plugins/builtin/volatility/headless.ts +6 -1
- package/src/plugins/builtin/world-indices/headless.ts +2 -0
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +159 -0
- package/src/plugins/builtin/world-venue-map/basemap.ts +232 -0
- package/src/plugins/builtin/world-venue-map/client.ts +45 -0
- package/src/plugins/builtin/world-venue-map/country-labels.ts +78 -0
- package/src/plugins/builtin/world-venue-map/entity-detail.tsx +147 -0
- package/src/plugins/builtin/world-venue-map/entity-table.ts +59 -0
- package/src/plugins/builtin/world-venue-map/evidence.ts +77 -0
- package/src/plugins/builtin/world-venue-map/feed.ts +293 -0
- package/src/plugins/builtin/world-venue-map/geo-draw.tsx +248 -0
- package/src/plugins/builtin/world-venue-map/geo-series.ts +142 -0
- package/src/plugins/builtin/world-venue-map/geo-svg.tsx +448 -0
- package/src/plugins/builtin/world-venue-map/headless.ts +146 -0
- package/src/plugins/builtin/world-venue-map/ids.ts +1 -0
- package/src/plugins/builtin/world-venue-map/index.ts +69 -6
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +565 -0
- package/src/plugins/builtin/world-venue-map/layers.ts +406 -0
- package/src/plugins/builtin/world-venue-map/map-symbols.ts +220 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +557 -85
- package/src/plugins/builtin/world-venue-map/model.ts +23 -4
- package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +202 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/labels.chunk.ts +244 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e000s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e015s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e030s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e045s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e060s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e075s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e090s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e105s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e120s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e135s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e150s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/e165s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w015s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w030s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w045s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w060s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w075s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w090s60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w105s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w120s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135n75.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w135s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w150s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w165s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n00.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180n60.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s15.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s30.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/tiles/w180s45.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/world-50m.chunk.ts +4 -0
- package/src/plugins/builtin/world-venue-map/pane.tsx +35 -44
- package/src/plugins/builtin/world-venue-map/use-geo.ts +55 -0
- package/src/plugins/builtin/world-venue-map/venue-header.tsx +32 -0
- package/src/plugins/builtin/yield-curve/headless.ts +16 -0
- package/src/plugins/loader.ts +13 -1
- package/src/plugins/registry/pane-settings.ts +1 -0
- package/src/renderers/browser/app-services.ts +3 -1
- package/src/renderers/dom/build-assets.ts +81 -3
- package/src/renderers/dom/data-table/dom.ts +31 -0
- package/src/renderers/dom/data-table/index.tsx +5 -0
- package/src/renderers/dom/data-table/row.tsx +2 -0
- package/src/renderers/dom/desktop/controls.tsx +7 -3
- package/src/renderers/dom/desktop/list-view.tsx +35 -10
- package/src/renderers/dom/desktop/popover.tsx +73 -14
- package/src/renderers/dom/host/box.tsx +113 -17
- package/src/renderers/dom/host/drag-shield.ts +24 -0
- package/src/renderers/dom/host/input.tsx +14 -3
- package/src/renderers/dom/host/live-frame.ts +54 -0
- package/src/renderers/dom/host/mouse.ts +8 -1
- package/src/renderers/dom/host/scroll-box.tsx +6 -5
- package/src/renderers/dom/host/tabs.tsx +3 -2
- package/src/renderers/dom/styles.css +16 -9
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +7 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +2 -0
- package/src/renderers/electrobun/bun/desktop/initialization.ts +13 -0
- package/src/renderers/electrobun/shared/protocol.ts +10 -1
- package/src/renderers/electrobun/view/backend-rpc.ts +10 -4
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +4 -0
- package/src/renderers/electrobun/view/host/native.ts +0 -10
- package/src/renderers/electrobun/view/host/window-move.ts +28 -0
- package/src/renderers/electrobun/view/remote/persistence.ts +15 -2
- package/src/renderers/electrobun/view/rpc-timeout.ts +14 -3
- package/src/renderers/electrobun/view/ui-host.tsx +2 -5
- package/src/renderers/opentui/host.tsx +5 -0
- package/src/renderers/opentui/ui-host.tsx +7 -1
- package/src/sources/gloomberb-cloud/index.ts +25 -4
- package/src/sources/gloomberb-cloud/normalizers.ts +43 -23
- package/src/sources/provider-router/batches.ts +3 -3
- package/src/sources/provider-router/cached-routes.ts +4 -1
- package/src/sources/provider-router/financial-routes.ts +2 -2
- package/src/sources/provider-router/financials.ts +76 -12
- package/src/sources/provider-router/history.ts +15 -10
- package/src/sources/provider-router/primary.ts +2 -2
- package/src/sources/sec-registrant.ts +75 -0
- package/src/state/app/context/index.tsx +24 -8
- package/src/state/hooks/quote-streaming.ts +41 -26
- package/src/state/pane-scroll-registry.tsx +67 -35
- package/src/sync/core-contributors.ts +4 -0
- package/src/telemetry/crash-reports.ts +4 -1
- package/src/test-support/cli-context.ts +10 -2
- package/src/test-support/margin-account.ts +108 -0
- package/src/theme/heat-colors.ts +266 -84
- package/src/time-series/resolution.ts +15 -0
- package/src/time-series/resolve.ts +1 -1
- package/src/time-series/use-chart-resolution.ts +1 -1
- package/src/types/context-menu.ts +6 -0
- package/src/types/data-provider.ts +2 -0
- package/src/types/financials.ts +35 -3
- package/src/types/headless.ts +79 -2
- package/src/types/plugin.ts +20 -1
- package/src/types/ticker.ts +15 -0
- package/src/ui/host.tsx +26 -0
- package/src/ui/index.tsx +8 -3
- package/src/ui/scroll-box-axis.ts +26 -0
- package/src/updater/index.ts +9 -11
- package/src/utils/async-deadline.ts +21 -0
- package/src/utils/cli-output.ts +5 -1
- package/src/utils/crypto-pair.ts +41 -0
- package/src/utils/currency-units.ts +19 -0
- package/src/utils/depositary-receipt.ts +70 -0
- package/src/utils/display-number.ts +63 -0
- package/src/utils/exchanges.ts +72 -0
- package/src/utils/fire-and-forget.ts +24 -0
- package/src/utils/format.ts +13 -0
- package/src/utils/fundamentals.ts +17 -1
- package/src/utils/price-earnings.ts +70 -3
- package/src/utils/price-history-integrity.ts +19 -6
- package/src/utils/price-history.ts +58 -13
- package/src/utils/rpc-timeout-error.ts +27 -0
- package/src/utils/sec.ts +13 -1
- package/src/utils/utc-time.ts +79 -0
|
@@ -62,6 +62,7 @@ function coverageSummary(coverage: RiskCoverage, limit = Infinity) {
|
|
|
62
62
|
coveredValue: coverage.coveredValue,
|
|
63
63
|
holdings: coverage.holdings,
|
|
64
64
|
covered: coverage.covered,
|
|
65
|
+
convertedFromLocalCurrency: coverage.converted,
|
|
65
66
|
leftOut: coverage.leftOut
|
|
66
67
|
.slice(0, limit)
|
|
67
68
|
.map((row) => ({ symbol: row.symbol, reason: row.reason, share: row.share })),
|
|
@@ -69,12 +70,14 @@ function coverageSummary(coverage: RiskCoverage, limit = Infinity) {
|
|
|
69
70
|
};
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
/** One line for the whole coverage in place of a
|
|
73
|
-
function
|
|
73
|
+
/** One line for the whole coverage in place of a note per left-out holding. */
|
|
74
|
+
function coverageLine(coverage: RiskCoverage | undefined): { error?: string; note?: string } {
|
|
74
75
|
const shortfall = riskCoverageShortfall(coverage);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return
|
|
76
|
+
// No estimate at all is a failure; an estimate that leaves holdings out is a caveat.
|
|
77
|
+
if (shortfall) return { error: `Basket estimates unavailable: ${shortfall.title} ${shortfall.message}`.trim() };
|
|
78
|
+
return coverage?.leftOut.length
|
|
79
|
+
? { note: `Basket ${riskCoverageText(coverage)}; metadata.coverage lists each with its reason.` }
|
|
80
|
+
: {};
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
/** One view, its strongest or first rows, and the portfolio's totals instead of the model. */
|
|
@@ -101,6 +104,7 @@ function compactRiskRows(model: PortfolioRiskModel, view: RiskView): { rows: Ris
|
|
|
101
104
|
|
|
102
105
|
export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
103
106
|
shape: "bundle",
|
|
107
|
+
freshness: { source: "Local portfolio and Gloom Cloud", status: "not-a-feed", basis: "risk model on daily closes" },
|
|
104
108
|
argument: {
|
|
105
109
|
kind: "free-text",
|
|
106
110
|
optional: true,
|
|
@@ -115,7 +119,7 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
115
119
|
"Explicit local evidence for account returns and attribution",
|
|
116
120
|
],
|
|
117
121
|
limitations: [
|
|
118
|
-
`Fixed-current-weight USD equity basket over the holdings that qualify, largest ${RISK_HISTORY_LIMIT} by value; metadata.coverage states the covered share of market value and each holding left out`,
|
|
122
|
+
`Fixed-current-weight USD equity basket over the holdings that qualify, largest ${RISK_HISTORY_LIMIT} by value; foreign listings convert to USD at daily FX closes; metadata.coverage states the covered share of market value and each holding left out`,
|
|
119
123
|
"No account performance inferred",
|
|
120
124
|
"ETF price-return factor proxies",
|
|
121
125
|
"Historical percentiles need 20 rolling samples",
|
|
@@ -237,9 +241,12 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
237
241
|
: view === "factors"
|
|
238
242
|
? covered && model.factors.every((row) => row.value != null)
|
|
239
243
|
: model.complete;
|
|
244
|
+
// A basket view with too little covered shows no estimate, and the report says why rather than leaving dashes.
|
|
245
|
+
const shortfall = BASKET_VIEWS.has(view as RiskView) ? coverageLine(model.coverage).error : undefined;
|
|
240
246
|
return {
|
|
241
247
|
complete,
|
|
242
|
-
errors: [...
|
|
248
|
+
errors: [...(shortfall ? [shortfall] : []), ...model.warnings],
|
|
249
|
+
notes: [...riskCoverageNotices(model.coverage), ...model.notes],
|
|
243
250
|
sections: RISK_VIEWS.map((view) => ({
|
|
244
251
|
title: view,
|
|
245
252
|
columns: RISK_COLUMNS,
|
|
@@ -253,17 +260,16 @@ export const portfolioRiskHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
253
260
|
if (!model?.rows) return result;
|
|
254
261
|
const view = isRiskView(args.options.view) ? args.options.view : "risk";
|
|
255
262
|
const { rows, notices } = compactRiskRows(model, view);
|
|
256
|
-
// Each left-out holding is in metadata.coverage; the
|
|
263
|
+
// Each left-out holding is in metadata.coverage; the notes keep one line for all of them.
|
|
257
264
|
const perHolding = new Set(riskCoverageNotices(model.coverage));
|
|
258
265
|
const basketView = BASKET_VIEWS.has(view);
|
|
259
|
-
const
|
|
260
|
-
const errors = [
|
|
261
|
-
|
|
262
|
-
...(result.errors ?? []).filter((error) => !perHolding.has(error)),
|
|
263
|
-
];
|
|
266
|
+
const coverage = basketView ? coverageLine(model.coverage) : {};
|
|
267
|
+
const errors = [...new Set([...(coverage.error ? [coverage.error] : []), ...(result.errors ?? [])])];
|
|
268
|
+
const notes = [...(coverage.note ? [coverage.note] : []), ...(result.notes ?? []).filter((note) => !perHolding.has(note))];
|
|
264
269
|
return {
|
|
265
270
|
complete: result.complete,
|
|
266
271
|
...(errors.length ? { errors } : {}),
|
|
272
|
+
...(notes.length ? { notes } : {}),
|
|
267
273
|
sections: [{ title: view, columns: RISK_COLUMNS, rows: rows.map(displayRow) }],
|
|
268
274
|
metadata: {
|
|
269
275
|
portfolio: {
|
|
@@ -46,6 +46,8 @@ interface PortfolioRiskHolding {
|
|
|
46
46
|
priceAsOf: string | null;
|
|
47
47
|
/** "close" when no current quote arrived and the latest completed close marks the holding. */
|
|
48
48
|
markSource?: "quote" | "close" | null;
|
|
49
|
+
/** The listing currency its closes were converted from at daily FX closes; null for a USD listing. */
|
|
50
|
+
convertedFrom: string | null;
|
|
49
51
|
historyAsOf: string | null;
|
|
50
52
|
returns: DatedReturn[];
|
|
51
53
|
error: string | null;
|
|
@@ -71,6 +73,8 @@ export interface RiskCoverage {
|
|
|
71
73
|
holdings: number;
|
|
72
74
|
/** Holdings that qualify for the basket. */
|
|
73
75
|
covered: number;
|
|
76
|
+
/** Covered holdings whose returns were converted to USD from their listing currency. */
|
|
77
|
+
converted: number;
|
|
74
78
|
unvalued: number;
|
|
75
79
|
minimumShare: number;
|
|
76
80
|
/** The basket views estimate only when qualifying holdings reach the minimum share. */
|
|
@@ -223,24 +227,28 @@ const coveragePercent = (share: number) => Math.floor(share * 100);
|
|
|
223
227
|
const holdingCount = (count: number) => `${count} holding${count === 1 ? "" : "s"}`;
|
|
224
228
|
const shareText = (share: number) =>
|
|
225
229
|
share < 0.001 ? "under 0.1%" : `${(share * 100).toFixed(1)}%`;
|
|
226
|
-
/**
|
|
230
|
+
/**
|
|
231
|
+
* "covers 78% of market value · 9 holdings left out · 2 converted from local
|
|
232
|
+
* currency", or null when every holding is in the basket in its own USD listing.
|
|
233
|
+
*/
|
|
227
234
|
export function riskCoverageText(coverage: RiskCoverage | undefined): string | null {
|
|
228
|
-
if (!coverage
|
|
235
|
+
if (!coverage) return null;
|
|
236
|
+
const converted = coverage.converted ? `${holdingCount(coverage.converted)} converted from local currency` : null;
|
|
237
|
+
if (!coverage.leftOut.length) return converted;
|
|
229
238
|
const covers = coverage.share == null
|
|
230
239
|
? "covers an unknown share of market value"
|
|
231
240
|
: `covers ${coverage.unvalued ? "at most " : ""}${coveragePercent(coverage.share)}% of market value`;
|
|
232
|
-
return
|
|
241
|
+
return [covers, `${holdingCount(coverage.leftOut.length)} left out`, ...(converted ? [converted] : [])].join(" · ");
|
|
233
242
|
}
|
|
234
|
-
/**
|
|
243
|
+
/** A reason reads as the tail of a sentence, so its first word loses its capital unless it is an acronym ("FX", "USD"). */
|
|
244
|
+
const lowerFirst = (text: string) => (/^[A-Z][a-z]/.test(text) ? text[0]!.toLowerCase() + text.slice(1) : text);
|
|
245
|
+
/** One sentence per left-out holding, largest first, naming the holding and why it is out. */
|
|
235
246
|
export function riskCoverageNotices(coverage: RiskCoverage | undefined): string[] {
|
|
236
247
|
if (!coverage?.leftOut.length) return [];
|
|
237
|
-
return
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
`${row.symbol} (${row.share == null ? "value unknown" : `${shareText(row.share)} of market value`}): ${row.reason}`,
|
|
242
|
-
),
|
|
243
|
-
];
|
|
248
|
+
return coverage.leftOut.map(
|
|
249
|
+
(row) =>
|
|
250
|
+
`${row.symbol} (${row.share == null ? "value unknown" : `${shareText(row.share)} of market value`}) is excluded from the risk estimate: ${lowerFirst(row.reason.replace(/\.$/, ""))}.`,
|
|
251
|
+
);
|
|
244
252
|
}
|
|
245
253
|
/** Why the basket views show no estimate, when too little of the account qualifies. */
|
|
246
254
|
export function riskCoverageShortfall(
|
|
@@ -321,10 +329,13 @@ export function buildPortfolioRisk(
|
|
|
321
329
|
? { price: quote.price, currency: quote.currency, stale: !!quote.stale }
|
|
322
330
|
: null;
|
|
323
331
|
const quantity = signedQuantity(lots);
|
|
332
|
+
// A converted listing is marked and returned in USD; its own currency is what the holding records.
|
|
333
|
+
const convertedFrom = history?.converted?.currency ?? null;
|
|
324
334
|
const listingCurrency =
|
|
325
335
|
quote?.currency ?? close?.currency ?? history?.listing?.currency ?? ticker.metadata.currency;
|
|
336
|
+
const foreign = !convertedFrom && listingCurrency !== "USD";
|
|
326
337
|
const error =
|
|
327
|
-
syntheticPositionUnsupportedReason(ticker,
|
|
338
|
+
syntheticPositionUnsupportedReason(ticker, "USD", portfolio.id) ??
|
|
328
339
|
(lots.some((row) => !Number.isFinite(row.shares))
|
|
329
340
|
? "Invalid position quantity"
|
|
330
341
|
: null) ??
|
|
@@ -332,10 +343,14 @@ export function buildPortfolioRisk(
|
|
|
332
343
|
? "Historical account-currency FX is required"
|
|
333
344
|
: null) ??
|
|
334
345
|
(ticker.metadata.currency &&
|
|
335
|
-
mark?.currency &&
|
|
336
|
-
ticker.metadata.currency !== mark
|
|
346
|
+
(convertedFrom ?? mark?.currency) &&
|
|
347
|
+
ticker.metadata.currency !== (convertedFrom ?? mark?.currency)
|
|
337
348
|
? "Holding and quote currencies differ"
|
|
338
349
|
: null) ??
|
|
350
|
+
// A foreign listing that did not convert says why: no pair, stale or gapped FX.
|
|
351
|
+
(foreign
|
|
352
|
+
? (history?.error ?? syntheticPositionUnsupportedReason(ticker, listingCurrency, portfolio.id))
|
|
353
|
+
: null) ??
|
|
339
354
|
history?.error ??
|
|
340
355
|
(!history ? "Daily history unavailable" : null);
|
|
341
356
|
const priceDate = close ? close.date : quoteDate(quote?.lastUpdated);
|
|
@@ -376,6 +391,7 @@ export function buildPortfolioRisk(
|
|
|
376
391
|
: outsideValue(ticker, portfolio, quote ?? history?.listing ?? null, rates),
|
|
377
392
|
priceAsOf: priceDate,
|
|
378
393
|
markSource: close ? "close" : quote ? "quote" : null,
|
|
394
|
+
convertedFrom,
|
|
379
395
|
historyAsOf: history?.asOf ?? null,
|
|
380
396
|
returns,
|
|
381
397
|
error,
|
|
@@ -395,6 +411,7 @@ export function buildPortfolioRisk(
|
|
|
395
411
|
share,
|
|
396
412
|
holdings: holdings.length,
|
|
397
413
|
covered: qualifying.length,
|
|
414
|
+
converted: qualifying.filter((row) => row.convertedFrom != null).length,
|
|
398
415
|
unvalued: holdings.length - valued.length,
|
|
399
416
|
minimumShare: RISK_MIN_COVERAGE,
|
|
400
417
|
sufficient,
|
|
@@ -416,14 +433,24 @@ export function buildPortfolioRisk(
|
|
|
416
433
|
holding.weight =
|
|
417
434
|
book?.rows.find((row) => row.id === holding.id)?.weight ?? null;
|
|
418
435
|
const closeMarked = members.filter((row) => row.markSource === "close").length;
|
|
436
|
+
const converted = members.filter((row) => row.convertedFrom != null).length;
|
|
419
437
|
const held = new Set(holdings.map((row) => row.id));
|
|
420
|
-
|
|
421
|
-
|
|
438
|
+
// Caveats about an estimate that was made; the warnings are what failed.
|
|
439
|
+
const notes = [
|
|
422
440
|
...(closeMarked
|
|
423
441
|
? [
|
|
424
442
|
`${closeMarked} holding${closeMarked === 1 ? "" : "s"} had no current quote; weighted at the latest completed close.`,
|
|
425
443
|
]
|
|
426
444
|
: []),
|
|
445
|
+
// Daily closes pair by date, so a market that closes before or after the US session is not synchronous with it.
|
|
446
|
+
...(converted
|
|
447
|
+
? [
|
|
448
|
+
"Converted holdings are matched to the US close of the same date; where their market closes at another time, correlations and betas to US holdings read lower than they are.",
|
|
449
|
+
]
|
|
450
|
+
: []),
|
|
451
|
+
];
|
|
452
|
+
const warnings = [
|
|
453
|
+
...market.warnings,
|
|
427
454
|
// A held instrument's failure is its left-out reason; factor proxies report here.
|
|
428
455
|
...market.histories.flatMap((row) =>
|
|
429
456
|
row.error && !held.has(riskInstrumentId(row.instrument))
|
|
@@ -561,7 +588,7 @@ export function buildPortfolioRisk(
|
|
|
561
588
|
asOf: row.priceAsOf,
|
|
562
589
|
detail: row.leftOut
|
|
563
590
|
? row.leftOut
|
|
564
|
-
: `${row.quantity} shares; ${formatNumber(row.value ?? undefined)} ${row.currency}${row.markSource === "close" ? ` at ${row.priceAsOf} close` : ""}; history ${row.historyAsOf}`,
|
|
591
|
+
: `${row.quantity} shares; ${formatNumber(row.value ?? undefined)} ${row.currency}${row.markSource === "close" ? ` at ${row.priceAsOf} close` : ""}${row.convertedFrom ? ` from ${row.convertedFrom} at daily FX` : ""}; history ${row.historyAsOf}`,
|
|
565
592
|
...(row.leftOut ? { leftOut: row.leftOut } : {}),
|
|
566
593
|
})),
|
|
567
594
|
correlation: correlation.map((row) => ({
|
|
@@ -733,6 +760,7 @@ export function buildPortfolioRisk(
|
|
|
733
760
|
coverage.leftOut.length === 0 &&
|
|
734
761
|
metrics.some((row) => row.value != null),
|
|
735
762
|
warnings: [...new Set(warnings)],
|
|
763
|
+
notes,
|
|
736
764
|
fetchedAt: market.fetchedAt,
|
|
737
765
|
};
|
|
738
766
|
}
|
|
@@ -444,6 +444,7 @@ export function PortfolioRiskPane({ focused, width, height }: PaneProps) {
|
|
|
444
444
|
// views say what they need in the body, with the import action.
|
|
445
445
|
const notices = [
|
|
446
446
|
...riskCoverageNotices(model?.coverage),
|
|
447
|
+
...(model?.notes ?? []),
|
|
447
448
|
...(model?.warnings ?? []),
|
|
448
449
|
...(derived.error ? [derived.error] : []),
|
|
449
450
|
...(resource.error ? [resource.error] : []),
|
|
@@ -178,14 +178,35 @@ function fredSeries(id: string, asOf: Date): CloudFredSeriesPayload {
|
|
|
178
178
|
};
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Daily closes of the pair that prices `currency` against the dollar, every
|
|
183
|
+
* weekday as FX trades, wobbling around the rate the endpoint reports.
|
|
184
|
+
*/
|
|
185
|
+
function fxPairHistory(symbol: string, asOf: Date): CloudMarketResponse<CloudPricePointPayload[]> | null {
|
|
186
|
+
const currency = symbol.replace(/(USD)?=X$/, "");
|
|
187
|
+
const rate = BROKER_FX_RATES[currency];
|
|
188
|
+
if (rate == null) return null;
|
|
189
|
+
const usdQuoted = symbol.endsWith("USD=X");
|
|
190
|
+
const data: CloudPricePointPayload[] = [];
|
|
191
|
+
const today = Date.parse(asOf.toISOString().slice(0, 10));
|
|
192
|
+
for (let day = today - 240 * 86_400_000; day < today; day += 86_400_000) {
|
|
193
|
+
if ([0, 6].includes(new Date(day).getUTCDay())) continue;
|
|
194
|
+
const usdPerUnit = rate * (1 + Math.sin(data.length / 5) / 100);
|
|
195
|
+
const close = usdQuoted ? usdPerUnit : 1 / usdPerUnit;
|
|
196
|
+
data.push({ date: new Date(day).toISOString(), open: close, high: close, low: close, close });
|
|
197
|
+
}
|
|
198
|
+
return { status: "success", data, providerMeta: { servedResolution: "1d", normalizedSymbol: symbol } };
|
|
199
|
+
}
|
|
200
|
+
|
|
181
201
|
/**
|
|
182
202
|
* Cloud responses for the broker account: US listings and the factor proxies
|
|
183
203
|
* quote and keep daily history, foreign listings quote in their own currency,
|
|
184
|
-
* the uncovered holdings have neither.
|
|
204
|
+
* the uncovered holdings have neither. Daily FX history exists only with `fx`.
|
|
185
205
|
*/
|
|
186
206
|
export function brokerRiskClient(
|
|
187
207
|
asOf: Date = now,
|
|
188
208
|
holdings: readonly BrokerFixtureHolding[] = brokerFixtureHoldings(),
|
|
209
|
+
{ fx = false }: { fx?: boolean } = {},
|
|
189
210
|
) {
|
|
190
211
|
const bySymbol = new Map(holdings.map((holding) => [normalizeSymbol(holding.symbol), holding]));
|
|
191
212
|
const find = (symbol: string) => bySymbol.get(normalizeSymbol(symbol));
|
|
@@ -217,6 +238,9 @@ export function brokerRiskClient(
|
|
|
217
238
|
},
|
|
218
239
|
getCloudHistory: async (symbol: string, exchange: string) => {
|
|
219
240
|
calls.histories.push(symbol);
|
|
241
|
+
if (symbol.endsWith("=X"))
|
|
242
|
+
return (fx && fxPairHistory(symbol, asOf)) ||
|
|
243
|
+
{ status: "empty" as const, data: null, reasonCode: "Daily history unavailable" };
|
|
220
244
|
const holding = find(symbol);
|
|
221
245
|
if (holding && holding.price == null)
|
|
222
246
|
return { status: "empty" as const, data: null, reasonCode: "Daily history unavailable" };
|
|
@@ -15,16 +15,18 @@ export const attentionHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
15
15
|
const metadata = { asOf: data.asOf, stale: data.stale, complete: data.status === "ready" && !data.truncated,
|
|
16
16
|
status: data.status, periodStart: data.periodStart, periodEnd: data.periodEnd, entitlement: data.entitlement,
|
|
17
17
|
privacy: data.privacy, coverage: data.coverage, methodologyUrl: data.methodologyUrl, selectedListing: data.selectedListing ?? null, historyEvidence: data.historyEvidence ?? null, unit: "rounded researcher-hours" };
|
|
18
|
-
|
|
18
|
+
// Published hour by hour, so not a feed, but the service says when publication has fallen behind.
|
|
19
|
+
const freshness = { status: data.stale ? "stale" as const : "not-a-feed" as const, basis: "hourly publication" };
|
|
20
|
+
if (tab === "sectors" || tab === "countries") return { metadata, freshness, sections: [{ title: tab === "sectors" ? "Sector attention" : "Country attention",
|
|
19
21
|
columns: [{ key: "name", header: "Group" }, { key: "researchUnits", header: "Research hours" }, { key: "sharePct", header: "Share %" }, { key: "tickers", header: "Tickers" }], rows: data[tab].map((row) => ({ ...row })) }] };
|
|
20
|
-
if (tab === "history") return { metadata, sections: [{ title: "Published hourly history", columns: [{ key: "symbol", header: "Ticker" },
|
|
22
|
+
if (tab === "history") return { metadata, freshness, sections: [{ title: "Published hourly history", columns: [{ key: "symbol", header: "Ticker" },
|
|
21
23
|
{ key: "bucketStart", header: "Hour (UTC)" }, { key: "researchUnits", header: "Research hours" }],
|
|
22
24
|
rows: data.history && data.selectedListing ? data.history.map((point) => ({ symbol: data.selectedListing!.symbol, ...point })) : data.rows.flatMap((row) => row.history.map((point) => ({ symbol: row.symbol, ...point }))) }] };
|
|
23
|
-
if (tab === "evidence") return { metadata, sections: [{ title: "Publication evidence", columns: [{ key: "symbol", header: "Ticker" },
|
|
25
|
+
if (tab === "evidence") return { metadata, freshness, sections: [{ title: "Publication evidence", columns: [{ key: "symbol", header: "Ticker" },
|
|
24
26
|
{ key: "periodStart", header: "Period start" }, { key: "periodEnd", header: "Period end" }, { key: "asOf", header: "Published" },
|
|
25
27
|
{ key: "confidence", header: "Quality" }, { key: "marketAsOf", header: "Market as of" }],
|
|
26
28
|
rows: data.rows.map((row) => ({ symbol: row.symbol, ...row.evidence, baselinePeriods: row.baselinePeriods, marketAsOf: row.marketAsOf, news: row.news })) }] };
|
|
27
|
-
return { metadata, sections: [{ title: tab === "abnormal" ? "Abnormal attention" : "Research ranking", columns: [
|
|
29
|
+
return { metadata, freshness, sections: [{ title: tab === "abnormal" ? "Abnormal attention" : "Research ranking", columns: [
|
|
28
30
|
{ key: "rank", header: "Rank" }, { key: "symbol", header: "Ticker" }, { key: "name", header: "Name" }, { key: "researchUnits", header: "Research hours" },
|
|
29
31
|
{ key: "sharePct", header: "Share %" }, { key: "zScore", header: "Latest-hour Z-score" }, { key: "priceChangePct", header: "Price %" },
|
|
30
32
|
{ key: "relativeVolume", header: "Relative volume" }, { key: "sector", header: "Sector" }, { key: "country", header: "Country" },
|
|
@@ -7,7 +7,7 @@ import { AttentionPane } from "./pane";
|
|
|
7
7
|
export const attentionModule: PluginModule = {
|
|
8
8
|
panes: [{ id: "attention", name: "Research Attention", icon: "A", component: AttentionPane, defaultPosition: "right", defaultMode: "floating",
|
|
9
9
|
defaultFloatingSize: { width: 126, height: 32 }, tableExport: true, headless: attentionHeadless },
|
|
10
|
-
{ id: "attention-trending", name: "Gloom Trending", icon: "A", component: TrendingPane, defaultPosition: "right", defaultMode: "floating", defaultFloatingSize: { width: 58, height: 12 } }],
|
|
10
|
+
{ id: "attention-trending", reportFreshness: { status: "not-a-feed", basis: "hourly publication" }, name: "Gloom Trending", icon: "A", component: TrendingPane, defaultPosition: "right", defaultMode: "floating", defaultFloatingSize: { width: 58, height: 12 } }],
|
|
11
11
|
paneTemplates: [{ id: "attention-pane", paneId: "attention", label: "Research Attention",
|
|
12
12
|
description: "Pro research attention: rankings, abnormal activity, sectors, countries and privacy-qualified hourly history.",
|
|
13
13
|
keywords: ["attention", "trending", "research", "activity"], shortcut: { prefix: "ATTN", argKind: "text", argPlaceholder: "TICKER", argOptional: true },
|
|
@@ -58,7 +58,7 @@ function Evidence({ row, data, width, height }: { row: DetailRow; data: Attentio
|
|
|
58
58
|
const sameDay = row.evidence.periodStart.slice(0, 10) === row.evidence.periodEnd.slice(0, 10);
|
|
59
59
|
const period = sameDay ? `${hour(row.evidence.periodStart)} to ${row.evidence.periodEnd.slice(11, 16)} UTC` : `${hour(row.evidence.periodStart)} to ${date(row.evidence.periodEnd)}`;
|
|
60
60
|
const latest = point?.bucketStart === row.history.at(-1)?.bucketStart;
|
|
61
|
-
return <ScrollBox width={width} height={desktop ? undefined : height} flexGrow={1} flexBasis={0} contentOptions={{ paddingX: 1 }}>
|
|
61
|
+
return <ScrollBox scrollY width={width} height={desktop ? undefined : height} flexGrow={1} flexBasis={0} contentOptions={{ paddingX: 1 }}>
|
|
62
62
|
<KeyValueRow label="Listing" value={row.symbol} detail={row.name ?? undefined} labelWidth={20} />
|
|
63
63
|
<SectionHeading title="Publication" />
|
|
64
64
|
<KeyValueRow label="Research hours" value={number(row.researchUnits)} detail={`rounded to ${data.privacy.rounding}`} labelWidth={20} />
|
|
@@ -159,7 +159,7 @@ export function AttentionPane({ width, height, focused }: PaneProps) {
|
|
|
159
159
|
const cell = (row: AttentionRow | AttentionGroup | Locked, column: DataTableColumn, _index: number, state: { selected: boolean }): DataTableCell => {
|
|
160
160
|
if (isLocked(row)) return desktop ? { text: "", content: <Blurred><Text fg={colors.textDim}>{column.id === "name" ? "Additional research" : "Hidden"}</Text></Blurred> }
|
|
161
161
|
: { text: column.id === columns[0]!.id && row.id === "locked:0" ? "Pro" : "░░░", color: colors.textDim };
|
|
162
|
-
if (column.id === "sharePct") return { ...shareCell(number(row.sharePct, 1), maxShare ? row.sharePct / maxShare : null, column.width, colors, state.selected
|
|
162
|
+
if (column.id === "sharePct") return { ...shareCell(number(row.sharePct, 1), maxShare ? row.sharePct / maxShare : null, column.width, colors, state.selected), value: row.sharePct };
|
|
163
163
|
if ("symbol" in row) {
|
|
164
164
|
const numeric = typeof row[column.id as keyof AttentionRow] === "number" ? row[column.id as keyof AttentionRow] as number : undefined;
|
|
165
165
|
switch (column.id) {
|
|
@@ -15,6 +15,7 @@ const awardRecord = (row: AwardRow) => ({ id: row.id, date: row.awardDate, dateB
|
|
|
15
15
|
|
|
16
16
|
export const awardsHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
17
17
|
shape: "bundle", argument: { kind: "free-text", optional: true, placeholder: "ticker", description: "Optional verified listed-company ticker, including exchange suffix." },
|
|
18
|
+
freshness: { source: "Public procurement records", status: "not-a-feed", basis: "published awards" },
|
|
18
19
|
discovery: { aliases: ["AWARDS"], dataRequirements: ["Verified Gloom Cloud account"],
|
|
19
20
|
limitations: ["Pro dataset; free accounts receive a limited preview", "Published procurement records; source coverage varies by jurisdiction",
|
|
20
21
|
"Currencies and prime awards, subawards and notices are separate", "Award obligations are not revenue or remaining backlog", "Unresolved recipients retain their legal names"] },
|
|
@@ -240,7 +240,7 @@ function AwardsView({ width, height, focused, symbol }: PaneProps & { symbol: st
|
|
|
240
240
|
if (column.id === "contracts") return { text: item.row.count.toLocaleString("en-US"), value: item.row.count, color: colors.textDim };
|
|
241
241
|
if (column.id === "scope") return { text: awardScope(item.row.source), color: colors.textDim };
|
|
242
242
|
return item.row.sharePercent === null ? missingCell(colors)
|
|
243
|
-
: { ...shareCell(`${item.row.sharePercent.toFixed(1)}%`, maxShare ? item.row.sharePercent / maxShare : null, column.width, colors, state.selected
|
|
243
|
+
: { ...shareCell(`${item.row.sharePercent.toFixed(1)}%`, maxShare ? item.row.sharePercent / maxShare : null, column.width, colors, state.selected), value: item.row.sharePercent };
|
|
244
244
|
}
|
|
245
245
|
const award = item.row;
|
|
246
246
|
if (column.id === "date") return { text: award.awardDate, value: award.awardDate };
|
|
@@ -8,6 +8,7 @@ import { parseRule } from "./rules";
|
|
|
8
8
|
|
|
9
9
|
export const backtestHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
10
10
|
shape: "bundle",
|
|
11
|
+
freshness: { status: "not-a-feed", basis: "backtest on daily closes", cadence: "daily", observedKey: "date", oldest: null },
|
|
11
12
|
argument: { kind: "ticker", description: "Instrument to test" },
|
|
12
13
|
describe: (args) => `BT ${args.symbols[0] ?? ""}`,
|
|
13
14
|
discovery: {
|
|
@@ -32,6 +32,7 @@ export const bondCalculatorHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
32
32
|
return {
|
|
33
33
|
complete: errors.length === 0,
|
|
34
34
|
errors,
|
|
35
|
+
freshness: { source: "Your inputs, US Treasury", status: "not-a-feed", basis: "calculator", asOf: result.spread?.asOf ?? null },
|
|
35
36
|
metadata: { settlement: draft.settlement, terms: result.terms, source: "Manual bond inputs; Treasury par yields via Gloom Cloud / FRED",
|
|
36
37
|
treasuryAsOf: result.spread?.asOf ?? null, percentile: null, percentileReason: "Hypothetical bond has no historical sample", units: "Prices and DV01 per 100 face", mode: draft.mode },
|
|
37
38
|
sections: [
|
|
@@ -4,6 +4,7 @@ import type { PluginModule } from "../plugin-module";
|
|
|
4
4
|
export const buildoutModule: PluginModule = {
|
|
5
5
|
panes: [{
|
|
6
6
|
id: "buildout",
|
|
7
|
+
reportFreshness: { status: "not-a-feed", basis: "infrastructure research" },
|
|
7
8
|
name: "TheBuildout",
|
|
8
9
|
icon: "T",
|
|
9
10
|
component: BuildoutPane,
|
|
@@ -18,7 +18,7 @@ function Evidence({ event, width, height }: { event: CatalystEvent; width: numbe
|
|
|
18
18
|
const facts = catalystFacts(event);
|
|
19
19
|
const procedures = Array.isArray(event.metadata?.proceduralStatements) ? event.metadata.proceduralStatements.filter((value): value is string => typeof value === "string") : [];
|
|
20
20
|
const documents = Array.isArray(event.metadata?.documents) ? event.metadata.documents.filter((value): value is { url: string; title?: string; label?: string } => !!value && typeof value === "object" && "url" in value && typeof value.url === "string" && /^https?:\/\//.test(value.url)) : [];
|
|
21
|
-
return <ScrollBox width={width} height={desktop ? undefined : height} flexGrow={1} flexBasis={0} contentOptions={{ paddingX: 1 }}>
|
|
21
|
+
return <ScrollBox scrollY width={width} height={desktop ? undefined : height} flexGrow={1} flexBasis={0} contentOptions={{ paddingX: 1 }}>
|
|
22
22
|
<KeyValueRow label="Classification" value={`${catalystLabel(event.type)} · ${catalystAgency(event.agency)} · ${event.country ?? event.jurisdiction}`} labelWidth={18} />
|
|
23
23
|
<KeyValueRow label="Status" value={humanLabel(event.status)} detail={`Revision ${event.revision}`} labelWidth={18} />
|
|
24
24
|
<KeyValueRow label="Announced" value={catalystDate(event, "announced")} labelWidth={18} />
|
|
@@ -5,7 +5,9 @@ import { catalystCell, catalystChangeText, catalystDate, catalystQuery, catalyst
|
|
|
5
5
|
|
|
6
6
|
function definition(litigation: boolean): HeadlessPaneDefinition<"bundle"> {
|
|
7
7
|
return {
|
|
8
|
-
shape: "bundle",
|
|
8
|
+
shape: "bundle",
|
|
9
|
+
freshness: { source: litigation ? "Court and agency dockets" : "Regulator, court and trade records", status: "not-a-feed", basis: "published records" },
|
|
10
|
+
argument: { kind: "ticker", optional: !litigation, description: litigation ? "Company ticker, including exchange-qualified international listings." : "Optional ticker; omit for market-wide events." },
|
|
9
11
|
options: [
|
|
10
12
|
{ key: "tab", type: "enum", values: [{ value: "calendar" }, { value: "changes" }], defaultValue: "calendar", description: "Dated events or observed revisions." },
|
|
11
13
|
{ key: "type", type: "enum", values: CATALYST_TYPES.map((value) => ({ value })), description: "Event type." },
|
|
@@ -89,6 +89,8 @@ export function createCdsHeadless(
|
|
|
89
89
|
): HeadlessPaneDefinition<"rows"> {
|
|
90
90
|
return {
|
|
91
91
|
shape: "rows",
|
|
92
|
+
// Public dissemination of swap trades, held back by rule for some trades.
|
|
93
|
+
freshness: { source: "DTCC", status: "delayed" },
|
|
92
94
|
argument: {
|
|
93
95
|
kind: "free-text",
|
|
94
96
|
placeholder: "ticker or issuer",
|
|
@@ -6,6 +6,7 @@ export const centralBankRatesHeadless: HeadlessPaneDefinition<"bundle"> = {
|
|
|
6
6
|
discovery: { aliases: ["CBR", "CBRT"], dataRequirements: ["Gloom Cloud central-bank-rates endpoint"],
|
|
7
7
|
limitations: ["Published policy observations with individual dates", "Policy instruments differ", "Only US meeting dates are maintained"] },
|
|
8
8
|
shape: "bundle", options: [], argument: { kind: "none" }, describe: "G20 central bank policy rates",
|
|
9
|
+
freshness: { source: "Central banks and BIS", status: "not-a-feed", basis: "published policy rates" },
|
|
9
10
|
async load(_args, ctx) {
|
|
10
11
|
const data = await fetchCentralBankRates(ctx.apiClient);
|
|
11
12
|
const errors = policyNotices(data);
|
|
@@ -2,8 +2,10 @@ import { financialPeriodCoverage } from "../../../time-series/financial-period-c
|
|
|
2
2
|
import { FINANCIAL_VINTAGE_NOTICE, SEC_EPS_BASIS_NOTICE } from "../../../utils/financial-statements";
|
|
3
3
|
import { graphRowsForFinancials, summarizeResolvedSeries } from "../../../time-series/reporting";
|
|
4
4
|
import { priceHistoryIntegrityNotices, chartPriceHistoryIntegrityNotices } from "../../../time-series/market";
|
|
5
|
-
import type { HeadlessPaneContext, HeadlessPaneDefinition, HeadlessSeriesResult } from "../../../types/headless";
|
|
6
|
-
import type { ChartResolutionResult, ChartSeriesSpec, ChartSpec } from "../../../time-series/types";
|
|
5
|
+
import type { HeadlessPaneContext, HeadlessPaneDefinition, HeadlessPaneFreshness, HeadlessSeries, HeadlessSeriesResult } from "../../../types/headless";
|
|
6
|
+
import type { CapabilitySeriesSource, ChartResolutionResult, ChartSeriesSpec, ChartSpec, ChartViewportSpec } from "../../../time-series/types";
|
|
7
|
+
import { resolveGeoChartSeries } from "../world-venue-map/geo-series";
|
|
8
|
+
import { GEO_SERIES_CAPABILITY_ID } from "./series-expression";
|
|
7
9
|
import { mergePriceHistoryWindows, priceHistoryAcquisitionIdentity, priceHistoryTailAcquisition, resolveChartSpecData } from "../../../time-series/resolve";
|
|
8
10
|
import { intersectChartResolutionSupport, isIntradayResolution, normalizeChartResolutionSupport, type ManualChartResolution } from "../../../time-series/resolution";
|
|
9
11
|
import { intradaySessionDates, loadIntradayWindow, resolveIntradayRequest, type IntradayRequest, type IntradayWindow, type LoadedIntradayWindow } from "./session-history";
|
|
@@ -16,6 +18,7 @@ import { createChartSeriesResolver } from "../../../capabilities";
|
|
|
16
18
|
import { parsePublicTickerKey, publicTickerKey, resolveExchangeTimeZone } from "../../../utils/exchanges";
|
|
17
19
|
import { parseChartSpec } from "./chart-spec";
|
|
18
20
|
import { paneSchemas } from "./headless-schema";
|
|
21
|
+
import { barHistoryFreshness, REPORTED_DATA } from "../shared/report-freshness";
|
|
19
22
|
|
|
20
23
|
export interface ChartPaneModel extends HeadlessSeriesResult {
|
|
21
24
|
/** The renderer consumes the full model; generic reports project series and metadata. */
|
|
@@ -37,6 +40,23 @@ export interface ChartPaneModel extends HeadlessSeriesResult {
|
|
|
37
40
|
};
|
|
38
41
|
}
|
|
39
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Map series read straight from the Cloud client, so a report or screenshot
|
|
45
|
+
* charts them where plugin capability handlers are not running; every other
|
|
46
|
+
* capability series goes through the registry as before.
|
|
47
|
+
*/
|
|
48
|
+
function headlessCapabilityResolver(context: HeadlessPaneContext) {
|
|
49
|
+
const registry = context.capabilities ? createChartSeriesResolver(context.capabilities) : null;
|
|
50
|
+
return async (source: CapabilitySeriesSource, viewport: ChartViewportSpec, spec: ChartSeriesSpec) => {
|
|
51
|
+
if (source.capabilityId === GEO_SERIES_CAPABILITY_ID) {
|
|
52
|
+
const request = <T,>(path: string, init?: RequestInit) => context.apiClient.geo<T>(path, { ...init, signal: init?.signal ?? context.signal });
|
|
53
|
+
return resolveGeoChartSeries(request, source.seriesId, viewport, context.signal);
|
|
54
|
+
}
|
|
55
|
+
if (!registry) throw new Error(`Chart series capability "${source.capabilityId}" is unavailable. Enable its plugin or provider.`);
|
|
56
|
+
return registry(source, viewport, spec);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
40
60
|
export async function loadChartPaneModel(
|
|
41
61
|
spec: ChartSpec,
|
|
42
62
|
context: HeadlessPaneContext,
|
|
@@ -101,7 +121,7 @@ export async function loadChartPaneModel(
|
|
|
101
121
|
if (!primary || rank < primary.rank) primaryHistories.set(key, { key: variantKey, rank });
|
|
102
122
|
}
|
|
103
123
|
},
|
|
104
|
-
|
|
124
|
+
resolveCapabilitySeries: headlessCapabilityResolver(context),
|
|
105
125
|
loadFredSeries: async (request) => ({
|
|
106
126
|
data: await context.apiClient.getCloudFredSeries(request.seriesId, {
|
|
107
127
|
startDate: request.startDate,
|
|
@@ -189,6 +209,20 @@ export async function loadChartPaneModel(
|
|
|
189
209
|
};
|
|
190
210
|
}
|
|
191
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Price series are bar histories, stale once bars of the coarsest size stop
|
|
214
|
+
* arriving; fundamentals, valuations and economic series are reported data.
|
|
215
|
+
*/
|
|
216
|
+
function chartFreshness(series: readonly HeadlessSeries[]): HeadlessPaneFreshness {
|
|
217
|
+
const order = ["1wk", "1mo"];
|
|
218
|
+
const resolutions = series.map((entry) => (entry as HeadlessSeries & { historyResolution?: string }).historyResolution);
|
|
219
|
+
if (!series.length || resolutions.some((resolution) => !resolution)) return { ...REPORTED_DATA, basis: "reported and published data" };
|
|
220
|
+
const coarsest = resolutions.reduce((worst, resolution) => (
|
|
221
|
+
order.indexOf(resolution!) > order.indexOf(worst!) ? resolution : worst
|
|
222
|
+
), resolutions[0]);
|
|
223
|
+
return barHistoryFreshness(coarsest);
|
|
224
|
+
}
|
|
225
|
+
|
|
192
226
|
export function chartHeadless(template: keyof typeof paneSchemas): HeadlessPaneDefinition<"series"> {
|
|
193
227
|
return {
|
|
194
228
|
...paneSchemas[template],
|
|
@@ -262,6 +296,7 @@ export function chartHeadless(template: keyof typeof paneSchemas): HeadlessPaneD
|
|
|
262
296
|
}
|
|
263
297
|
}
|
|
264
298
|
model.snapshot.intradayHistories = intradayHistories;
|
|
299
|
+
model.freshness = chartFreshness(model.series);
|
|
265
300
|
const priceDomainFailures = intradayHistories.flatMap(({ symbol, exchange, priceDomainFailure }) =>
|
|
266
301
|
priceDomainFailure ? [{ symbol, exchange, ...priceDomainFailure }] : []);
|
|
267
302
|
if (priceDomainFailures.length) {
|
|
@@ -253,7 +253,9 @@ const chartComposerTemplates: PaneTemplateDef[] = [
|
|
|
253
253
|
label: "Chart Series",
|
|
254
254
|
placeholder: "AAPL:price, MSFT:revenue, FRED:CPIAUCSL",
|
|
255
255
|
type: "text",
|
|
256
|
-
|
|
256
|
+
// Empty falls back to the active ticker in createInstance, as `G` with no argument does.
|
|
257
|
+
required: false,
|
|
258
|
+
body: ["Enter comma-separated SYMBOL:field or FRED:series expressions, or leave empty to chart the active ticker."],
|
|
257
259
|
}],
|
|
258
260
|
canCreate: () => true,
|
|
259
261
|
createInstance: (context, options) => {
|
|
@@ -33,6 +33,14 @@ export const CHART_FIELD_IDS = {
|
|
|
33
33
|
evEbitda: "valuation.evEbitda",
|
|
34
34
|
} as const;
|
|
35
35
|
|
|
36
|
+
/** Series of things with a place (chokepoint transits, port calls), served with the map's layers. */
|
|
37
|
+
export const GEO_SERIES_CAPABILITY_ID = "geo-series";
|
|
38
|
+
|
|
39
|
+
/** `GEO:<series id or short alias>`, e.g. `GEO:SUEZ`. */
|
|
40
|
+
export function formatGeoSeriesExpression(seriesId: string): string {
|
|
41
|
+
return `GEO:${seriesId}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
36
44
|
export type ParsedSeriesExpression =
|
|
37
45
|
| { kind: "security"; symbol: string; exchange?: string; fieldId: string; label?: string }
|
|
38
46
|
| { kind: "economic"; provider: "fred"; seriesId: string; label?: string }
|
|
@@ -96,6 +104,12 @@ export function parseSeriesExpression(value: string): ParsedSeriesExpression | n
|
|
|
96
104
|
? { kind: "capability", capabilityId, seriesId }
|
|
97
105
|
: null;
|
|
98
106
|
}
|
|
107
|
+
if (parts[0]?.trim().toUpperCase() === "GEO") {
|
|
108
|
+
const seriesId = trimmed.slice(trimmed.indexOf(":") + 1).trim();
|
|
109
|
+
return parts.length >= 2 && isValidChartSeriesId(seriesId)
|
|
110
|
+
? { kind: "capability", capabilityId: GEO_SERIES_CAPABILITY_ID, seriesId }
|
|
111
|
+
: null;
|
|
112
|
+
}
|
|
99
113
|
if (parts[0]?.trim().toUpperCase() === "FRED") {
|
|
100
114
|
const seriesId = parts.length === 2 ? parts[1]?.trim().toUpperCase() ?? "" : "";
|
|
101
115
|
return /^[A-Z0-9._-]{1,80}$/.test(seriesId)
|
|
@@ -160,7 +174,7 @@ export function parseChartExpression(value: string): ParsedSeriesExpression[] {
|
|
|
160
174
|
if (parsed) return parsed;
|
|
161
175
|
const display = leg.trim() || "empty series";
|
|
162
176
|
throw new Error(
|
|
163
|
-
`Invalid chart series "${display}". Use SYMBOL, SYMBOL:field, FUT:code, UST:maturity, FRED:series, or CAP:capability-id:series-id.`,
|
|
177
|
+
`Invalid chart series "${display}". Use SYMBOL, SYMBOL:field, FUT:code, UST:maturity, FRED:series, GEO:series, or CAP:capability-id:series-id.`,
|
|
164
178
|
);
|
|
165
179
|
});
|
|
166
180
|
}
|
|
@@ -168,7 +182,9 @@ export function parseChartExpression(value: string): ParsedSeriesExpression[] {
|
|
|
168
182
|
export function formatSeriesExpression(series: ChartSeriesSpec): string {
|
|
169
183
|
if (series.source.kind === "economic") return `FRED:${series.source.seriesId}`;
|
|
170
184
|
if (series.source.kind === "capability") {
|
|
171
|
-
return
|
|
185
|
+
return series.source.capabilityId === GEO_SERIES_CAPABILITY_ID
|
|
186
|
+
? formatGeoSeriesExpression(series.source.seriesId)
|
|
187
|
+
: `CAP:${series.source.capabilityId}:${series.source.seriesId}`;
|
|
172
188
|
}
|
|
173
189
|
return `${publicTickerKey(series.source.instrument.symbol, series.source.instrument.exchange)}:${series.source.fieldId}`;
|
|
174
190
|
}
|
|
@@ -4,6 +4,8 @@ import type { AppConfig } from "../../../types/config";
|
|
|
4
4
|
import { t } from "../../../i18n";
|
|
5
5
|
import { chatController } from "./controller";
|
|
6
6
|
import { formatChannelLabel } from "./channel-labels";
|
|
7
|
+
import { describeConversationStartError, knownConversationRefusal } from "./direct-messages";
|
|
8
|
+
import { buildChatUserByUsername } from "./content/user-map";
|
|
7
9
|
|
|
8
10
|
export const DEFAULT_CHAT_CHANNEL_ID = "everyone";
|
|
9
11
|
export const LAST_VISITED_CHAT_CHANNEL_KEY = "lastChatChannelId";
|
|
@@ -87,9 +89,23 @@ export async function openDmTargetFromCommand(ctx: GloomPluginContext, usernames
|
|
|
87
89
|
openDefaultChatPane(ctx);
|
|
88
90
|
return;
|
|
89
91
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
// The command bar shows a thrown message as it is, so it says why.
|
|
93
|
+
const snapshot = chatController.getSnapshot();
|
|
94
|
+
const userByUsername = buildChatUserByUsername(snapshot.channels, snapshot.messages);
|
|
95
|
+
const refusal = knownConversationRefusal(usernames, {
|
|
96
|
+
userByUsername,
|
|
97
|
+
currentUserId: snapshot.user?.id,
|
|
98
|
+
channels: snapshot.channels,
|
|
99
|
+
});
|
|
100
|
+
if (refusal) throw new Error(refusal);
|
|
101
|
+
let channel: ChatChannel;
|
|
102
|
+
try {
|
|
103
|
+
channel = usernames.length === 1
|
|
104
|
+
? await chatController.openDirectChannel({ username: usernames[0] })
|
|
105
|
+
: await chatController.openGroupChannel({ usernames });
|
|
106
|
+
} catch (error) {
|
|
107
|
+
throw new Error(describeConversationStartError(error, usernames, userByUsername));
|
|
108
|
+
}
|
|
93
109
|
openChatChannelFromCommand(ctx, channel.id);
|
|
94
110
|
}
|
|
95
111
|
|