gloomberb 0.16.6 → 0.17.1
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/chat-pane-link.ts +47 -0
- package/src/api-client/chat.ts +9 -1
- package/src/api-client/data.ts +42 -2
- package/src/api-client/doe.ts +19 -0
- package/src/api-client/equity-screener.ts +3 -0
- package/src/api-client/europe-energy.ts +91 -0
- package/src/api-client/index.ts +7 -0
- package/src/api-client/letters.ts +41 -0
- package/src/api-client/normalizers.ts +36 -6
- package/src/api-client/organization-tickers.ts +44 -0
- package/src/api-client/request.ts +3 -1
- package/src/api-client/types.ts +27 -1
- package/src/app/runtime/desktop-deeplink.ts +48 -15
- package/src/app/runtime/update.ts +16 -0
- package/src/architecture/core-builtin-allowlist.json +1 -1
- package/src/architecture/dom-cell-metrics-allowlist.json +102 -0
- package/src/ask-gloom/pane-context.ts +23 -19
- package/src/ask-gloom/pane-request.ts +2 -2
- package/src/cli/commands/fred-series.ts +77 -11
- package/src/cli/commands/market.ts +134 -25
- package/src/cli/commands/options-chain.ts +75 -1
- package/src/cli/commands/overview.ts +29 -20
- package/src/cli/commands/ticker.ts +82 -20
- package/src/cli/desktop-pane-shot-view.ts +114 -0
- package/src/cli/desktop-pane-shot.ts +30 -31
- package/src/cli/entry.ts +7 -0
- package/src/cli/export-source.ts +43 -0
- package/src/cli/freshness.ts +18 -3
- package/src/cli/glossary.ts +17 -0
- package/src/cli/history-rows.ts +174 -13
- package/src/cli/index.ts +14 -6
- package/src/cli/known-gaps.ts +14 -3
- package/src/cli/listing-arg.ts +20 -2
- package/src/cli/listing-suggestion.ts +159 -0
- package/src/cli/native-smoke.ts +13 -0
- package/src/cli/not-a-ticker.ts +13 -1
- package/src/cli/pane-functions/capabilities.ts +16 -8
- package/src/cli/pane-functions/catalog.ts +39 -7
- package/src/cli/pane-functions/dom.ts +39 -13
- package/src/cli/pane-functions/function-help.ts +54 -7
- package/src/cli/pane-functions/headless.ts +38 -8
- package/src/cli/pane-functions/index.ts +85 -3
- package/src/cli/pane-functions/lock-note.ts +56 -0
- package/src/cli/pane-functions/report-notices.ts +6 -3
- package/src/cli/pane-functions/report.ts +16 -2
- package/src/cli/pane-functions/resolver.ts +7 -4
- package/src/cli/report-tables.ts +31 -7
- package/src/cli/result.ts +54 -11
- package/src/cli/symbol-rows.ts +18 -1
- package/src/components/chart/composite/axis-overlays.tsx +2 -0
- package/src/components/chart/composite/composite-chart.tsx +4 -21
- package/src/components/chart/composite/legend.tsx +10 -6
- package/src/components/chart/composite/price-axis-labels.tsx +1 -0
- package/src/components/command-bar/list/model.ts +2 -0
- package/src/components/command-bar/list/view.tsx +2 -1
- package/src/components/command-bar/pane-templates/items.ts +1 -1
- package/src/components/command-bar/routes/ticker-search/actions.ts +1 -0
- package/src/components/command-bar/routes/ticker-search/results.ts +3 -1
- package/src/components/command-bar/workflow/ops.ts +8 -97
- package/src/components/command-bar/workflow/pane-reuse.ts +177 -0
- package/src/components/data-table/view.tsx +1 -0
- package/src/components/feed-data-table/stack-view.tsx +18 -42
- package/src/components/index.ts +3 -2
- package/src/components/layout/header.tsx +58 -14
- package/src/components/layout/missing-pane.tsx +2 -0
- package/src/components/layout/shell/chrome.ts +10 -4
- package/src/components/layout/shell/index.tsx +1 -0
- package/src/components/layout/shell/pane/ask.ts +12 -7
- package/src/components/layout/shell/pane/capture.ts +8 -34
- package/src/components/markdown-text.tsx +37 -6
- package/src/components/reader/article-reader.tsx +91 -266
- package/src/components/reader/detail-reader.tsx +210 -0
- package/src/components/reader/reader-text.tsx +239 -0
- package/src/components/table-view-shared.tsx +8 -4
- package/src/components/ticker/badge/list.tsx +15 -4
- package/src/components/ui/choice-dialog.tsx +3 -0
- package/src/components/ui/column-grid.tsx +206 -0
- package/src/components/ui/data-table/types.ts +7 -0
- package/src/components/ui/detail-scroll-body.tsx +31 -4
- package/src/components/ui/display.tsx +86 -4
- package/src/components/ui/fill.ts +8 -0
- package/src/components/ui/icon.tsx +11 -1
- package/src/components/ui/index.ts +2 -0
- package/src/components/ui/list-view.tsx +3 -1
- package/src/components/ui/query-bar-keys.tsx +2 -0
- package/src/components/ui/query-bar.tsx +9 -1
- package/src/components/ui/select-button.tsx +3 -0
- package/src/data/config/store/fold-panes.ts +202 -11
- package/src/data/config/store/migrations.ts +13 -1
- package/src/docs/snapshot.json +29 -0
- package/src/i18n/es.ts +14 -0
- package/src/i18n/ja.ts +14 -0
- package/src/i18n/ko.ts +14 -0
- package/src/i18n/zh-cn.ts +14 -0
- package/src/i18n/zh-tw.ts +14 -0
- package/src/layout/desk-keys.ts +7 -0
- package/src/layout/desks.ts +2 -2
- package/src/market-data/market/status.ts +67 -6
- package/src/market-data/quotes/contributions.ts +15 -0
- package/src/market-data/quotes/regular-session-valuation.ts +131 -0
- package/src/market-data/quotes/resolution.ts +4 -0
- package/src/market-data/quotes/screener-live-quotes.ts +31 -7
- package/src/market-data/snapshot-provider.ts +6 -3
- package/src/notifications/app-badge.ts +30 -0
- package/src/plugins/builtin/account-management/calendar-tab.tsx +1 -1
- package/src/plugins/builtin/account-management/form-components.tsx +57 -8
- package/src/plugins/builtin/account-management/keyboard.ts +5 -0
- package/src/plugins/builtin/account-management/model.ts +27 -0
- package/src/plugins/builtin/account-management/pane.tsx +62 -2
- package/src/plugins/builtin/account-management/password-dialog.tsx +3 -2
- package/src/plugins/builtin/alerts/cli.ts +6 -4
- package/src/plugins/builtin/analytics/index.tsx +1 -1
- package/src/plugins/builtin/awards/pane.tsx +29 -18
- package/src/plugins/builtin/backtest/pane.tsx +11 -4
- package/src/plugins/builtin/bond-calculator/index.tsx +3 -5
- package/src/plugins/builtin/buildout/detail/company.tsx +11 -7
- package/src/plugins/builtin/buildout/detail/ui.tsx +9 -12
- package/src/plugins/builtin/builtin-plugin-meta.ts +5 -4
- package/src/plugins/builtin/catalysts/model.ts +92 -10
- package/src/plugins/builtin/catalysts/pane.tsx +6 -4
- package/src/plugins/builtin/cds/index.tsx +21 -30
- package/src/plugins/builtin/changelog/index.tsx +11 -12
- package/src/plugins/builtin/chart-composer/headless-schema.ts +2 -0
- package/src/plugins/builtin/chart-composer/headless.ts +87 -5
- package/src/plugins/builtin/chart-composer/pane.tsx +3 -2
- package/src/plugins/builtin/chart-composer/session-history.ts +20 -5
- package/src/plugins/builtin/chat/command-bar.ts +6 -8
- package/src/plugins/builtin/chat/content/composer-runtime.ts +2 -2
- package/src/plugins/builtin/chat/content/composer.tsx +13 -4
- package/src/plugins/builtin/chat/content/footer.tsx +15 -5
- package/src/plugins/builtin/chat/content/handle-prompt.tsx +326 -0
- package/src/plugins/builtin/chat/content/index.tsx +113 -9
- package/src/plugins/builtin/chat/content/layout-metrics.ts +4 -0
- package/src/plugins/builtin/chat/content/open-targets.ts +20 -4
- package/src/plugins/builtin/chat/content/scroll.ts +6 -1
- package/src/plugins/builtin/chat/content/transcript.tsx +11 -2
- package/src/plugins/builtin/chat/ghost-user.ts +1 -1
- package/src/plugins/builtin/chat/handle-prompt.ts +128 -0
- package/src/plugins/builtin/chat/index.tsx +44 -21
- package/src/plugins/builtin/chat/layout.ts +7 -14
- package/src/plugins/builtin/chat/message/desktop.tsx +59 -11
- package/src/plugins/builtin/chat/message/header.tsx +69 -21
- package/src/plugins/builtin/chat/message/pane-chip.tsx +223 -0
- package/src/plugins/builtin/chat/message/person-icons.tsx +53 -0
- package/src/plugins/builtin/chat/message/profile-popover.tsx +73 -9
- package/src/plugins/builtin/chat/message/render-state.ts +15 -2
- package/src/plugins/builtin/chat/message/terminal.tsx +33 -8
- package/src/plugins/builtin/chat/message/types.ts +3 -0
- package/src/plugins/builtin/chat/pane-links/model.ts +149 -0
- package/src/plugins/builtin/chat/pane-links/open.ts +29 -0
- package/src/plugins/builtin/chat/pane-links/previews.ts +119 -0
- package/src/plugins/builtin/chat/pane-state.ts +5 -8
- package/src/plugins/builtin/chat/people.ts +202 -0
- package/src/plugins/builtin/chat/profile-popover.ts +18 -2
- package/src/plugins/builtin/chat/status-widget.tsx +3 -8
- package/src/plugins/builtin/chat/unread-badge.ts +65 -0
- package/src/plugins/builtin/chat/unread-inbox-pane.tsx +9 -6
- package/src/plugins/builtin/clinical-trials/client.ts +26 -1
- package/src/plugins/builtin/clinical-trials/index.tsx +10 -2
- package/src/plugins/builtin/clinical-trials/model.ts +269 -0
- package/src/plugins/builtin/clinical-trials/pane.tsx +247 -62
- package/src/plugins/builtin/clinical-trials/sponsor-tickers.ts +156 -0
- package/src/plugins/builtin/cloud/askg/attached-pane.tsx +3 -3
- package/src/plugins/builtin/cloud/askg/pane-attachment.ts +3 -3
- package/src/plugins/builtin/cloud/askg/pane.tsx +2 -1
- package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +3 -2
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +1 -0
- package/src/plugins/builtin/cloud/thesis/detail.tsx +11 -9
- package/src/plugins/builtin/comment-letters/pane.tsx +30 -11
- package/src/plugins/builtin/commodities-energy/index.tsx +179 -0
- package/src/plugins/builtin/commodity-balances/client.ts +208 -0
- package/src/plugins/builtin/commodity-balances/headless.ts +66 -0
- package/src/plugins/builtin/commodity-balances/index.tsx +32 -0
- package/src/plugins/builtin/commodity-balances/model.ts +261 -0
- package/src/plugins/builtin/commodity-balances/pane.tsx +227 -0
- package/src/plugins/builtin/composite-plugins.ts +26 -1
- package/src/plugins/builtin/congress-trades/detail.tsx +8 -4
- package/src/plugins/builtin/connections/pane.tsx +16 -5
- package/src/plugins/builtin/cpi/pane.tsx +5 -4
- package/src/plugins/builtin/credit-boards/index.tsx +21 -42
- package/src/plugins/builtin/credit-boards/model.ts +0 -2
- package/src/plugins/builtin/credit-conditions/index.tsx +10 -19
- package/src/plugins/builtin/credit-documents/index.tsx +27 -10
- package/src/plugins/builtin/debt-maturities/index.tsx +3 -17
- package/src/plugins/builtin/debug/index.tsx +2 -2
- package/src/plugins/builtin/dividend-yield/client.ts +3 -1
- package/src/plugins/builtin/dividend-yield/headless.ts +3 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +3 -1
- package/src/plugins/builtin/dividend-yield/provider-client.ts +3 -1
- package/src/plugins/builtin/docs/blocks.tsx +4 -3
- package/src/plugins/builtin/docs/pane.tsx +16 -8
- package/src/plugins/builtin/doe/index.tsx +11 -4
- package/src/plugins/builtin/doe/pane.tsx +5 -4
- package/src/plugins/builtin/doe/prices.ts +84 -0
- package/src/plugins/builtin/doe/series.ts +4 -1
- package/src/plugins/builtin/earnings/index.tsx +2 -0
- package/src/plugins/builtin/earnings-calls/headless.ts +7 -21
- package/src/plugins/builtin/earnings-calls/index.tsx +2 -0
- package/src/plugins/builtin/earnings-calls/lock-note.ts +17 -0
- package/src/plugins/builtin/earnings-calls/pane.tsx +2 -12
- package/src/plugins/builtin/equity-screener/client.ts +1 -1
- package/src/plugins/builtin/equity-screener/headless.ts +95 -3
- package/src/plugins/builtin/equity-screener/live.ts +82 -31
- package/src/plugins/builtin/equity-screener/model.ts +121 -68
- package/src/plugins/builtin/equity-screener/pane.tsx +60 -23
- package/src/plugins/builtin/estimate-revisions/client.ts +1 -1
- package/src/plugins/builtin/estimate-revisions/headless.ts +9 -2
- package/src/plugins/builtin/estimate-revisions/index.tsx +3 -0
- package/src/plugins/builtin/estimate-revisions/lock-note.ts +23 -0
- package/src/plugins/builtin/executives/index.tsx +18 -0
- package/src/plugins/builtin/executives/pane.tsx +3 -1
- package/src/plugins/builtin/exposure/charts.tsx +4 -3
- package/src/plugins/builtin/filing-events/index.tsx +18 -0
- package/src/plugins/builtin/fixed-income/index.tsx +46 -0
- package/src/plugins/builtin/fixed-income/model.ts +27 -0
- package/src/plugins/builtin/fixed-income/pane.tsx +163 -0
- package/src/plugins/builtin/fixed-income/shortcut.ts +52 -0
- package/src/plugins/builtin/futures/index.tsx +24 -7
- package/src/plugins/builtin/futures/series.ts +23 -2
- package/src/plugins/builtin/futures/use-front-returns.ts +3 -2
- package/src/plugins/builtin/futures-curve/pane.tsx +6 -4
- package/src/plugins/builtin/gpu/equities.tsx +9 -6
- package/src/plugins/builtin/help/shortcut-table.tsx +4 -2
- package/src/plugins/builtin/insider/detail.tsx +20 -12
- package/src/plugins/builtin/insider/index.tsx +2 -2
- package/src/plugins/builtin/iv-history/format.ts +3 -0
- package/src/plugins/builtin/iv-history/headless.ts +3 -1
- package/src/plugins/builtin/iv-history/index.tsx +6 -1
- package/src/plugins/builtin/iv-history/model.ts +3 -1
- package/src/plugins/builtin/iv-history/screen-pane.tsx +16 -6
- package/src/plugins/builtin/iv-history/universe.ts +1 -1
- package/src/plugins/builtin/jobs/headless.ts +6 -20
- package/src/plugins/builtin/jobs/index.tsx +2 -0
- package/src/plugins/builtin/jobs/lock-note.ts +16 -0
- package/src/plugins/builtin/jodi/client.ts +220 -0
- package/src/plugins/builtin/jodi/headless.ts +63 -0
- package/src/plugins/builtin/jodi/index.tsx +32 -0
- package/src/plugins/builtin/jodi/model.ts +75 -0
- package/src/plugins/builtin/jodi/pane.tsx +141 -0
- package/src/plugins/builtin/market-heatmap/evidence.ts +13 -4
- package/src/plugins/builtin/market-heatmap/headless.ts +3 -3
- package/src/plugins/builtin/market-heatmap/index.tsx +41 -23
- package/src/plugins/builtin/market-heatmap/live.ts +2 -1
- package/src/plugins/builtin/market-heatmap/portfolio.ts +67 -21
- package/src/plugins/builtin/market-movers/table.ts +2 -2
- package/src/plugins/builtin/market-valuation/align.ts +10 -9
- package/src/plugins/builtin/mna/distress/model.ts +52 -1
- package/src/plugins/builtin/mna/distress/pane.tsx +17 -12
- package/src/plugins/builtin/mna/index.tsx +2 -0
- package/src/plugins/builtin/news/wire/index.tsx +2 -2
- package/src/plugins/builtin/news/wire/industry-pane.tsx +28 -14
- package/src/plugins/builtin/news/wire/letters/client.ts +108 -0
- package/src/plugins/builtin/news/wire/letters/model.ts +69 -0
- package/src/plugins/builtin/news/wire/letters/pane.tsx +155 -0
- package/src/plugins/builtin/news/wire/mutes.ts +2 -1
- package/src/plugins/builtin/news/wire/news/query-presets.ts +4 -1
- package/src/plugins/builtin/openfda/client.ts +123 -15
- package/src/plugins/builtin/openfda/model.ts +163 -0
- package/src/plugins/builtin/openfda/pane.tsx +109 -65
- package/src/plugins/builtin/openfda/types.ts +25 -0
- package/src/plugins/builtin/options/index.tsx +2 -1
- package/src/plugins/builtin/options/model-spot.ts +94 -0
- package/src/plugins/builtin/options/open-interest-as-of.ts +63 -0
- package/src/plugins/builtin/options/view.tsx +56 -10
- package/src/plugins/builtin/options-scenario/client.ts +33 -9
- package/src/plugins/builtin/options-scenario/csp.ts +168 -0
- package/src/plugins/builtin/options-scenario/evidence.ts +3 -0
- package/src/plugins/builtin/options-scenario/headless.ts +24 -8
- package/src/plugins/builtin/options-scenario/index.tsx +3 -1
- package/src/plugins/builtin/options-scenario/pane.tsx +32 -6
- package/src/plugins/builtin/pe-band/model.ts +3 -2
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +1 -1
- package/src/plugins/builtin/plugin-module.ts +3 -1
- package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +1 -1
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +19 -4
- package/src/plugins/builtin/portfolio-list/cli/render.ts +2 -2
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +39 -0
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +18 -5
- package/src/plugins/builtin/portfolio-list/live-valuation.ts +25 -13
- package/src/plugins/builtin/power/evidence.ts +32 -3
- package/src/plugins/builtin/power/gas-client.ts +110 -0
- package/src/plugins/builtin/power/gas-model.ts +194 -0
- package/src/plugins/builtin/power/gas.tsx +145 -0
- package/src/plugins/builtin/power/headless.ts +4 -1
- package/src/plugins/builtin/power/index.tsx +19 -9
- package/src/plugins/builtin/power/pane.tsx +2 -3
- package/src/plugins/builtin/power/prices-headless.ts +75 -7
- package/src/plugins/builtin/power/prices.tsx +36 -13
- package/src/plugins/builtin/primary-dealers/client.ts +108 -0
- package/src/plugins/builtin/primary-dealers/headless.ts +53 -0
- package/src/plugins/builtin/primary-dealers/index.tsx +17 -0
- package/src/plugins/builtin/primary-dealers/model.ts +206 -0
- package/src/plugins/builtin/primary-dealers/pane.tsx +149 -0
- package/src/plugins/builtin/relative-rotation/index.tsx +3 -0
- package/src/plugins/builtin/research/analyst-model.ts +9 -5
- package/src/plugins/builtin/research/headless-schema.ts +2 -1
- package/src/plugins/builtin/research/relative-valuation-headless.ts +68 -32
- package/src/plugins/builtin/research/relative-valuation-model.ts +45 -24
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +39 -4
- package/src/plugins/builtin/risk-factors/index.tsx +18 -0
- package/src/plugins/builtin/risk-factors/pane.tsx +2 -1
- package/src/plugins/builtin/scanner/flow-pane.tsx +8 -1
- package/src/plugins/builtin/scanner/headless.ts +9 -2
- package/src/plugins/builtin/scanner/index.ts +3 -0
- package/src/plugins/builtin/scanner/lock-note.ts +17 -0
- package/src/plugins/builtin/sec/filing-display.tsx +3 -36
- package/src/plugins/builtin/sec/index.tsx +131 -43
- package/src/plugins/builtin/sec/model.ts +148 -2
- package/src/plugins/builtin/sec/row-summaries.ts +105 -0
- package/src/plugins/builtin/sectors/index.tsx +2 -0
- package/src/plugins/builtin/sectors/sector-model.ts +2 -2
- package/src/plugins/builtin/series-inventory.ts +2 -1
- package/src/plugins/builtin/shared/cloud-denied.ts +39 -8
- package/src/plugins/builtin/shared/locked-rows.tsx +1 -1
- package/src/plugins/builtin/shared/pro-lock-note.ts +58 -0
- package/src/plugins/builtin/shared/series-list-detail.tsx +10 -5
- package/src/plugins/builtin/shared/use-quote-board.ts +179 -43
- package/src/plugins/builtin/shared/wall-teaser.tsx +2 -2
- package/src/plugins/builtin/shared/zip-text.ts +46 -0
- package/src/plugins/builtin/short-interest/watch-model.ts +11 -2
- package/src/plugins/builtin/social-mentions/client.ts +3 -3
- package/src/plugins/builtin/social-mentions/headless.ts +6 -2
- package/src/plugins/builtin/social-mentions/index.tsx +2 -1
- package/src/plugins/builtin/social-mentions/lock-note.ts +15 -0
- package/src/plugins/builtin/supply-chain/flow.tsx +15 -13
- package/src/plugins/builtin/supply-chain/graph.tsx +6 -4
- package/src/plugins/builtin/supply-chain/pane.tsx +8 -5
- package/src/plugins/builtin/themes/model.ts +2 -2
- package/src/plugins/builtin/ticker-detail/financials/aggregation.ts +25 -1
- package/src/plugins/builtin/ticker-detail/financials/ratios.ts +87 -23
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/headless.ts +6 -3
- package/src/plugins/builtin/ticker-detail/overview/components.tsx +105 -104
- package/src/plugins/builtin/ticker-detail/overview/model.ts +12 -3
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +41 -13
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +8 -6
- package/src/plugins/builtin/time-sales/headless.ts +22 -0
- package/src/plugins/builtin/trace-bonds/client.ts +196 -0
- package/src/plugins/builtin/trace-bonds/headless.ts +69 -0
- package/src/plugins/builtin/trace-bonds/index.tsx +33 -0
- package/src/plugins/builtin/trace-bonds/model.ts +115 -0
- package/src/plugins/builtin/trace-bonds/pane.tsx +191 -0
- package/src/plugins/builtin/treasury-auctions/index.tsx +33 -47
- package/src/plugins/builtin/treasury-daily/client.ts +96 -0
- package/src/plugins/builtin/treasury-daily/headless.ts +69 -0
- package/src/plugins/builtin/treasury-daily/index.tsx +17 -0
- package/src/plugins/builtin/treasury-daily/model.ts +69 -0
- package/src/plugins/builtin/treasury-daily/pane.tsx +140 -0
- package/src/plugins/builtin/vol-surface/pane.tsx +6 -3
- package/src/plugins/builtin/world-venue-map/entity-detail.tsx +15 -2
- package/src/plugins/builtin/world-venue-map/map.tsx +1 -0
- package/src/plugins/builtin-editorial.ts +1 -1
- package/src/plugins/catalog-browser.ts +25 -2
- package/src/plugins/marketplace/model.ts +57 -21
- package/src/public/__snapshots__/public-api.test.ts.snap +2 -0
- package/src/renderers/dom/build-assets.ts +14 -5
- package/src/renderers/dom/data-table/index.tsx +53 -18
- package/src/renderers/dom/data-table/row.tsx +1 -1
- package/src/renderers/dom/desktop/controls.tsx +2 -1
- package/src/renderers/dom/desktop/icons.tsx +25 -0
- package/src/renderers/dom/desktop/list-view.tsx +1 -1
- package/src/renderers/dom/desktop/menu.tsx +1 -1
- package/src/renderers/dom/desktop/popover.tsx +6 -15
- package/src/renderers/dom/desktop/query-bar.tsx +3 -1
- package/src/renderers/dom/host/chart-surface.tsx +7 -2
- package/src/renderers/dom/host/input.tsx +27 -3
- package/src/renderers/dom/host/resize-rows.ts +111 -0
- package/src/renderers/dom/host/sticky-scroll.ts +22 -3
- package/src/renderers/dom/host/style.ts +14 -0
- package/src/renderers/dom/host/surface-3d.tsx +8 -5
- package/src/renderers/dom/host/surface-fit.ts +10 -6
- package/src/renderers/dom/host/text.tsx +2 -2
- package/src/renderers/dom/styles.css +85 -10
- package/src/renderers/electrobun/bun/desktop/app-badge.ts +37 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +8 -0
- package/src/renderers/electrobun/bun/desktop/macos-dock-badge.ts +37 -0
- package/src/renderers/electrobun/bun/desktop/macos-dock-icon.ts +2 -40
- package/src/renderers/electrobun/bun/desktop/macos-objc.ts +41 -0
- package/src/renderers/electrobun/bun/tui-entry.ts +18 -1
- package/src/renderers/electrobun/shared/protocol.ts +2 -0
- package/src/renderers/electrobun/view/app-badge-host.ts +17 -0
- package/src/renderers/electrobun/view/app-services.ts +2 -22
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +8 -3
- package/src/renderers/electrobun/view/main.tsx +2 -0
- package/src/renderers/electrobun/view/news-source.ts +42 -0
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +5 -1
- package/src/series/validate.ts +6 -1
- package/src/shares/api.ts +5 -1
- package/src/shares/dialog.tsx +2 -1
- package/src/shares/location.ts +31 -0
- package/src/shares/open.ts +26 -0
- package/src/shares/pane-image.ts +18 -6
- package/src/shares/personal-pane.ts +42 -54
- package/src/sources/gloomberb-cloud/index.ts +7 -2
- package/src/sources/gloomberb-cloud/normalizers.ts +5 -0
- package/src/sources/history-coverage.ts +22 -4
- package/src/sources/history-result.ts +3 -1
- package/src/sources/provider-errors.ts +2 -1
- package/src/sources/provider-router/batches.ts +18 -2
- package/src/sources/provider-router/financials.ts +5 -0
- package/src/sources/provider-router/index.ts +2 -1
- package/src/state/app/context/index.tsx +3 -2
- package/src/test-support/builtin-panes.ts +31 -0
- package/src/tickers/listing-venues.ts +22 -0
- package/src/tickers/search/index.ts +7 -2
- package/src/tickers/search/ranking.ts +19 -0
- package/src/time-series/chart-data.ts +2 -0
- package/src/time-series/parsed-history-cache.ts +41 -11
- package/src/time-series/resolve.ts +47 -15
- package/src/types/config.ts +1 -1
- package/src/types/data-provider.ts +13 -1
- package/src/types/financials.ts +35 -0
- package/src/types/headless.ts +22 -0
- package/src/types/plugin.ts +46 -6
- package/src/types/price-history.ts +2 -0
- package/src/ui/host.tsx +6 -0
- package/src/utils/crypto-pair.ts +1 -1
- package/src/utils/currency-pair.ts +66 -0
- package/src/utils/decimal-comma.ts +57 -0
- package/src/utils/financial-statements.ts +25 -0
- package/src/utils/fundamentals.ts +41 -1
- package/src/utils/guards.ts +25 -0
- package/src/utils/local-utc-offset.ts +37 -0
- package/src/utils/plugin-proxy-hosts.json +8 -1
- package/src/components/chart/composite/crosshair-readout.tsx +0 -150
- package/src/plugins/builtin/chat/message/ai-badge.tsx +0 -18
- package/src/plugins/builtin/credit-boards/pane.tsx +0 -30
|
@@ -13,7 +13,8 @@ import type { DesktopWindowBridge } from "../../types/desktop-window";
|
|
|
13
13
|
import { requestAccountManagementTab } from "../../plugins/builtin/account-management/navigation";
|
|
14
14
|
import { openTeamPane } from "../../plugins/builtin/cloud/team/pane-request";
|
|
15
15
|
import { chatController } from "../../plugins/builtin/chat/controller";
|
|
16
|
-
import { getShare } from "../../shares/api";
|
|
16
|
+
import { getShare, type ShareRecord } from "../../shares/api";
|
|
17
|
+
import { openShareLink, registerShareOpener } from "../../shares/open";
|
|
17
18
|
import { openPaneShare } from "../../shares/pane";
|
|
18
19
|
import { PluginOffError, notifyPluginOff } from "../../plugins/plugin-off";
|
|
19
20
|
import { materializeMarketplaceLayout } from "../../shares/portable-layout";
|
|
@@ -514,15 +515,44 @@ async function handleOpenLayout(
|
|
|
514
515
|
notifySuccess(options.pluginRegistry, `Layout "${entry.name}" added.`);
|
|
515
516
|
}
|
|
516
517
|
|
|
517
|
-
|
|
518
|
-
|
|
518
|
+
/**
|
|
519
|
+
* Opens a pane share in this app: the web app's `?share=` hand-off, a
|
|
520
|
+
* gloomberb://share link and a share link in chat all come through here.
|
|
521
|
+
* With `fallback`, a share this app cannot read or that holds a snapshot
|
|
522
|
+
* goes there (its web page) instead of to an error.
|
|
523
|
+
*/
|
|
524
|
+
async function openShareInApp(
|
|
525
|
+
id: string,
|
|
519
526
|
pluginRegistry: PluginRegistry,
|
|
527
|
+
options: { retry: () => void; fallback?: () => void },
|
|
520
528
|
): Promise<void> {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
529
|
+
let share: ShareRecord | null;
|
|
530
|
+
try {
|
|
531
|
+
share = await getShare(id, fetch, { trackView: false });
|
|
532
|
+
} catch (error) {
|
|
533
|
+
if (options.fallback) options.fallback();
|
|
534
|
+
else notifyError(pluginRegistry, error instanceof Error ? error.message : "Could not open shared pane.");
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
if (!share) {
|
|
538
|
+
notifyError(pluginRegistry, "This share is unavailable or has expired.");
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
if (share.kind !== "pane") {
|
|
542
|
+
if (options.fallback) options.fallback();
|
|
543
|
+
else notifyError(pluginRegistry, "This link contains a snapshot, not a live pane.");
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
try {
|
|
547
|
+
await openPaneShare(pluginRegistry, share.data);
|
|
548
|
+
notifySuccess(pluginRegistry, "Opened shared pane.");
|
|
549
|
+
} catch (error) {
|
|
550
|
+
if (error instanceof PluginOffError) {
|
|
551
|
+
notifyPluginOff(pluginRegistry, error, options.retry);
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
notifyError(pluginRegistry, error instanceof Error ? error.message : "Could not open shared pane.");
|
|
555
|
+
}
|
|
526
556
|
}
|
|
527
557
|
|
|
528
558
|
export function handleDesktopDeepLink(rawUrl: string, options: DesktopDeepLinkHandlerOptions): void {
|
|
@@ -569,13 +599,7 @@ export function handleDesktopDeepLink(rawUrl: string, options: DesktopDeepLinkHa
|
|
|
569
599
|
handleOpenNews(action, options.pluginRegistry);
|
|
570
600
|
return;
|
|
571
601
|
case "open-share":
|
|
572
|
-
void
|
|
573
|
-
if (error instanceof PluginOffError) {
|
|
574
|
-
notifyPluginOff(options.pluginRegistry, error, () => handleDesktopDeepLink(rawUrl, options));
|
|
575
|
-
return;
|
|
576
|
-
}
|
|
577
|
-
notifyError(options.pluginRegistry, error instanceof Error ? error.message : "Could not open shared pane.");
|
|
578
|
-
});
|
|
602
|
+
void openShareInApp(action.id, options.pluginRegistry, { retry: () => handleDesktopDeepLink(rawUrl, options) });
|
|
579
603
|
return;
|
|
580
604
|
case "open-layout":
|
|
581
605
|
void handleOpenLayout(action, options).catch((error) => {
|
|
@@ -600,6 +624,15 @@ export function useDesktopDeepLinkRuntime({
|
|
|
600
624
|
pluginRegistry: PluginRegistry;
|
|
601
625
|
stateRef: { current: AppState };
|
|
602
626
|
}) {
|
|
627
|
+
// Share links opened inside the app (chat's share chips) take the same path, in every renderer.
|
|
628
|
+
useEffect(() => {
|
|
629
|
+
if (!initialized) return;
|
|
630
|
+
return registerShareOpener((id, { fallback }) => openShareInApp(id, pluginRegistry, {
|
|
631
|
+
fallback,
|
|
632
|
+
retry: () => openShareLink(id, fallback),
|
|
633
|
+
}));
|
|
634
|
+
}, [initialized, pluginRegistry]);
|
|
635
|
+
|
|
603
636
|
useEffect(() => {
|
|
604
637
|
if (!initialized || desktopWindowKind === "detached" || !desktopDeepLinkBridge) return;
|
|
605
638
|
return desktopDeepLinkBridge.subscribe((deeplink) => {
|
|
@@ -10,13 +10,25 @@ import {
|
|
|
10
10
|
performUpdate,
|
|
11
11
|
type ReleaseInfo,
|
|
12
12
|
type UpdateCheckResult,
|
|
13
|
+
type UpdateProgress,
|
|
13
14
|
} from "../../updater";
|
|
14
15
|
import { VERSION } from "../../version";
|
|
16
|
+
import { debugLog } from "../../utils/debug-log";
|
|
15
17
|
import { reportCrash } from "../../telemetry/crash-reports";
|
|
16
18
|
import { runAutomated } from "../../telemetry/usage-counts";
|
|
17
19
|
|
|
18
20
|
const UPDATE_CHECK_INTERVAL_MS = 60 * 60_000; // hourly
|
|
19
21
|
|
|
22
|
+
const updateLog = debugLog.createLogger("update");
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The header and the command bar show a failed update's message, and the header
|
|
26
|
+
* cuts it to its room: the log keeps what the updater actually said.
|
|
27
|
+
*/
|
|
28
|
+
function logUpdateFailure(progress: UpdateProgress): void {
|
|
29
|
+
if (progress.phase === "error") updateLog.error("update failed", { error: progress.error });
|
|
30
|
+
}
|
|
31
|
+
|
|
20
32
|
/** An update is being downloaded, applied, or is downloaded and waiting for a restart. */
|
|
21
33
|
function updateInFlight(progress: AppState["updateProgress"]): boolean {
|
|
22
34
|
return progress?.phase === "downloading" || progress?.phase === "replacing" || progress?.phase === "ready";
|
|
@@ -53,6 +65,7 @@ export function useAppUpdateRuntime({
|
|
|
53
65
|
const startUpdate = useCallback((release: ReleaseInfo) => {
|
|
54
66
|
dispatch({ type: "SET_UPDATE_PROGRESS", progress: { phase: "downloading", percent: 0 } });
|
|
55
67
|
void performUpdate(release, (progress) => {
|
|
68
|
+
logUpdateFailure(progress);
|
|
56
69
|
dispatch({ type: "SET_UPDATE_PROGRESS", progress });
|
|
57
70
|
});
|
|
58
71
|
}, [dispatch]);
|
|
@@ -66,6 +79,7 @@ export function useAppUpdateRuntime({
|
|
|
66
79
|
dispatch({ type: "SET_UPDATE_PROGRESS", progress: { phase: "replacing" } });
|
|
67
80
|
void applyUpdate((progress) => {
|
|
68
81
|
if (progress.phase === "error") restartingRef.current = false;
|
|
82
|
+
logUpdateFailure(progress);
|
|
69
83
|
dispatch({ type: "SET_UPDATE_PROGRESS", progress });
|
|
70
84
|
});
|
|
71
85
|
}, [dispatch, enabled, isDetachedWindow, stateRef]);
|
|
@@ -91,6 +105,8 @@ export function useAppUpdateRuntime({
|
|
|
91
105
|
return { kind: "error", error: message || "Update check failed" };
|
|
92
106
|
});
|
|
93
107
|
|
|
108
|
+
if (result.kind === "error") updateLog.warn("update check failed", { error: result.error });
|
|
109
|
+
|
|
94
110
|
if (!manual) {
|
|
95
111
|
if (result.kind === "available") {
|
|
96
112
|
dispatch({ type: "SET_UPDATE_AVAILABLE", release: result.release });
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"src/layout-marketplace/gallery.tsx": ["cloud"],
|
|
41
41
|
"src/layout-marketplace/linked-sync.ts": ["cloud"],
|
|
42
42
|
"src/layout/desks.ts": ["chart-composer"],
|
|
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"],
|
|
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","commodities-energy","commodity-balances","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","fixed-income","futures","futures-curve","fx-matrix","gpu","help","insider","ipo-calendar","iv-history","jobs","jodi","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","primary-dealers","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","trace-bonds","treasury-auctions","treasury-daily","vol-surface","volatility","world-indices","world-venue-map","yield-curve"],
|
|
44
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"],
|
|
45
45
|
"src/plugins/catalog.ts": ["debug"],
|
|
46
46
|
"src/remote/controller.ts": ["custom-view"],
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"src/components/layout/pane/header.tsx": {
|
|
3
|
+
"uses": 2,
|
|
4
|
+
"why": "The title bar's inset for the window controls comes from the shell's header geometry, which the terminal shares, in cells."
|
|
5
|
+
},
|
|
6
|
+
"src/components/layout/pane/sizing.ts": {
|
|
7
|
+
"uses": 3,
|
|
8
|
+
"why": "Panes receive their size in cells (PaneProps); this gives the desktop's taller chrome row in those cells."
|
|
9
|
+
},
|
|
10
|
+
"src/components/layout/shell/drag/slide.ts": {
|
|
11
|
+
"uses": 4,
|
|
12
|
+
"why": "A dragged pane moves by offsets of the saved layout, which is kept in cells."
|
|
13
|
+
},
|
|
14
|
+
"src/components/layout/shell/pane/layers.tsx": {
|
|
15
|
+
"uses": 6,
|
|
16
|
+
"why": "Pane rectangles in the saved layout are in cells; this is where they become pixels."
|
|
17
|
+
},
|
|
18
|
+
"src/components/ui/select-button.tsx": {
|
|
19
|
+
"uses": 2,
|
|
20
|
+
"why": "A select's width is given in cells by the pane, as its terminal button's is."
|
|
21
|
+
},
|
|
22
|
+
"src/renderers/dom/data-table/dom.ts": {
|
|
23
|
+
"uses": 26,
|
|
24
|
+
"why": "The table's scroll and pointer API speaks rows and columns to callers shared with the terminal (j/k, paging, visible range); a row of text is one line tall."
|
|
25
|
+
},
|
|
26
|
+
"src/renderers/dom/data-table/index.tsx": {
|
|
27
|
+
"uses": 19,
|
|
28
|
+
"why": "Every pane gives its columns in cells (DataTableColumn.width) and rows are one line tall: the horizontal extent, the overflow decision, virtualization and paging follow from them."
|
|
29
|
+
},
|
|
30
|
+
"src/renderers/dom/data-table/row.tsx": {
|
|
31
|
+
"uses": 10,
|
|
32
|
+
"why": "Column widths and gaps are cells in the column model every pane uses; a row is one line tall."
|
|
33
|
+
},
|
|
34
|
+
"src/renderers/dom/desktop/controls.tsx": {
|
|
35
|
+
"uses": 6,
|
|
36
|
+
"why": "Callers give a button's size in cells; a framed field keeps its text one cell off its frame, as the terminal's does."
|
|
37
|
+
},
|
|
38
|
+
"src/renderers/dom/desktop/list-view.tsx": {
|
|
39
|
+
"uses": 2,
|
|
40
|
+
"why": "The caller gives a list's height in rows."
|
|
41
|
+
},
|
|
42
|
+
"src/renderers/dom/desktop/query-bar.tsx": {
|
|
43
|
+
"uses": 1,
|
|
44
|
+
"why": "The pane gives its search field's width in cells."
|
|
45
|
+
},
|
|
46
|
+
"src/renderers/dom/desktop/select-field.tsx": {
|
|
47
|
+
"uses": 2,
|
|
48
|
+
"why": "An inline select is one row tall, the row it sits in."
|
|
49
|
+
},
|
|
50
|
+
"src/renderers/dom/dom-ui-host.tsx": {
|
|
51
|
+
"uses": 6,
|
|
52
|
+
"why": "Exposes the cell size to components that still size in cells (chart bitmaps, the company logo)."
|
|
53
|
+
},
|
|
54
|
+
"src/renderers/dom/host/input.tsx": {
|
|
55
|
+
"uses": 3,
|
|
56
|
+
"why": "Callers give a field's width and height in cells; a one-line field is one row tall."
|
|
57
|
+
},
|
|
58
|
+
"src/renderers/dom/host/live-frame.ts": {
|
|
59
|
+
"uses": 8,
|
|
60
|
+
"why": "A resize's live frame is in cells, the pane's unit, until the pane renders at the new size."
|
|
61
|
+
},
|
|
62
|
+
"src/renderers/dom/host/mouse.ts": {
|
|
63
|
+
"uses": 10,
|
|
64
|
+
"why": "Pointer handlers receive cell coordinates, the event API every renderer shares."
|
|
65
|
+
},
|
|
66
|
+
"src/renderers/dom/host/scroll-box.tsx": {
|
|
67
|
+
"uses": 22,
|
|
68
|
+
"why": "The scroller's API (scrollTop, scrollBy, viewport) is in rows and columns for callers shared with the terminal; content insets are given in cells."
|
|
69
|
+
},
|
|
70
|
+
"src/renderers/dom/host/size-observer.ts": {
|
|
71
|
+
"uses": 6,
|
|
72
|
+
"why": "Observed sizes are reported in cells, as callers expect."
|
|
73
|
+
},
|
|
74
|
+
"src/renderers/dom/host/style.ts": {
|
|
75
|
+
"uses": 27,
|
|
76
|
+
"why": "Maps the shared Box and Text props that components give in cells (width, height, padding, margin, gap, position) to pixels."
|
|
77
|
+
},
|
|
78
|
+
"src/renderers/dom/host/surface-fit.ts": {
|
|
79
|
+
"uses": 4,
|
|
80
|
+
"why": "A chart takes its box when its cells come within a cell of it, because panes still count their space in cells."
|
|
81
|
+
},
|
|
82
|
+
"src/renderers/dom/host/tabs.tsx": {
|
|
83
|
+
"uses": 2,
|
|
84
|
+
"why": "A tab strip is one row tall, the row every caller reserves for it."
|
|
85
|
+
},
|
|
86
|
+
"src/renderers/dom/host/text.tsx": {
|
|
87
|
+
"uses": 2,
|
|
88
|
+
"why": "The ASCII wordmark draws one glyph per cell."
|
|
89
|
+
},
|
|
90
|
+
"src/renderers/dom/input-host.tsx": {
|
|
91
|
+
"uses": 4,
|
|
92
|
+
"why": "The viewport is reported in cells (useViewport), the unit every renderer shares."
|
|
93
|
+
},
|
|
94
|
+
"src/renderers/dom/native-renderer.ts": {
|
|
95
|
+
"uses": 4,
|
|
96
|
+
"why": "The renderer's width and height are reported in cells, the unit every renderer shares."
|
|
97
|
+
},
|
|
98
|
+
"src/renderers/dom/styles.css": {
|
|
99
|
+
"uses": 14,
|
|
100
|
+
"why": "Defines the cell size and the base line height; status, footer and hint lines are one row; a few insets are one cell, as the terminal's (the floating pane's two-cell grip, a query bar segment)."
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { ResolvedPane } from "../layout/pane-manager";
|
|
1
2
|
import type { PluginRegistry } from "../plugins/registry";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
3
|
+
import { panePersonalData } from "../shares/personal-pane";
|
|
4
|
+
import { resolveTickerForPane, type AppState } from "../state/app/context";
|
|
5
|
+
import type { LayoutConfig } from "../types/config";
|
|
4
6
|
import type { PaneSharePrivateFields } from "../types/plugin";
|
|
5
|
-
import type { TickerRecord } from "../types/ticker";
|
|
6
7
|
import type { AskGloomPaneAttachment } from "./pane-request";
|
|
7
8
|
|
|
8
9
|
/** A handful of the pane's own settings is enough to say how it is set up. */
|
|
@@ -50,14 +51,13 @@ function functionCode(registry: Pick<PluginRegistry, "paneTemplates">, paneType:
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
export interface PaneAttachmentSource {
|
|
53
|
-
registry: Pick<PluginRegistry, "
|
|
54
|
-
|
|
54
|
+
registry: Pick<PluginRegistry, "paneTemplates" | "brokers" | "getPanePluginId" | "getBrokerPluginId">;
|
|
55
|
+
pane: Pick<ResolvedPane, "instance" | "def">;
|
|
56
|
+
state: AppState;
|
|
57
|
+
/** The layout the pane is in, as the share path reads it for `personalData`. */
|
|
58
|
+
layout: LayoutConfig;
|
|
55
59
|
/** What the header calls it. */
|
|
56
60
|
title: string;
|
|
57
|
-
symbol: string | null;
|
|
58
|
-
paneState?: Readonly<Record<string, unknown>>;
|
|
59
|
-
config: Pick<AppConfig, "portfolios" | "brokerInstances">;
|
|
60
|
-
tickers?: ReadonlyMap<string, TickerRecord>;
|
|
61
61
|
/** The tab each of its tab strips has open, outermost first. */
|
|
62
62
|
activeTabs?: readonly string[];
|
|
63
63
|
visibleText: string | null;
|
|
@@ -70,16 +70,17 @@ export interface PaneAttachmentSource {
|
|
|
70
70
|
*/
|
|
71
71
|
export function buildAskGloomPaneAttachment({
|
|
72
72
|
registry,
|
|
73
|
-
|
|
73
|
+
pane,
|
|
74
|
+
state,
|
|
75
|
+
layout,
|
|
74
76
|
title,
|
|
75
|
-
symbol,
|
|
76
|
-
paneState,
|
|
77
|
-
config,
|
|
78
|
-
tickers,
|
|
79
77
|
activeTabs = [],
|
|
80
78
|
visibleText,
|
|
81
79
|
}: PaneAttachmentSource): AskGloomPaneAttachment {
|
|
82
|
-
const
|
|
80
|
+
const { instance } = pane;
|
|
81
|
+
const symbol = resolveTickerForPane(state, instance.instanceId);
|
|
82
|
+
const paneState = state.paneState[instance.instanceId];
|
|
83
|
+
const privateFields = pane.def.portableShare?.private;
|
|
83
84
|
const args: Record<string, string> = {};
|
|
84
85
|
const tabs = activeTabs.map((tab) => tab.trim()).filter(Boolean);
|
|
85
86
|
if (tabs.length > 0) args.tab = tabs.join(" > ").slice(0, MAX_ARG_VALUE_LENGTH);
|
|
@@ -100,14 +101,17 @@ export function buildAskGloomPaneAttachment({
|
|
|
100
101
|
symbol,
|
|
101
102
|
args,
|
|
102
103
|
visibleText,
|
|
103
|
-
personal: showsPersonalData({ registry,
|
|
104
|
+
personal: showsPersonalData({ registry, state, layout, pane }),
|
|
104
105
|
};
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
/**
|
|
108
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Whatever the pane shows as personal data, as sharing its picture reads it.
|
|
110
|
+
* A pane that cannot be read for it counts as personal: its contents then wait for a yes.
|
|
111
|
+
*/
|
|
112
|
+
function showsPersonalData(source: Parameters<typeof panePersonalData>[0]): boolean {
|
|
109
113
|
try {
|
|
110
|
-
return
|
|
114
|
+
return panePersonalData(source) !== null;
|
|
111
115
|
} catch {
|
|
112
116
|
return true;
|
|
113
117
|
}
|
|
@@ -23,8 +23,8 @@ export interface AskGloomPaneAttachment {
|
|
|
23
23
|
/** Its text as drawn when asked, bounded; null when none could be read. */
|
|
24
24
|
visibleText: string | null;
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
* anything it shows leaves the device.
|
|
26
|
+
* The pane shows personal data (`PaneDef.personalData`), so Ask Gloom
|
|
27
|
+
* asks before anything it shows leaves the device.
|
|
28
28
|
*/
|
|
29
29
|
personal: boolean;
|
|
30
30
|
}
|
|
@@ -19,18 +19,44 @@ export function isSpreadSeries(seriesId: string): boolean {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* The
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
22
|
+
* The unit a series' observations export in, for the `currency_or_unit`
|
|
23
|
+
* column beside its bare `value`: `bp` for a spread (exported in basis
|
|
24
|
+
* points), `pct` for a percent, otherwise FRED's own units, with "annual
|
|
25
|
+
* rate" as the text header says it. Null when FRED's metadata did not come
|
|
26
|
+
* back.
|
|
27
27
|
*/
|
|
28
|
-
export function
|
|
29
|
-
if (isSpreadSeries(seriesId)) return "
|
|
30
|
-
const
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
export function fredUnit(seriesId: string, info: { units?: string | null; seasonalAdjustment?: string | null } | null | undefined): string | null {
|
|
29
|
+
if (isSpreadSeries(seriesId)) return "bp";
|
|
30
|
+
const units = info?.units?.trim();
|
|
31
|
+
if (!units) return null;
|
|
32
|
+
if (/^percent$/i.test(units)) return "pct";
|
|
33
|
+
const annualRate = /annual rate/i.test(info?.seasonalAdjustment ?? "") && !/annual rate/i.test(units);
|
|
34
|
+
return `${units}${annualRate ? ", annual rate" : ""}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** How often a series observes, in FRED's word lower-cased: `Weekly, Ending Friday` is `weekly`. Null when FRED does not say. */
|
|
38
|
+
export function fredInterval(frequency: string | null | undefined): string | null {
|
|
39
|
+
const word = frequency?.split(",")[0]?.trim().toLowerCase();
|
|
40
|
+
return word || null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The observations from the series' first one on: Gloom Cloud answers a
|
|
45
|
+
* `--start` before a series begins with a blank row for every day in between
|
|
46
|
+
* (DEXSFUS from 1975 has five years of them before 1980-01-02). FRED's
|
|
47
|
+
* `observationStart` says where it begins; without it the blank rows before
|
|
48
|
+
* the first value go. Blank rows after it (a holiday's ".") stay.
|
|
49
|
+
*/
|
|
50
|
+
export function fredObservationsFromStart<T extends { date: string; value: number | null }>(
|
|
51
|
+
observations: readonly T[],
|
|
52
|
+
seriesStart: string | null | undefined,
|
|
53
|
+
): T[] {
|
|
54
|
+
const first = seriesStart && /^\d{4}-\d{2}-\d{2}$/.test(seriesStart)
|
|
55
|
+
? seriesStart
|
|
56
|
+
: observations.reduce<string | null>((earliest, observation) => (
|
|
57
|
+
observation.value != null && Number.isFinite(observation.value) && (!earliest || observation.date < earliest) ? observation.date : earliest
|
|
58
|
+
), null);
|
|
59
|
+
return first ? observations.filter((observation) => observation.date >= first) : [...observations];
|
|
34
60
|
}
|
|
35
61
|
|
|
36
62
|
/**
|
|
@@ -144,3 +170,43 @@ export function fredEmptyMessage(startDate: string, latest: { date: string; valu
|
|
|
144
170
|
? `Latest observation: ${latest.date}${latest.value == null ? "" : ` (${latest.value})`}. Nothing on or after ${startDate}.`
|
|
145
171
|
: "No results.";
|
|
146
172
|
}
|
|
173
|
+
|
|
174
|
+
/** What an export of nothing on or after `--start` says to try instead: a start that reaches the latest observation. */
|
|
175
|
+
export function fredEmptyAdvice(seriesId: string, latest: { date: string } | null): string {
|
|
176
|
+
return latest
|
|
177
|
+
? `Latest observation: ${latest.date}. Try: gloomberb fred ${seriesId} --start ${latest.date.slice(0, 4)}`
|
|
178
|
+
: `No observations came back for ${seriesId}. Try an earlier --start, or gloomberb fred --list for the series served.`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** A series as `fred --list` shows it. */
|
|
182
|
+
export interface FredListRow {
|
|
183
|
+
id: string;
|
|
184
|
+
title: string;
|
|
185
|
+
group: string;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** How well a word of the filter matches a series, best first: its id or group name, a word of its group or title, the start of its id, then any text. */
|
|
189
|
+
function matchTier(term: string, row: FredListRow, words: readonly string[]): number {
|
|
190
|
+
if (row.id.toLowerCase() === term || row.group.toLowerCase() === term) return 0;
|
|
191
|
+
if (words.some((word) => word.startsWith(term))) return 1;
|
|
192
|
+
if (row.id.toLowerCase().startsWith(term)) return 2;
|
|
193
|
+
return 3;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* The series that carry every word of the filter in their id, title or group,
|
|
198
|
+
* the ones it names first: a group or a word of the title ahead of the id that
|
|
199
|
+
* only has it inside (`fx` is the FX group, not FDEFX, whose id spells it).
|
|
200
|
+
* Catalog order breaks ties; an empty filter keeps the catalog as it is.
|
|
201
|
+
*/
|
|
202
|
+
export function filterFredSeries(rows: readonly FredListRow[], filter: string): FredListRow[] {
|
|
203
|
+
const terms = filter.toLowerCase().split(/\s+/).filter(Boolean);
|
|
204
|
+
const ranked = rows.flatMap((row, index) => {
|
|
205
|
+
const text = `${row.id} ${row.title} ${row.group}`.toLowerCase();
|
|
206
|
+
if (!terms.every((term) => text.includes(term))) return [];
|
|
207
|
+
const words = `${row.title} ${row.group}`.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);
|
|
208
|
+
const tiers = terms.map((term) => matchTier(term, row, words));
|
|
209
|
+
return [{ row, index, worst: Math.max(0, ...tiers), total: tiers.reduce((sum, tier) => sum + tier, 0) }];
|
|
210
|
+
});
|
|
211
|
+
return ranked.sort((a, b) => a.worst - b.worst || a.total - b.total || a.index - b.index).map((entry) => entry.row);
|
|
212
|
+
}
|