gloomberb 0.16.2 → 0.16.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -1
- package/src/api-client/askg.ts +43 -0
- package/src/api-client/auth.ts +15 -0
- package/src/api-client/beneficial-owners.ts +4 -0
- package/src/api-client/chat.ts +19 -0
- package/src/api-client/company-kpis.ts +14 -2
- package/src/api-client/data.ts +34 -16
- package/src/api-client/index.ts +12 -0
- package/src/api-client/normalizers.ts +27 -0
- package/src/api-client/paths.ts +88 -23
- package/src/api-client/request.ts +2 -1
- package/src/api-client/research-activity.ts +31 -0
- package/src/api-client/socket.ts +39 -8
- package/src/api-client/types.ts +57 -1
- package/src/api-client/upgrade-experiment.ts +90 -0
- package/src/app/global-shortcuts.ts +11 -1
- package/src/app/keybindings/actions.ts +10 -0
- package/src/app/pane-runtime/index.tsx +8 -0
- package/src/app/pane-runtime/pane-template-runtime.ts +5 -0
- package/src/app/pane-runtime/plugin-bindings.ts +65 -25
- package/src/app/pane-runtime/ticker-inspector-runtime.ts +12 -0
- package/src/app/pane-runtime/ticker-open-runtime.ts +18 -1
- package/src/app/runtime/desktop-deeplink.ts +5 -0
- package/src/app/star-prompt/model.ts +98 -0
- package/src/app/star-prompt/runtime.ts +41 -0
- package/src/app/star-prompt/status-line.tsx +190 -0
- package/src/app.tsx +13 -7
- package/src/architecture/core-builtin-allowlist.json +70 -0
- package/src/brokers/account-cache.ts +45 -0
- package/src/brokers/signed-in/adapter.ts +33 -2
- package/src/brokers/signed-in/client.ts +10 -0
- package/src/brokers/signed-in/sign-in-dialog.tsx +23 -9
- package/src/brokers/signed-in/sign-in.ts +62 -5
- package/src/capabilities/registry.ts +8 -1
- package/src/capabilities/types.ts +2 -0
- package/src/cli/command-options.ts +74 -0
- package/src/cli/commands/command-utils.ts +29 -0
- package/src/cli/commands/crypto-hints.ts +12 -4
- package/src/cli/commands/market.ts +524 -148
- package/src/cli/commands/options-chain.ts +172 -0
- package/src/cli/commands/options-leaps.ts +422 -0
- package/src/cli/commands/overview.ts +223 -42
- package/src/cli/commands/search.ts +29 -8
- package/src/cli/commands/system.ts +99 -19
- package/src/cli/commands/themes.ts +64 -0
- package/src/cli/commands/ticker.ts +200 -73
- package/src/cli/desktop-pane-shot.ts +100 -16
- package/src/cli/errors.ts +25 -2
- package/src/cli/freshness.ts +7 -4
- package/src/cli/fx-pair.ts +57 -0
- package/src/cli/help.ts +40 -7
- package/src/cli/history-rows.ts +187 -15
- package/src/cli/index-roots.ts +51 -0
- package/src/cli/index.ts +21 -13
- package/src/cli/listing-arg.ts +211 -3
- package/src/cli/not-a-ticker.ts +37 -0
- package/src/cli/options.ts +55 -7
- package/src/cli/pane-functions/capabilities.ts +13 -2
- package/src/cli/pane-functions/catalog.ts +13 -2
- package/src/cli/pane-functions/data.ts +36 -5
- package/src/cli/pane-functions/dom.ts +89 -28
- package/src/cli/pane-functions/freshness.ts +205 -26
- package/src/cli/pane-functions/function-help.ts +71 -24
- package/src/cli/pane-functions/headless.ts +168 -35
- package/src/cli/pane-functions/index.ts +12 -2
- package/src/cli/pane-functions/market-session.ts +133 -0
- package/src/cli/pane-functions/options.ts +15 -4
- package/src/cli/pane-functions/report-notices.ts +63 -0
- package/src/cli/pane-functions/report.ts +12 -1
- package/src/cli/pane-functions/resolver.ts +32 -8
- package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
- package/src/cli/pane-functions/screenshot.ts +109 -23
- package/src/cli/registry.ts +8 -4
- package/src/cli/report-tables.ts +460 -0
- package/src/cli/result.ts +63 -16
- package/src/cli/row-window.ts +76 -0
- package/src/cli/scroll-truncation.ts +34 -0
- package/src/components/chart/composite/composite-chart.tsx +43 -4
- package/src/components/chart/composite/legend.tsx +39 -6
- package/src/components/chart/composite/rasterizer.ts +64 -4
- package/src/components/chart/composite/series-cues.ts +71 -0
- package/src/components/chart/composite/text-renderer.ts +16 -8
- package/src/components/chart/composite/types.ts +3 -0
- package/src/components/command-bar/commands/direct/index.ts +9 -1
- package/src/components/command-bar/commands/plugin/items.ts +3 -1
- package/src/components/command-bar/commands/registry.ts +7 -0
- package/src/components/command-bar/layout-items/focused-pane.ts +38 -0
- package/src/components/command-bar/pane-templates/workflow.ts +5 -0
- package/src/components/command-bar/routes/root/command-items.ts +2 -0
- package/src/components/command-bar/routes/root/plugin-turn-on.ts +92 -0
- package/src/components/command-bar/routes/root/results.ts +40 -10
- package/src/components/command-bar/routes/root/runtime.ts +8 -0
- package/src/components/command-bar/routes/root/search-providers.ts +97 -14
- package/src/components/command-bar/surface/index.tsx +18 -4
- package/src/components/command-bar/theme-picker.tsx +48 -13
- package/src/components/command-bar/workflow/ops.ts +5 -3
- package/src/components/data-table/export.ts +6 -51
- package/src/components/data-table/view.tsx +31 -10
- package/src/components/layout/floating-pane.tsx +6 -2
- package/src/components/layout/market-summary.ts +23 -9
- package/src/components/layout/pane/content.tsx +46 -29
- package/src/components/layout/pane/cycle-order.ts +2 -11
- package/src/components/layout/pane/header.tsx +2 -1
- package/src/components/layout/pane/title.ts +1 -1
- package/src/components/layout/presentation.ts +22 -0
- package/src/components/layout/shell/active-drag.ts +67 -35
- package/src/components/layout/shell/cursor-occlusion.ts +6 -5
- package/src/components/layout/shell/drag/index.ts +16 -7
- package/src/components/layout/shell/drag/live.ts +193 -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 +84 -57
- package/src/components/layout/shell/layout-state.ts +5 -11
- package/src/components/layout/shell/menu.ts +28 -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 +461 -180
- package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
- package/src/components/layout/shell/pane/new-layout.ts +116 -0
- package/src/components/layout/shell/shortcuts.ts +5 -2
- package/src/components/layout/shell/terminal-pointer-runtime.ts +18 -18
- package/src/components/layout/shell/visible-layout.ts +44 -1
- package/src/components/layout/shell/window-mode/overlays.tsx +12 -4
- package/src/components/layout/status-bar.tsx +4 -1
- package/src/components/markdown-text.tsx +9 -5
- package/src/components/metric-treemap/heat-surface.tsx +27 -8
- package/src/components/metric-treemap/heat-tiles.ts +48 -17
- package/src/components/onboarding/onboarding-frame.tsx +33 -10
- package/src/components/onboarding/onboarding-wizard.tsx +49 -40
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +5 -2
- package/src/components/onboarding/pro-step-layout.ts +86 -0
- package/src/components/onboarding/use-onboarding-upgrade.ts +6 -2
- package/src/components/ui/button.tsx +10 -0
- package/src/components/ui/data-table/index.tsx +38 -0
- package/src/components/ui/data-table/types.ts +8 -1
- package/src/components/ui/data-table/visible-range.ts +2 -0
- package/src/components/ui/icon.tsx +11 -2
- package/src/components/ui/index.ts +1 -1
- package/src/core/connection-health.ts +1 -1
- package/src/core/state/app/layout-reducer.ts +89 -3
- package/src/core/state/app/state.ts +8 -5
- package/src/core/state/app/types.ts +13 -2
- package/src/data/config/layout.ts +55 -21
- package/src/data/config/store/fold-panes.ts +149 -0
- package/src/data/config/store/migrations.ts +7 -0
- package/src/data/config/store/node.ts +27 -6
- package/src/data/config/store/normalize.ts +37 -3
- package/src/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 +14 -1
- package/src/i18n/ja.ts +14 -1
- package/src/i18n/ko.ts +14 -1
- package/src/i18n/zh-cn.ts +14 -1
- package/src/i18n/zh-tw.ts +14 -1
- package/src/layout/desks.ts +1 -2
- package/src/layout/pane-layout-move.ts +264 -0
- package/src/layout/pane-manager/hidden-panes.ts +160 -0
- package/src/layout/pane-manager/index.ts +1 -0
- package/src/market-data/coordinator/entries.ts +7 -1
- package/src/market-data/coordinator/quotes.ts +2 -2
- package/src/market-data/market/freshness.ts +156 -11
- package/src/market-data/market/status.ts +40 -0
- package/src/market-data/options-alternatives.ts +69 -0
- package/src/market-data/quotes/contributions.ts +19 -2
- package/src/market-data/quotes/freshness.ts +5 -0
- package/src/market-data/quotes/metadata.ts +16 -0
- package/src/market-data/quotes/screener-live-quotes.ts +56 -5
- package/src/plugins/builtin/account-management/keyboard.ts +3 -0
- package/src/plugins/builtin/account-management/model.ts +1 -0
- package/src/plugins/builtin/account-management/navigation.ts +1 -1
- package/src/plugins/builtin/account-management/pane.tsx +31 -4
- package/src/plugins/builtin/alerts/quotes.ts +3 -0
- package/src/plugins/builtin/analytics/pane-model.ts +10 -6
- package/src/plugins/builtin/analytics/risk-headless.ts +3 -1
- package/src/plugins/builtin/analytics/risk-model.ts +37 -8
- package/src/plugins/builtin/analytics/risk-pane.tsx +8 -4
- package/src/plugins/builtin/attention/pane.tsx +1 -1
- package/src/plugins/builtin/backtest/pane.tsx +1 -1
- package/src/plugins/builtin/broker-manager/detail.tsx +4 -0
- package/src/plugins/builtin/broker-manager/index.tsx +7 -3
- package/src/plugins/builtin/broker-manager/model.ts +8 -0
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -2
- package/src/plugins/builtin/broker-manager/sign-in-end.ts +82 -0
- package/src/plugins/builtin/broker-manager/table.ts +5 -0
- package/src/plugins/builtin/builtin-plugin-meta.ts +121 -11
- package/src/plugins/builtin/catalysts/detail.tsx +1 -1
- package/src/plugins/builtin/chart-composer/pane.tsx +1 -1
- package/src/plugins/builtin/chat/channels.ts +34 -36
- package/src/plugins/builtin/chat/command-bar.ts +138 -0
- package/src/plugins/builtin/chat/composer-commands.ts +21 -1
- package/src/plugins/builtin/chat/content/composer-runtime.ts +11 -1
- package/src/plugins/builtin/chat/content/footer.tsx +5 -3
- package/src/plugins/builtin/chat/content/index.tsx +21 -1
- package/src/plugins/builtin/chat/content/mentions.ts +2 -1
- package/src/plugins/builtin/chat/content/user-map.ts +3 -1
- package/src/plugins/builtin/chat/controller/index.ts +48 -0
- package/src/plugins/builtin/chat/conversations.ts +256 -0
- package/src/plugins/builtin/chat/discord-command.ts +91 -0
- package/src/plugins/builtin/chat/edit-window.ts +12 -6
- package/src/plugins/builtin/chat/ghost-user.ts +14 -0
- package/src/plugins/builtin/chat/index.tsx +40 -2
- package/src/plugins/builtin/chat/layout.ts +2 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +2 -1
- package/src/plugins/builtin/chat/message/header.tsx +24 -15
- package/src/plugins/builtin/chat/message/profile-popover.tsx +2 -1
- package/src/plugins/builtin/chat/message/render-state.ts +3 -0
- package/src/plugins/builtin/chat/pane-requests.ts +60 -0
- package/src/plugins/builtin/chat/pane-state.ts +32 -2
- package/src/plugins/builtin/chat/pane.tsx +8 -0
- package/src/plugins/builtin/cloud/askg/controller.ts +112 -4
- package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
- package/src/plugins/builtin/cloud/askg/manifest.ts +1 -0
- package/src/plugins/builtin/cloud/askg/model.ts +129 -70
- package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
- package/src/plugins/builtin/cloud/askg/protocol.ts +40 -2
- package/src/plugins/builtin/cloud/askg/tool-display.ts +437 -0
- package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -0
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -9
- package/src/plugins/builtin/cloud/mcp-connect/command.ts +24 -0
- package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +360 -0
- package/src/plugins/builtin/cloud/mcp-connect/model.ts +135 -0
- package/src/plugins/builtin/cloud/mcp-connect/sections.ts +62 -0
- package/src/plugins/builtin/cloud/plugin.tsx +36 -1
- package/src/plugins/builtin/cloud/starter-symbols.ts +8 -0
- package/src/plugins/builtin/cloud/terminal-relay/acm-tab.tsx +89 -0
- package/src/plugins/builtin/cloud/terminal-relay/client.ts +97 -0
- package/src/plugins/builtin/cloud/terminal-relay/connect-section.tsx +57 -0
- package/src/plugins/builtin/cloud/terminal-relay/engine.ts +666 -0
- package/src/plugins/builtin/cloud/terminal-relay/grants.ts +137 -0
- package/src/plugins/builtin/cloud/terminal-relay/host.tsx +81 -0
- package/src/plugins/builtin/cloud/terminal-relay/indicator.tsx +82 -0
- package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +234 -0
- package/src/plugins/builtin/cloud/terminal-relay/policy.ts +153 -0
- package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +168 -0
- package/src/plugins/builtin/cloud/terminal-relay/redact.ts +73 -0
- package/src/plugins/builtin/cloud/terminal-relay/summary.ts +62 -0
- package/src/plugins/builtin/cloud/upgrade-dialog.tsx +26 -2
- package/src/plugins/builtin/cloud/upgrade-personalization.ts +57 -0
- package/src/plugins/builtin/cloud/upgrade-tickers.ts +124 -0
- package/src/plugins/builtin/comment-letters/client.ts +1 -3
- package/src/plugins/builtin/company-attention/pane.tsx +1 -1
- package/src/plugins/builtin/company-kpis/client.ts +23 -8
- package/src/plugins/builtin/company-kpis/headless.ts +3 -1
- package/src/plugins/builtin/company-kpis/pane.tsx +15 -7
- package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
- package/src/plugins/builtin/composite-plugins.ts +107 -64
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +4 -4
- package/src/plugins/builtin/credit-boards/index.tsx +21 -21
- package/src/plugins/builtin/credit-boards/model.ts +0 -1
- package/src/plugins/builtin/credit-boards/pane.tsx +30 -0
- package/src/plugins/builtin/credit-boards/sovr-pane.tsx +4 -4
- package/src/plugins/builtin/debt-maturities/client.ts +37 -9
- package/src/plugins/builtin/debt-maturities/headless.ts +3 -1
- package/src/plugins/builtin/debt-maturities/pane.tsx +5 -4
- package/src/plugins/builtin/dividend-yield/index.tsx +1 -1
- package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
- package/src/plugins/builtin/earnings-calls/data.ts +28 -7
- package/src/plugins/builtin/earnings-calls/headless.ts +3 -2
- package/src/plugins/builtin/earnings-calls/pane.tsx +10 -5
- package/src/plugins/builtin/econ/calendar-model.ts +42 -17
- package/src/plugins/builtin/econ/detail-view.tsx +2 -2
- package/src/plugins/builtin/econ/index.tsx +68 -22
- package/src/plugins/builtin/econ-statistics/headless.ts +12 -2
- package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
- package/src/plugins/builtin/econ-statistics/view.ts +17 -0
- package/src/plugins/builtin/executives/data.ts +17 -6
- package/src/plugins/builtin/executives/pane.tsx +16 -7
- package/src/plugins/builtin/filing-events/pane.tsx +22 -5
- package/src/plugins/builtin/fx-matrix/freshness.ts +65 -0
- package/src/plugins/builtin/fx-matrix/index.tsx +22 -1
- package/src/plugins/builtin/fx-matrix/pairs.ts +1 -1
- package/src/plugins/builtin/fx-matrix/settings.ts +42 -2
- package/src/plugins/builtin/gpu/headless.ts +9 -3
- package/src/plugins/builtin/gpu/model.ts +14 -5
- package/src/plugins/builtin/help/index.tsx +1 -0
- package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
- package/src/plugins/builtin/holders/beneficial-view.tsx +7 -3
- package/src/plugins/builtin/holders/client.ts +3 -6
- package/src/plugins/builtin/holders/format.ts +31 -1
- package/src/plugins/builtin/holders/headless.ts +32 -6
- package/src/plugins/builtin/holders/pane.tsx +25 -13
- package/src/plugins/builtin/holders/report-header.ts +46 -5
- package/src/plugins/builtin/insider/index.tsx +4 -4
- package/src/plugins/builtin/iv-history/charts.tsx +21 -7
- package/src/plugins/builtin/iv-history/client.ts +12 -2
- package/src/plugins/builtin/iv-history/format.ts +33 -2
- package/src/plugins/builtin/iv-history/headless.ts +22 -10
- package/src/plugins/builtin/iv-history/index.tsx +3 -3
- package/src/plugins/builtin/iv-history/model.ts +61 -13
- package/src/plugins/builtin/iv-history/pane.tsx +11 -3
- package/src/plugins/builtin/iv-history/screen-pane.tsx +42 -18
- package/src/plugins/builtin/jobs/pane.tsx +1 -1
- package/src/plugins/builtin/kelly-sizer/headless.ts +149 -0
- package/src/plugins/builtin/kelly-sizer/history.ts +80 -0
- package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
- package/src/plugins/builtin/kelly-sizer/pane.tsx +121 -45
- package/src/plugins/builtin/kelly-sizer/portfolio.ts +25 -0
- package/src/plugins/builtin/kelly-sizer/sections.tsx +14 -0
- package/src/plugins/builtin/kelly-sizer/types.ts +9 -1
- package/src/plugins/builtin/layout-manager/index.tsx +9 -1
- package/src/plugins/builtin/macro-day/client.ts +24 -0
- package/src/plugins/builtin/macro-day/headless.ts +11 -8
- package/src/plugins/builtin/macro-day/index.tsx +3 -0
- package/src/plugins/builtin/macro-day/model.ts +11 -6
- package/src/plugins/builtin/macro-day/pane.tsx +12 -8
- package/src/plugins/builtin/macro-day/release-table.ts +40 -0
- package/src/plugins/builtin/macro-day/releases.ts +62 -44
- package/src/plugins/builtin/market-heatmap/data.ts +25 -5
- package/src/plugins/builtin/market-heatmap/evidence.ts +90 -0
- package/src/plugins/builtin/market-heatmap/index.tsx +144 -63
- package/src/plugins/builtin/market-heatmap/model.ts +94 -3
- package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
- package/src/plugins/builtin/market-movers/headless.ts +31 -4
- package/src/plugins/builtin/market-movers/index.tsx +8 -1
- package/src/plugins/builtin/market-movers/model.ts +71 -17
- package/src/plugins/builtin/market-movers/table.ts +50 -23
- package/src/plugins/builtin/members/pane.tsx +10 -0
- package/src/plugins/builtin/news/headless.ts +9 -2
- package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
- package/src/plugins/builtin/openfda/client.ts +1 -1
- package/src/plugins/builtin/options/carry.ts +95 -0
- package/src/plugins/builtin/options/index.tsx +58 -5
- package/src/plugins/builtin/options/strike-window.ts +183 -0
- package/src/plugins/builtin/options/table.ts +55 -3
- package/src/plugins/builtin/options/types.ts +8 -1
- package/src/plugins/builtin/options/view.tsx +161 -12
- package/src/plugins/builtin/options-positioning/headless.ts +4 -2
- package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
- package/src/plugins/builtin/options-scenario/client.ts +73 -17
- package/src/plugins/builtin/options-scenario/headless.ts +71 -24
- package/src/plugins/builtin/options-scenario/hedge.ts +284 -0
- package/src/plugins/builtin/options-scenario/index.tsx +9 -2
- package/src/plugins/builtin/options-scenario/model.ts +33 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +40 -16
- package/src/plugins/builtin/pe-band/model.ts +2 -2
- package/src/plugins/builtin/pe-band/report-dates.ts +11 -7
- package/src/plugins/builtin/perps/equity-row.tsx +8 -5
- package/src/plugins/builtin/perps/model.ts +16 -5
- package/src/plugins/builtin/perps/pane.tsx +1 -1
- package/src/plugins/builtin/plugin-marketplace/model.ts +64 -21
- package/src/plugins/builtin/plugin-marketplace/packs.ts +118 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +344 -32
- package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
- package/src/plugins/builtin/plugin-module.ts +87 -4
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +16 -1
- package/src/plugins/builtin/portfolio-list/allocation.ts +3 -0
- package/src/plugins/builtin/portfolio-list/cached-account.ts +18 -9
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +71 -36
- package/src/plugins/builtin/portfolio-list/cli/render.ts +89 -18
- package/src/plugins/builtin/portfolio-list/cli/shared.ts +2 -16
- package/src/plugins/builtin/portfolio-list/headless.ts +40 -7
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +7 -4
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +22 -4
- package/src/plugins/builtin/portfolio-list/summary/live-accounts.ts +11 -1
- package/src/plugins/builtin/realized-vol/headless.ts +3 -0
- package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +2 -2
- package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -1
- package/src/plugins/builtin/research/relative-valuation-model.ts +7 -3
- package/src/plugins/builtin/revenue-breakdown/client.ts +13 -6
- package/src/plugins/builtin/revenue-breakdown/headless.ts +4 -1
- package/src/plugins/builtin/revenue-breakdown/pane.tsx +7 -4
- package/src/plugins/builtin/reverse-dcf/headless.ts +5 -1
- package/src/plugins/builtin/reverse-dcf/model.ts +2 -1
- package/src/plugins/builtin/reverse-dcf/pane.tsx +1 -1
- package/src/plugins/builtin/risk-factors/data.ts +23 -9
- package/src/plugins/builtin/risk-factors/headless.ts +5 -2
- package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
- package/src/plugins/builtin/seasonality/pane.tsx +1 -1
- package/src/plugins/builtin/sec/index.tsx +5 -5
- package/src/plugins/builtin/sectors/client.ts +10 -2
- package/src/plugins/builtin/sectors/headless.ts +35 -6
- package/src/plugins/builtin/sectors/index.tsx +18 -1
- package/src/plugins/builtin/sectors/sector-model.ts +150 -41
- package/src/plugins/builtin/shared/command-tab.ts +51 -0
- package/src/plugins/builtin/shared/headless-market-data.ts +33 -1
- package/src/plugins/builtin/shared/members-menu.tsx +260 -0
- package/src/plugins/builtin/shared/report-freshness.ts +50 -2
- package/src/plugins/builtin/shared/ticker-request.ts +25 -1
- package/src/plugins/builtin/shared/use-quote-board.ts +25 -5
- package/src/plugins/builtin/shared/volatility/options.ts +1 -46
- package/src/plugins/builtin/short-interest/index.tsx +19 -4
- package/src/plugins/builtin/short-interest/surface.tsx +4 -4
- package/src/plugins/builtin/short-volume/index.tsx +1 -10
- package/src/plugins/builtin/short-volume/pane.tsx +1 -1
- package/src/plugins/builtin/social-mentions/pane.tsx +1 -1
- package/src/plugins/builtin/supply-chain/model.ts +1 -1
- package/src/plugins/builtin/themes/pane.tsx +3 -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 +63 -25
- package/src/plugins/builtin/ticker-detail/overview/model.ts +9 -4
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +3 -2
- package/src/plugins/builtin/ticker-detail/pane.tsx +4 -5
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +94 -6
- package/src/plugins/builtin/treasury-auctions/cache.ts +5 -2
- package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
- package/src/plugins/builtin/treasury-auctions/headless.ts +40 -4
- package/src/plugins/builtin/treasury-auctions/index.tsx +11 -9
- package/src/plugins/builtin/treasury-auctions/model.ts +197 -30
- package/src/plugins/builtin/treasury-auctions/pane.tsx +35 -11
- package/src/plugins/builtin/treasury-auctions/types.ts +11 -1
- package/src/plugins/builtin/vol-surface/charts.tsx +1 -3
- package/src/plugins/builtin/vol-surface/client.ts +6 -2
- package/src/plugins/builtin/vol-surface/evidence.ts +11 -6
- package/src/plugins/builtin/vol-surface/headless.ts +124 -20
- package/src/plugins/builtin/vol-surface/model.ts +23 -11
- package/src/plugins/builtin/vol-surface/pane.tsx +38 -27
- package/src/plugins/builtin/vol-surface/tables.ts +124 -0
- package/src/plugins/builtin/world-indices/client.ts +22 -4
- package/src/plugins/builtin/world-indices/headless.ts +54 -27
- package/src/plugins/builtin/world-indices/model.ts +4 -2
- package/src/plugins/builtin/world-indices/table.tsx +13 -2
- package/src/plugins/builtin/world-venue-map/basemap-layer.tsx +2 -0
- package/src/plugins/builtin/world-venue-map/basemap.ts +18 -0
- package/src/plugins/builtin/world-venue-map/country-labels.ts +78 -0
- package/src/plugins/builtin/world-venue-map/geo-series.ts +1 -1
- package/src/plugins/builtin/world-venue-map/geo-svg.tsx +2 -1
- package/src/plugins/builtin/world-venue-map/index.ts +6 -6
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +27 -14
- package/src/plugins/builtin/world-venue-map/layers.ts +68 -10
- package/src/plugins/builtin/world-venue-map/map.tsx +198 -62
- package/src/plugins/builtin/world-venue-map/model.ts +16 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/index.chunk.ts +3 -0
- package/src/plugins/builtin/world-venue-map/natural-earth/labels.chunk.ts +244 -0
- package/src/plugins/builtin/world-venue-map/pane.tsx +16 -10
- package/src/plugins/builtin/yield-curve/index.tsx +1 -1
- package/src/plugins/builtin-editorial.ts +126 -0
- package/src/plugins/catalog-backend.ts +16 -9
- package/src/plugins/catalog-browser.ts +127 -63
- package/src/plugins/catalog-manifest.ts +73 -40
- package/src/plugins/catalog-ui.ts +26 -6
- package/src/plugins/extracted-plugins.ts +7 -1
- package/src/plugins/ownership.ts +150 -7
- package/src/plugins/plugin-functions.ts +54 -0
- package/src/plugins/plugin-off.ts +36 -0
- package/src/plugins/registry/host-actions.ts +16 -0
- package/src/plugins/registry/index.ts +84 -24
- package/src/plugins/registry/plugin-state.ts +25 -1
- package/src/plugins/runtime/context.tsx +29 -0
- package/src/react/input.ts +48 -1
- package/src/remote/app-host.tsx +5 -0
- package/src/remote/controller.ts +3 -53
- package/src/remote/matching.ts +69 -0
- package/src/remote/schema.ts +1 -1
- package/src/remote/semantic-tree.tsx +14 -0
- package/src/remote/types.ts +2 -0
- package/src/renderers/browser/app-services.ts +3 -1
- package/src/renderers/dom/data-table/dom.ts +31 -0
- package/src/renderers/dom/data-table/index.tsx +5 -0
- package/src/renderers/dom/desktop/icons.tsx +14 -0
- package/src/renderers/dom/desktop/query-bar.tsx +59 -32
- package/src/renderers/dom/host/box.tsx +113 -17
- package/src/renderers/dom/host/drag-shield.ts +35 -0
- package/src/renderers/dom/host/live-frame.ts +62 -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/input-host.tsx +6 -1
- package/src/renderers/dom/styles.css +26 -5
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +7 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +7 -1
- package/src/renderers/electrobun/bun/desktop/detached-windows.ts +12 -1
- package/src/renderers/electrobun/bun/desktop/initialization.ts +15 -1
- package/src/renderers/electrobun/shared/protocol.ts +12 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +4 -1
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +101 -5
- 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/main.tsx +4 -1
- package/src/renderers/electrobun/view/remote/persistence.ts +15 -2
- package/src/renderers/electrobun/view/ui-host.tsx +2 -5
- package/src/renderers/opentui/input-host.tsx +6 -1
- package/src/renderers/opentui/start.tsx +9 -0
- package/src/renderers/opentui/ui-host.tsx +7 -1
- package/src/shares/portable-layout.ts +16 -6
- package/src/sources/gloomberb-cloud/index.ts +19 -10
- package/src/sources/gloomberb-cloud/normalizers.ts +20 -21
- package/src/sources/listing-symbols.ts +11 -5
- package/src/sources/provider-errors.ts +88 -3
- package/src/sources/provider-router/batches.ts +3 -3
- package/src/sources/provider-router/cached-routes.ts +8 -4
- package/src/sources/provider-router/financial-routes.ts +13 -7
- package/src/sources/provider-router/financials.ts +106 -16
- package/src/sources/provider-router/history.ts +27 -11
- package/src/sources/provider-router/index.ts +1 -1
- package/src/sources/provider-router/primary.ts +24 -6
- package/src/sources/sec-edgar.ts +68 -8
- package/src/state/pane-scroll-registry.tsx +67 -35
- package/src/sync/core-contributors.ts +4 -3
- package/src/test-support/cli-context.ts +2 -1
- package/src/test-support/data-provider.ts +34 -0
- package/src/test-support/margin-account.ts +108 -0
- package/src/test-support/shell-pane-keys.tsx +1 -0
- package/src/theme/series-colors.ts +46 -0
- package/src/theme/themes.ts +149 -0
- package/src/tickers/search/index.ts +22 -2
- package/src/tickers/search/ranking.ts +45 -1
- package/src/tickers/search/types.ts +3 -1
- package/src/time-series/resolution.ts +15 -0
- package/src/time-series/resolve.ts +1 -14
- package/src/types/config.ts +61 -1
- package/src/types/financials.ts +32 -3
- package/src/types/headless.ts +11 -0
- package/src/types/instrument.ts +8 -0
- package/src/types/plugin.ts +49 -3
- package/src/ui/host.tsx +16 -0
- package/src/ui/index.tsx +10 -3
- package/src/ui/scroll-box-axis.ts +26 -0
- package/src/utils/cli-output.ts +14 -1
- package/src/utils/currency-units.ts +8 -3
- package/src/utils/depositary-receipt.ts +54 -10
- package/src/utils/display-number.ts +63 -0
- package/src/utils/exchanges.ts +13 -0
- package/src/utils/format.ts +2 -1
- package/src/utils/fundamentals.ts +17 -1
- package/src/utils/fx-market-hours.ts +34 -0
- package/src/utils/option-expiry.ts +126 -0
- package/src/utils/price-history-integrity.ts +19 -6
- package/src/utils/price-history.ts +39 -6
- package/src/utils/rpc-timeout-error.ts +6 -2
- package/src/utils/sec-eps-basis.ts +159 -30
- package/src/utils/sec.ts +38 -34
- package/src/utils/throttled-fetch.ts +51 -22
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { notATickerSymbol } from "../sources/provider-errors";
|
|
2
|
+
|
|
3
|
+
// "Not a ticker: APPLE." as the router words it; the symbol ends at the sentence's own period.
|
|
4
|
+
const NOT_A_TICKER_SENTENCE = /Not a ticker: ((?:(?!\.\s)[^\n`\x1b])+?)\.(?=\s|\x1b|$)(?! Try `gloomberb search)/g;
|
|
5
|
+
|
|
6
|
+
/** The symbol as the user typed it on the command line (`Apple`), not as the router saw it (`APPLE`). */
|
|
7
|
+
function typedSymbol(symbol: string, args: readonly string[]): string {
|
|
8
|
+
const wanted = symbol.toUpperCase();
|
|
9
|
+
for (const arg of args) {
|
|
10
|
+
for (const part of arg.split(",")) {
|
|
11
|
+
const typed = part.trim().replace(/^\$/, "");
|
|
12
|
+
if (typed.toUpperCase() === wanted) return typed;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return symbol;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** "Try `gloomberb search Apple`." naming what the user typed; a venue (`Apple:NYSE`) is not part of a search. */
|
|
19
|
+
function searchHint(typed: string): string {
|
|
20
|
+
const query = typed.split(":")[0]!.trim() || typed;
|
|
21
|
+
return `Try \`gloomberb search ${/\s/.test(query) ? JSON.stringify(query) : query}\`.`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Adds the search hint after each "Not a ticker: APPLE." in text meant for a person. The router
|
|
26
|
+
* only knows the symbol upper-cased, so the hint reads the user's own spelling from `args`.
|
|
27
|
+
*/
|
|
28
|
+
export function withSearchHints(text: string, args: readonly string[]): string {
|
|
29
|
+
return text.includes("Not a ticker: ")
|
|
30
|
+
? text.replace(NOT_A_TICKER_SENTENCE, (sentence, symbol: string) => `${sentence} ${searchHint(typedSymbol(symbol, args))}`)
|
|
31
|
+
: text;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Whether an error message says the symbol is not a ticker. */
|
|
35
|
+
export function isNotATickerMessage(message: string | null | undefined): boolean {
|
|
36
|
+
return message != null && notATickerSymbol(message) !== null;
|
|
37
|
+
}
|
package/src/cli/options.ts
CHANGED
|
@@ -5,6 +5,10 @@ export interface CliGlobalOptions {
|
|
|
5
5
|
quiet: boolean;
|
|
6
6
|
color: boolean | null;
|
|
7
7
|
limit?: number;
|
|
8
|
+
/** `--tail <n>`: the newest n rows of a dated series, in their printed order. Never set with `limit`. */
|
|
9
|
+
tail?: number;
|
|
10
|
+
/** `--width <n>`: fit tables to n columns. Unset, a terminal's own width fits them and piped output is not fitted. */
|
|
11
|
+
width?: number;
|
|
8
12
|
refresh: boolean;
|
|
9
13
|
dryRun: boolean;
|
|
10
14
|
yes: boolean;
|
|
@@ -15,6 +19,8 @@ export interface ParsedCliArgs {
|
|
|
15
19
|
options: CliGlobalOptions;
|
|
16
20
|
/** `--help` or `-h` appeared before `--`. The flag is removed from args. */
|
|
17
21
|
help: boolean;
|
|
22
|
+
/** Index in `args` where the arguments after a bare `--` begin; they are never options. */
|
|
23
|
+
literalStart: number;
|
|
18
24
|
}
|
|
19
25
|
|
|
20
26
|
export function isCliHelpFlag(arg: string): boolean {
|
|
@@ -30,23 +36,49 @@ export const DEFAULT_CLI_OPTIONS: CliGlobalOptions = {
|
|
|
30
36
|
yes: false,
|
|
31
37
|
};
|
|
32
38
|
|
|
33
|
-
function
|
|
34
|
-
if (!value) throw new Error(
|
|
39
|
+
function parseRowCount(flag: "--limit" | "--tail", value: string | undefined): number {
|
|
40
|
+
if (!value) throw new Error(`Missing value for ${flag}.`);
|
|
35
41
|
const parsed = Number(value);
|
|
36
42
|
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
37
|
-
throw new Error(
|
|
43
|
+
throw new Error(`${flag} must be a positive integer.`);
|
|
38
44
|
}
|
|
39
45
|
return parsed;
|
|
40
46
|
}
|
|
41
47
|
|
|
48
|
+
/** Commands whose own `--width` is a size in pixels, so it is not the table width. */
|
|
49
|
+
const PIXEL_WIDTH_COMMANDS = new Set(["shot", "screenshot"]);
|
|
50
|
+
const MIN_TABLE_WIDTH = 20;
|
|
51
|
+
|
|
52
|
+
function parseColumnCount(value: string | undefined): number {
|
|
53
|
+
const parsed = Number(value);
|
|
54
|
+
if (!value || !Number.isInteger(parsed) || parsed < MIN_TABLE_WIDTH) {
|
|
55
|
+
throw new Error(`--width must be a whole number of columns, ${MIN_TABLE_WIDTH} or more, such as --width 80.`);
|
|
56
|
+
}
|
|
57
|
+
return parsed;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** The first word that is not an option or the value of one: the command the arguments are for. */
|
|
61
|
+
function commandWord(rawArgs: readonly string[]): string | undefined {
|
|
62
|
+
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
63
|
+
const arg = rawArgs[index]!;
|
|
64
|
+
if (arg === "--") return rawArgs[index + 1];
|
|
65
|
+
if (arg === "--limit" || arg === "--tail" || arg === "--width") index += 1;
|
|
66
|
+
else if (!arg.startsWith("-")) return arg;
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
42
71
|
export function parseCliGlobalArgs(rawArgs: string[]): ParsedCliArgs {
|
|
43
72
|
const options: CliGlobalOptions = { ...DEFAULT_CLI_OPTIONS };
|
|
44
73
|
const args: string[] = [];
|
|
45
74
|
let help = false;
|
|
75
|
+
let literalStart: number | null = null;
|
|
76
|
+
const ownsWidth = PIXEL_WIDTH_COMMANDS.has(commandWord(rawArgs)?.toLowerCase() ?? "");
|
|
46
77
|
|
|
47
78
|
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
48
79
|
const arg = rawArgs[index]!;
|
|
49
80
|
if (arg === "--") {
|
|
81
|
+
literalStart = args.length;
|
|
50
82
|
args.push(...rawArgs.slice(index + 1));
|
|
51
83
|
break;
|
|
52
84
|
}
|
|
@@ -90,17 +122,33 @@ export function parseCliGlobalArgs(rawArgs: string[]): ParsedCliArgs {
|
|
|
90
122
|
options.yes = true;
|
|
91
123
|
continue;
|
|
92
124
|
}
|
|
93
|
-
if (arg === "--
|
|
125
|
+
if (!ownsWidth && arg === "--width") {
|
|
94
126
|
index += 1;
|
|
95
|
-
options.
|
|
127
|
+
options.width = parseColumnCount(rawArgs[index]);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (!ownsWidth && arg.startsWith("--width=")) {
|
|
131
|
+
options.width = parseColumnCount(arg.slice("--width=".length));
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (arg === "--limit" || arg === "--tail") {
|
|
135
|
+
index += 1;
|
|
136
|
+
options[arg === "--limit" ? "limit" : "tail"] = parseRowCount(arg, rawArgs[index]);
|
|
96
137
|
continue;
|
|
97
138
|
}
|
|
98
139
|
if (arg.startsWith("--limit=")) {
|
|
99
|
-
options.limit =
|
|
140
|
+
options.limit = parseRowCount("--limit", arg.slice("--limit=".length));
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (arg.startsWith("--tail=")) {
|
|
144
|
+
options.tail = parseRowCount("--tail", arg.slice("--tail=".length));
|
|
100
145
|
continue;
|
|
101
146
|
}
|
|
102
147
|
args.push(arg);
|
|
103
148
|
}
|
|
149
|
+
if (options.limit != null && options.tail != null) {
|
|
150
|
+
throw new Error("Use --limit or --tail, not both: --limit keeps the first rows, --tail the newest.");
|
|
151
|
+
}
|
|
104
152
|
|
|
105
|
-
return { args, options, help };
|
|
153
|
+
return { args, options, help, literalStart: literalStart ?? args.length };
|
|
106
154
|
}
|
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
export type PaneFunctionReadiness = "ready" | "partial" | "live-dom" | "unsupported";
|
|
10
10
|
type PaneFunctionScreenshotReadiness = PaneFunctionReadiness;
|
|
11
11
|
type PaneFunctionTickerCardinality = "none" | "one" | "one-or-more" | "two-or-more" | "one-or-two";
|
|
12
|
+
/** A headless option, or a rendered view's, which may name its value, show an example and check what is typed. */
|
|
12
13
|
export type PaneFunctionOptionDef = HeadlessPaneOptionDef;
|
|
13
14
|
export type NormalizedPaneFunctionOptions = Record<string, string | number | boolean>;
|
|
14
15
|
|
|
@@ -64,7 +65,7 @@ function fallbackCapability(
|
|
|
64
65
|
limitations: [dataPane
|
|
65
66
|
? RENDERED_VIEW_LIMITATION
|
|
66
67
|
: "This pane is an interactive surface and does not expose a data report."],
|
|
67
|
-
options: [],
|
|
68
|
+
options: [...(pane.reportOptions ?? [])],
|
|
68
69
|
};
|
|
69
70
|
}
|
|
70
71
|
|
|
@@ -134,6 +135,11 @@ function resolveOptionDef(
|
|
|
134
135
|
));
|
|
135
136
|
}
|
|
136
137
|
|
|
138
|
+
/** Whether the function has an option of its own under this name or an alias. */
|
|
139
|
+
export function capabilityHasOption(capability: PaneFunctionCapability, key: string): boolean {
|
|
140
|
+
return resolveOptionDef(capability, key) !== undefined;
|
|
141
|
+
}
|
|
142
|
+
|
|
137
143
|
function normalizeEnumValue(option: PaneFunctionOptionDef, rawValue: string): string {
|
|
138
144
|
const token = optionToken(rawValue);
|
|
139
145
|
const match = option.values?.find((candidate) => (
|
|
@@ -154,6 +160,7 @@ function normalizeOptionValue(option: PaneFunctionOptionDef, rawValue: string |
|
|
|
154
160
|
throw new Error(`Invalid --${option.key} value "${rawValue}". Use true or false.`);
|
|
155
161
|
}
|
|
156
162
|
if (rawValue === true) throw new Error(`--${option.key} requires a value.`);
|
|
163
|
+
if (option.normalize) return option.normalize(rawValue);
|
|
157
164
|
if (option.type === "enum") return normalizeEnumValue(option, rawValue);
|
|
158
165
|
if (option.type === "integer") {
|
|
159
166
|
const value = Number(rawValue);
|
|
@@ -175,7 +182,11 @@ export function normalizeCapabilityOptions(
|
|
|
175
182
|
settings: { strict?: boolean } = {},
|
|
176
183
|
): NormalizedPaneFunctionOptions {
|
|
177
184
|
if (!capability.botSafe) {
|
|
178
|
-
|
|
185
|
+
// A rendered view takes any pane setting; the options it declares are checked.
|
|
186
|
+
return Object.fromEntries(Object.entries(options).map(([key, value]) => {
|
|
187
|
+
const option = resolveOptionDef(capability, key);
|
|
188
|
+
return option ? [option.key, normalizeOptionValue(option, value)] : [key, value];
|
|
189
|
+
}));
|
|
179
190
|
}
|
|
180
191
|
|
|
181
192
|
const normalized: Record<string, string | number | boolean> = {};
|
|
@@ -259,6 +259,11 @@ function paneCatalogSearchScore(entry: PaneCatalogEntry, query: string): number
|
|
|
259
259
|
].filter((value): value is string => !!value).join(" ").toLowerCase();
|
|
260
260
|
|
|
261
261
|
let score = searchable.includes(query.toLowerCase()) ? 12 : 0;
|
|
262
|
+
// A query that is one of the function's own keywords ("hedge" for OSA) beats one found inside a
|
|
263
|
+
// longer keyword ("hedge funds" for 13F).
|
|
264
|
+
const keywords = [entry.label, ...entry.keywords, ...entry.capability.aliases]
|
|
265
|
+
.filter((value): value is string => !!value).map((value) => value.toLowerCase().replace(/\s+/g, " "));
|
|
266
|
+
if (keywords.includes(terms.join(" "))) score += 4;
|
|
262
267
|
let matchedTerms = 0;
|
|
263
268
|
for (const term of terms) {
|
|
264
269
|
const normalized = normalizeLookupToken(term);
|
|
@@ -320,7 +325,8 @@ function optionChoices(option: PaneFunctionOptionDef): string[] {
|
|
|
320
325
|
|
|
321
326
|
function optionFlags(option: PaneFunctionOptionDef): string {
|
|
322
327
|
const choices = optionChoices(option).join("|");
|
|
323
|
-
|
|
328
|
+
const value = choices && choices.length <= MAX_INLINE_CHOICES ? choices : option.values?.length ? "value" : option.placeholder ?? option.type;
|
|
329
|
+
return `--${option.key} <${value}>`;
|
|
324
330
|
}
|
|
325
331
|
|
|
326
332
|
function optionDescription(option: PaneFunctionOptionDef): string {
|
|
@@ -365,7 +371,12 @@ function renderCatalogEntry(entry: PaneCatalogEntry): string {
|
|
|
365
371
|
}
|
|
366
372
|
|
|
367
373
|
lines.push("", renderSection("Examples"));
|
|
368
|
-
if (capability.reportReadiness !== "unsupported")
|
|
374
|
+
if (capability.reportReadiness !== "unsupported") {
|
|
375
|
+
lines.push(...wrapCommandLine(`gloomberb fn ${invocation}`, width));
|
|
376
|
+
for (const option of capability.options) {
|
|
377
|
+
if (option.example) lines.push(...wrapCommandLine(`gloomberb fn ${invocation} ${option.example}`, width));
|
|
378
|
+
}
|
|
379
|
+
}
|
|
369
380
|
lines.push(...wrapCommandLine(`gloomberb shot ${invocation} --output ${entry.token.toLowerCase()}.png`, width));
|
|
370
381
|
return lines.join("\n");
|
|
371
382
|
}
|
|
@@ -9,6 +9,7 @@ import { cleanTickerInput } from "./options";
|
|
|
9
9
|
import { parsePublicTickerKey, publicTickerKey } from "../../utils/exchanges";
|
|
10
10
|
import type { ResolvedPaneFunction } from "./resolver";
|
|
11
11
|
import { toMarketDataContext } from "../../market-data/selectors";
|
|
12
|
+
import { quoteMetadataFromQuote } from "../../market-data/quotes/metadata";
|
|
12
13
|
import { loadSeasonalityHistory, SEASONALITY_HISTORY_RESOLUTION } from "../../plugins/builtin/seasonality/client";
|
|
13
14
|
import type { InstrumentRef } from "../../market-data/request-types";
|
|
14
15
|
import { CORRELATION_HISTORY_RESOLUTION, loadCorrelationHistory } from "../../plugins/builtin/correlation/history";
|
|
@@ -22,6 +23,26 @@ const SHOT_PRICE_HISTORY_RANGE = "5Y" as const;
|
|
|
22
23
|
const FINANCIAL_ANALYSIS_PANE_ID = "financial-analysis";
|
|
23
24
|
const FINANCIAL_ANALYSIS_TEMPLATE_ID = "financial-analysis-pane";
|
|
24
25
|
|
|
26
|
+
async function loadStoredShotTicker(context: MarketContext, symbol: string): Promise<TickerRecord | null> {
|
|
27
|
+
const normalized = cleanTickerInput(symbol);
|
|
28
|
+
const { symbol: bare } = parsePublicTickerKey(normalized);
|
|
29
|
+
return await context.store.loadTicker(normalized)
|
|
30
|
+
?? (bare !== normalized ? await context.store.loadTicker(bare) : null);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* A holding the pane can value without a quote: some position carries the
|
|
35
|
+
* broker's own mark or market value. An option contract no quote covers stays
|
|
36
|
+
* at that mark in the pane, so a failed quote lookup for it is not an error.
|
|
37
|
+
*/
|
|
38
|
+
export async function loadBrokerMarkedHolding(context: MarketContext, symbol: string): Promise<TickerRecord | null> {
|
|
39
|
+
const ticker = await loadStoredShotTicker(context, symbol);
|
|
40
|
+
const marked = ticker?.metadata.positions.some(({ shares, markPrice, marketValue }) => (
|
|
41
|
+
shares !== 0 && (Number.isFinite(markPrice) || Number.isFinite(marketValue))
|
|
42
|
+
));
|
|
43
|
+
return marked ? ticker : null;
|
|
44
|
+
}
|
|
45
|
+
|
|
25
46
|
export async function fetchTickerFinancials(
|
|
26
47
|
context: MarketContext,
|
|
27
48
|
symbol: string,
|
|
@@ -32,8 +53,7 @@ export async function fetchTickerFinancials(
|
|
|
32
53
|
}> {
|
|
33
54
|
const normalized = cleanTickerInput(symbol);
|
|
34
55
|
const instrument = parsePublicTickerKey(normalized);
|
|
35
|
-
const tickerFile = await context
|
|
36
|
-
?? (instrument.symbol !== normalized ? await context.store.loadTicker(instrument.symbol) : null);
|
|
56
|
+
const tickerFile = await loadStoredShotTicker(context, symbol);
|
|
37
57
|
const exchange = instrument.exchange ?? tickerFile?.metadata.exchange ?? "";
|
|
38
58
|
const financials = await context.dataProvider.getTickerFinancials(instrument.symbol, exchange);
|
|
39
59
|
return { tickerFile, financials, instrument: { symbol: instrument.symbol, ...(exchange ? { exchange } : {}) } };
|
|
@@ -142,14 +162,25 @@ export function isFinancialAnalysisFunction(resolved: ResolvedPaneFunction): boo
|
|
|
142
162
|
&& resolved.instance.settings?.lockedTabId === "financials";
|
|
143
163
|
}
|
|
144
164
|
|
|
145
|
-
|
|
165
|
+
/**
|
|
166
|
+
* The ticker a shot shows for a symbol that is not saved. Without a usable
|
|
167
|
+
* quote (a thin US listing after the close), the listing comes from the quote
|
|
168
|
+
* metadata kept when the quote was dropped, or else from asking the source
|
|
169
|
+
* for it, so the pane still knows a US stock from a listing abroad. What no
|
|
170
|
+
* source knows stays empty rather than guessed from the base currency.
|
|
171
|
+
*/
|
|
172
|
+
export async function createFallbackTicker(symbol: string, financials: TickerFinancials | null, context: MarketContext): Promise<TickerRecord> {
|
|
146
173
|
const instrument = parsePublicTickerKey(symbol);
|
|
147
174
|
const quote = financials?.quote;
|
|
175
|
+
const known = quote ? quoteMetadataFromQuote(quote) : financials?.quoteMetadata;
|
|
176
|
+
const listing = instrument.exchange || known?.listingExchangeName
|
|
177
|
+
? known
|
|
178
|
+
: await context.dataProvider.getQuoteMetadata?.(instrument.symbol, "").catch(() => null) ?? known;
|
|
148
179
|
return {
|
|
149
180
|
metadata: {
|
|
150
181
|
ticker: instrument.symbol,
|
|
151
|
-
exchange: instrument.exchange ??
|
|
152
|
-
currency:
|
|
182
|
+
exchange: instrument.exchange ?? listing?.listingExchangeName ?? "",
|
|
183
|
+
currency: listing?.currency ?? "",
|
|
153
184
|
name: quote?.name ?? instrument.symbol,
|
|
154
185
|
portfolios: [],
|
|
155
186
|
watchlists: [],
|
|
@@ -7,6 +7,8 @@ import type { ResolvedPaneFunction } from "./resolver";
|
|
|
7
7
|
import { collectShotSymbols } from "./data";
|
|
8
8
|
import { renderDesktopShot, type PaneScreenshotResult } from "./screenshot";
|
|
9
9
|
import { deriveRenderedFreshness, formatFreshnessLine, type ReportFreshness } from "./freshness";
|
|
10
|
+
import { exportTextTable, reportFooterLines, type CliReportTables } from "../report-tables";
|
|
11
|
+
import { renderedReportFreshness, renderedReportNotices, renderedReportObservations } from "./report-notices";
|
|
10
12
|
|
|
11
13
|
const DOM_REPORT_WIDTH = 1280;
|
|
12
14
|
const DOM_REPORT_HEIGHT = 720;
|
|
@@ -17,12 +19,6 @@ function rowsContainEllipsis(rows: DesktopPaneShotRenderedRow[]): boolean {
|
|
|
17
19
|
return rows.some((row) => row.cells.some((cell) => /\u2026|\.\.\./.test(cell.text)));
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
function isDomReportTruncated(
|
|
21
|
-
render: Pick<PaneScreenshotResult["render"], "rows" | "truncated">,
|
|
22
|
-
): boolean {
|
|
23
|
-
return render.truncated || rowsContainEllipsis(render.rows);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
22
|
/** Column identity per cell; a repeated label within one row stays distinct. */
|
|
27
23
|
function domCellKeys(row: DesktopPaneShotRenderedRow): string[] {
|
|
28
24
|
const seen = new Map<string, number>();
|
|
@@ -42,7 +38,13 @@ function cellText(cell: DesktopPaneShotRenderedRow["cells"][number]): string {
|
|
|
42
38
|
return cell.instant ? formatUtcTime(cell.instant) || cell.text : cell.text;
|
|
43
39
|
}
|
|
44
40
|
|
|
45
|
-
|
|
41
|
+
interface DomTable {
|
|
42
|
+
tableIndex: number;
|
|
43
|
+
columns: Array<{ key: string; header: string }>;
|
|
44
|
+
rows: Array<Map<string, DesktopPaneShotRenderedRow["cells"][number]>>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function domTables(rows: DesktopPaneShotRenderedRow[]): DomTable[] {
|
|
46
48
|
const byTable = new Map<number, DesktopPaneShotRenderedRow[]>();
|
|
47
49
|
for (const row of rows) {
|
|
48
50
|
const tableRows = byTable.get(row.tableIndex) ?? [];
|
|
@@ -50,7 +52,7 @@ function renderDomTables(rows: DesktopPaneShotRenderedRow[]): string[] {
|
|
|
50
52
|
byTable.set(row.tableIndex, tableRows);
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
return [...byTable.entries()].
|
|
55
|
+
return [...byTable.entries()].map(([tableIndex, tableRows]) => {
|
|
54
56
|
// Captured rows omit blank cells, so a cell's position is not its column.
|
|
55
57
|
const columns: Array<{ key: string; header: string }> = [];
|
|
56
58
|
for (const row of tableRows) {
|
|
@@ -66,22 +68,55 @@ function renderDomTables(rows: DesktopPaneShotRenderedRow[]): string[] {
|
|
|
66
68
|
previous = position;
|
|
67
69
|
}
|
|
68
70
|
}
|
|
69
|
-
|
|
71
|
+
return {
|
|
72
|
+
tableIndex,
|
|
70
73
|
columns,
|
|
71
|
-
tableRows.map((row) => {
|
|
74
|
+
rows: tableRows.map((row) => {
|
|
72
75
|
const keys = domCellKeys(row);
|
|
73
|
-
|
|
74
|
-
return columns.map((column) => textByKey.get(column.key) ?? "");
|
|
76
|
+
return new Map(row.cells.map((cell, cellIndex) => [keys[cellIndex]!, cell]));
|
|
75
77
|
}),
|
|
76
|
-
|
|
77
|
-
return [
|
|
78
|
-
...(index > 0 ? [""] : []),
|
|
79
|
-
...(byTable.size > 1 ? [renderSection(`Rendered table ${tableIndex + 1}`)] : []),
|
|
80
|
-
output,
|
|
81
|
-
];
|
|
78
|
+
};
|
|
82
79
|
});
|
|
83
80
|
}
|
|
84
81
|
|
|
82
|
+
function domTableTitle(table: DomTable): string {
|
|
83
|
+
return `Rendered table ${table.tableIndex + 1}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function renderDomTables(rows: DesktopPaneShotRenderedRow[]): string[] {
|
|
87
|
+
const tables = domTables(rows);
|
|
88
|
+
return tables.flatMap((table, index) => [
|
|
89
|
+
...(index > 0 ? [""] : []),
|
|
90
|
+
...(tables.length > 1 ? [renderSection(domTableTitle(table))] : []),
|
|
91
|
+
renderTable(
|
|
92
|
+
table.columns,
|
|
93
|
+
table.rows.map((cells) => table.columns.map((column) => {
|
|
94
|
+
const cell = cells.get(column.key);
|
|
95
|
+
return cell ? cellText(cell) : "";
|
|
96
|
+
})),
|
|
97
|
+
),
|
|
98
|
+
]);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** The rendered tables as `--csv` writes them, with the instant behind a shortened time. */
|
|
102
|
+
function domReportTables(
|
|
103
|
+
rows: DesktopPaneShotRenderedRow[],
|
|
104
|
+
title: string,
|
|
105
|
+
freshness: ReportFreshness,
|
|
106
|
+
incomplete: boolean | string,
|
|
107
|
+
notices: readonly string[],
|
|
108
|
+
): CliReportTables {
|
|
109
|
+
const tables = domTables(rows);
|
|
110
|
+
return {
|
|
111
|
+
tables: tables.map((table) => exportTextTable(
|
|
112
|
+
tables.length > 1 ? domTableTitle(table) : title,
|
|
113
|
+
table.columns.map((column) => column.header),
|
|
114
|
+
table.rows.map((cells) => table.columns.map((column) => cells.get(column.key))),
|
|
115
|
+
)),
|
|
116
|
+
footer: reportFooterLines({ freshness, incomplete, notes: notices }),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
85
120
|
function renderedFailureReason(
|
|
86
121
|
result: PaneScreenshotResult,
|
|
87
122
|
rows: DesktopPaneShotRenderedRow[],
|
|
@@ -99,8 +134,10 @@ function renderedFailureReason(
|
|
|
99
134
|
return null;
|
|
100
135
|
}
|
|
101
136
|
|
|
137
|
+
/** The rows a report reads: every row of a table that publishes them all, else what the viewport shows. */
|
|
102
138
|
function reportRows(result: PaneScreenshotResult): DesktopPaneShotRenderedRow[] {
|
|
103
|
-
|
|
139
|
+
const rows = result.render.reportRows ?? result.render.rows;
|
|
140
|
+
if (rows.length > 0) return rows;
|
|
104
141
|
if (
|
|
105
142
|
result.render.loadingStateDetected
|
|
106
143
|
|| result.render.errorStateDetected
|
|
@@ -122,15 +159,20 @@ export function buildDomPaneReportFromRender(
|
|
|
122
159
|
result: PaneScreenshotResult,
|
|
123
160
|
): PaneFunctionReport {
|
|
124
161
|
const rows = reportRows(result);
|
|
125
|
-
const hasStructuredRows = result.render.rows.length > 0;
|
|
126
|
-
|
|
127
|
-
const truncationReasons = [...result.render.truncationReasons];
|
|
162
|
+
const hasStructuredRows = (result.render.reportRows ?? result.render.rows).length > 0;
|
|
163
|
+
// A table that reported every row is whole, whatever the viewport cut from the capture.
|
|
164
|
+
const truncationReasons = [...(result.render.reportTruncationReasons ?? result.render.truncationReasons)];
|
|
128
165
|
if (rowsContainEllipsis(rows) && !truncationReasons.includes("one or more cells are visibly clipped")) {
|
|
129
166
|
truncationReasons.push("one or more cells are visibly clipped");
|
|
130
167
|
}
|
|
168
|
+
const truncated = truncationReasons.length > 0
|
|
169
|
+
|| (result.render.reportTruncationReasons ? false : result.render.truncated);
|
|
131
170
|
const failureReason = renderedFailureReason(result, rows);
|
|
132
171
|
const unavailableSymbols = failureReason && result.symbols.length > 0 ? result.symbols : [];
|
|
133
|
-
|
|
172
|
+
// What the view leaves out and how to see more: FXC's other currencies, OMON's strikes outside its window.
|
|
173
|
+
const rendered = renderedReportNotices(result.render.semanticUi ?? []);
|
|
174
|
+
const notices = [...(resolved.pane.reportNotices?.(resolved.instance.settings ?? {}) ?? []), ...rendered.notices];
|
|
175
|
+
const textLines = [resolved.label, "", ...notices, ...(notices.length > 0 ? [""] : [])];
|
|
134
176
|
if (hasStructuredRows) {
|
|
135
177
|
textLines.push(...renderDomTables(rows));
|
|
136
178
|
} else if (result.render.visibleText) {
|
|
@@ -139,11 +181,15 @@ export function buildDomPaneReportFromRender(
|
|
|
139
181
|
textLines.push(failureReason ?? "No rendered values were available.");
|
|
140
182
|
}
|
|
141
183
|
if (failureReason && rows.length > 0) textLines.push("", failureReason);
|
|
142
|
-
|
|
184
|
+
// A pane that knows its feed dates the report; the footer and cell times fill in the rest.
|
|
185
|
+
const declared = { ...resolved.pane.reportFreshness, ...renderedReportFreshness(result.render.semanticUi ?? []) };
|
|
186
|
+
const freshness = deriveRenderedFreshness(declared, {
|
|
143
187
|
footerText: result.render.footerText ?? "",
|
|
144
188
|
cellTimes: rows.flatMap((row) => row.cells.flatMap((cell) => cell.instant ?? [])),
|
|
189
|
+
observed: renderedReportObservations(result.render.semanticUi ?? []),
|
|
145
190
|
});
|
|
146
191
|
|
|
192
|
+
const complete = failureReason === null && !truncated;
|
|
147
193
|
return {
|
|
148
194
|
data: {
|
|
149
195
|
kind: "rendered-view",
|
|
@@ -153,7 +199,7 @@ export function buildDomPaneReportFromRender(
|
|
|
153
199
|
options: resolved.options,
|
|
154
200
|
rowCount: rows.length,
|
|
155
201
|
empty: rows.length === 0,
|
|
156
|
-
complete
|
|
202
|
+
complete,
|
|
157
203
|
unavailableSymbols,
|
|
158
204
|
rows,
|
|
159
205
|
visibleText: result.render.visibleText,
|
|
@@ -161,9 +207,17 @@ export function buildDomPaneReportFromRender(
|
|
|
161
207
|
truncationReasons,
|
|
162
208
|
limitation: DOM_LIMITATION,
|
|
163
209
|
...(failureReason ? { reason: failureReason } : {}),
|
|
210
|
+
...(notices.length > 0 ? { metadata: { ...rendered.facts, notices } } : {}),
|
|
164
211
|
freshness,
|
|
165
212
|
},
|
|
166
213
|
text: textLines.join("\n").trimEnd(),
|
|
214
|
+
tables: domReportTables(
|
|
215
|
+
rows,
|
|
216
|
+
resolved.label,
|
|
217
|
+
freshness,
|
|
218
|
+
!complete && (failureReason ?? (truncationReasons.length > 0 ? truncationReasons.join("; ") : true)),
|
|
219
|
+
notices,
|
|
220
|
+
),
|
|
167
221
|
};
|
|
168
222
|
}
|
|
169
223
|
|
|
@@ -173,15 +227,20 @@ export function appendDomReportFooter(
|
|
|
173
227
|
truncated: boolean,
|
|
174
228
|
freshness: ReportFreshness,
|
|
175
229
|
): string {
|
|
176
|
-
const clipping = truncated ? "The rendered view is clipped." : "The rendered view may be clipped.";
|
|
177
230
|
return [
|
|
178
231
|
text,
|
|
179
232
|
"",
|
|
180
|
-
|
|
233
|
+
domReportNote(elapsedMs, truncated),
|
|
181
234
|
cliStyles.muted(formatFreshnessLine(freshness)),
|
|
182
235
|
].join("\n");
|
|
183
236
|
}
|
|
184
237
|
|
|
238
|
+
/** What a rendered-view report says about where its values come from. */
|
|
239
|
+
export function domReportNote(elapsedMs: number, truncated: boolean): string {
|
|
240
|
+
const clipping = truncated ? "The rendered view is clipped." : "The rendered view may be clipped.";
|
|
241
|
+
return `Rendered view: values come from the visible pane. ${clipping} Render time: ${elapsedMs} ms.`;
|
|
242
|
+
}
|
|
243
|
+
|
|
185
244
|
function failedDomReport(
|
|
186
245
|
resolved: ResolvedPaneFunction,
|
|
187
246
|
rawArg: string,
|
|
@@ -193,6 +252,7 @@ function failedDomReport(
|
|
|
193
252
|
.trim();
|
|
194
253
|
const reason = `The rendered view could not be read: ${message || "unknown renderer error"}`;
|
|
195
254
|
const symbols = collectShotSymbols(resolved, rawArg);
|
|
255
|
+
const freshness = deriveRenderedFreshness(resolved.pane.reportFreshness, { footerText: "", cellTimes: [] });
|
|
196
256
|
return {
|
|
197
257
|
data: {
|
|
198
258
|
kind: "rendered-view",
|
|
@@ -210,9 +270,10 @@ function failedDomReport(
|
|
|
210
270
|
truncationReasons: [],
|
|
211
271
|
limitation: DOM_LIMITATION,
|
|
212
272
|
reason,
|
|
213
|
-
freshness
|
|
273
|
+
freshness,
|
|
214
274
|
},
|
|
215
275
|
text: [resolved.label, "", reason].join("\n"),
|
|
276
|
+
tables: { tables: [], footer: reportFooterLines({ freshness, incomplete: reason }) },
|
|
216
277
|
};
|
|
217
278
|
}
|
|
218
279
|
|