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
|
@@ -21,6 +21,7 @@ import type { SignedInBroker } from "./client";
|
|
|
21
21
|
import {
|
|
22
22
|
BrokerSignInController,
|
|
23
23
|
runBrokerSignIn,
|
|
24
|
+
type BrokerSignInOptions,
|
|
24
25
|
type BrokerSignInOutcome,
|
|
25
26
|
type BrokerSignInSnapshot,
|
|
26
27
|
} from "./sign-in";
|
|
@@ -59,9 +60,10 @@ export function useBrokerSignInAttempt(
|
|
|
59
60
|
broker: SignedInBroker,
|
|
60
61
|
write: boolean,
|
|
61
62
|
onOutcome: (outcome: "connected" | "signed-out") => void,
|
|
63
|
+
options: BrokerSignInOptions = {},
|
|
62
64
|
): { snapshot: BrokerSignInSnapshot; restart(): void; finish(): void } {
|
|
63
65
|
const controllerRef = useRef<BrokerSignInController | null>(null);
|
|
64
|
-
if (!controllerRef.current) controllerRef.current = new BrokerSignInController(broker, write);
|
|
66
|
+
if (!controllerRef.current) controllerRef.current = new BrokerSignInController(broker, write, {}, options);
|
|
65
67
|
const controller = controllerRef.current;
|
|
66
68
|
const [snapshot, setSnapshot] = useState(controller.getSnapshot());
|
|
67
69
|
const onOutcomeRef = useRef(onOutcome);
|
|
@@ -110,12 +112,13 @@ function BrokerSignInDialog({
|
|
|
110
112
|
dismiss,
|
|
111
113
|
broker,
|
|
112
114
|
write,
|
|
113
|
-
|
|
115
|
+
renew,
|
|
116
|
+
}: PromptContext<BrokerSignInOutcome> & { broker: SignedInBroker; write: boolean; renew: boolean }) {
|
|
114
117
|
useAppLanguage();
|
|
115
118
|
const { height: termHeight } = useViewport();
|
|
116
119
|
// Close after a beat so "Connected" is visible; enter skips the wait. Signed
|
|
117
120
|
// out closes at once, for the host to sign in to Gloom.
|
|
118
|
-
const { snapshot, restart, finish } = useBrokerSignInAttempt(broker, write, resolve);
|
|
121
|
+
const { snapshot, restart, finish } = useBrokerSignInAttempt(broker, write, resolve, { renew });
|
|
119
122
|
|
|
120
123
|
useDialogKeyboard((event) => {
|
|
121
124
|
event.stopPropagation();
|
|
@@ -170,6 +173,8 @@ export interface BrokerSignInRequest {
|
|
|
170
173
|
broker: SignedInBroker;
|
|
171
174
|
/** Ask for trading as well as reading. Defaults to whether the broker takes orders. */
|
|
172
175
|
write?: boolean;
|
|
176
|
+
/** Sign in again although the broker is connected. */
|
|
177
|
+
renew?: boolean;
|
|
173
178
|
resolve: (connected: boolean) => void;
|
|
174
179
|
}
|
|
175
180
|
|
|
@@ -178,13 +183,17 @@ const requestListeners = new Set<(request: BrokerSignInRequest) => void>();
|
|
|
178
183
|
/**
|
|
179
184
|
* Connects a signed-in broker, signing in to Gloom first when needed.
|
|
180
185
|
* Resolves true once the broker is connected, false when the user cancels or
|
|
181
|
-
* no dialog host is mounted.
|
|
186
|
+
* no dialog host is mounted. A broker that is already connected is done at
|
|
187
|
+
* once unless `renew` asks for a new sign-in.
|
|
182
188
|
*/
|
|
183
|
-
export function requestBrokerSignIn(
|
|
189
|
+
export function requestBrokerSignIn(
|
|
190
|
+
broker: SignedInBroker,
|
|
191
|
+
options: { write?: boolean; renew?: boolean } = {},
|
|
192
|
+
): Promise<boolean> {
|
|
184
193
|
if (requestListeners.size === 0) return Promise.resolve(false);
|
|
185
194
|
return new Promise((resolve) => {
|
|
186
195
|
const write = options.write ?? Boolean(broker.capabilities.orders);
|
|
187
|
-
for (const listener of requestListeners) listener({ broker, write, resolve });
|
|
196
|
+
for (const listener of requestListeners) listener({ broker, write, renew: options.renew, resolve });
|
|
188
197
|
});
|
|
189
198
|
}
|
|
190
199
|
|
|
@@ -203,13 +212,18 @@ export function BrokerSignInDialogHost() {
|
|
|
203
212
|
void runBrokerSignIn(request.broker, request.write, {
|
|
204
213
|
isSignedIn: () => apiClient.isSignedIn(),
|
|
205
214
|
signInToGloom: () => promptGloomSignIn(dialog),
|
|
206
|
-
connectBroker: async (broker, write) => await dialog.prompt<BrokerSignInOutcome>({
|
|
215
|
+
connectBroker: async (broker, write, renew) => await dialog.prompt<BrokerSignInOutcome>({
|
|
207
216
|
size: "full",
|
|
208
217
|
content: (context: unknown) => (
|
|
209
|
-
<BrokerSignInDialog
|
|
218
|
+
<BrokerSignInDialog
|
|
219
|
+
{...(context as PromptContext<BrokerSignInOutcome>)}
|
|
220
|
+
broker={broker}
|
|
221
|
+
write={write}
|
|
222
|
+
renew={renew}
|
|
223
|
+
/>
|
|
210
224
|
),
|
|
211
225
|
}) ?? "cancelled",
|
|
212
|
-
})
|
|
226
|
+
}, { renew: request.renew })
|
|
213
227
|
.then(request.resolve, () => request.resolve(false))
|
|
214
228
|
.finally(() => {
|
|
215
229
|
openRef.current = false;
|
|
@@ -24,9 +24,21 @@ export interface BrokerSignInSnapshot {
|
|
|
24
24
|
error: string | null;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/** What a read of the account's connection tells the flow. */
|
|
28
|
+
export type BrokerConnectionRead = Pick<SignedInBrokerConnection, "status"> & { connectedAt?: string | null };
|
|
29
|
+
|
|
30
|
+
export interface BrokerSignInOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Sign in again although the broker is connected, to start a new sign-in
|
|
33
|
+
* before the broker ends the old one. Without it a connected broker is done
|
|
34
|
+
* at once, as when a device adds a connection the account already holds.
|
|
35
|
+
*/
|
|
36
|
+
renew?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
27
39
|
export interface BrokerSignInIo {
|
|
28
40
|
start(brokerId: string, write: boolean): Promise<{ connectUrl: string; code: string; expiresAt: string }>;
|
|
29
|
-
fetchConnection(brokerId: string): Promise<
|
|
41
|
+
fetchConnection(brokerId: string): Promise<BrokerConnectionRead>;
|
|
30
42
|
now(): number;
|
|
31
43
|
delay(ms: number): Promise<void>;
|
|
32
44
|
}
|
|
@@ -58,10 +70,37 @@ function codeDeadline(expiresAt: string, now: number): number {
|
|
|
58
70
|
return Number.isFinite(parsed) && parsed > now ? parsed : now + DEFAULT_CODE_TTL_MS;
|
|
59
71
|
}
|
|
60
72
|
|
|
73
|
+
function stamp(value: string | null | undefined): number | null {
|
|
74
|
+
const parsed = value ? Date.parse(value) : Number.NaN;
|
|
75
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Whether `now` shows a sign-in made after `before` was read. Renewing a
|
|
80
|
+
* connection takes more than connected: a broker that was connected when the
|
|
81
|
+
* flow began stays connected while the user signs in again, until Gloom stamps
|
|
82
|
+
* the new sign-in. Both reads are Gloom's, so a device clock that runs fast or
|
|
83
|
+
* slow cannot matter.
|
|
84
|
+
*/
|
|
85
|
+
function signedInSince(before: BrokerConnectionRead, now: BrokerConnectionRead): boolean {
|
|
86
|
+
if (now.status !== "connected") return false;
|
|
87
|
+
if (before.status !== "connected") return true;
|
|
88
|
+
const at = stamp(now.connectedAt);
|
|
89
|
+
const was = stamp(before.connectedAt);
|
|
90
|
+
return at !== null && (was === null || at > was);
|
|
91
|
+
}
|
|
92
|
+
|
|
61
93
|
export class BrokerSignInController {
|
|
62
94
|
private readonly io: BrokerSignInIo;
|
|
63
95
|
private readonly listeners = new Set<(snapshot: BrokerSignInSnapshot) => void>();
|
|
64
96
|
private generation = 0;
|
|
97
|
+
/**
|
|
98
|
+
* Renewing only: the account's connection as first seen. It outlives a
|
|
99
|
+
* restarted code, so a sign-in finished while "r" asked for a new one still
|
|
100
|
+
* counts.
|
|
101
|
+
*/
|
|
102
|
+
private before: BrokerConnectionRead | null = null;
|
|
103
|
+
private readonly renew: boolean;
|
|
65
104
|
private snapshot: BrokerSignInSnapshot = { phase: "starting", connectUrl: null, code: null, error: null };
|
|
66
105
|
|
|
67
106
|
constructor(
|
|
@@ -69,8 +108,10 @@ export class BrokerSignInController {
|
|
|
69
108
|
/** Ask for trading as well as reading when the broker offers it. */
|
|
70
109
|
private readonly write: boolean,
|
|
71
110
|
io: Partial<BrokerSignInIo> = {},
|
|
111
|
+
options: BrokerSignInOptions = {},
|
|
72
112
|
) {
|
|
73
113
|
this.io = { ...defaultIo, ...io };
|
|
114
|
+
this.renew = options.renew === true;
|
|
74
115
|
}
|
|
75
116
|
|
|
76
117
|
getSnapshot(): BrokerSignInSnapshot {
|
|
@@ -102,6 +143,14 @@ export class BrokerSignInController {
|
|
|
102
143
|
private async run(generation: number): Promise<void> {
|
|
103
144
|
const stale = () => this.generation !== generation;
|
|
104
145
|
let retryMs = POLL_INTERVAL_MS;
|
|
146
|
+
// Renewing: read before a code exists, so nothing the user does can come
|
|
147
|
+
// first. A failed read leaves the first poll to stand in for it: no
|
|
148
|
+
// sign-in finishes within a poll interval.
|
|
149
|
+
if (this.renew && !this.before) {
|
|
150
|
+
const read = await this.io.fetchConnection(this.broker.id).catch(() => null);
|
|
151
|
+
if (stale()) return;
|
|
152
|
+
this.before ??= read;
|
|
153
|
+
}
|
|
105
154
|
// Each iteration is one code: start, poll until connected, and loop again
|
|
106
155
|
// when the code expired so the link refreshes instead of dead-ending.
|
|
107
156
|
while (!stale()) {
|
|
@@ -132,8 +181,14 @@ export class BrokerSignInController {
|
|
|
132
181
|
await this.io.delay(POLL_INTERVAL_MS);
|
|
133
182
|
if (stale()) return;
|
|
134
183
|
try {
|
|
184
|
+
const connection = await this.io.fetchConnection(this.broker.id);
|
|
135
185
|
// Connected is enough: a user who declined trading still gets a read-only connection.
|
|
136
|
-
|
|
186
|
+
let done = connection.status === "connected";
|
|
187
|
+
if (this.renew) {
|
|
188
|
+
this.before ??= connection;
|
|
189
|
+
done = signedInSince(this.before, connection);
|
|
190
|
+
}
|
|
191
|
+
if (done) {
|
|
137
192
|
if (!stale()) this.update({ phase: "connected", error: null });
|
|
138
193
|
this.generation += 1;
|
|
139
194
|
return;
|
|
@@ -154,7 +209,7 @@ export interface BrokerSignInSteps {
|
|
|
154
209
|
isSignedIn(): boolean;
|
|
155
210
|
/** The Gloom device sign-in; true once signed in. */
|
|
156
211
|
signInToGloom(): Promise<boolean>;
|
|
157
|
-
connectBroker(broker: SignedInBroker, write: boolean): Promise<BrokerSignInOutcome>;
|
|
212
|
+
connectBroker(broker: SignedInBroker, write: boolean, renew: boolean): Promise<BrokerSignInOutcome>;
|
|
158
213
|
}
|
|
159
214
|
|
|
160
215
|
/**
|
|
@@ -166,13 +221,15 @@ export async function runBrokerSignIn(
|
|
|
166
221
|
broker: SignedInBroker,
|
|
167
222
|
write: boolean | undefined,
|
|
168
223
|
steps: BrokerSignInSteps,
|
|
224
|
+
options: BrokerSignInOptions = {},
|
|
169
225
|
): Promise<boolean> {
|
|
170
226
|
if (!steps.isSignedIn() && !await steps.signInToGloom()) return false;
|
|
171
227
|
// Trading is asked for only where the broker takes orders from Gloom.
|
|
172
228
|
const scope = write ?? Boolean(broker.capabilities.orders);
|
|
173
|
-
|
|
229
|
+
const renew = options.renew === true;
|
|
230
|
+
let outcome = await steps.connectBroker(broker, scope, renew);
|
|
174
231
|
if (outcome === "signed-out" && await steps.signInToGloom()) {
|
|
175
|
-
outcome = await steps.connectBroker(broker, scope);
|
|
232
|
+
outcome = await steps.connectBroker(broker, scope, renew);
|
|
176
233
|
}
|
|
177
234
|
return outcome === "connected";
|
|
178
235
|
}
|
|
@@ -159,7 +159,14 @@ export class CapabilityRegistry {
|
|
|
159
159
|
|
|
160
160
|
private resolveOperation(capabilityId: string, operationId: string, options: { renderer?: boolean }) {
|
|
161
161
|
const entry = this.capabilities.get(capabilityId);
|
|
162
|
-
if (!entry || !this.isEnabled(entry))
|
|
162
|
+
if (!entry || !this.isEnabled(entry)) {
|
|
163
|
+
const pluginName = entry && this.options.isPluginEnabled?.(entry.pluginId) === false
|
|
164
|
+
? this.options.pluginName?.(entry.pluginId)
|
|
165
|
+
: undefined;
|
|
166
|
+
throw new Error(pluginName
|
|
167
|
+
? `Turn on ${pluginName} to use ${entry!.capability.name}.`
|
|
168
|
+
: `Capability "${capabilityId}" is not available.`);
|
|
169
|
+
}
|
|
163
170
|
const operation = entry.capability.operations[operationId];
|
|
164
171
|
if (!operation) throw new Error(`Capability operation "${capabilityId}.${operationId}" is not available.`);
|
|
165
172
|
if (options.renderer && operation.rendererSafe !== true) {
|
|
@@ -132,6 +132,8 @@ export interface CapabilityManifest {
|
|
|
132
132
|
|
|
133
133
|
export interface CapabilityRegistryOptions {
|
|
134
134
|
isPluginEnabled?(pluginId: string): boolean;
|
|
135
|
+
/** Names the plugin a switched-off capability belongs to, so the error can say what to turn on. */
|
|
136
|
+
pluginName?(pluginId: string): string | undefined;
|
|
135
137
|
isCapabilityEnabled?(capability: PluginCapability, pluginId: string): boolean;
|
|
136
138
|
connectionHealth?: ConnectionHealthRegistry;
|
|
137
139
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { CliCommandDef } from "../types/plugin";
|
|
2
|
+
import { fail } from "./errors";
|
|
3
|
+
import { suggestCliOption } from "./help";
|
|
4
|
+
|
|
5
|
+
/** A built-in command, which may say more about an option it does not take than the list of those it does. */
|
|
6
|
+
export interface BuiltinCliCommandDef extends CliCommandDef {
|
|
7
|
+
/** A sentence for an unknown option people reach for, such as `--from` on `history`; null for the rest. */
|
|
8
|
+
unknownOptionHint?(flag: string): string | null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface DeclaredOption {
|
|
12
|
+
flag: string;
|
|
13
|
+
takesValue: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** `--range`, `--range=5Y`: an option. `-5`, `---`, `--` and plain words are not. */
|
|
17
|
+
const OPTION_TOKEN = /^--[a-z]/i;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The options a command's help declares, from each spelling such as
|
|
21
|
+
* `--range <range>` (takes a value) or `--all` (a switch). Null when it takes
|
|
22
|
+
* any option: `--<option> <value>` on `fn` and `shot`.
|
|
23
|
+
*/
|
|
24
|
+
function declaredOptions(command: CliCommandDef): Map<string, DeclaredOption> | null {
|
|
25
|
+
const declared = new Map<string, DeclaredOption>();
|
|
26
|
+
for (const option of command.help?.options ?? []) {
|
|
27
|
+
for (const spelling of option.flags.split(",")) {
|
|
28
|
+
const trimmed = spelling.trim();
|
|
29
|
+
if (trimmed.startsWith("--<")) return null;
|
|
30
|
+
const match = /^(--?[a-z][\w-]*)(?:[ =](.+))?$/i.exec(trimmed);
|
|
31
|
+
if (match) declared.set(match[1]!, { flag: match[1]!, takesValue: match[2] != null });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return declared;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function failUnknownOption(command: BuiltinCliCommandDef, flag: string, declared: Map<string, DeclaredOption>): never {
|
|
38
|
+
const flags = [...declared.keys()];
|
|
39
|
+
const suggestion = suggestCliOption(flag, flags);
|
|
40
|
+
const help = `See gloomberb help ${command.name}.`;
|
|
41
|
+
fail(`Unknown option ${flag} for ${command.name}.`, [
|
|
42
|
+
command.unknownOptionHint?.(flag) ?? "",
|
|
43
|
+
suggestion ? `Did you mean ${suggestion}?` : "",
|
|
44
|
+
flags.length > 0 ? `Options: ${flags.join(", ")}. ${help}` : `${command.name} takes no options. ${help}`,
|
|
45
|
+
].filter(Boolean).join("\n"));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Fails on the first `--option` a built-in command does not declare, which it
|
|
50
|
+
* would otherwise ignore and answer as if it had not been given: `history
|
|
51
|
+
* --from 1995-01-01` printing the default year. Global flags are already out
|
|
52
|
+
* of `args`; a declared option's value is skipped whatever it looks like, and
|
|
53
|
+
* nothing from `literalStart` on (after a bare `--`) is read as an option.
|
|
54
|
+
*/
|
|
55
|
+
export function checkCliCommandOptions(
|
|
56
|
+
command: BuiltinCliCommandDef,
|
|
57
|
+
args: readonly string[],
|
|
58
|
+
literalStart = args.length,
|
|
59
|
+
): void {
|
|
60
|
+
const declared = declaredOptions(command);
|
|
61
|
+
if (!declared) return;
|
|
62
|
+
for (let index = 0; index < Math.min(literalStart, args.length); index += 1) {
|
|
63
|
+
const arg = args[index]!;
|
|
64
|
+
if (!OPTION_TOKEN.test(arg)) continue;
|
|
65
|
+
const equals = arg.indexOf("=");
|
|
66
|
+
const flag = equals >= 0 ? arg.slice(0, equals) : arg;
|
|
67
|
+
const option = declared.get(flag);
|
|
68
|
+
if (!option) failUnknownOption(command, flag, declared);
|
|
69
|
+
if (!option.takesValue && equals >= 0) {
|
|
70
|
+
fail(`${flag} takes no value.`, `Write it alone, as ${flag}. See gloomberb help ${command.name}.`);
|
|
71
|
+
}
|
|
72
|
+
if (option.takesValue && equals < 0) index += 1;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -46,6 +46,35 @@ export function requireArg(value: string | undefined, usage: string, ctx: CliCom
|
|
|
46
46
|
return value;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Fails on arguments past the `max` a command takes rather than dropping them:
|
|
51
|
+
* `fx NGN ZAR` printing NGN alone reads as an answer for both. `usage` is the
|
|
52
|
+
* command's usage line without `gloomberb`, `takes` what it takes ("one
|
|
53
|
+
* currency", "no arguments").
|
|
54
|
+
*/
|
|
55
|
+
export function rejectExtraArgs(
|
|
56
|
+
args: readonly string[],
|
|
57
|
+
max: number,
|
|
58
|
+
{ usage, takes, advice }: { usage: string; takes: string; advice?: string },
|
|
59
|
+
ctx: Pick<CliCommandContext, "fail">,
|
|
60
|
+
): void {
|
|
61
|
+
if (args.length <= max) return;
|
|
62
|
+
const command = usage.split(" ")[0];
|
|
63
|
+
ctx.fail(`${command} takes ${takes}; got ${args.join(" ")}.`, [advice, `Usage: gloomberb ${usage}`].filter(Boolean).join("\n"));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** The one argument a command takes, such as a symbol: missing fails with the usage line, extras are not dropped. */
|
|
67
|
+
export function requireOneArg(
|
|
68
|
+
args: readonly string[],
|
|
69
|
+
usage: string,
|
|
70
|
+
noun: string,
|
|
71
|
+
ctx: CliCommandContext,
|
|
72
|
+
): string {
|
|
73
|
+
const value = requireArg(args[0], `Usage: gloomberb ${usage}`, ctx);
|
|
74
|
+
rejectExtraArgs(args, 1, { usage, takes: `one ${noun}`, advice: `Run it once per ${noun}.` }, ctx);
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
|
|
49
78
|
export function isoDate(value: unknown): string {
|
|
50
79
|
if (value instanceof Date) return value.toISOString();
|
|
51
80
|
if (typeof value === "number") return new Date(value).toISOString();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isCryptoInstrumentType } from "../../tickers/search/ranking";
|
|
2
2
|
import type { Quote } from "../../types/financials";
|
|
3
3
|
import { isCryptoPairSymbol } from "../../utils/crypto-pair";
|
|
4
|
+
import { isNotATickerMessage } from "../not-a-ticker";
|
|
4
5
|
|
|
5
6
|
/** Where a crypto pair that will not load can still be read. `fn CRYP` takes no argument. */
|
|
6
7
|
export const CRYPTO_BOARD_HINT = "Crypto prices may be briefly unavailable; the CRYP function (gloomberb fn CRYP) shows the crypto board.";
|
|
@@ -42,11 +43,15 @@ interface QuoteNoteResult {
|
|
|
42
43
|
error: string | null;
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* The router words a failure as "<reason> for <symbol>"; drop the symbol so equal reasons group.
|
|
48
|
+
* Any other line, such as a sentence the data service wrote, is kept as it reads.
|
|
49
|
+
*/
|
|
46
50
|
function failureReason(message: string, symbol: string): string {
|
|
47
|
-
const line = (message.split("\n")[0] ?? "").trim()
|
|
51
|
+
const line = (message.split("\n")[0] ?? "").trim();
|
|
52
|
+
const bare = line.replace(/\.+$/, "");
|
|
48
53
|
const suffix = ` for ${symbol}`;
|
|
49
|
-
return
|
|
54
|
+
return bare.toLowerCase().endsWith(suffix.toLowerCase()) ? bare.slice(0, -suffix.length) : line;
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
/**
|
|
@@ -63,7 +68,10 @@ export function quoteNotes(results: QuoteNoteResult[], options: { exchange?: str
|
|
|
63
68
|
if (!symbols.includes(result.target.symbol)) failures.set(reason, [...symbols, result.target.symbol]);
|
|
64
69
|
}
|
|
65
70
|
const notes = [...failures].map(([reason, symbols]) => (
|
|
66
|
-
|
|
71
|
+
// "Not a ticker: APPLE." already names its symbol.
|
|
72
|
+
isNotATickerMessage(reason)
|
|
73
|
+
? reason
|
|
74
|
+
: `${symbols.join(", ")}: ${reason}${symbols.some(isCryptoPairSymbol) ? `${/[.!?]$/.test(reason) ? "" : "."} ${CRYPTO_BOARD_HINT}` : ""}`
|
|
67
75
|
));
|
|
68
76
|
if (!options.exchange) {
|
|
69
77
|
for (const result of results) {
|